aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/examples/example-textballoons.qdoc2
-rw-r--r--doc/src/examples/examples-toys.qdoc13
-rw-r--r--doc/src/examples/examples.qdoc202
-rw-r--r--doc/src/images/qml-canvas-example.pngbin0 -> 18373 bytes
-rw-r--r--doc/src/images/qml-draganddrop-example.pngbin0 -> 24196 bytes
-rw-r--r--doc/src/images/qml-keyinteraction-example.pngbin0 -> 26514 bytes
-rw-r--r--doc/src/images/qml-mousearea-example.pngbin0 -> 18556 bytes
-rw-r--r--doc/src/images/qml-positioners-example.pngbin9828 -> 17947 bytes
-rw-r--r--doc/src/images/qml-righttoleft-example.pngbin0 -> 35323 bytes
-rw-r--r--doc/src/images/qml-threading-example.pngbin0 -> 22778 bytes
-rw-r--r--doc/src/qml/qmltypes.qdoc2
-rw-r--r--doc/src/qml/qtdeclarative.qdoc2
-rw-r--r--examples/demos/calculator/CalculatorCore/calculator.js18
-rw-r--r--examples/demos/calculator/calculator-mobile.qml10
-rw-r--r--examples/demos/calculator/calculator.qdoc4
-rw-r--r--examples/demos/clocks/clocks.qdoc37
-rw-r--r--examples/localstorage/localstorage.qml4
-rw-r--r--examples/qml/dynamicscene/content/Button.qml7
-rw-r--r--examples/qml/dynamicscene/content/Sun.qml35
-rw-r--r--examples/qml/dynamicscene/dynamicscene.qml26
-rw-r--r--examples/qml/i18n/i18n.qml40
-rw-r--r--examples/quick/accessibility/accessibility.qml2
-rw-r--r--examples/quick/animation/animation.qml2
-rw-r--r--examples/quick/canvas/canvas.qml1
-rw-r--r--examples/quick/draganddrop/draganddrop.qml2
-rw-r--r--examples/quick/imageelements/content/BorderImageSelector.qml4
-rw-r--r--examples/quick/imageelements/content/arrow.pngbin0 -> 404 bytes
-rw-r--r--examples/quick/imageelements/imageelements.qml2
-rw-r--r--examples/quick/modelviews/listview/content/SmallText.qml46
-rw-r--r--examples/quick/modelviews/listview/content/TextButton.qml8
-rw-r--r--examples/quick/modelviews/listview/expandingdelegates.qml8
-rw-r--r--examples/quick/modelviews/listview/highlight.qml6
-rw-r--r--examples/quick/positioners/positioners-transitions.qml4
-rw-r--r--examples/quick/righttoleft/righttoleft.qml2
-rw-r--r--examples/quick/shadereffects/shadereffects.qml13
-rw-r--r--examples/quick/text/text.qml2
-rw-r--r--examples/quick/threading/threading.qml2
-rw-r--r--examples/quick/touchinteraction/touchinteraction.qml2
-rw-r--r--src/3rdparty/javascriptcore/COPYING.LIB488
-rw-r--r--src/3rdparty/javascriptcore/DateMath.cpp393
-rw-r--r--src/3rdparty/javascriptcore/DateMath.h190
-rw-r--r--src/3rdparty/javascriptcore/VERSION15
-rw-r--r--src/imports/imports.pro2
-rw-r--r--src/imports/particles/particles.pro19
-rw-r--r--src/imports/particles/plugin.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/selectiontool.h)53
-rw-r--r--src/imports/particles/qmldir1
-rw-r--r--src/imports/testlib/TestCase.qml14
-rw-r--r--src/imports/testlib/testcase.qdoc25
-rw-r--r--src/imports/window/plugin.cpp65
-rw-r--r--src/imports/window/qmldir1
-rw-r--r--src/imports/window/window.pro19
-rw-r--r--src/plugins/accessible/quick/main.cpp6
-rw-r--r--src/plugins/accessible/quick/qaccessiblequickview.cpp7
-rw-r--r--src/plugins/plugins.pro4
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.cpp)243
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h (renamed from src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.h)56
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro6
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp24
-rw-r--r--src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h6
-rw-r--r--src/plugins/qmltooling/shared/abstracttool.h2
-rw-r--r--src/plugins/qmltooling/shared/abstractviewinspector.cpp38
-rw-r--r--src/plugins/qmltooling/shared/abstractviewinspector.h12
-rw-r--r--src/plugins/qmltooling/shared/qmlinspectorconstants.h5
-rw-r--r--src/plugins/qmltooling/shared/qqmlinspectorprotocol.h7
-rw-r--r--src/qml/animations/qanimationgroupjob.cpp16
-rw-r--r--src/qml/debugger/qqmldebug.h4
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp7
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp16
-rw-r--r--src/qml/debugger/qqmlenginedebugservice_p.h1
-rw-r--r--src/qml/debugger/qqmlprofilerservice.cpp4
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h37
-rw-r--r--src/qml/qml/qqmlabstractexpression_p.h2
-rw-r--r--src/qml/qml/qqmlaccessors_p.h2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp184
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h88
-rw-r--r--src/qml/qml/qqmlcompiler.cpp31
-rw-r--r--src/qml/qml/qqmlcomponent.cpp3
-rw-r--r--src/qml/qml/qqmldata_p.h14
-rw-r--r--src/qml/qml/qqmldirparser.cpp12
-rw-r--r--src/qml/qml/qqmlengine.cpp14
-rw-r--r--src/qml/qml/qqmlexpression.cpp33
-rw-r--r--src/qml/qml/qqmlexpression_p.h7
-rw-r--r--src/qml/qml/qqmlimport.cpp36
-rw-r--r--src/qml/qml/qqmlinstruction.cpp3
-rw-r--r--src/qml/qml/qqmlinstruction_p.h2
-rw-r--r--src/qml/qml/qqmlproperty.cpp37
-rw-r--r--src/qml/qml/qqmlproperty_p.h8
-rw-r--r--src/qml/qml/qqmlrewrite.cpp17
-rw-r--r--src/qml/qml/qqmlrewrite_p.h29
-rw-r--r--src/qml/qml/qqmlscript.cpp5
-rw-r--r--src/qml/qml/qqmlvme.cpp86
-rw-r--r--src/qml/qml/v4/qv4bindings.cpp456
-rw-r--r--src/qml/qml/v4/qv4bindings_p.h6
-rw-r--r--src/qml/qml/v4/qv4compiler.cpp267
-rw-r--r--src/qml/qml/v4/qv4compiler_p_p.h16
-rw-r--r--src/qml/qml/v4/qv4instruction.cpp130
-rw-r--r--src/qml/qml/v4/qv4instruction_p.h85
-rw-r--r--src/qml/qml/v4/qv4ir.cpp37
-rw-r--r--src/qml/qml/v4/qv4ir_p.h6
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp30
-rw-r--r--src/qml/qml/v4/qv4irbuilder_p.h4
-rw-r--r--src/qml/qml/v4/qv4program_p.h4
-rw-r--r--src/qml/qml/v8/qjsvalue_p.h2
-rw-r--r--src/qml/qml/v8/qv8bindings.cpp23
-rw-r--r--src/qml/qml/v8/qv8bindings_p.h20
-rw-r--r--src/qml/qml/v8/qv8contextwrapper.cpp2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp43
-rw-r--r--src/qml/qml/v8/qv8qobjectwrapper.cpp29
-rw-r--r--src/qml/qml/v8/v8.pri6
-rw-r--r--src/qmltest/qmltest.pro4
-rw-r--r--src/qmltest/quicktest.cpp34
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp682
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h22
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp30
-rw-r--r--src/quick/items/qquickcanvas.cpp17
-rw-r--r--src/quick/items/qquickcanvas.h2
-rw-r--r--src/quick/items/qquickflickable.cpp3
-rw-r--r--src/quick/items/qquickimplicitsizeitem.cpp12
-rw-r--r--src/quick/items/qquickitem.cpp53
-rw-r--r--src/quick/items/qquickitem_p.h2
-rw-r--r--src/quick/items/qquickitemchangelistener_p.h2
-rw-r--r--src/quick/items/qquicklistview.cpp11
-rw-r--r--src/quick/items/qquickloader.cpp81
-rw-r--r--src/quick/items/qquickloader_p_p.h7
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp2
-rw-r--r--src/quick/items/qquickpathview.cpp143
-rw-r--r--src/quick/items/qquickpathview_p.h7
-rw-r--r--src/quick/items/qquickpathview_p_p.h9
-rw-r--r--src/quick/items/qquickshadereffect.cpp960
-rw-r--r--src/quick/items/qquickshadereffect_p.h69
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp210
-rw-r--r--src/quick/items/qquickshadereffectnode_p.h52
-rw-r--r--src/quick/items/qquickspriteengine.cpp3
-rw-r--r--src/quick/items/qquicktext.cpp9
-rw-r--r--src/quick/items/qquicktextcontrol.cpp74
-rw-r--r--src/quick/items/qquicktextcontrol_p.h4
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h4
-rw-r--r--src/quick/items/qquicktextedit.cpp12
-rw-r--r--src/quick/items/qquicktextinput.cpp82
-rw-r--r--src/quick/items/qquicktextinput_p_p.h9
-rw-r--r--src/quick/items/qquicktextnode.cpp22
-rw-r--r--src/quick/items/qquickvisualdatamodel.cpp2
-rw-r--r--src/quick/items/qquickwindowmanager.cpp2
-rw-r--r--src/quick/items/qquickwindowmodule_p.h4
-rw-r--r--src/quick/particles/qquickcustomparticle.cpp387
-rw-r--r--src/quick/particles/qquickcustomparticle_p.h48
-rw-r--r--src/quick/particles/qquickparticleemitter_p.h3
-rw-r--r--src/quick/particles/qquickparticlesmodule_p.h10
-rw-r--r--src/quick/qtquick2.cpp6
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp25
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h11
-rw-r--r--src/quick/scenegraph/util/qsgpainternode.cpp5
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp4
-rw-r--r--src/quick/util/qquickconnections.cpp5
-rw-r--r--src/quick/util/qquickpropertychanges.cpp124
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp3
-rw-r--r--tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp27
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.cpp5
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/InnerObject.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/OuterObject.qml5
-rw-r--r--tests/auto/qml/qqmlecmascript/data/deleteLaterObjectMethodCall.qml22
-rw-r--r--tests/auto/qml/qqmlecmascript/data/ownershipQmlIncubated.qml27
-rw-r--r--tests/auto/qml/qqmlecmascript/data/replaceBinding.qml26
-rw-r--r--tests/auto/qml/qqmlecmascript/data/singleV8BindingDestroyedDuringEvaluation.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp53
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp56
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml5
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.2.qml5
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.errors.txt1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.qml4
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.errors.txt1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.qml5
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/imports/com/nokia/AutoTestQmlNestedPluginType/qmldir1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp (renamed from src/plugins/qmltooling/qmldbg_qtquick2/selectiontool.cpp)81
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.pro7
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp43
-rw-r--r--tests/auto/qml/qqmlparser/tst_qqmlparser.cpp7
-rw-r--r--tests/auto/qml/qqmlproperty/data/invalidBinding.qml16
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp158
-rw-r--r--tests/auto/qml/qqmlqt/data/dateTimeConversion.qml6
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp8
-rw-r--r--tests/auto/qml/v4/data/conversions.1.qml13
-rw-r--r--tests/auto/qml/v4/data/conversions.2.qml13
-rw-r--r--tests/auto/qml/v4/data/conversions.3.qml13
-rw-r--r--tests/auto/qml/v4/data/conversions.4.qml13
-rw-r--r--tests/auto/qml/v4/data/conversions.5.qml13
-rw-r--r--tests/auto/qml/v4/data/conversions.6.qml13
-rw-r--r--tests/auto/qml/v4/data/conversions.7.qml13
-rw-r--r--tests/auto/qml/v4/data/conversions.8.qml13
-rw-r--r--tests/auto/qml/v4/data/subscriptions.1.qml16
-rw-r--r--tests/auto/qml/v4/testtypes.cpp1
-rw-r--r--tests/auto/qml/v4/testtypes.h57
-rw-r--r--tests/auto/qml/v4/tst_v4.cpp343
-rw-r--r--tests/auto/qmltest/selftests/tst_datadriven.qml78
-rw-r--r--tests/auto/quick/examples/examples.pro2
-rw-r--r--tests/auto/quick/examples/tst_examples.cpp8
-rw-r--r--tests/auto/quick/qquickaccessible/data/statictext.qml4
-rw-r--r--tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp40
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_arc.qml74
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml28
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml1
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_composite.qml21
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_path.qml134
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp13
-rw-r--r--tests/auto/quick/qquickflipable/data/flip-flipable.qml28
-rw-r--r--tests/auto/quick/qquickflipable/tst_qquickflipable.cpp15
-rw-r--r--tests/auto/quick/qquickgridview/tst_qquickgridview.cpp13
-rw-r--r--tests/auto/quick/qquickitem/data/focusSubItemInNonFocusScope.qml23
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp131
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp10
-rw-r--r--tests/auto/quick/qquickloader/data/RedRect.qml8
-rw-r--r--tests/auto/quick/qquickloader/data/implicitSize.qml5
-rw-r--r--tests/auto/quick/qquickloader/data/loadedSignal.2.qml31
-rw-r--r--tests/auto/quick/qquickloader/data/loadedSignal.qml48
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp65
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp4
-rw-r--r--tests/auto/quick/qquickpathview/data/panels.qml44
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp87
-rw-r--r--tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp2
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp5
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp2
-rw-r--r--tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp120
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp132
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp3
-rw-r--r--tests/auto/quick/quick.pro3
-rw-r--r--tests/auto/quick/shared/viewtestutil.cpp8
-rw-r--r--tools/qmlprofiler/qmlprofiler.pro2
-rw-r--r--tools/qmlscene/qmlscene.pro2
235 files changed, 5468 insertions, 4208 deletions
diff --git a/doc/src/examples/example-textballoons.qdoc b/doc/src/examples/example-textballoons.qdoc
index be004f59ed..299ceeb808 100644
--- a/doc/src/examples/example-textballoons.qdoc
+++ b/doc/src/examples/example-textballoons.qdoc
@@ -28,7 +28,7 @@
/*!
\title Scenegraph Painted Item Example
- \example declarative/painteditem/textballoons
+ \example quick/painteditem/textballoons
The Painted Item example shows how to use the QML Scene Graph framework to
implement custom scenegraph items using QPainter.
diff --git a/doc/src/examples/examples-toys.qdoc b/doc/src/examples/examples-toys.qdoc
index 7414579e19..87d2ad58f6 100644
--- a/doc/src/examples/examples-toys.qdoc
+++ b/doc/src/examples/examples-toys.qdoc
@@ -47,16 +47,3 @@
\image qml-corkboards-example.png
*/
-/*!
- \title QML Example - Dynamic Scene
- \example declarative/toys/dynamicscene
- \brief This example demonstrates creating components dynamically.
- \image qml-dynamicscene-example.png
-*/
-
-/*!
- \title QML Example - Clocks
- \example declarative/toys/clocks
- \brief This example demonstrates creating components and using them multiple times.
- \image qml-clocks-example.png
-*/
diff --git a/doc/src/examples/examples.qdoc b/doc/src/examples/examples.qdoc
index a99dc8c263..b5cd036c03 100644
--- a/doc/src/examples/examples.qdoc
+++ b/doc/src/examples/examples.qdoc
@@ -51,39 +51,39 @@ This set of code samples are part of the collection of \l{Qt Examples}.
Qt Quick Applications
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/calculator}{Calculator}
+ \l{demos/calculator}{Calculator}
\image qml-calculator-example-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/flickr}{Flickr Mobile}
+ \l{demos/flickr}{Flickr Mobile}
\image qml-flickr-demo-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/minehunt}{Minehunt}
+ \l{demos/minehunt}{Minehunt}
\image qml-minehunt-demo-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/photoviewer}{Photo Viewer}
+ \l{demos/photoviewer}{Photo Viewer}
\image qml-photoviewer-demo-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/rssnews}{RSS News Reader}
+ \l{demos/rssnews}{RSS News Reader}
\image qml-rssnews-demo-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/samegame}{Same Game}
+ \l{demos/samegame}{Same Game}
\image qml-samegame-demo-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/snake}{Snake}
+ \l{demos/snake}{Snake}
\image qml-snake-demo-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/twitter}{Twitter}
+ \l{demos/twitter}{Twitter}
\image qml-twitter-demo-small.png
\enddiv
\div {class="threecolumn_piece"}
- \l{demos/declarative/webbrowser}{Web Browser}
+ \l{demos/webbrowser}{Web Browser}
\image qml-webbrowser-demo-small.png
\enddiv
\enddiv
@@ -93,132 +93,19 @@ This set of code samples are part of the collection of \l{Qt Examples}.
\enddiv
Code samples demonstrate a general use for QML features. Some showcase
how elements or properties can be used in an application.
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- QML Features
- \enddiv
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Mouse and Keyboard Input
- \enddiv
- \list
- \li \l{declarative/text/fonts}{Fonts}
- \li \l{declarative/text/textselection}{Text Selection}
- \li \l{declarative/keyinteraction/focus}{Keyboard Focus}
- \li \l{declarative/touchinteraction/mousearea}{MouseArea}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- States and Transitions
- \enddiv
- \list
- \li \l{declarative/animation/states}{States}
- \li \l{declarative/animation/basics}{Animation Essentials}
- \li \l{declarative/animation/behaviors}{Behaviors}
- \li \l{declarative/animation/easing}{Easing}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- UI Components
- \enddiv
- \list
- \li \l{declarative/ui-components/dialcontrol}{Dial Control}
- \li \l{declarative/ui-components/flipable}{Flipable}
- \li \l{declarative/ui-components/progressbar}{Progress Bar}
- \li \l{declarative/ui-components/scrollbar}{Scroll Bar}
- \li \l{declarative/ui-components/searchbox}{Search Box}
- \li \l{declarative/ui-components/slideswitch}{Slide Switch}
- \li \l{declarative/ui-components/spinner}{Spinner}
- \li \l{declarative/ui-components/tabwidget}{Tab Widget}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Positioners and Layout
- \enddiv
- \list
- \li \l{declarative/positioners}{Row and Column}
- \li \l{declarative/righttoleft/layoutmirroring}{Layout Mirroring}
- \li \l{declarative/righttoleft/layoutdirection}{Layout Direction}
- \li \l{declarative/righttoleft/textalignment}{Text Alignment}
- \li \l{declarative/screenorientation}{Screen Orientation}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Data with Models and Views
- \enddiv
- \list
- \li \l{declarative/modelviews/gridview}{GridView}
- \li \l{declarative/modelviews/listview}{ListView}
- \li \l{declarative/modelviews/pathview}{PathView}
- \li \l{declarative/modelviews/package}{Package}
- \li \l{declarative/modelviews/visualitemmodel}{VisualItemModel}
- \li \l{declarative/modelviews/stringlistmodel}{String ListModel}
- \li \l{declarative/modelviews/objectlistmodel}{Object ListModel}
- \li \l{declarative/modelviews/abstractitemmodel}{AbstractItemModel}
- \li \l{declarative/modelviews/webview}{WebView}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Advance UI Components
- \enddiv
- \list
- \li \l{declarative/modelviews/parallax}{Parallax}
- \li \l{declarative/toys/clocks}{Clocks}
- \li \l{declarative/toys/corkboards}{Corkboards}
- \li \l{declarative/toys/dynamicscene}{Dynamic Scene}
- \li \l{declarative/toys/tic-tac-toe}{Tic Tac Toe}
- \li \l{declarative/toys/tvtennis}{TV Tennis}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Image Elements
- \enddiv
- \list
- \li \l{declarative/imageelements/borderimage}{BorderImage}
- \li \l{declarative/imageelements/image}{Image}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Loading Resources
- \enddiv
- \list
- \li \l{declarative/sqllocalstorage}{SQL Local Storage}
- \li \l{declarative/xml/xmlhttprequest}{XmlHttpRequest}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Localization
- \enddiv
- \list
- \li \l{declarative/i18n}{Translation}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Threading
- \enddiv
- \list
- \li \l{declarative/threading/threadedlistmodel}{Threaded ListModel}
- \li \l{declarative/threading/workerscript}{WorkerScript Element}
- \endlist
- \enddiv
- \div {class="threecolumn_piece"}
- \div {class="heading"}
- Graphical Effects
- \enddiv
- \list
- \li \l{declarative/shadereffects}{Shader Effects}
- \endlist
- \enddiv
+ \li \l{quick/keyinteraction}{Keyboard Focus}
+ \li \l{quick/mousearea}{MouseArea}
+ \li \l{quick/animation}{Animations}
+ \li \l{quick/positioners}{Positioners}
+ \li \l{quick/righttoleft}{Right to Left}
+ \li \l{quick/modelviews}{Model Views}
+ \li \l{quick/imageelements}{Image Elements}
+ \li \l{localstorage}{SQL Local Storage}
+ \li \l{qml/xmlhttprequest}{XmlHttpRequest}
+ \li \l{qml/i18n}{Translation}
+ \li \l{quick/threading}{Threading}
+ \li \l{quick/shadereffects}{Shader Effects}
+ \endlist
\enddiv
\div {class="threecolumn_area"}
\div {class="heading"}
@@ -231,16 +118,16 @@ This set of code samples are part of the collection of \l{Qt Examples}.
From Qt C++ to QML
\enddiv
\list
- \li \l {declarative/cppextensions/referenceexamples/adding}{Exporting C++ Classes}
- \li \l {declarative/cppextensions/referenceexamples/properties}{Exporting Qt C++ Properties}
- \li \l {declarative/cppextensions/referenceexamples/coercion}{C++ Inheritance and Coercion}
- \li \l {declarative/cppextensions/referenceexamples/default}{Default Property}
- \li \l {declarative/cppextensions/referenceexamples/grouped}{Grouped Properties}
- \li \l {declarative/cppextensions/referenceexamples/attached}{Attached Properties}
- \li \l {declarative/cppextensions/referenceexamples/signal}{Signal Support}
- \li \l {declarative/cppextensions/referenceexamples/methods}{Methods Support}
- \li \l {declarative/cppextensions/referenceexamples/valuesource}{Property Value Source}
- \li \l {declarative/cppextensions/referenceexamples/binding}{Binding}
+ \li \l {qml/cppextensions/referenceexamples/adding}{Exporting C++ Classes}
+ \li \l {qml/cppextensions/referenceexamples/properties}{Exporting Qt C++ Properties}
+ \li \l {qml/cppextensions/referenceexamples/coercion}{C++ Inheritance and Coercion}
+ \li \l {qml/cppextensions/referenceexamples/default}{Default Property}
+ \li \l {qml/cppextensions/referenceexamples/grouped}{Grouped Properties}
+ \li \l {qml/cppextensions/referenceexamples/attached}{Attached Properties}
+ \li \l {qml/cppextensions/referenceexamples/signal}{Signal Support}
+ \li \l {qml/cppextensions/referenceexamples/methods}{Methods Support}
+ \li \l {qml/cppextensions/referenceexamples/valuesource}{Property Value Source}
+ \li \l {qml/cppextensions/referenceexamples/binding}{Binding}
\endlist
\enddiv
\div {class="threecolumn_piece"}
@@ -248,9 +135,9 @@ This set of code samples are part of the collection of \l{Qt Examples}.
Plugins and Resources
\enddiv
\list
- \li \l{declarative/cppextensions/plugins}{Plugins}
- \li \l{declarative/cppextensions/imageprovider}{Image Provider}
- \li \l{declarative/cppextensions/networkaccessmanagerfactory}{Network Access Manager}
+ \li \l{qml/cppextensions/plugins}{Plugins}
+ \li \l{qml/cppextensions/imageprovider}{Image Provider}
+ \li \l{qml/cppextensions/networkaccessmanagerfactory}{Network Access Manager}
\li \l{src/imports/folderlistmodel}{Folder List Model} - a C++ model plugin
\endlist
\enddiv
@@ -259,8 +146,23 @@ This set of code samples are part of the collection of \l{Qt Examples}.
Qt UI and QML Integration
\enddiv
\list
- \li \l{declarative-cppextensions-qgraphicslayouts.html}{QGraphicsLayouts}
- \li \l{declarative/cppextensions/qwidgets}{QWidgets}
+ \li \l{qml-cppextensions-qgraphicslayouts.html}{QGraphicsLayouts}
+ \li \l{qml/cppextensions/qwidgets}{QWidgets}
+ \endlist
+ \enddiv
+ \div {class="threecolumn_piece"}
+ \div {class="heading"}
+ UI Components
+ \enddiv
+ \list
+ \li \l{tutorials/ui-components/dialcontrol}{Dial Control}
+ \li \l{tutorials/ui-components/flipable}{Flipable}
+ \li \l{tutorials/ui-components/progressbar}{Progress Bar}
+ \li \l{tutorials/ui-components/scrollbar}{Scroll Bar}
+ \li \l{tutorials/ui-components/searchbox}{Search Box}
+ \li \l{tutorials/ui-components/slideswitch}{Slide Switch}
+ \li \l{tutorials/ui-components/spinner}{Spinner}
+ \li \l{tutorials/ui-components/tabwidget}{Tab Widget}
\endlist
\enddiv
\enddiv
diff --git a/doc/src/images/qml-canvas-example.png b/doc/src/images/qml-canvas-example.png
new file mode 100644
index 0000000000..2651ad6ff5
--- /dev/null
+++ b/doc/src/images/qml-canvas-example.png
Binary files differ
diff --git a/doc/src/images/qml-draganddrop-example.png b/doc/src/images/qml-draganddrop-example.png
new file mode 100644
index 0000000000..b64f4d63a4
--- /dev/null
+++ b/doc/src/images/qml-draganddrop-example.png
Binary files differ
diff --git a/doc/src/images/qml-keyinteraction-example.png b/doc/src/images/qml-keyinteraction-example.png
new file mode 100644
index 0000000000..7f4dd77907
--- /dev/null
+++ b/doc/src/images/qml-keyinteraction-example.png
Binary files differ
diff --git a/doc/src/images/qml-mousearea-example.png b/doc/src/images/qml-mousearea-example.png
new file mode 100644
index 0000000000..d93dc92d74
--- /dev/null
+++ b/doc/src/images/qml-mousearea-example.png
Binary files differ
diff --git a/doc/src/images/qml-positioners-example.png b/doc/src/images/qml-positioners-example.png
index 90d70ff307..0c02f4a56a 100644
--- a/doc/src/images/qml-positioners-example.png
+++ b/doc/src/images/qml-positioners-example.png
Binary files differ
diff --git a/doc/src/images/qml-righttoleft-example.png b/doc/src/images/qml-righttoleft-example.png
new file mode 100644
index 0000000000..03c3c48f10
--- /dev/null
+++ b/doc/src/images/qml-righttoleft-example.png
Binary files differ
diff --git a/doc/src/images/qml-threading-example.png b/doc/src/images/qml-threading-example.png
new file mode 100644
index 0000000000..6ed79ab190
--- /dev/null
+++ b/doc/src/images/qml-threading-example.png
Binary files differ
diff --git a/doc/src/qml/qmltypes.qdoc b/doc/src/qml/qmltypes.qdoc
index ae4ad47c3d..b75c191616 100644
--- a/doc/src/qml/qmltypes.qdoc
+++ b/doc/src/qml/qmltypes.qdoc
@@ -70,6 +70,8 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
Alternatively, these functions provide a way for other types of C++ types
to be visible in the QML context.
\list
+ \li \l qmlRegisterModuleApi() is suited for registering either a QJSValue
+ or QObject module API (shared instance) into a namespace
\li \l qmlRegisterUncreatableType() is suited for attached
properties and enum types.
\li \l qmlRegisterTypeNotAvailable() is for
diff --git a/doc/src/qml/qtdeclarative.qdoc b/doc/src/qml/qtdeclarative.qdoc
index 48cc898458..5ad637ab50 100644
--- a/doc/src/qml/qtdeclarative.qdoc
+++ b/doc/src/qml/qtdeclarative.qdoc
@@ -351,7 +351,7 @@
// third, register the module API provider with QML by calling this function in an initialization function.
...
- qmlRegisterModuleApi("Qt.example.qobjectApi", 1, 0, example_qobject_module_api_provider);
+ qmlRegisterModuleApi<ModuleApiExample>("Qt.example.qobjectApi", 1, 0, example_qobject_module_api_provider);
...
\endcode
diff --git a/examples/demos/calculator/CalculatorCore/calculator.js b/examples/demos/calculator/CalculatorCore/calculator.js
index e2b5692cf3..b4b0d9eea9 100644
--- a/examples/demos/calculator/CalculatorCore/calculator.js
+++ b/examples/demos/calculator/CalculatorCore/calculator.js
@@ -7,7 +7,7 @@ var timer = 0
function disabled(op) {
if (op == "." && display.text.toString().search(/\./) != -1) {
return true
- } else if (op == squareRoot && display.text.toString().search(/-/) != -1) {
+ } else if (op == window.squareRoot && display.text.toString().search(/-/) != -1) {
return true
} else {
return false
@@ -16,9 +16,9 @@ function disabled(op) {
function doOperation(op) {
if (op == '*')//Keyboard Aliases
- op = multiplication;
+ op = window.multiplication;
if (op == '/')
- op = division;
+ op = window.division;
if (disabled(op)) {
return
}
@@ -40,14 +40,14 @@ function doOperation(op) {
display.text = Number(display.text.valueOf()) + Number(curVal.valueOf())
} else if (display.currentOperation.text == "-") {
display.text = Number(curVal) - Number(display.text.valueOf())
- } else if (display.currentOperation.text == multiplication) {
+ } else if (display.currentOperation.text == window.multiplication) {
display.text = Number(curVal) * Number(display.text.valueOf())
- } else if (display.currentOperation.text == division) {
+ } else if (display.currentOperation.text == window.division) {
display.text = Number(Number(curVal) / Number(display.text.valueOf())).toString()
} else if (display.currentOperation.text == "=") {
}
- if (op == "+" || op == "-" || op == multiplication || op == division) {
+ if (op == "+" || op == "-" || op == window.multiplication || op == window.division) {
display.currentOperation.text = op
curVal = display.text.valueOf()
return
@@ -64,9 +64,9 @@ function doOperation(op) {
display.text = (Math.abs(display.text.valueOf())).toString()
} else if (op == "Int") {
display.text = (Math.floor(display.text.valueOf())).toString()
- } else if (op == plusminus) {
+ } else if (op == window.plusminus) {
display.text = (display.text.valueOf() * -1).toString()
- } else if (op == squareRoot) {
+ } else if (op == window.squareRoot) {
display.text = (Math.sqrt(display.text.valueOf())).toString()
} else if (op == "mc") {
memory = 0;
@@ -76,7 +76,7 @@ function doOperation(op) {
display.text = memory.toString()
} else if (op == "m-") {
memory = display.text.valueOf()
- } else if (op == leftArrow) {
+ } else if (op == window.leftArrow) {
display.text = display.text.toString().slice(0, -1)
if (display.text.length == 0) {
display.text = "0"
diff --git a/examples/demos/calculator/calculator-mobile.qml b/examples/demos/calculator/calculator-mobile.qml
index 7ee622f698..d042c756fc 100644
--- a/examples/demos/calculator/calculator-mobile.qml
+++ b/examples/demos/calculator/calculator-mobile.qml
@@ -95,7 +95,7 @@ Rectangle {
Row {
spacing: 6
Button { width: column.w; height: column.h; color: 'purple'; operation: "Off" }
- Button { width: column.w; height: column.h; color: 'purple'; operation: leftArrow }
+ Button { width: column.w; height: column.h; color: 'purple'; operation: window.leftArrow }
Button { width: column.w; height: column.h; color: 'purple'; operation: "C" }
Button { width: column.w; height: column.h; color: 'purple'; operation: "AC" }
}
@@ -118,12 +118,12 @@ Rectangle {
Button { width: grid.w; height: column.h; operation: "7"; color: 'blue' }
Button { width: grid.w; height: column.h; operation: "8"; color: 'blue' }
Button { width: grid.w; height: column.h; operation: "9"; color: 'blue' }
- Button { width: grid.w; height: column.h; operation: division }
- Button { width: grid.w; height: column.h; operation: squareRoot }
+ Button { width: grid.w; height: column.h; operation: window.division }
+ Button { width: grid.w; height: column.h; operation: window.squareRoot }
Button { width: grid.w; height: column.h; operation: "4"; color: 'blue' }
Button { width: grid.w; height: column.h; operation: "5"; color: 'blue' }
Button { width: grid.w; height: column.h; operation: "6"; color: 'blue' }
- Button { width: grid.w; height: column.h; operation: multiplication }
+ Button { width: grid.w; height: column.h; operation: window.multiplication }
Button { width: grid.w; height: column.h; operation: "x^2" }
Button { width: grid.w; height: column.h; operation: "1"; color: 'blue' }
Button { width: grid.w; height: column.h; operation: "2"; color: 'blue' }
@@ -132,7 +132,7 @@ Rectangle {
Button { width: grid.w; height: column.h; operation: "1/x" }
Button { width: grid.w; height: column.h; operation: "0"; color: 'blue' }
Button { width: grid.w; height: column.h; operation: "." }
- Button { width: grid.w; height: column.h; operation: plusminus }
+ Button { width: grid.w; height: column.h; operation: window.plusminus }
Button { width: grid.w; height: column.h; operation: "+" }
Button { width: grid.w; height: column.h; operation: "="; color: 'red' }
}
diff --git a/examples/demos/calculator/calculator.qdoc b/examples/demos/calculator/calculator.qdoc
index e94bdb4cfd..793948703e 100644
--- a/examples/demos/calculator/calculator.qdoc
+++ b/examples/demos/calculator/calculator.qdoc
@@ -27,9 +27,9 @@
/*!
\title QML Demo - Calculator
- \example declarative/calculator
+ \example demos/calculator
\brief This is an example calculator application written in QML.
- \image qml-calculator-demo-small.png
+ \image qml-calculator-example-small.png
The Calculator demo implements a simple calculator in QML. It is written for desktop and portrait devices,
although on device it supports orientation changes.
diff --git a/examples/demos/clocks/clocks.qdoc b/examples/demos/clocks/clocks.qdoc
new file mode 100644
index 0000000000..54479bae17
--- /dev/null
+++ b/examples/demos/clocks/clocks.qdoc
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms
+** and conditions contained in a signed written agreement between you
+** and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \title QML Demo - Clocks
+ \example demos/clocks
+ \brief This example demonstrates creating components and using them multiple times.
+ \image qml-clocks-example.png
+
+ This demo give a simple world clock application, containing multiple clocks from around the world.
+
+ In doing this, it reuses a signle Clock component with some slight changes to the parameters.
+*/
diff --git a/examples/localstorage/localstorage.qml b/examples/localstorage/localstorage.qml
index f967518de8..714774c78e 100644
--- a/examples/localstorage/localstorage.qml
+++ b/examples/localstorage/localstorage.qml
@@ -43,7 +43,7 @@ import "../shared" as Examples
/*!
\title QtQuick Examples - Local Storage
- \example qtquick/localstorage
+ \example localstorage
\brief This is a collection of QML local storage examples
\image qml-localstorage-example.png
@@ -63,4 +63,4 @@ Item {
addExample("Hello World", "Simple SQL operations with local storage API", Qt.resolvedUrl("hello.qml"));
}
}
-} \ No newline at end of file
+}
diff --git a/examples/qml/dynamicscene/content/Button.qml b/examples/qml/dynamicscene/content/Button.qml
index 014692274a..ba7db501cc 100644
--- a/examples/qml/dynamicscene/content/Button.qml
+++ b/examples/qml/dynamicscene/content/Button.qml
@@ -54,16 +54,14 @@ Rectangle {
gradient: Gradient {
GradientStop {
position: 0.0
- color: !mouseArea.pressed ? activePalette.light : activePalette.button
+ color: !mouseArea.pressed ? "#eeeeee" : "#888888"
}
GradientStop {
position: 1.0
- color: !mouseArea.pressed ? activePalette.button : activePalette.dark
+ color: !mouseArea.pressed ? "#888888" : "#333333"
}
}
- SystemPalette { id: activePalette }
-
MouseArea {
id: mouseArea
anchors.fill: parent
@@ -75,6 +73,5 @@ Rectangle {
anchors.centerIn:parent
font.pointSize: 10
text: parent.text
- color: activePalette.buttonText
}
}
diff --git a/examples/qml/dynamicscene/content/Sun.qml b/examples/qml/dynamicscene/content/Sun.qml
index b84516eecc..9a956c9855 100644
--- a/examples/qml/dynamicscene/content/Sun.qml
+++ b/examples/qml/dynamicscene/content/Sun.qml
@@ -47,32 +47,27 @@ Image {
property string image: "images/sun.png"
source: image
-
- // once item is created, start moving offscreen
- NumberAnimation on y {
- to: (window.height / 2) + window.centerOffset
- running: created
- onRunningChanged: {
- if (running)
- duration = (window.height + window.centerOffset - sun.y) * 10;
- else
- state = "OffScreen"
- }
- }
-
- states: State {
- name: "OffScreen"
- StateChangeScript {
- script: { sun.created = false; sun.destroy() }
- }
- }
-
onCreatedChanged: {
if (created) {
sun.z = 1; // above the sky but below the ground layer
window.activeSuns++;
+ // once item is created, start moving offscreen
+ dropYAnim.duration = (window.height + window.centerOffset - sun.y) * 16;
+ dropAnim.running = true;
} else {
window.activeSuns--;
}
}
+
+ SequentialAnimation on y{
+ id: dropAnim
+ running: false
+ NumberAnimation {
+ id: dropYAnim
+ to: (window.height / 2) + window.centerOffset
+ }
+ ScriptAction {
+ script: { sun.created = false; sun.destroy() }
+ }
+ }
}
diff --git a/examples/qml/dynamicscene/dynamicscene.qml b/examples/qml/dynamicscene/dynamicscene.qml
index c64df5cfc0..4771742621 100644
--- a/examples/qml/dynamicscene/dynamicscene.qml
+++ b/examples/qml/dynamicscene/dynamicscene.qml
@@ -38,6 +38,13 @@
**
****************************************************************************/
+/*!
+ \title QML Example - Dynamic Scene
+ \example qml/dynamicscene
+ \brief This example demonstrates creating components dynamically.
+ \image qml-dynamicscene-example.png
+*/
+
import QtQuick 2.0
import QtQuick.Particles 2.0
import "content"
@@ -95,7 +102,7 @@ Item {
// sky
Rectangle {
id: sky
- anchors { left: parent.left; top: toolbox.bottom; right: parent.right; bottomMargin: -centerOffset; bottom: parent.verticalCenter }
+ anchors { left: parent.left; top: toolbox.bottom; right: parent.right; bottomMargin: -window.centerOffset; bottom: parent.verticalCenter }
gradient: Gradient {
GradientStop { id: gradientStopA; position: 0.0; color: "#0E1533" }
GradientStop { id: gradientStopB; position: 1.0; color: "#437284" }
@@ -127,21 +134,19 @@ Item {
Rectangle {
id: ground
z: 2 // just above the sun so that the sun can set behind it
- anchors { left: parent.left; top: parent.verticalCenter; topMargin: centerOffset; right: parent.right; bottom: parent.bottom }
+ anchors { left: parent.left; top: parent.verticalCenter; topMargin: window.centerOffset; right: parent.right; bottom: parent.bottom }
gradient: Gradient {
GradientStop { position: 0.0; color: "ForestGreen" }
GradientStop { position: 1.0; color: "DarkGreen" }
}
}
- SystemPalette { id: activePalette }
-
- // right-hand panel
+ // top panel
Rectangle {
id: toolbox
- height: centerOffset * 2
- color: activePalette.window
+ height: window.centerOffset * 2
+ color: "white"
anchors { right: parent.right; top: parent.top; left: parent.left}
Column {
@@ -192,7 +197,7 @@ Item {
}
}
- Text { text: "Active Suns: " + activeSuns }
+ Text { text: "Active Suns: " + window.activeSuns }
}
}
@@ -202,7 +207,7 @@ Item {
z: 1000
width: parent.width
height: popupColumn.height + 16
- color: activePalette.window
+ color: "white"
property bool poppedUp: false
property int downY: window.height - (createButton.height + 16)
@@ -213,7 +218,6 @@ Item {
Column {
id: popupColumn
y: 8
- anchors.centerIn: parent
spacing: 8
Row {
@@ -250,7 +254,7 @@ Item {
selectByMouse: true
wrapMode: TextEdit.WordWrap
- text: "import QtQuick 2.0\nImage {\n id: smile\n x: 360 * Math.random()\n y: 180 * Math.random() \n source: 'content/images/face-smile.png'\n NumberAnimation on opacity { \n to: 0; duration: 1500\n }\n Component.onCompleted: smile.destroy(1500);\n}"
+ text: "import QtQuick 2.0\nImage {\n id: smile\n x: 360 * Math.random()\n y: 40 * Math.random() \n source: 'content/images/face-smile.png'\n NumberAnimation on opacity { \n to: 0; duration: 1500\n }\n Component.onCompleted: smile.destroy(1500);\n}"
}
}
}
diff --git a/examples/qml/i18n/i18n.qml b/examples/qml/i18n/i18n.qml
index f8bf30d0f0..2ffdd1914f 100644
--- a/examples/qml/i18n/i18n.qml
+++ b/examples/qml/i18n/i18n.qml
@@ -40,23 +40,29 @@
import QtQuick 2.0
-//
-// The QML runtime automatically loads a translation from the i18n subdirectory of the root
-// QML file, based on the system language.
-//
-// The files are created/updated by running:
-//
-// lupdate i18n.qml -ts i18n/base.ts
-//
-// Translations for new languages are created by copying i18n/base.ts to i18n/qml_<lang>.ts
-// The .ts files can then be edited with Linguist:
-//
-// linguist i18n/qml_fr.ts
-//
-// The run-time translation files are then generated by running:
-//
-// lrelease i18n/*.ts
-//
+/*!
+ \title QML Examples - Internationalization
+ \example qml/i18n
+ \image qml-i18n-example.png
+ \brief This is an internationalization example
+
+ The QML runtime automatically loads a translation from the i18n subdirectory of the root
+ QML file, based on the system language.
+
+ The files are created/updated by running:
+
+ lupdate i18n.qml -ts i18n/base.ts
+
+ Translations for new languages are created by copying i18n/base.ts to i18n/qml_<lang>.ts
+ The .ts files can then be edited with Linguist:
+
+ linguist i18n/qml_fr.ts
+
+ The run-time translation files are then generated by running:
+
+ lrelease i18n/*.ts
+*/
+
Rectangle {
width: 640; height: 480
diff --git a/examples/quick/accessibility/accessibility.qml b/examples/quick/accessibility/accessibility.qml
index e987561bb1..5e4b0f8dcd 100644
--- a/examples/quick/accessibility/accessibility.qml
+++ b/examples/quick/accessibility/accessibility.qml
@@ -44,7 +44,7 @@ import "content"
/*!
\title QtQuick Examples - Accessibility
- \example qtquick/accessibility
+ \example quick/accessibility
\brief This example has accessible buttons.
*/
diff --git a/examples/quick/animation/animation.qml b/examples/quick/animation/animation.qml
index bca68457d9..f478cb713b 100644
--- a/examples/quick/animation/animation.qml
+++ b/examples/quick/animation/animation.qml
@@ -43,7 +43,7 @@ import "../../shared" as Examples
/*!
\title QtQuick Examples - Animation
- \example qtquick/animation
+ \example quick/animation
\brief This is a collection of QML Animation examples.
\image qml-animations-example.png
diff --git a/examples/quick/canvas/canvas.qml b/examples/quick/canvas/canvas.qml
index bdb58f4c78..cf3c37a4c3 100644
--- a/examples/quick/canvas/canvas.qml
+++ b/examples/quick/canvas/canvas.qml
@@ -45,6 +45,7 @@ import "../../shared" as Examples
\title QtQuick Examples - Canvas
\example quick/canvas
\brief This is a collection of QML Canvas examples.
+ \image qml-canvas-example.png
This is a collection of small QML examples relating to Canvas item. Each example is
a small QML file emphasizing a particular element or feature.
diff --git a/examples/quick/draganddrop/draganddrop.qml b/examples/quick/draganddrop/draganddrop.qml
index 88e6d5e021..9f56177f23 100644
--- a/examples/quick/draganddrop/draganddrop.qml
+++ b/examples/quick/draganddrop/draganddrop.qml
@@ -43,7 +43,7 @@ import "../../shared" as Examples
/*!
\title QtQuick Examples - Drag and Drop
- \example qtquick/draganddrop
+ \example quick/draganddrop
\brief This is a collection of QML drag and drop examples
\image qml-draganddrop-example.png
diff --git a/examples/quick/imageelements/content/BorderImageSelector.qml b/examples/quick/imageelements/content/BorderImageSelector.qml
index f3a534b3cd..8084b512fd 100644
--- a/examples/quick/imageelements/content/BorderImageSelector.qml
+++ b/examples/quick/imageelements/content/BorderImageSelector.qml
@@ -56,7 +56,7 @@ Item {
curIdx += steps;
}
Image {
- source: "../../../shared/images/back.png"
+ source: "arrow.png"
MouseArea{
anchors.fill: parent
onClicked: selector.advance(-1)
@@ -68,7 +68,7 @@ Item {
Behavior on opacity {NumberAnimation{}}
}
Image {
- source: "../../../shared/images/back.png"
+ source: "arrow.png"
mirror: true
MouseArea{
anchors.fill: parent
diff --git a/examples/quick/imageelements/content/arrow.png b/examples/quick/imageelements/content/arrow.png
new file mode 100644
index 0000000000..506ac42fcf
--- /dev/null
+++ b/examples/quick/imageelements/content/arrow.png
Binary files differ
diff --git a/examples/quick/imageelements/imageelements.qml b/examples/quick/imageelements/imageelements.qml
index bb23ef6979..adfa43a659 100644
--- a/examples/quick/imageelements/imageelements.qml
+++ b/examples/quick/imageelements/imageelements.qml
@@ -43,7 +43,7 @@ import "../../shared"
/*!
\title QML Examples - Image Elements
- \example declarative/imageelements
+ \example quick/imageelements
\brief This is a collection of QML examples
\image qml-imageelements-example.png
diff --git a/examples/quick/modelviews/listview/content/SmallText.qml b/examples/quick/modelviews/listview/content/SmallText.qml
new file mode 100644
index 0000000000..e27446827f
--- /dev/null
+++ b/examples/quick/modelviews/listview/content/SmallText.qml
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Text {
+ font.pixelSize: 12
+}
+
diff --git a/examples/quick/modelviews/listview/content/TextButton.qml b/examples/quick/modelviews/listview/content/TextButton.qml
index 980ee21553..9f0e673f8a 100644
--- a/examples/quick/modelviews/listview/content/TextButton.qml
+++ b/examples/quick/modelviews/listview/content/TextButton.qml
@@ -52,12 +52,10 @@ Rectangle {
radius: 10
gradient: Gradient {
- GradientStop { id: gradientStop; position: 0.0; color: palette.light }
- GradientStop { position: 1.0; color: palette.button }
+ GradientStop { id: gradientStop; position: 0.0; color: "#eeeeee" }
+ GradientStop { position: 1.0; color: "#888888" }
}
- SystemPalette { id: palette }
-
MouseArea {
id: mouseArea
anchors.fill: parent
@@ -72,7 +70,7 @@ Rectangle {
states: State {
name: "pressed"
when: mouseArea.pressed
- PropertyChanges { target: gradientStop; color: palette.dark }
+ PropertyChanges { target: gradientStop; color: "#333333" }
}
}
diff --git a/examples/quick/modelviews/listview/expandingdelegates.qml b/examples/quick/modelviews/listview/expandingdelegates.qml
index 43a9662422..02d5edc1d1 100644
--- a/examples/quick/modelviews/listview/expandingdelegates.qml
+++ b/examples/quick/modelviews/listview/expandingdelegates.qml
@@ -106,13 +106,13 @@ Rectangle {
font.bold: true; font.pointSize: 16
}
- Text {
+ SmallText {
text: "Ingredients"
- font.pointSize: 12; font.bold: true
+ font.bold: true
opacity: recipe.detailsOpacity
}
- Text {
+ SmallText {
text: ingredients
wrapMode: Text.WordWrap
width: parent.width
@@ -127,7 +127,7 @@ Rectangle {
anchors { top: topLayout.bottom; topMargin: 10; bottom: parent.bottom; bottomMargin: 10 }
opacity: recipe.detailsOpacity
- Text {
+ SmallText {
id: methodTitle
anchors.top: parent.top
text: "Method"
diff --git a/examples/quick/modelviews/listview/highlight.qml b/examples/quick/modelviews/listview/highlight.qml
index 2dca1f4b18..239a946523 100644
--- a/examples/quick/modelviews/listview/highlight.qml
+++ b/examples/quick/modelviews/listview/highlight.qml
@@ -56,9 +56,9 @@ Rectangle {
id: wrapper
width: 200; height: 55
Column {
- Text { text: 'Name: ' + name }
- Text { text: 'Type: ' + type }
- Text { text: 'Age: ' + age }
+ SmallText { text: 'Name: ' + name }
+ SmallText { text: 'Type: ' + type }
+ SmallText { text: 'Age: ' + age }
}
// indent the item if it is the current item
states: State {
diff --git a/examples/quick/positioners/positioners-transitions.qml b/examples/quick/positioners/positioners-transitions.qml
index 6081c9f8a8..f1b61c1740 100644
--- a/examples/quick/positioners/positioners-transitions.qml
+++ b/examples/quick/positioners/positioners-transitions.qml
@@ -43,12 +43,12 @@ import QtQuick 2.0
Rectangle {
id: page
width: 320; height: 480
- property int effectiveOpacity: 1.0
+ property real effectiveOpacity: 1.0
Timer {
interval: 2000
running: true
repeat: true
- onTriggered: effectiveOpacity = (effectiveOpacity == 1.0 ? 0.0 : 1.0)
+ onTriggered: effectiveOpacity = (effectiveOpacity == 1.0 ? 0.0 : 1.0);
}
Column {
diff --git a/examples/quick/righttoleft/righttoleft.qml b/examples/quick/righttoleft/righttoleft.qml
index 6561595603..b95f671d95 100644
--- a/examples/quick/righttoleft/righttoleft.qml
+++ b/examples/quick/righttoleft/righttoleft.qml
@@ -43,7 +43,7 @@ import "../../shared" as Examples
/*!
\title QtQuick Examples - Right to Left
- \example qtquick/Right to Left
+ \example quick/righttoleft
\brief This is a collection of QML Right to Left examples.
\image qml-righttoleft-example.png
diff --git a/examples/quick/shadereffects/shadereffects.qml b/examples/quick/shadereffects/shadereffects.qml
index b76c960a8f..4b3bb2a5e2 100644
--- a/examples/quick/shadereffects/shadereffects.qml
+++ b/examples/quick/shadereffects/shadereffects.qml
@@ -43,11 +43,12 @@ import QtQuick 2.0
import "content"
Rectangle {
+ id: root
width: 320
height: 480
/*!
\title QML Examples - Shader Effects
- \example declarative/shadereffects
+ \example quick/shadereffects
\image qml-shadereffects-example.png
\brief This is a shader effects example
@@ -56,10 +57,10 @@ Rectangle {
*/
property color col: "lightsteelblue"
gradient: Gradient {
- GradientStop { position: 0.0; color: Qt.tint(col, "#20FFFFFF") }
- GradientStop { position: 0.1; color: Qt.tint(col, "#20AAAAAA") }
- GradientStop { position: 0.9; color: Qt.tint(col, "#20666666") }
- GradientStop { position: 1.0; color: Qt.tint(col, "#20000000") }
+ GradientStop { position: 0.0; color: Qt.tint(root.col, "#20FFFFFF") }
+ GradientStop { position: 0.1; color: Qt.tint(root.col, "#20AAAAAA") }
+ GradientStop { position: 0.9; color: Qt.tint(root.col, "#20666666") }
+ GradientStop { position: 1.0; color: Qt.tint(root.col, "#20000000") }
}
ShaderEffectSource {
@@ -241,7 +242,7 @@ Rectangle {
width: 160
height: 160
property variant source: theSource
- property color tint: sliderToColor(colorizeSlider.value)
+ property color tint: root.sliderToColor(colorizeSlider.value)
fragmentShader: "
uniform sampler2D source;
uniform lowp vec4 tint;
diff --git a/examples/quick/text/text.qml b/examples/quick/text/text.qml
index e9c40773c9..e8be93cb69 100644
--- a/examples/quick/text/text.qml
+++ b/examples/quick/text/text.qml
@@ -42,7 +42,7 @@ import QtQuick 2.0
import "../../shared"
/*!
\title QML Examples - Text
- \example declarative/text
+ \example quick/text
\brief This is a collection of QML examples
\image qml-text-example.png
diff --git a/examples/quick/threading/threading.qml b/examples/quick/threading/threading.qml
index 7ba8b8f70d..b96c6975ac 100644
--- a/examples/quick/threading/threading.qml
+++ b/examples/quick/threading/threading.qml
@@ -43,7 +43,7 @@ import "../../shared" as Examples
/*!
\title QtQuick Examples - Threading
- \example qtquick/threading
+ \example quick/threading
\brief This is a collection of QML Multithreading examples.
\image qml-threading-example.png
diff --git a/examples/quick/touchinteraction/touchinteraction.qml b/examples/quick/touchinteraction/touchinteraction.qml
index 0be625a160..e64c145714 100644
--- a/examples/quick/touchinteraction/touchinteraction.qml
+++ b/examples/quick/touchinteraction/touchinteraction.qml
@@ -43,7 +43,7 @@ import "../../shared"
/*!
\title QtQuick Examples - Touch Interaction
- \example qtquick/touchinteraction
+ \example quick/touchinteraction
\brief This is a collection of QML Touch Interaction examples.
\image qml-touchinteraction-example.png
diff --git a/src/3rdparty/javascriptcore/COPYING.LIB b/src/3rdparty/javascriptcore/COPYING.LIB
deleted file mode 100644
index 87c4a33dd8..0000000000
--- a/src/3rdparty/javascriptcore/COPYING.LIB
+++ /dev/null
@@ -1,488 +0,0 @@
-
-
-NOTE! The LGPL below is copyrighted by the Free Software Foundation, but
-the instance of code that it refers to (the kde libraries) are copyrighted
-by the authors who actually wrote it.
-
----------------------------------------------------------------------------
- GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor
- Boston, MA 02110-1301, USA.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL. It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it. You can use it for
-your libraries, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
- Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library. If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software. To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
- Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs. This
-license, the GNU Library General Public License, applies to certain
-designated libraries. This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
- The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it. Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program. However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
- Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries. We
-concluded that weaker conditions might promote sharing better.
-
- However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves. This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them. (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.) The hope is that this
-will lead to faster development of free libraries.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, while the latter only
-works together with the library.
-
- Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
- GNU LIBRARY GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License"). Each licensee is
-addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- c) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- d) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/src/3rdparty/javascriptcore/DateMath.cpp b/src/3rdparty/javascriptcore/DateMath.cpp
deleted file mode 100644
index be99d2ca25..0000000000
--- a/src/3rdparty/javascriptcore/DateMath.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc. All rights reserved.
- * Copyright (C) 2007-2009 Torch Mobile, Inc.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Alternatively, the contents of this file may be used under the terms
- * of either the Mozilla Public License Version 1.1, found at
- * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
- * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
- * (the "GPL"), in which case the provisions of the MPL or the GPL are
- * applicable instead of those above. If you wish to allow use of your
- * version of this file only under the terms of one of those two
- * licenses (the MPL or the GPL) and not to allow others to use your
- * version of this file under the LGPL, indicate your decision by
- * deletingthe provisions above and replace them with the notice and
- * other provisions required by the MPL or the GPL, as the case may be.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under any of the LGPL, the MPL or the GPL.
-
- * Copyright 2006-2008 the V8 project authors. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "DateMath.h"
-
-#include <algorithm>
-#include <limits.h>
-#include <limits>
-#include <time.h>
-#include <cmath>
-
-//#if HAVE(SYS_TIME_H)
-#if defined(EXISTS_SYS_TIME)
-#include <sys/time.h>
-#endif
-
-//#if HAVE(SYS_TIMEB_H)
-#if defined(EXISTS_SYS_TIMEB)
-#include <sys/timeb.h>
-#endif
-
-#define NaN std::numeric_limits<double>::quiet_NaN()
-
-using namespace QV8DateConverter::WTF;
-
-namespace QV8DateConverter {
-
-namespace WTF {
-
-/* Constants */
-
-static const double minutesPerDay = 24.0 * 60.0;
-static const double secondsPerDay = 24.0 * 60.0 * 60.0;
-static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0;
-
-static const double usecPerSec = 1000000.0;
-
-static const double maxUnixTime = 2145859200.0; // 12/31/2037
-// ECMAScript asks not to support for a date of which total
-// millisecond value is larger than the following value.
-// See 15.9.1.14 of ECMA-262 5th edition.
-static const double maxECMAScriptTime = 8.64E15;
-
-// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
-// First for non-leap years, then for leap years.
-static const int firstDayOfMonth[2][12] = {
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
- {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
-};
-
-static inline bool isLeapYear(int year)
-{
- if (year % 4 != 0)
- return false;
- if (year % 400 == 0)
- return true;
- if (year % 100 == 0)
- return false;
- return true;
-}
-
-static inline int daysInYear(int year)
-{
- return 365 + isLeapYear(year);
-}
-
-static inline double daysFrom1970ToYear(int year)
-{
- // The Gregorian Calendar rules for leap years:
- // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years.
- // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years.
- // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years.
-
- static const int leapDaysBefore1971By4Rule = 1970 / 4;
- static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100;
- static const int leapDaysBefore1971By400Rule = 1970 / 400;
-
- const double yearMinusOne = year - 1;
- const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule;
- const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule;
- const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule;
-
- return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
-}
-
-static inline double msToDays(double ms)
-{
- return floor(ms / msPerDay);
-}
-
-int msToYear(double ms)
-{
- int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
- double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
- if (msFromApproxYearTo1970 > ms)
- return approxYear - 1;
- if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms)
- return approxYear + 1;
- return approxYear;
-}
-
-int dayInYear(double ms, int year)
-{
- return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year));
-}
-
-static inline double msToMilliseconds(double ms)
-{
- double result = fmod(ms, msPerDay);
- if (result < 0)
- result += msPerDay;
- return result;
-}
-
-// 0: Sunday, 1: Monday, etc.
-static inline int msToWeekDay(double ms)
-{
- int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
- if (wd < 0)
- wd += 7;
- return wd;
-}
-
-static inline int msToSeconds(double ms)
-{
- double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
- if (result < 0)
- result += secondsPerMinute;
- return static_cast<int>(result);
-}
-
-static inline int msToMinutes(double ms)
-{
- double result = fmod(floor(ms / msPerMinute), minutesPerHour);
- if (result < 0)
- result += minutesPerHour;
- return static_cast<int>(result);
-}
-
-static inline int msToHours(double ms)
-{
- double result = fmod(floor(ms/msPerHour), hoursPerDay);
- if (result < 0)
- result += hoursPerDay;
- return static_cast<int>(result);
-}
-
-int monthFromDayInYear(int dayInYear, bool leapYear)
-{
- const int d = dayInYear;
- int step;
-
- if (d < (step = 31))
- return 0;
- step += (leapYear ? 29 : 28);
- if (d < step)
- return 1;
- if (d < (step += 31))
- return 2;
- if (d < (step += 30))
- return 3;
- if (d < (step += 31))
- return 4;
- if (d < (step += 30))
- return 5;
- if (d < (step += 31))
- return 6;
- if (d < (step += 31))
- return 7;
- if (d < (step += 30))
- return 8;
- if (d < (step += 31))
- return 9;
- if (d < (step += 30))
- return 10;
- return 11;
-}
-
-static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth)
-{
- startDayOfThisMonth = startDayOfNextMonth;
- startDayOfNextMonth += daysInThisMonth;
- return (dayInYear <= startDayOfNextMonth);
-}
-
-int dayInMonthFromDayInYear(int dayInYear, bool leapYear)
-{
- const int d = dayInYear;
- int step;
- int next = 30;
-
- if (d <= next)
- return d + 1;
- const int daysInFeb = (leapYear ? 29 : 28);
- if (checkMonth(d, step, next, daysInFeb))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- if (checkMonth(d, step, next, 31))
- return d - step;
- if (checkMonth(d, step, next, 30))
- return d - step;
- step = next;
- return d - step;
-}
-
-static inline int monthToDayInYear(int month, bool isLeapYear)
-{
- return firstDayOfMonth[isLeapYear][month];
-}
-
-static inline double timeToMS(double hour, double min, double sec, double ms)
-{
- return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms);
-}
-
-double dateToDaysFrom1970(int year, int month, int day)
-{
- year += month / 12;
-
- month %= 12;
- if (month < 0) {
- month += 12;
- --year;
- }
-
- double yearday = floor(daysFrom1970ToYear(year));
- int monthday = monthToDayInYear(month, isLeapYear(year));
-
- return yearday + monthday + day - 1;
-}
-
-static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
-{
- double days = (day - 32075)
- + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
- + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
- - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
- - 2440588;
- return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
-}
-
-// We follow the recommendation of RFC 2822 to consider all
-// obsolete time zones not listed here equivalent to "-0000".
-static const struct KnownZone {
- const
- char tzName[4];
- int tzOffset;
-} known_zones[] = {
- { "UT", 0 },
- { "GMT", 0 },
- { "EST", -300 },
- { "EDT", -240 },
- { "CST", -360 },
- { "CDT", -300 },
- { "MST", -420 },
- { "MDT", -360 },
- { "PST", -480 },
- { "PDT", -420 }
-};
-
-double timeClip(double t)
-{
-#if defined(_MSC_VER)
- if (!_finite(t) || fabs(t) > maxECMAScriptTime)
- return NaN;
- return t >= 0 ? floor(t) : ceil(t);
-#else
-
-#if defined(__QNXNTO__)
- if (!isfinite(t) || fabs(t) > maxECMAScriptTime)
- return NaN;
-#else
- if (!std::isfinite(t) || fabs(t) > maxECMAScriptTime)
- return NaN;
-#endif
-
- return trunc(t);
-#endif
-}
-} // namespace WTF
-
-namespace JSC {
-
-double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds)
-{
- double day = dateToDaysFrom1970(t.year + 1900, t.month, t.monthDay);
- double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
- double result = (day * WTF::msPerDay) + ms;
-
- return result;
-}
-
-// input is UTC
-void msToGregorianDateTime(double ms, GregorianDateTime& tm)
-{
- const int year = msToYear(ms);
- tm.second = msToSeconds(ms);
- tm.minute = msToMinutes(ms);
- tm.hour = msToHours(ms);
- tm.weekDay = msToWeekDay(ms);
- tm.yearDay = dayInYear(ms, year);
- tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year));
- tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year));
- tm.year = year - 1900;
- tm.isDST = false;
- tm.utcOffset = static_cast<long>(0); // no ExecState :. cannot calculate offset. Assume UTC output.
- tm.timeZone = NULL;
-}
-
-} // namespace JSC
-
-} // namespace QV8DateConverter
-
diff --git a/src/3rdparty/javascriptcore/DateMath.h b/src/3rdparty/javascriptcore/DateMath.h
deleted file mode 100644
index 5adb0d358c..0000000000
--- a/src/3rdparty/javascriptcore/DateMath.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- */
-
-#ifndef DateMath_h
-#define DateMath_h
-
-#include <math.h>
-#include <string.h>
-#include <time.h>
-
-namespace QV8DateConverter {
-
-namespace WTF {
-
-double timeClip(double);
-
-const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
-const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-const double hoursPerDay = 24.0;
-const double minutesPerHour = 60.0;
-const double secondsPerHour = 60.0 * 60.0;
-const double secondsPerMinute = 60.0;
-const double msPerSecond = 1000.0;
-const double msPerMinute = 60.0 * 1000.0;
-const double msPerHour = 60.0 * 60.0 * 1000.0;
-const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
-const double msPerMonth = 2592000000.0;
-
-// Returns the number of days from 1970-01-01 to the specified date.
-double dateToDaysFrom1970(int year, int month, int day);
-int msToYear(double ms);
-int dayInYear(double ms, int year);
-int monthFromDayInYear(int dayInYear, bool leapYear);
-int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
-
-} // namespace WTF
-
-using WTF::dateToDaysFrom1970;
-using WTF::dayInMonthFromDayInYear;
-using WTF::dayInYear;
-using WTF::minutesPerHour;
-using WTF::monthFromDayInYear;
-using WTF::msPerDay;
-using WTF::msPerSecond;
-using WTF::msToYear;
-using WTF::secondsPerMinute;
-
-namespace JSC {
-struct GregorianDateTime;
-
-void msToGregorianDateTime(double, GregorianDateTime&);
-double gregorianDateTimeToMS(const GregorianDateTime&, double);
-
-// Intentionally overridding the default tm of the system.
-// The members of tm differ on various operating systems.
-struct GregorianDateTime {
- GregorianDateTime()
- : second(0)
- , minute(0)
- , hour(0)
- , weekDay(0)
- , monthDay(0)
- , yearDay(0)
- , month(0)
- , year(0)
- , isDST(0)
- , utcOffset(0)
- , timeZone(0)
- {
- }
-
- ~GregorianDateTime()
- {
- delete [] timeZone;
- }
-
- GregorianDateTime(const tm& inTm)
- : second(inTm.tm_sec)
- , minute(inTm.tm_min)
- , hour(inTm.tm_hour)
- , weekDay(inTm.tm_wday)
- , monthDay(inTm.tm_mday)
- , yearDay(inTm.tm_yday)
- , month(inTm.tm_mon)
- , year(inTm.tm_year)
- , isDST(inTm.tm_isdst)
- {
- utcOffset = static_cast<int>(0);
- timeZone = 0;
- }
-
- operator tm() const
- {
- tm ret;
- memset(&ret, 0, sizeof(ret));
-
- ret.tm_sec = second;
- ret.tm_min = minute;
- ret.tm_hour = hour;
- ret.tm_wday = weekDay;
- ret.tm_mday = monthDay;
- ret.tm_yday = yearDay;
- ret.tm_mon = month;
- ret.tm_year = year;
- ret.tm_isdst = isDST;
- return ret;
- }
-
- void copyFrom(const GregorianDateTime& rhs)
- {
- second = rhs.second;
- minute = rhs.minute;
- hour = rhs.hour;
- weekDay = rhs.weekDay;
- monthDay = rhs.monthDay;
- yearDay = rhs.yearDay;
- month = rhs.month;
- year = rhs.year;
- isDST = rhs.isDST;
- utcOffset = rhs.utcOffset;
- if (rhs.timeZone) {
- int inZoneSize = strlen(rhs.timeZone) + 1;
- timeZone = new char[inZoneSize];
- strncpy(timeZone, rhs.timeZone, inZoneSize);
- } else
- timeZone = 0;
- }
-
- int second;
- int minute;
- int hour;
- int weekDay;
- int monthDay;
- int yearDay;
- int month;
- int year;
- int isDST;
- int utcOffset;
- char* timeZone;
-};
-
-static inline int gmtoffset(const GregorianDateTime& t)
-{
- return t.utcOffset;
-}
-
-} // namespace JSC
-
-} // namespace QV8DateConverter
-
-#endif // DateMath_h
diff --git a/src/3rdparty/javascriptcore/VERSION b/src/3rdparty/javascriptcore/VERSION
deleted file mode 100644
index af6229afcb..0000000000
--- a/src/3rdparty/javascriptcore/VERSION
+++ /dev/null
@@ -1,15 +0,0 @@
-This is a snapshot of the files: DateMath.h and DateMath.cpp
-from a snapshot of JavaScriptCore from
-
- git://gitorious.org/qtwebkit/qtwebkit.git
-
-The commit imported was from the
-
- javascriptcore-snapshot-27012011 branch/tag
-
-and has the sha1 checksum
-
- 3ab0f621048fbeb480b687a28ed31d92d8506150
-
-The two files were then modified slightly so that unneeded
-functionality was removed (mostly regarding timezone offset).
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index b62275b009..f7861ac009 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
-SUBDIRS += qtquick2 folderlistmodel localstorage
+SUBDIRS += qtquick2 particles window folderlistmodel localstorage
contains(QT_CONFIG, qmltest): SUBDIRS += testlib
contains(QT_CONFIG, xmlpatterns) : SUBDIRS += xmllistmodel
diff --git a/src/imports/particles/particles.pro b/src/imports/particles/particles.pro
new file mode 100644
index 0000000000..dc3198d124
--- /dev/null
+++ b/src/imports/particles/particles.pro
@@ -0,0 +1,19 @@
+TARGET = particlesplugin
+TARGETPATH = QtQuick/Particles.2
+include(../qimportbase.pri)
+
+SOURCES += \
+ plugin.cpp
+
+QT += quick-private qml-private
+
+OTHER_FILES += \
+ qmldir
+
+DESTDIR = $$QT.qml.imports/$$TARGETPATH
+target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+qmldir.files += $$PWD/qmldir
+qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+INSTALLS += target qmldir
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/selectiontool.h b/src/imports/particles/plugin.cpp
index c2aa26a1a7..b5680b5ed1 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/selectiontool.h
+++ b/src/imports/particles/plugin.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -39,48 +39,27 @@
**
****************************************************************************/
-#ifndef SELECTIONTOOL_H
-#define SELECTIONTOOL_H
+#include <QtQml/qqmlextensionplugin.h>
-#include "abstracttool.h"
+#include <private/qquickparticlesmodule_p.h>
-#include <QtCore/QList>
-#include <QtCore/QPoint>
+QT_BEGIN_NAMESPACE
-QT_FORWARD_DECLARE_CLASS(QQuickItem)
-
-namespace QmlJSDebugger {
-namespace QtQuick2 {
-
-class QQuickViewInspector;
-class HoverHighlight;
-
-class SelectionTool : public AbstractTool
+//![class decl]
+class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
public:
- explicit SelectionTool(QQuickViewInspector *inspector);
-
- void leaveEvent(QEvent *);
-
- void mousePressEvent(QMouseEvent *);
- void mouseMoveEvent(QMouseEvent *) {}
- void mouseReleaseEvent(QMouseEvent *) {}
- void mouseDoubleClickEvent(QMouseEvent *) {}
-
- void hoverMoveEvent(QMouseEvent *);
- void wheelEvent(QWheelEvent *) {}
-
- void keyPressEvent(QKeyEvent *) {}
- void keyReleaseEvent(QKeyEvent *) {}
-
-private:
- QQuickViewInspector *inspector() const;
-
- HoverHighlight *m_hoverHighlight;
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Particles"));
+ Q_UNUSED(uri);
+ QQuickParticlesModule::defineModule();
+ }
};
+//![class decl]
-} // namespace QtQuick2
-} // namespace QmlJSDebugger
+QT_END_NAMESPACE
-#endif // SELECTIONTOOL_H
+#include "plugin.moc"
diff --git a/src/imports/particles/qmldir b/src/imports/particles/qmldir
new file mode 100644
index 0000000000..593915f83f
--- /dev/null
+++ b/src/imports/particles/qmldir
@@ -0,0 +1 @@
+plugin particlesplugin
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 1f9de5e998..371bba9fde 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -607,6 +607,10 @@ Item {
functionsToRun.splice(index, 1)
}
qtest_results.functionName = prop
+
+ if (!(datafunc in testCase))
+ datafunc = "init_data";
+
if (datafunc in testCase) {
if (qtest_runInternal(datafunc)) {
var table = qtest_testCaseResult
@@ -624,9 +628,13 @@ Item {
qtest_runFunction(prop, row)
qtest_results.dataTag = ""
}
- if (!haveData)
- qtest_results.warn("no data supplied for " + prop + "() by " + datafunc + "()"
- , util.callerFile(), util.callerLine());
+ if (!haveData) {
+ if (datafunc === "init_data")
+ qtest_runFunction(prop, null, isBenchmark)
+ else
+ qtest_results.warn("no data supplied for " + prop + "() by " + datafunc + "()"
+ , util.callerFile(), util.callerLine());
+ }
qtest_results.clearTestTable()
}
} else if (isBenchmark) {
diff --git a/src/imports/testlib/testcase.qdoc b/src/imports/testlib/testcase.qdoc
index f928cdaa44..29f7a2d287 100644
--- a/src/imports/testlib/testcase.qdoc
+++ b/src/imports/testlib/testcase.qdoc
@@ -51,8 +51,8 @@
element:
\code
- import QtQuick 1.0
- import QtQuickTest 1.0
+ import QtQuick 2.0
+ import QtTest 1.0
TestCase {
name: "MathTests"
@@ -97,15 +97,24 @@
\section1 Data-driven tests
Table data can be provided to a test using a function name that ends
- with "_data":
+ with "_data". Alternatively, the \c init_data() function can be used
+ to provide default test data for all test functions in a TestCase element:
+
\code
- import QtQuick 1.0
- import QtQuickTest 1.0
+ import QtQuick 2.0
+ import QtTest 1.0
TestCase {
name: "DataTests"
+ function init_data() {
+ return [
+ {tag:"init_data_1", a:1, b:2, answer: 3},
+ {tag:"init_data_2", a:2, b:4, answer: 6}
+ ];
+ }
+
function test_table_data() {
return [
{tag: "2 + 2 = 4", a: 2, b: 2, answer: 4 },
@@ -114,6 +123,12 @@
}
function test_table(data) {
+ //data comes from test_table_data
+ compare(data.a + data.b, data.answer)
+ }
+
+ function test__default_table(data) {
+ //data comes from init_data
compare(data.a + data.b, data.answer)
}
}
diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp
new file mode 100644
index 0000000000..b0c8c90890
--- /dev/null
+++ b/src/imports/window/plugin.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQml/qqmlextensionplugin.h>
+
+#include <private/qquickwindowmodule_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//![class decl]
+class QtQuick2WindowPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Window"));
+ Q_UNUSED(uri);
+ QQuickWindowModule::defineModule();
+ }
+};
+//![class decl]
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/imports/window/qmldir b/src/imports/window/qmldir
new file mode 100644
index 0000000000..32844a6ed6
--- /dev/null
+++ b/src/imports/window/qmldir
@@ -0,0 +1 @@
+plugin windowplugin
diff --git a/src/imports/window/window.pro b/src/imports/window/window.pro
new file mode 100644
index 0000000000..42b6f5911d
--- /dev/null
+++ b/src/imports/window/window.pro
@@ -0,0 +1,19 @@
+TARGET = windowplugin
+TARGETPATH = QtQuick/Window.2
+include(../qimportbase.pri)
+
+SOURCES += \
+ plugin.cpp
+
+QT += quick-private qml-private
+
+OTHER_FILES += \
+ qmldir
+
+DESTDIR = $$QT.qml.imports/$$TARGETPATH
+target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+qmldir.files += $$PWD/qmldir
+qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+
+INSTALLS += target qmldir
diff --git a/src/plugins/accessible/quick/main.cpp b/src/plugins/accessible/quick/main.cpp
index 2c75e594c2..6592c59e0f 100644
--- a/src/plugins/accessible/quick/main.cpp
+++ b/src/plugins/accessible/quick/main.cpp
@@ -46,6 +46,7 @@
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
+#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickaccessibleattached_p.h>
#include <qaccessibleplugin.h>
@@ -86,8 +87,11 @@ QAccessibleInterface *AccessibleQuickFactory::create(const QString &classname, Q
if (classname == QLatin1String("QQuickView")) {
return new QAccessibleQuickView(qobject_cast<QQuickView *>(object)); // FIXME
} else if (classname == QLatin1String("QQuickItem")) {
- QQuickItem * item = qobject_cast<QQuickItem *>(object);
+ QQuickItem *item = qobject_cast<QQuickItem *>(object);
Q_ASSERT(item);
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ if (!itemPrivate->isAccessible)
+ return 0;
QVariant v = QQuickAccessibleAttached::property(item, "role");
bool ok;
diff --git a/src/plugins/accessible/quick/qaccessiblequickview.cpp b/src/plugins/accessible/quick/qaccessiblequickview.cpp
index 2df1f243b8..ed8167f4d1 100644
--- a/src/plugins/accessible/quick/qaccessiblequickview.cpp
+++ b/src/plugins/accessible/quick/qaccessiblequickview.cpp
@@ -127,7 +127,11 @@ static QQuickItem *childAt_helper(QQuickItem *item, int x, int y)
}
QScopedPointer<QAccessibleInterface> accessibleInterface(QAccessible::queryAccessibleInterface(item));
- if (accessibleInterface && accessibleInterface->childCount() == 0) {
+ // this item has no Accessible attached property
+ if (!accessibleInterface)
+ return 0;
+
+ if (accessibleInterface->childCount() == 0) {
return (itemScreenRect(item).contains(x, y)) ? item : 0;
}
@@ -155,6 +159,7 @@ QAccessibleInterface *QAccessibleQuickView::childAt(int x, int y) const
if (root) {
if (QQuickItem *item = childAt_helper(root, x, y))
return QAccessible::queryAccessibleInterface(item);
+ return QAccessible::queryAccessibleInterface(root);
}
return 0;
}
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index ae42ba1ba4..9ef8c7ab72 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,3 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += qmltooling
-SUBDIRS += accessible
+contains(QT_CONFIG, accessibility) {
+ SUBDIRS += accessible
+}
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp
index bb4048ee92..da959933f7 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/highlight.cpp
@@ -81,14 +81,14 @@ void Highlight::adjust()
}
-void SelectionHighlight::paint(QPainter *painter)
+void HoverHighlight::paint(QPainter *painter)
{
painter->setPen(QColor(108, 141, 221));
painter->drawRect(QRect(0, 0, width() - 1, height() - 1));
}
-void HoverHighlight::paint(QPainter *painter)
+void SelectionHighlight::paint(QPainter *painter)
{
painter->setPen(QPen(QColor(0, 22, 159)));
painter->drawRect(QRect(1, 1, width() - 3, height() - 3));
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp
index 171f1a52e9..67b12822be 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.cpp
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.cpp
@@ -39,14 +39,19 @@
**
****************************************************************************/
-#include "zoomtool.h"
+#include "inspecttool.h"
+
+#include "highlight.h"
#include "qquickviewinspector.h"
#include <QtCore/QLineF>
+
#include <QtGui/QMouseEvent>
#include <QtGui/QWheelEvent>
#include <QtGui/QTouchEvent>
#include <QtGui/QKeyEvent>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QStyleHints>
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
@@ -54,67 +59,107 @@
namespace QmlJSDebugger {
namespace QtQuick2 {
-ZoomTool::ZoomTool(QQuickViewInspector *inspector, QQuickView *view) :
+InspectTool::InspectTool(QQuickViewInspector *inspector, QQuickView *view) :
AbstractTool(inspector),
+ m_originalSmooth(view->rootItem()->smooth()),
m_dragStarted(false),
m_pinchStarted(false),
+ m_didPressAndHold(false),
+ m_tapEvent(false),
+ m_rootItem(view->rootItem()),
+ m_originalPosition(view->rootItem()->pos()),
m_currentScale(1.0f),
- m_smoothScaleFactor(0.05f),
+ m_smoothScaleFactor(Constants::ZoomSnapDelta),
m_minScale(0.125f),
m_maxScale(48.0f),
- m_tapScaleCounter(0)
+ m_originalScale(view->rootItem()->scale()),
+ m_touchTimestamp(0),
+ m_hoverHighlight(new HoverHighlight(inspector->overlay())),
+ m_lastItem(0),
+ m_lastClickedItem(0)
{
- m_rootItem = view->rootItem();
- m_originalSmooth = m_rootItem->smooth();
- if (!m_originalSmooth)
- m_rootItem->setSmooth(true);
- m_originalPosition = m_rootItem->pos();
- m_originalScale = m_rootItem->scale();
+ //Press and Hold Timer
+ m_pressAndHoldTimer.setSingleShot(true);
+ m_pressAndHoldTimer.setInterval(Constants::PressAndHoldTimeout);
+ connect(&m_pressAndHoldTimer, SIGNAL(timeout()), SLOT(zoomTo100()));
+ enable(true);
}
-ZoomTool::~ZoomTool()
+InspectTool::~InspectTool()
{
- // restoring the original states.
- m_rootItem->setScale(m_originalScale);
- m_rootItem->setPos(m_originalPosition);
- if (!m_originalSmooth)
- m_rootItem->setSmooth(m_originalSmooth);
+ enable(false);
}
-void ZoomTool::mousePressEvent(QMouseEvent *event)
+void InspectTool::enable(bool enable)
{
- m_mousePosition = event->posF();
- if (event->buttons() & Qt::LeftButton) {
- m_dragStartPosition = event->posF();
- m_dragStarted = false;
+ if (!enable) {
+ inspector()->setSelectedItems(QList<QQuickItem*>());
+ // restoring the original states.
+ if (m_rootItem) {
+ m_rootItem->setScale(m_originalScale);
+ m_rootItem->setPos(m_originalPosition);
+ m_rootItem->setSmooth(m_originalSmooth);
+ }
+ } else {
+ if (m_rootItem) {
+ m_originalSmooth = m_rootItem->smooth();
+ m_originalScale = m_rootItem->scale();
+ m_originalPosition = m_rootItem->pos();
+ m_rootItem->setSmooth(true);
+ }
}
}
-void ZoomTool::mouseMoveEvent(QMouseEvent *event)
+void InspectTool::leaveEvent(QEvent *)
{
- if (m_pinchStarted)
- return;
+ m_hoverHighlight->setVisible(false);
+}
+void InspectTool::mousePressEvent(QMouseEvent *event)
+{
m_mousePosition = event->posF();
- if (!m_dragStarted
- && event->buttons() & Qt::LeftButton
- && ((m_dragStartPosition - event->posF()).manhattanLength()
- > Constants::DragStartDistance)) {
- m_dragStarted = true;
- }
- if (m_dragStarted) {
- m_adjustedOrigin += event->posF() - m_dragStartPosition;
- m_dragStartPosition = event->posF();
- m_rootItem->setPos(m_adjustedOrigin);
+ if (event->button() == Qt::LeftButton) {
+ m_pressAndHoldTimer.start();
+ initializeDrag(event->posF());
}
}
-void ZoomTool::hoverMoveEvent(QMouseEvent *event)
+void InspectTool::mouseReleaseEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->posF();
+ m_pressAndHoldTimer.stop();
+ if (event->button() == Qt::LeftButton)
+ selectItem();
+}
+
+void InspectTool::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->posF();
+ m_pressAndHoldTimer.stop();
+ if (event->button() == Qt::LeftButton)
+ selectNextItem();
+}
+
+void InspectTool::mouseMoveEvent(QMouseEvent *event)
+{
+ m_mousePosition = event->posF();
+ moveItem(event->buttons() & Qt::LeftButton);
+}
+
+void InspectTool::hoverMoveEvent(QMouseEvent *event)
{
m_mousePosition = event->posF();
+ m_pressAndHoldTimer.stop();
+ QQuickItem *item = inspector()->topVisibleItemAt(event->pos());
+ if (!item || item == m_lastClickedItem) {
+ m_hoverHighlight->setVisible(false);
+ } else {
+ m_hoverHighlight->setItem(item);
+ m_hoverHighlight->setVisible(true);
+ }
}
-void ZoomTool::wheelEvent(QWheelEvent *event)
+void InspectTool::wheelEvent(QWheelEvent *event)
{
if (event->orientation() != Qt::Vertical)
return;
@@ -133,13 +178,7 @@ void ZoomTool::wheelEvent(QWheelEvent *event)
}
}
-void ZoomTool::mouseDoubleClickEvent(QMouseEvent *event)
-{
- m_mousePosition = event->posF();
- zoomTo100();
-}
-
-void ZoomTool::keyReleaseEvent(QKeyEvent *event)
+void InspectTool::keyReleaseEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Plus:
@@ -166,16 +205,31 @@ void ZoomTool::keyReleaseEvent(QKeyEvent *event)
}
}
-void ZoomTool::touchEvent(QTouchEvent *event)
+void InspectTool::touchEvent(QTouchEvent *event)
{
QList<QTouchEvent::TouchPoint> touchPoints = event->touchPoints();
switch (event->type()) {
case QEvent::TouchBegin:
- // fall through..
+ if (touchPoints.count() == 1 && (event->touchPointStates() & Qt::TouchPointPressed)) {
+ if (!m_pressAndHoldTimer.isActive())
+ m_pressAndHoldTimer.start();
+ m_mousePosition = touchPoints.first().pos();
+ initializeDrag(touchPoints.first().pos());
+ m_tapEvent = true;
+ } else {
+ m_tapEvent = false;
+ }
+ break;
case QEvent::TouchUpdate: {
- if ((touchPoints.count() == 2)
- && (!(event->touchPointStates() & Qt::TouchPointReleased))) {
+ if (touchPoints.count() > 1)
+ m_tapEvent = false;
+ if ((touchPoints.count() == 1)
+ && (event->touchPointStates() & Qt::TouchPointMoved)) {
+ m_mousePosition = touchPoints.first().pos();
+ moveItem(true);
+ } else if ((touchPoints.count() == 2)
+ && (!(event->touchPointStates() & Qt::TouchPointReleased))) {
// determine scale factor
const QTouchEvent::TouchPoint &touchPoint0 = touchPoints.first();
const QTouchEvent::TouchPoint &touchPoint1 = touchPoints.last();
@@ -188,21 +242,27 @@ void ZoomTool::touchEvent(QTouchEvent *event)
QPointF newcenter = (touchPoint0.pos() + touchPoint1.pos()) / 2;
m_pinchStarted = true;
- m_tapScaleCounter = 0;
scaleView(touchScaleFactor, newcenter, oldcenter);
}
break;
}
case QEvent::TouchEnd: {
+ m_pressAndHoldTimer.stop();
if (m_pinchStarted) {
m_pinchStarted = false;
- } else if ((touchPoints.count() == 1)
- &&(!m_dragStarted)) {
- ++m_tapScaleCounter;
- qreal factor = 1.0f + (1.0f / (m_tapScaleCounter + 1));
- scaleView(factor, touchPoints.first().pos(),
- touchPoints.first().pos());
}
+ if (touchPoints.count() == 1 && !m_dragStarted &&
+ !m_didPressAndHold && m_tapEvent) {
+ m_tapEvent = false;
+ bool doubleTap = event->timestamp() - m_touchTimestamp
+ < static_cast<ulong>(qApp->styleHints()->mouseDoubleClickInterval());
+ if (doubleTap)
+ selectNextItem();
+ else
+ selectItem();
+ m_touchTimestamp = event->timestamp();
+ }
+ m_didPressAndHold = false;
break;
}
default:
@@ -210,8 +270,9 @@ void ZoomTool::touchEvent(QTouchEvent *event)
}
}
-void ZoomTool::scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter)
+void InspectTool::scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter)
{
+ m_pressAndHoldTimer.stop();
if (((m_currentScale * factor) > m_maxScale)
|| ((m_currentScale * factor) < m_minScale)) {
return;
@@ -224,29 +285,29 @@ void ZoomTool::scaleView(const qreal &factor, const QPointF &newcenter, const QP
m_rootItem->setPos(m_adjustedOrigin);
}
-void ZoomTool::zoomIn()
+void InspectTool::zoomIn()
{
qreal newScale = nextZoomScale(ZoomIn);
scaleView(newScale / m_currentScale, m_mousePosition, m_mousePosition);
}
-void ZoomTool::zoomOut()
+void InspectTool::zoomOut()
{
qreal newScale = nextZoomScale(ZoomOut);
scaleView(newScale / m_currentScale, m_mousePosition, m_mousePosition);
}
-void ZoomTool::zoomTo100()
+void InspectTool::zoomTo100()
{
+ m_didPressAndHold = true;
m_currentScale = 1.0;
m_adjustedOrigin = QPointF(0, 0);
- m_tapScaleCounter = 0;
m_rootItem->setPos(m_adjustedOrigin);
m_rootItem->setScale(m_currentScale);
}
-qreal ZoomTool::nextZoomScale(ZoomDirection direction)
+qreal InspectTool::nextZoomScale(ZoomDirection direction)
{
static QList<qreal> zoomScales =
QList<qreal>()
@@ -286,5 +347,67 @@ qreal ZoomTool::nextZoomScale(ZoomDirection direction)
return 1.0f;
}
+void InspectTool::initializeDrag(const QPointF &pos)
+{
+ m_dragStartPosition = pos;
+ m_dragStarted = false;
+}
+
+void InspectTool::dragItemToPosition()
+{
+ m_adjustedOrigin += m_mousePosition - m_dragStartPosition;
+ m_dragStartPosition = m_mousePosition;
+ m_rootItem->setPos(m_adjustedOrigin);
+}
+
+void InspectTool::moveItem(bool valid)
+{
+ if (m_pinchStarted)
+ return;
+
+ if (!m_dragStarted
+ && valid
+ && ((m_dragStartPosition - m_mousePosition).manhattanLength()
+ > qApp->styleHints()->startDragDistance())) {
+ m_pressAndHoldTimer.stop();
+ m_dragStarted = true;
+ }
+ if (m_dragStarted)
+ dragItemToPosition();
+}
+
+void InspectTool::selectNextItem()
+{
+ if (m_lastClickedItem != inspector()->topVisibleItemAt(m_mousePosition))
+ return;
+ QList<QQuickItem*> items = inspector()->itemsAt(m_mousePosition);
+ for (int i = 0; i < items.count(); i++) {
+ if (m_lastItem == items[i]) {
+ if (i + 1 < items.count())
+ m_lastItem = items[i+1];
+ else
+ m_lastItem = items[0];
+ inspector()->setSelectedItems(QList<QQuickItem*>() << m_lastItem);
+ break;
+ }
+ }
+}
+
+void InspectTool::selectItem()
+{
+ if (!inspector()->topVisibleItemAt(m_mousePosition))
+ return;
+ if (m_lastClickedItem == inspector()->topVisibleItemAt(m_mousePosition))
+ return;
+ m_lastClickedItem = inspector()->topVisibleItemAt(m_mousePosition);
+ m_lastItem = m_lastClickedItem;
+ inspector()->setSelectedItems(QList<QQuickItem*>() << m_lastClickedItem);
+}
+
+QQuickViewInspector *InspectTool::inspector() const
+{
+ return static_cast<QQuickViewInspector*>(AbstractTool::inspector());
+}
+
} // namespace QtQuick2
} // namespace QmlJSDebugger
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.h b/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h
index 02ed8e09df..25d0c634b2 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/zoomtool.h
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/inspecttool.h
@@ -39,12 +39,14 @@
**
****************************************************************************/
-#ifndef ZOOMTOOL_H
-#define ZOOMTOOL_H
+#ifndef INSPECTTOOL_H
+#define INSPECTTOOL_H
#include "abstracttool.h"
#include <QtCore/QPointF>
+#include <QtCore/QPointer>
+#include <QtCore/QTimer>
QT_FORWARD_DECLARE_CLASS(QQuickView)
QT_FORWARD_DECLARE_CLASS(QQuickItem)
@@ -53,46 +55,59 @@ namespace QmlJSDebugger {
namespace QtQuick2 {
class QQuickViewInspector;
+class HoverHighlight;
-class ZoomTool : public AbstractTool
+class InspectTool : public AbstractTool
{
Q_OBJECT
-
public:
enum ZoomDirection {
ZoomIn,
ZoomOut
};
- explicit ZoomTool(QQuickViewInspector *inspector, QQuickView *view);
- virtual ~ZoomTool();
- void leaveEvent(QEvent *) {}
+ InspectTool(QQuickViewInspector *inspector, QQuickView *view);
+ ~InspectTool();
+
+ void enable(bool enable);
- void mousePressEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *) {}
- void mouseDoubleClickEvent(QMouseEvent *event);
+ void leaveEvent(QEvent *);
- void hoverMoveEvent(QMouseEvent *event);
- void wheelEvent(QWheelEvent *event);
+ void mousePressEvent(QMouseEvent *);
+ void mouseMoveEvent(QMouseEvent *);
+ void mouseReleaseEvent(QMouseEvent *);
+ void mouseDoubleClickEvent(QMouseEvent *);
+
+ void hoverMoveEvent(QMouseEvent *);
+ void wheelEvent(QWheelEvent *);
void keyPressEvent(QKeyEvent *) {}
- void keyReleaseEvent(QKeyEvent *event);
+ void keyReleaseEvent(QKeyEvent *);
void touchEvent(QTouchEvent *event);
private:
+ QQuickViewInspector *inspector() const;
qreal nextZoomScale(ZoomDirection direction);
void scaleView(const qreal &factor, const QPointF &newcenter, const QPointF &oldcenter);
- void zoomTo100();
void zoomIn();
void zoomOut();
+ void initializeDrag(const QPointF &pos);
+ void dragItemToPosition();
+ void moveItem(bool valid);
+ void selectNextItem();
+ void selectItem();
+
+private slots:
+ void zoomTo100();
private:
bool m_originalSmooth;
bool m_dragStarted;
bool m_pinchStarted;
- QQuickItem *m_rootItem;
+ bool m_didPressAndHold;
+ bool m_tapEvent;
+ QPointer<QQuickItem> m_rootItem;
QPointF m_adjustedOrigin;
QPointF m_dragStartPosition;
QPointF m_mousePosition;
@@ -101,11 +116,16 @@ private:
qreal m_smoothScaleFactor;
qreal m_minScale;
qreal m_maxScale;
- qreal m_tapScaleCounter;
qreal m_originalScale;
+ ulong m_touchTimestamp;
+ QTimer m_pressAndHoldTimer;
+
+ HoverHighlight *m_hoverHighlight;
+ QQuickItem *m_lastItem;
+ QQuickItem *m_lastClickedItem;
};
} // namespace QtQuick2
} // namespace QmlJSDebugger
-#endif // ZOOMTOOL_H
+#endif // INSPECTTOOL_H
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
index 33bda11dcc..f40e3f0b04 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/qmldbg_qtquick2.pro
@@ -12,22 +12,20 @@ INCLUDEPATH *= $$PWD $$PWD/../shared
SOURCES += \
qtquick2plugin.cpp \
highlight.cpp \
- selectiontool.cpp \
qquickviewinspector.cpp \
../shared/abstracttool.cpp \
../shared/abstractviewinspector.cpp \
- zoomtool.cpp
+ inspecttool.cpp
HEADERS += \
qtquick2plugin.h \
highlight.h \
- selectiontool.h \
qquickviewinspector.h \
../shared/abstracttool.h \
../shared/abstractviewinspector.h \
../shared/qqmlinspectorprotocol.h \
../shared/qmlinspectorconstants.h \
- zoomtool.h
+ inspecttool.h
OTHER_FILES += qtquick2plugin.json
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
index 0a73540b40..95ce86678c 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.cpp
@@ -43,8 +43,7 @@
#include "qqmlinspectorprotocol.h"
#include "highlight.h"
-#include "selectiontool.h"
-#include "zoomtool.h"
+#include "inspecttool.h"
#include <QtQuick/private/qquickitem_p.h>
@@ -120,8 +119,7 @@ QQuickViewInspector::QQuickViewInspector(QQuickView *view, QObject *parent) :
AbstractViewInspector(parent),
m_view(view),
m_overlay(new QQuickItem),
- m_selectionTool(new SelectionTool(this)),
- m_zoomTool(0),
+ m_inspectTool(new InspectTool(this, view)),
m_designMode(true)
{
// Try to make sure the overlay is always on top
@@ -131,7 +129,7 @@ QQuickViewInspector::QQuickViewInspector(QQuickView *view, QObject *parent) :
m_overlay->setParentItem(root);
view->installEventFilter(this);
- setCurrentTool(m_selectionTool);
+ setCurrentTool(m_inspectTool);
}
void QQuickViewInspector::changeCurrentObjects(const QList<QObject*> &objects)
@@ -165,23 +163,13 @@ void QQuickViewInspector::reparentQmlObject(QObject *object, QObject *newParent)
void QQuickViewInspector::changeTool(InspectorProtocol::Tool tool)
{
switch (tool) {
- case InspectorProtocol::ColorPickerTool:
- // TODO
- emit colorPickerActivated();
- break;
case InspectorProtocol::SelectMarqueeTool:
// TODO
emit marqueeSelectToolActivated();
break;
- case InspectorProtocol::SelectTool:
- setCurrentTool(m_selectionTool);
- emit selectToolActivated();
- break;
- case InspectorProtocol::ZoomTool:
- if (!m_zoomTool)
- m_zoomTool = new ZoomTool(this, m_view);
- setCurrentTool(m_zoomTool);
- emit zoomToolActivated();
+ case InspectorProtocol::InspectTool:
+ setCurrentTool(m_inspectTool);
+ emit inspectToolActivated();
break;
}
}
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h
index e8fdf351de..0fd2948279 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h
+++ b/src/plugins/qmltooling/qmldbg_qtquick2/qquickviewinspector.h
@@ -55,9 +55,8 @@ QT_END_NAMESPACE
namespace QmlJSDebugger {
namespace QtQuick2 {
-class SelectionTool;
+class InspectTool;
class SelectionHighlight;
-class ZoomTool;
class QQuickViewInspector : public AbstractViewInspector
{
@@ -99,8 +98,7 @@ private:
QQuickView *m_view;
QQuickItem *m_overlay;
- SelectionTool *m_selectionTool;
- ZoomTool *m_zoomTool;
+ InspectTool *m_inspectTool;
QList<QWeakPointer<QQuickItem> > m_selectedItems;
QHash<QQuickItem*, SelectionHighlight*> m_highlightItems;
diff --git a/src/plugins/qmltooling/shared/abstracttool.h b/src/plugins/qmltooling/shared/abstracttool.h
index 7e5ba65fd4..ef9894a852 100644
--- a/src/plugins/qmltooling/shared/abstracttool.h
+++ b/src/plugins/qmltooling/shared/abstracttool.h
@@ -64,6 +64,8 @@ public:
AbstractViewInspector *inspector() const { return m_inspector; }
+ virtual void enable(bool enable) = 0;
+
virtual void leaveEvent(QEvent *event) = 0;
virtual void mousePressEvent(QMouseEvent *event) = 0;
diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.cpp b/src/plugins/qmltooling/shared/abstractviewinspector.cpp
index 135da1b8b7..60a95986b0 100644
--- a/src/plugins/qmltooling/shared/abstractviewinspector.cpp
+++ b/src/plugins/qmltooling/shared/abstractviewinspector.cpp
@@ -100,6 +100,7 @@ void AbstractViewInspector::setDesignModeBehavior(bool value)
return;
m_designModeBehavior = value;
+ m_currentTool->enable(m_designModeBehavior);
emit designModeBehaviorChanged(value);
sendDesignModeBehavior(value);
}
@@ -163,19 +164,9 @@ void AbstractViewInspector::setShowAppOnTop(bool appOnTop)
emit showAppOnTopChanged(appOnTop);
}
-void AbstractViewInspector::changeToColorPickerTool()
+void AbstractViewInspector::changeToInspectTool()
{
- changeTool(InspectorProtocol::ColorPickerTool);
-}
-
-void AbstractViewInspector::changeToZoomTool()
-{
- changeTool(InspectorProtocol::ZoomTool);
-}
-
-void AbstractViewInspector::changeToSingleSelectTool()
-{
- changeTool(InspectorProtocol::SelectTool);
+ changeTool(InspectorProtocol::InspectTool);
}
void AbstractViewInspector::changeToMarqueeSelectTool()
@@ -272,18 +263,12 @@ bool AbstractViewInspector::keyReleaseEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_V:
- changeTool(InspectorProtocol::SelectTool);
+ changeTool(InspectorProtocol::InspectTool);
break;
// disabled because multiselection does not do anything useful without design mode
// case Qt::Key_M:
// changeTool(InspectorProtocol::SelectMarqueeTool);
// break;
- case Qt::Key_I:
- changeTool(InspectorProtocol::ColorPickerTool);
- break;
- case Qt::Key_Z:
- changeTool(InspectorProtocol::ZoomTool);
- break;
case Qt::Key_Space:
setAnimationPaused(!animationPaused());
break;
@@ -332,8 +317,8 @@ void AbstractViewInspector::handleMessage(const QByteArray &message)
if (QObject *obj = QQmlDebugService::objectForId(debugId))
selectedObjects << obj;
}
-
- changeCurrentObjects(selectedObjects);
+ if (m_designModeBehavior)
+ changeCurrentObjects(selectedObjects);
break;
}
case InspectorProtocol::Reload: {
@@ -497,17 +482,6 @@ void AbstractViewInspector::sendShowAppOnTop(bool showAppOnTop)
m_debugService->sendMessage(message);
}
-void AbstractViewInspector::sendColorChanged(const QColor &color)
-{
- QByteArray message;
- QDataStream ds(&message, QIODevice::WriteOnly);
-
- ds << InspectorProtocol::ColorChanged
- << color;
-
- m_debugService->sendMessage(message);
-}
-
QString AbstractViewInspector::idStringForObject(QObject *obj) const
{
const int id = QQmlDebugService::idForObject(obj);
diff --git a/src/plugins/qmltooling/shared/abstractviewinspector.h b/src/plugins/qmltooling/shared/abstractviewinspector.h
index 04ca02917e..17f9e26660 100644
--- a/src/plugins/qmltooling/shared/abstractviewinspector.h
+++ b/src/plugins/qmltooling/shared/abstractviewinspector.h
@@ -45,7 +45,6 @@
#include <QtCore/QHash>
#include <QtCore/QObject>
#include <QtCore/QStringList>
-#include <QtGui/QColor>
#include "qqmlinspectorprotocol.h"
#include "qmlinspectorconstants.h"
@@ -109,10 +108,7 @@ signals:
void showAppOnTopChanged(bool showAppOnTop);
void reloadRequested();
void marqueeSelectToolActivated();
- void selectToolActivated();
- void zoomToolActivated();
- void colorPickerActivated();
- void selectedColorChanged(const QColor &color);
+ void inspectToolActivated();
void animationSpeedChanged(qreal factor);
void animationPausedChanged(bool paused);
@@ -132,15 +128,11 @@ protected:
virtual bool wheelEvent(QWheelEvent *event);
virtual bool touchEvent(QTouchEvent *event);
-private slots:
- void sendColorChanged(const QColor &color);
-
private:
void sendDesignModeBehavior(bool inDesignMode);
- void changeToColorPickerTool();
void changeToZoomTool();
- void changeToSingleSelectTool();
+ void changeToInspectTool();
void changeToMarqueeSelectTool();
virtual void setDesignModeBehavior(bool value);
diff --git a/src/plugins/qmltooling/shared/qmlinspectorconstants.h b/src/plugins/qmltooling/shared/qmlinspectorconstants.h
index e5a0ee5450..4463283d9f 100644
--- a/src/plugins/qmltooling/shared/qmlinspectorconstants.h
+++ b/src/plugins/qmltooling/shared/qmlinspectorconstants.h
@@ -53,13 +53,10 @@ enum DesignTool {
MarqueeSelectionToolMode = 2,
MoveToolMode = 3,
ResizeToolMode = 4,
- ColorPickerMode = 5,
ZoomMode = 6
};
-static const int DragStartTime = 50;
-
-static const int DragStartDistance = 20;
+static const int PressAndHoldTimeout = 800;
static const double ZoomSnapDelta = 0.04;
diff --git a/src/plugins/qmltooling/shared/qqmlinspectorprotocol.h b/src/plugins/qmltooling/shared/qqmlinspectorprotocol.h
index 63772aa8e4..8527bf6394 100644
--- a/src/plugins/qmltooling/shared/qqmlinspectorprotocol.h
+++ b/src/plugins/qmltooling/shared/qqmlinspectorprotocol.h
@@ -60,7 +60,6 @@ public:
AnimationPausedChanged = 19, // highest value
ChangeTool = 1,
ClearComponentCache = 2,
- ColorChanged = 3,
CreateObject = 5,
CurrentObjectsChanged = 6,
DestroyObject = 7,
@@ -77,10 +76,8 @@ public:
};
enum Tool {
- ColorPickerTool,
- SelectMarqueeTool,
- SelectTool,
- ZoomTool
+ SelectMarqueeTool = 1,
+ InspectTool
};
static inline QString toString(Message message)
diff --git a/src/qml/animations/qanimationgroupjob.cpp b/src/qml/animations/qanimationgroupjob.cpp
index 83b2192313..59bceaaf4e 100644
--- a/src/qml/animations/qanimationgroupjob.cpp
+++ b/src/qml/animations/qanimationgroupjob.cpp
@@ -51,8 +51,7 @@ QAnimationGroupJob::QAnimationGroupJob()
QAnimationGroupJob::~QAnimationGroupJob()
{
- while (firstChild() != 0)
- delete firstChild();
+ clear();
}
void QAnimationGroupJob::topLevelAnimationLoopChanged()
@@ -123,9 +122,16 @@ void QAnimationGroupJob::removeAnimation(QAbstractAnimationJob *animation)
void QAnimationGroupJob::clear()
{
- //### should this remove and delete, or just remove?
- while (firstChild() != 0)
- delete firstChild(); //removeAnimation(firstChild());
+ QAbstractAnimationJob *child = firstChild();
+ QAbstractAnimationJob *nextSibling = 0;
+ while (child != 0) {
+ child->m_group = 0;
+ nextSibling = child->nextSibling();
+ delete child;
+ child = nextSibling;
+ }
+ m_firstChild = 0;
+ m_lastChild = 0;
}
void QAnimationGroupJob::resetUncontrolledAnimationsFinishTime()
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 318e0bd71f..115f3cbc3a 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -55,9 +55,9 @@ struct Q_QML_EXPORT QQmlDebuggingEnabler
};
// Execute code in constructor before first QQmlEngine is instantiated
-#if defined(QT_DECLARATIVE_DEBUG_NO_WARNING)
+#if defined(QT_QML_DEBUG_NO_WARNING)
static QQmlDebuggingEnabler qmlEnableDebuggingHelper(false);
-#elif defined(QT_DECLARATIVE_DEBUG)
+#elif defined(QT_QML_DEBUG) || defined(QT_DECLARATIVE_DEBUG)
static QQmlDebuggingEnabler qmlEnableDebuggingHelper(true);
#endif
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
index dcf93b400e..468b653a1f 100644
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ b/src/qml/debugger/qqmldebugserver.cpp
@@ -255,7 +255,7 @@ QQmlDebugServer *QQmlDebugServer::instance()
commandLineTested = true;
QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
-#ifndef QQML_NO_DEBUG_PROTOCOL
+#ifndef QT_QML_NO_DEBUGGER
// ### remove port definition when protocol is changed
int port = 0;
bool block = false;
@@ -398,7 +398,6 @@ void QQmlDebugServer::receiveMessage(const QByteArray &message)
iter.value()->stateChanged(newState);
}
- qDebug("QML Debugger: Connection established.");
d->messageArrivedCondition.wakeAll();
} else if (op == 1) {
@@ -458,14 +457,14 @@ void QQmlDebugServerPrivate::_q_sendMessages(const QList<QByteArray> &messages)
QList<QQmlDebugService*> QQmlDebugServer::services() const
{
- const Q_D(QQmlDebugServer);
+ Q_D(const QQmlDebugServer);
QReadLocker(&d->pluginsLock);
return d->plugins.values();
}
QStringList QQmlDebugServer::serviceNames() const
{
- const Q_D(QQmlDebugServer);
+ Q_D(const QQmlDebugServer);
QReadLocker(&d->pluginsLock);
return d->plugins.keys();
}
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
index cd09b69e48..d8997fd587 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/qml/debugger/qqmlenginedebugservice.cpp
@@ -67,7 +67,7 @@ QQmlEngineDebugService *QQmlEngineDebugService::instance()
}
QQmlEngineDebugService::QQmlEngineDebugService(QObject *parent)
- : QQmlDebugService(QStringLiteral("QmlDebugger"), 1, parent),
+ : QQmlDebugService(QStringLiteral("QmlDebugger"), 2, parent),
m_watch(new QQmlWatcher(this)),
m_statesDelegate(0)
{
@@ -86,7 +86,8 @@ QDataStream &operator<<(QDataStream &ds,
const QQmlEngineDebugService::QQmlObjectData &data)
{
ds << data.url << data.lineNumber << data.columnNumber << data.idString
- << data.objectName << data.objectType << data.objectId << data.contextId;
+ << data.objectName << data.objectType << data.objectId << data.contextId
+ << data.parentId;
return ds;
}
@@ -94,7 +95,8 @@ QDataStream &operator>>(QDataStream &ds,
QQmlEngineDebugService::QQmlObjectData &data)
{
ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
- >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId
+ >> data.parentId;
return ds;
}
@@ -264,7 +266,7 @@ void QQmlEngineDebugService::buildObjectDump(QDataStream &message,
QQmlObjectProperty prop;
prop.type = QQmlObjectProperty::SignalProperty;
prop.hasNotifySignal = false;
- QQmlExpression *expr = signalHandler->expression();
+ QQmlBoundSignalExpression *expr = signalHandler->expression();
if (expr) {
prop.value = expr->expression();
QObject *scope = expr->scopeObject();
@@ -376,7 +378,7 @@ QQmlEngineDebugService::objectData(QObject *object)
rv.objectName = object->objectName();
rv.objectId = QQmlDebugService::idForObject(object);
rv.contextId = QQmlDebugService::idForObject(qmlContext(object));
-
+ rv.parentId = QQmlDebugService::idForObject(object->parent());
QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
if (type) {
QString typeName = type->qmlTypeName();
@@ -603,9 +605,9 @@ bool QQmlEngineDebugService::setBinding(int objectId,
if (isLiteralValue) {
property.write(expression);
} else if (hasValidSignal(object, propertyName)) {
- QQmlExpression *qmlExpression = new QQmlExpression(context, object, expression.toString());
+ QQmlBoundSignalExpression *qmlExpression = new QQmlBoundSignalExpression(QQmlContextData::get(context), object, expression.toString(),
+ false, filename, line, column);
QQmlPropertyPrivate::setSignalExpression(property, qmlExpression);
- qmlExpression->setSourceLocation(filename, line, column);
} else if (property.isProperty()) {
QQmlBinding *binding = new QQmlBinding(expression.toString(), false, object, QQmlContextData::get(context), filename, line, column);;
binding->setTarget(property);
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/qml/debugger/qqmlenginedebugservice_p.h
index 19a5776e27..3b855cb602 100644
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ b/src/qml/debugger/qqmlenginedebugservice_p.h
@@ -83,6 +83,7 @@ public:
QString objectType;
int objectId;
int contextId;
+ int parentId;
};
struct QQmlObjectProperty {
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
index c643073308..7109286197 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/qml/debugger/qqmlprofilerservice.cpp
@@ -195,7 +195,7 @@ void QQmlProfilerService::rangeData(RangeType range, const QUrl &rData)
if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
return;
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1, -1, 0, 0};
+ QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeData, (int)range, rData.toString(), -1, -1, 0, 0};
processMessage(rd);
}
@@ -213,7 +213,7 @@ void QQmlProfilerService::rangeLocation(RangeType range, const QUrl &fileName, i
if (!QQmlDebugService::isDebuggingEnabled() || !m_enabled)
return;
- QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line, column, 0, 0};
+ QQmlProfilerData rd = {m_timer.nsecsElapsed(), (int)RangeLocation, (int)range, fileName.toString(), line, column, 0, 0};
processMessage(rd);
}
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index 2e351792cc..8662abb52e 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -54,7 +54,7 @@
//
#include <private/qqmldebugservice_p.h>
-#include "qqmlexpression.h"
+#include <private/qqmlboundsignal_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetaobject.h>
@@ -201,20 +201,20 @@ struct QQmlBindingProfiler {
};
struct QQmlHandlingSignalProfiler {
- QQmlHandlingSignalProfiler(const QMetaMethod &signal, QQmlExpression *expression)
+ QQmlHandlingSignalProfiler(const QMetaMethod &signal, QQmlBoundSignalExpression *expression)
{
enabled = QQmlProfilerService::instance
? QQmlProfilerService::instance->profilingEnabled() : false;
- if (enabled)
- init(signal, expression);
- }
-
- QQmlHandlingSignalProfiler(QObject *object, int index, QQmlExpression *expression)
- {
- enabled = QQmlProfilerService::instance
- ? QQmlProfilerService::instance->profilingEnabled() : false;
- if (enabled)
- init(object->metaObject()->method(index), expression);
+ if (enabled) {
+ QQmlProfilerService *service = QQmlProfilerService::instance;
+ service->startRange(QQmlProfilerService::HandlingSignal);
+ service->rangeData(QQmlProfilerService::HandlingSignal,
+ QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ")
+ + expression->expression());
+ service->rangeLocation(QQmlProfilerService::HandlingSignal,
+ expression->sourceFile(), expression->lineNumber(),
+ expression->columnNumber());
+ }
}
~QQmlHandlingSignalProfiler()
@@ -224,19 +224,6 @@ struct QQmlHandlingSignalProfiler {
}
bool enabled;
-
-private:
- void init(const QMetaMethod &signal, QQmlExpression *expression)
- {
- QQmlProfilerService *service = QQmlProfilerService::instance;
- service->startRange(QQmlProfilerService::HandlingSignal);
- service->rangeData(QQmlProfilerService::HandlingSignal,
- QString::fromLatin1(signal.methodSignature()) + QLatin1String(": ")
- + expression->expression());
- service->rangeLocation(QQmlProfilerService::HandlingSignal,
- expression->sourceFile(), expression->lineNumber(),
- expression->columnNumber());
- }
};
struct QQmlObjectCreatingProfiler {
diff --git a/src/qml/qml/qqmlabstractexpression_p.h b/src/qml/qml/qqmlabstractexpression_p.h
index fe2ee1762b..1d5ecac08e 100644
--- a/src/qml/qml/qqmlabstractexpression_p.h
+++ b/src/qml/qml/qqmlabstractexpression_p.h
@@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
-class QQmlAbstractExpression
+class Q_QML_PRIVATE_EXPORT QQmlAbstractExpression
{
public:
QQmlAbstractExpression();
diff --git a/src/qml/qml/qqmlaccessors_p.h b/src/qml/qml/qqmlaccessors_p.h
index 8e67a58511..7558ab3e35 100644
--- a/src/qml/qml/qqmlaccessors_p.h
+++ b/src/qml/qml/qqmlaccessors_p.h
@@ -47,7 +47,7 @@
#include <QtCore/qhash.h>
#include <QtCore/QReadWriteLock>
-#ifdef Q_OS_QNX
+#if defined(Q_OS_QNX) || defined(Q_OS_LINUX)
#include <stdint.h>
#endif
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 3a3bf403e6..b77484c7e5 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -49,6 +49,7 @@
#include "qqml.h"
#include "qqmlcontext.h"
#include "qqmlglobal_p.h"
+#include "qqmlrewrite_p.h"
#include <private/qqmlprofilerservice_p.h>
#include <private/qv8debugservice_p.h>
@@ -59,6 +60,105 @@ Q_DECLARE_METATYPE(QJSValue)
QT_BEGIN_NAMESPACE
+static QQmlJavaScriptExpression::VTable QQmlBoundSignalExpression_jsvtable = {
+ QQmlBoundSignalExpression::expressionIdentifier,
+ QQmlBoundSignalExpression::expressionChanged
+};
+
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QByteArray &expression,
+ bool isRewritten, const QString &fileName, int line, int column)
+ : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable)
+{
+ setNotifyOnValueChanged(false);
+ setContext(ctxt);
+ setScopeObject(scope);
+ m_expression = QString::fromUtf8(expression);
+ m_expressionFunctionValid = false;
+ m_expressionFunctionRewritten = isRewritten;
+ m_fileName = fileName;
+ m_line = line;
+ m_column = column;
+}
+
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QString &expression,
+ bool isRewritten, const QString &fileName, int line, int column)
+ : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable)
+{
+ setNotifyOnValueChanged(false);
+ setContext(ctxt);
+ setScopeObject(scope);
+ m_expression = expression;
+ m_expressionFunctionValid = false;
+ m_expressionFunctionRewritten = isRewritten;
+ m_fileName = fileName;
+ m_line = line;
+ m_column = column;
+}
+
+QQmlBoundSignalExpression::~QQmlBoundSignalExpression()
+{
+ qPersistentDispose(m_v8function);
+ qPersistentDispose(m_v8qmlscope);
+}
+
+QString QQmlBoundSignalExpression::expressionIdentifier(QQmlJavaScriptExpression *e)
+{
+ QQmlBoundSignalExpression *This = static_cast<QQmlBoundSignalExpression *>(e);
+ return QLatin1String("\"") + This->m_expression + QLatin1String("\"");
+}
+
+void QQmlBoundSignalExpression::expressionChanged(QQmlJavaScriptExpression *)
+{
+ // bound signals do not notify on change.
+}
+
+// This mirrors code in QQmlExpressionPrivate::value() and v8value().
+// Any change made here should be made there and vice versa.
+void QQmlBoundSignalExpression::evaluate(QObject *secondaryScope)
+{
+ Q_ASSERT (context() && engine());
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine());
+
+ ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
+ {
+ v8::HandleScope handle_scope;
+ v8::Context::Scope context_scope(ep->v8engine()->context());
+ if (!m_expressionFunctionValid) {
+ bool ok = true;
+ QString code;
+ if (m_expressionFunctionRewritten) {
+ code = m_expression;
+ } else {
+ QQmlRewrite::RewriteSignalHandler rewriteSignalHandler;
+ code = rewriteSignalHandler(m_expression, m_functionName, &ok);
+ }
+
+ if (ok)
+ m_v8function = evalFunction(context(), scopeObject(), code, m_fileName, m_line, &m_v8qmlscope);
+
+ if (m_v8function.IsEmpty() || m_v8function->IsNull()) {
+ ep->dereferenceScarceResources();
+ return; // could not evaluate function. Not valid.
+ }
+
+ setUseSharedContext(false);
+ m_expressionFunctionValid = true;
+ }
+
+ if (secondaryScope) {
+ QObject *restoreSecondaryScope = 0;
+ restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(m_v8qmlscope, secondaryScope);
+ QQmlJavaScriptExpression::evaluate(context(), m_v8function, 0);
+ ep->v8engine()->contextWrapper()->setSecondaryScope(m_v8qmlscope, restoreSecondaryScope);
+ } else {
+ QQmlJavaScriptExpression::evaluate(context(), m_v8function, 0);
+ }
+ }
+ ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
+}
+
+////////////////////////////////////////////////////////////////////////
+
class QQmlBoundSignalParameters : public QObject
{
Q_OBJECT
@@ -104,10 +204,9 @@ QQmlAbstractBoundSignal::~QQmlAbstractBoundSignal()
}
}
-void QQmlAbstractBoundSignal::addToObject()
+void QQmlAbstractBoundSignal::addToObject(QObject *obj)
{
Q_ASSERT(!m_prevSignal);
- QObject *obj = object();
Q_ASSERT(obj);
QQmlData *data = QQmlData::get(obj, true);
@@ -120,13 +219,15 @@ void QQmlAbstractBoundSignal::addToObject()
QQmlBoundSignal::QQmlBoundSignal(QObject *scope, const QMetaMethod &signal,
QObject *owner)
-: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0), m_owner(owner)
+: m_expression(0), m_params(0), m_scope(scope), m_signal(signal), m_paramsValid(false), m_isEvaluating(false)
{
// This is thread safe. Although it may be updated by two threads, they
// will both set it to the same value - so the worst thing that can happen
// is that they both do the work to figure it out. Boo hoo.
if (evaluateIdx == -1) evaluateIdx = metaObject()->methodCount();
+ addToObject(owner);
+
QQmlPropertyPrivate::connect(scope, m_signal.methodIndex(), this, evaluateIdx);
}
@@ -144,7 +245,7 @@ int QQmlBoundSignal::index() const
/*!
Returns the signal expression.
*/
-QQmlExpression *QQmlBoundSignal::expression() const
+QQmlBoundSignalExpression *QQmlBoundSignal::expression() const
{
return m_expression;
}
@@ -156,9 +257,9 @@ QQmlExpression *QQmlBoundSignal::expression() const
The QQmlBoundSignal instance takes ownership of \a e. The caller is
assumes ownership of the returned QQmlExpression.
*/
-QQmlExpression *QQmlBoundSignal::setExpression(QQmlExpression *e)
+QQmlBoundSignalExpression *QQmlBoundSignal::setExpression(QQmlBoundSignalExpression *e)
{
- QQmlExpression *rv = m_expression;
+ QQmlBoundSignalExpression *rv = m_expression;
m_expression = e;
if (m_expression) m_expression->setNotifyOnValueChanged(false);
return rv;
@@ -183,8 +284,8 @@ int QQmlBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a)
}
if (m_params) m_params->setValues(a);
- if (m_expression && m_expression->engine()) {
- QQmlExpressionPrivate::get(m_expression)->value(m_params);
+ if (m_expression && m_expression->context() && m_expression->engine()) {
+ m_expression->evaluate(m_params);
if (m_expression && m_expression->hasError())
QQmlEnginePrivate::warning(m_expression->engine(), m_expression->error());
}
@@ -247,7 +348,7 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method,
if (scope == "Qt")
meta = &QObject::staticQtMetaObject;
else
- meta = static_cast<QQmlBoundSignal*>(parent)->object()->metaObject();
+ meta = static_cast<QQmlBoundSignal*>(parent)->scope()->metaObject();
for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
QMetaEnum m = meta->enumerator(i);
if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) {
@@ -300,71 +401,6 @@ int QQmlBoundSignalParameters::metaCall(QMetaObject::Call c, int id, void **a)
}
}
-////////////////////////////////////////////////////////////////////////
-
-QQmlBoundSignalNoParams::QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal,
- QObject *owner)
-: m_expression(0), m_owner(owner), m_index(signal.methodIndex()), m_isEvaluating(false)
-{
- callback = &subscriptionCallback;
- QQmlNotifierEndpoint::connect(scope, m_index);
-}
-
-QQmlBoundSignalNoParams::~QQmlBoundSignalNoParams()
-{
- delete m_expression;
- m_expression = 0;
-}
-
-int QQmlBoundSignalNoParams::index() const
-{
- return m_index;
-}
-
-/*!
- Returns the signal expression.
-*/
-QQmlExpression *QQmlBoundSignalNoParams::expression() const
-{
- return m_expression;
-}
-
-/*!
- Sets the signal expression to \a e. Returns the current signal expression,
- or null if there is no signal expression.
-
- The QQmlBoundSignalNoParams instance takes ownership of \a e. The caller is
- assumes ownership of the returned QQmlExpression.
-*/
-QQmlExpression *QQmlBoundSignalNoParams::setExpression(QQmlExpression *e)
-{
- QQmlExpression *rv = m_expression;
- m_expression = e;
- if (m_expression) m_expression->setNotifyOnValueChanged(false);
- return rv;
-}
-
-void QQmlBoundSignalNoParams::subscriptionCallback(QQmlNotifierEndpoint *e)
-{
- QQmlBoundSignalNoParams *s = static_cast<QQmlBoundSignalNoParams*>(e);
- if (!s->m_expression)
- return;
-
- if (QQmlDebugService::isDebuggingEnabled())
- QV8DebugService::instance()->signalEmitted(QString::fromAscii(s->m_owner->metaObject()->method(s->m_index).methodSignature()));
-
- QQmlHandlingSignalProfiler prof(s->m_owner, s->m_index, s->m_expression);
-
- s->m_isEvaluating = true;
-
- if (s->m_expression && s->m_expression->engine()) {
- QQmlExpressionPrivate::get(s->m_expression)->value();
- if (s->m_expression && s->m_expression->hasError())
- QQmlEnginePrivate::warning(s->m_expression->engine(), s->m_expression->error());
- }
- s->m_isEvaluating = false;
-}
-
QT_END_NAMESPACE
#include <qqmlboundsignal.moc>
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index 5fc8c3522f..c6ce875d07 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -53,15 +53,51 @@
// We mean it.
//
-#include "qqmlexpression.h"
-
#include <QtCore/qmetaobject.h>
-#include <private/qqmlnotifier_p.h>
+#include <private/qqmlabstractexpression_p.h>
+#include <private/qqmljavascriptexpression_p.h>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
+class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlAbstractExpression, public QQmlJavaScriptExpression
+{
+public:
+ QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QByteArray &expression,
+ bool isRewritten, const QString &fileName, int line, int column);
+ QQmlBoundSignalExpression(QQmlContextData *ctxt, QObject *scope, const QString &expression,
+ bool isRewritten, const QString &fileName, int line, int column);
+ ~QQmlBoundSignalExpression();
+
+ // "inherited" from QQmlJavaScriptExpression.
+ static QString expressionIdentifier(QQmlJavaScriptExpression *);
+ static void expressionChanged(QQmlJavaScriptExpression *);
+
+ // evaluation of a bound signal expression doesn't return any value
+ void evaluate(QObject *secondaryScope = 0);
+
+ QString sourceFile() const { return m_fileName; }
+ int lineNumber() const { return m_line; }
+ int columnNumber() const { return m_column; }
+ QString expression() const { return m_expression; }
+
+ QQmlEngine *engine() const { return context() ? context()->engine : 0; }
+
+private:
+ v8::Persistent<v8::Object> m_v8qmlscope;
+ v8::Persistent<v8::Function> m_v8function;
+
+ QString m_expression;
+ QString m_functionName; // hint for debugger
+ QString m_fileName;
+ int m_line;
+ int m_column;
+
+ bool m_expressionFunctionValid:1;
+ bool m_expressionFunctionRewritten:1;
+};
+
class Q_QML_EXPORT QQmlAbstractBoundSignal
{
public:
@@ -69,11 +105,12 @@ public:
virtual ~QQmlAbstractBoundSignal();
virtual int index() const = 0;
- virtual QQmlExpression *expression() const = 0;
- virtual QQmlExpression *setExpression(QQmlExpression *) = 0;
- virtual QObject *object() = 0;
+ virtual QQmlBoundSignalExpression *expression() const = 0;
+ virtual QQmlBoundSignalExpression *setExpression(QQmlBoundSignalExpression *) = 0;
+ virtual QObject *scope() = 0;
- void addToObject();
+protected:
+ void addToObject(QObject *owner);
private:
friend class QQmlData;
@@ -93,9 +130,9 @@ public:
int index() const;
- QQmlExpression *expression() const;
- QQmlExpression *setExpression(QQmlExpression *);
- QObject *object() { return m_owner; }
+ QQmlBoundSignalExpression *expression() const;
+ QQmlBoundSignalExpression *setExpression(QQmlBoundSignalExpression *);
+ QObject *scope() { return m_scope; }
bool isEvaluating() const { return m_isEvaluating; }
@@ -103,39 +140,14 @@ protected:
virtual int qt_metacall(QMetaObject::Call c, int id, void **a);
private:
- QQmlExpression *m_expression;
+ QQmlBoundSignalExpression *m_expression;
+ QQmlBoundSignalParameters *m_params;
+ QObject *m_scope;
QMetaMethod m_signal;
bool m_paramsValid : 1;
bool m_isEvaluating : 1;
- QQmlBoundSignalParameters *m_params;
- QObject *m_owner;
-};
-
-class Q_QML_EXPORT QQmlBoundSignalNoParams : public QQmlAbstractBoundSignal,
- public QQmlNotifierEndpoint
-{
-public:
- QQmlBoundSignalNoParams(QObject *scope, const QMetaMethod &signal, QObject *owner);
- virtual ~QQmlBoundSignalNoParams();
-
- int index() const;
-
- QQmlExpression *expression() const;
- QQmlExpression *setExpression(QQmlExpression *);
- QObject *object() { return m_owner; }
-
- static void subscriptionCallback(QQmlNotifierEndpoint *e);
-
- bool isEvaluating() const { return m_isEvaluating; }
-
-private:
- QQmlExpression *m_expression;
- QObject *m_owner;
- int m_index;
- bool m_isEvaluating;
};
-
QT_END_NAMESPACE
#endif // QQMLBOUNDSIGNAL_P_H
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index dec9911481..54577f9b92 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -3468,6 +3468,7 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
store.value = js.compiledIndex;
store.context = js.bindingContext.stack;
store.owner = js.bindingContext.owner;
+ store.isAlias = prop->isAlias;
if (valueTypeProperty) {
store.isRoot = (compileState->root == valueTypeProperty->parent);
} else {
@@ -3488,30 +3489,29 @@ void QQmlCompiler::genBindingAssignment(QQmlScript::Value *binding,
} else if (ref.dataType == BindingReference::QtScript) {
const JSBindingReference &js = static_cast<const JSBindingReference &>(ref);
- QQmlInstruction store;
- store.assignBinding.value = output->indexForString(js.rewrittenExpression);
- store.assignBinding.context = js.bindingContext.stack;
- store.assignBinding.owner = js.bindingContext.owner;
- store.assignBinding.line = binding->location.start.line;
- store.assignBinding.column = binding->location.start.column;
+ Instruction::StoreBinding store;
+ store.value = output->indexForString(js.rewrittenExpression);
+ store.context = js.bindingContext.stack;
+ store.owner = js.bindingContext.owner;
+ store.line = binding->location.start.line;
+ store.column = binding->location.start.column;
+ store.isAlias = prop->isAlias;
if (valueTypeProperty) {
- store.assignBinding.isRoot = (compileState->root == valueTypeProperty->parent);
+ store.isRoot = (compileState->root == valueTypeProperty->parent);
} else {
- store.assignBinding.isRoot = (compileState->root == obj);
+ store.isRoot = (compileState->root == obj);
}
Q_ASSERT(js.bindingContext.owner == 0 ||
(js.bindingContext.owner != 0 && valueTypeProperty));
if (js.bindingContext.owner) {
- store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
+ store.property = genValueTypeData(prop, valueTypeProperty);
} else {
- store.assignBinding.property = prop->core;
+ store.property = prop->core;
}
- output->addInstructionHelper(
- !prop->isAlias ? QQmlInstruction::StoreBinding
- : QQmlInstruction::StoreBindingOnAlias
- , store);
+
+ output->addInstruction(store);
} else {
Q_ASSERT(!"Unhandled BindingReference::DataType type");
}
@@ -3588,8 +3588,7 @@ bool QQmlCompiler::completeComponentBuild()
bool isSharable = false;
binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable);
- if (isSharable && !binding.property->isAlias /* See above re alias */ &&
- binding.property->type != qMetaTypeId<QQmlBinding*>()) {
+ if (isSharable && binding.property->type != qMetaTypeId<QQmlBinding*>()) {
binding.dataType = BindingReference::V8;
sharedBindings.append(b);
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 7bddaadcd0..2e46192246 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1396,7 +1396,8 @@ void QV8IncubatorResource::statusChanged(Status s)
{
if (s == Ready) {
Q_ASSERT(QQmlData::get(object()));
- QQmlData::get(object())->setImplicitDestructible();
+ QQmlData::get(object())->explicitIndestructibleSet = false;
+ QQmlData::get(object())->indestructible = false;
}
if (!me.IsEmpty()) { // Will be false in synchronous mode
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index e7e001c4f2..3dd1c3ccba 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -181,11 +181,25 @@ public:
QQmlNotifier *objectNameNotifier() const;
QHash<int, QObject *> *attachedProperties() const;
+ static inline bool wasDeleted(QObject *);
private:
// For objectNameNotifier and attachedProperties
mutable QQmlDataExtended *extendedData;
};
+bool QQmlData::wasDeleted(QObject *object)
+{
+ if (!object)
+ return true;
+
+ QObjectPrivate *priv = QObjectPrivate::get(const_cast<QObject *>(object));
+ if (priv->wasDeleted)
+ return true;
+
+ return priv->declarativeData &&
+ static_cast<QQmlData *>(priv->declarativeData)->isQueuedForDeletion;
+}
+
QQmlNotifierEndpoint *QQmlData::notify(int index)
{
Q_ASSERT(index <= 0xFFFF);
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index df5f7f8ee9..82289311c9 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -297,16 +297,16 @@ QList<QQmlDirParser::TypeInfo> QQmlDirParser::typeInfos() const
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
- return debug << qPrintable(QString("{%1 %2.%3}").arg(component.typeName)
- .arg(component.majorVersion)
- .arg(component.minorVersion));
+ const QString output = QString::fromLatin1("{%1 %2.%3}").
+ arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
+ return debug << qPrintable(output);
}
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
{
- return debug << qPrintable(QString("{%1 %2.%3}").arg(script.nameSpace)
- .arg(script.majorVersion)
- .arg(script.minorVersion));
+ const QString output = QString::fromLatin1("{%1 %2.%3}").
+ arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
+ return debug << qPrintable(output);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 955c8ce414..153d6b325a 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -598,9 +598,17 @@ QQmlEngine::~QQmlEngine()
/*!
Clears the engine's internal component cache.
- Normally the QQmlEngine caches components loaded from qml
- files. This method clears this cache and forces the component to be
- reloaded.
+ This function causes the property metadata of all components previously
+ loaded by the engine to be destroyed. All previously loaded components and
+ the property bindings for all extant objects created from those components will
+ cease to function.
+
+ This function returns the engine to a state where it does not contain any loaded
+ component data. This may be useful in order to reload a smaller subset of the
+ previous component set, or to load a new version of a previously loaded component.
+
+ Once the component cache has been cleared, components must be loaded before
+ any new objects can be created.
*/
void QQmlEngine::clearComponentCache()
{
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index d760486605..940b3c8354 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -60,7 +60,7 @@ static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = {
QQmlExpressionPrivate::QQmlExpressionPrivate()
: QQmlJavaScriptExpression(&QQmlExpressionPrivate_jsvtable),
expressionFunctionValid(true), expressionFunctionRewritten(false),
- extractExpressionFromFunction(false), line(-1), dataRef(0)
+ line(-1)
{
}
@@ -68,8 +68,6 @@ QQmlExpressionPrivate::~QQmlExpressionPrivate()
{
qPersistentDispose(v8qmlscope);
qPersistentDispose(v8function);
- if (dataRef) dataRef->release();
- dataRef = 0;
}
void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QObject *me)
@@ -321,13 +319,7 @@ QQmlContext *QQmlExpression::context() const
QString QQmlExpression::expression() const
{
Q_D(const QQmlExpression);
- if (d->extractExpressionFromFunction && context()->engine()) {
- QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(context()->engine());
- v8::HandleScope handle_scope;
- v8::Context::Scope scope(v8engine->context());
-
- return v8engine->toString(v8::Handle<v8::Value>(d->v8function));
- } else if (!d->expressionUtf8.isEmpty()) {
+ if (!d->expressionUtf8.isEmpty()) {
return QString::fromUtf8(d->expressionUtf8);
} else {
return d->expression;
@@ -351,7 +343,7 @@ void QQmlExpression::setExpression(const QString &expression)
}
// Must be called with a valid handle scope
-v8::Local<v8::Value> QQmlExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
+v8::Local<v8::Value> QQmlExpressionPrivate::v8value(bool *isUndefined)
{
if (!expressionFunctionValid) {
bool ok = true;
@@ -369,21 +361,10 @@ v8::Local<v8::Value> QQmlExpressionPrivate::v8value(QObject *secondaryScope, boo
expressionFunctionValid = true;
}
-
- if (secondaryScope) {
- v8::Local<v8::Value> result;
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine);
- QObject *restoreSecondaryScope = 0;
- restoreSecondaryScope = ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
- result = evaluate(context(), v8function, isUndefined);
- ep->v8engine()->contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
- return result;
- } else {
- return evaluate(context(), v8function, isUndefined);
- }
+ return evaluate(context(), v8function, isUndefined);
}
-QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
+QVariant QQmlExpressionPrivate::value(bool *isUndefined)
{
Q_Q(QQmlExpression);
@@ -400,7 +381,7 @@ QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined
{
v8::HandleScope handle_scope;
v8::Context::Scope context_scope(ep->v8engine()->context());
- v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
+ v8::Local<v8::Value> result = v8value(isUndefined);
rv = ep->v8engine()->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
@@ -421,7 +402,7 @@ QVariant QQmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined
QVariant QQmlExpression::evaluate(bool *valueIsUndefined)
{
Q_D(QQmlExpression);
- return d->value(0, valueIsUndefined);
+ return d->value(valueIsUndefined);
}
/*!
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index 186e3aebf9..d32e2d314c 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -82,9 +82,9 @@ public:
void init(QQmlContextData *, const QString &, bool, QObject *, const QString &, int, int);
void init(QQmlContextData *, const QByteArray &, bool, QObject *, const QString &, int, int);
- QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
+ QVariant value(bool *isUndefined = 0);
- v8::Local<v8::Value> v8value(QObject *secondaryScope = 0, bool *isUndefined = 0);
+ v8::Local<v8::Value> v8value(bool *isUndefined = 0);
static inline QQmlExpressionPrivate *get(QQmlExpression *expr);
static inline QQmlExpression *get(QQmlExpressionPrivate *expr);
@@ -96,7 +96,6 @@ public:
bool expressionFunctionValid:1;
bool expressionFunctionRewritten:1;
- bool extractExpressionFromFunction:1;
// "Inherited" from QQmlJavaScriptExpression
static QString expressionIdentifier(QQmlJavaScriptExpression *);
@@ -113,8 +112,6 @@ public:
int line;
int column;
QString name; //function name, hint for the debugger
-
- QQmlRefCount *dataRef;
};
QQmlExpressionPrivate *QQmlExpressionPrivate::get(QQmlExpression *expr)
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 1224efdaac..be870cad4c 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -545,27 +545,27 @@ QString QQmlImportsPrivate::add(const QQmlDirComponents &qmldircomponentsnetwork
}
}
- // TODO: Should this search be omitted if found == true?
-
- // step 2: search for extension with encoded version major
- foreach (const QString &p, database->fileImportPath) {
- dir = p+Slash+url;
+ if (!found) {
+ // step 2: search for extension with encoded version major
+ foreach (const QString &p, database->fileImportPath) {
+ dir = p+Slash+url;
- QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir"));
- const QString absoluteFilePath = fi.absoluteFilePath();
+ QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir"));
+ const QString absoluteFilePath = fi.absoluteFilePath();
- if (fi.isFile()) {
- found = true;
+ if (fi.isFile()) {
+ found = true;
- const QString absolutePath = fi.absolutePath();
- if (absolutePath.at(0) == QLatin1Char(':'))
- url = QLatin1String("qrc://") + absolutePath.mid(1);
- else
- url = QUrl::fromLocalFile(fi.absolutePath()).toString();
- uri = resolvedUri(dir, database);
- if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
- return QString();
- break;
+ const QString absolutePath = fi.absolutePath();
+ if (absolutePath.at(0) == QLatin1Char(':'))
+ url = QLatin1String("qrc://") + absolutePath.mid(1);
+ else
+ url = QUrl::fromLocalFile(fi.absolutePath()).toString();
+ uri = resolvedUri(dir, database);
+ if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, &qmldirscripts, errors))
+ return QString();
+ break;
+ }
}
}
diff --git a/src/qml/qml/qqmlinstruction.cpp b/src/qml/qml/qqmlinstruction.cpp
index b37117e69b..82cf235712 100644
--- a/src/qml/qml/qqmlinstruction.cpp
+++ b/src/qml/qml/qqmlinstruction.cpp
@@ -210,9 +210,6 @@ void QQmlCompiledData::dump(QQmlInstruction *instr, int idx)
case QQmlInstruction::StoreBinding:
qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
break;
- case QQmlInstruction::StoreBindingOnAlias:
- qWarning().nospace() << idx << "\t\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property.coreIndex << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
- break;
case QQmlInstruction::StoreV4Binding:
qWarning().nospace() << idx << "\t\t" << "STORE_COMPILED_BINDING\t" << instr->assignV4Binding.property << "\t" << instr->assignV4Binding.value << "\t" << instr->assignV4Binding.context;
break;
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index b7533aca68..cfc530df04 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -114,7 +114,6 @@ QT_BEGIN_NAMESPACE
F(BeginObject, begin) \
F(InitV8Bindings, initV8Bindings) \
F(StoreBinding, assignBinding) \
- F(StoreBindingOnAlias, assignBinding) \
F(StoreV8Binding, assignBinding) \
F(StoreV4Binding, assignV4Binding) \
F(StoreValueSource, assignValueSource) \
@@ -251,6 +250,7 @@ union QQmlInstruction
short context;
short owner;
bool isRoot;
+ bool isAlias;
ushort line;
ushort column;
};
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index f68c345f3a..075c1f6c4f 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -920,7 +920,7 @@ QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valu
Returns the expression associated with this signal property, or 0 if no
signal expression exists.
*/
-QQmlExpression *
+QQmlBoundSignalExpression *
QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
{
if (!(that.type() & QQmlProperty::SignalProperty))
@@ -948,9 +948,9 @@ QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
Ownership of \a expr transfers to QML. Ownership of the return value is
assumed by the caller.
*/
-QQmlExpression *
+QQmlBoundSignalExpression *
QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
- QQmlExpression *expr)
+ QQmlBoundSignalExpression *expr)
{
if (!(that.type() & QQmlProperty::SignalProperty)) {
delete expr;
@@ -970,13 +970,8 @@ QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
return signalHandler->setExpression(expr);
if (expr) {
- QQmlAbstractBoundSignal *signal = 0;
- if (that.method().parameterTypes().count())
- signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object);
- else
- signal = new QQmlBoundSignalNoParams(that.d->object, that.method(), that.d->object);
- QQmlExpression *oldExpr = signal->setExpression(expr);
- signal->addToObject();
+ QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object);
+ QQmlBoundSignalExpression *oldExpr = signal->setExpression(expr);
return oldExpr;
} else {
return 0;
@@ -1531,13 +1526,29 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
return true;
const char *valueType = 0;
- if (value.userType() == QVariant::Invalid) valueType = "null";
- else valueType = QMetaType::typeName(value.userType());
+ const char *propertyType = 0;
+
+ if (value.userType() == QMetaType::QObjectStar) {
+ if (QObject *o = *(QObject **)value.constData()) {
+ valueType = o->metaObject()->className();
+
+ if (const QMetaObject *propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type)) {
+ propertyType = propertyMetaObject->className();
+ }
+ }
+ } else if (value.userType() != QVariant::Invalid) {
+ valueType = QMetaType::typeName(value.userType());
+ }
+
+ if (!valueType)
+ valueType = "null";
+ if (!propertyType)
+ propertyType = QMetaType::typeName(type);
expression->delayedError()->error.setDescription(QLatin1String("Unable to assign ") +
QLatin1String(valueType) +
QLatin1String(" to ") +
- QLatin1String(QMetaType::typeName(type)));
+ QLatin1String(propertyType));
return false;
}
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index f4a9ced53b..e33c95ae41 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -64,7 +64,7 @@
QT_BEGIN_NAMESPACE
class QQmlContext;
-class QQmlExpression;
+class QQmlBoundSignalExpression;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
@@ -140,9 +140,9 @@ public:
static QQmlAbstractBinding *setBinding(const QQmlProperty &that,
QQmlAbstractBinding *,
WriteFlags flags = DontRemoveBinding);
- static QQmlExpression *signalExpression(const QQmlProperty &that);
- static QQmlExpression *setSignalExpression(const QQmlProperty &that,
- QQmlExpression *) ;
+ static QQmlBoundSignalExpression *signalExpression(const QQmlProperty &that);
+ static QQmlBoundSignalExpression *setSignalExpression(const QQmlProperty &that,
+ QQmlBoundSignalExpression *) ;
static bool write(const QQmlProperty &that, const QVariant &, WriteFlags);
static bool writeBinding(QObject *, const QQmlPropertyData &,
QQmlContextData *context,
diff --git a/src/qml/qml/qqmlrewrite.cpp b/src/qml/qml/qqmlrewrite.cpp
index 72bd23955b..bbb17b631d 100644
--- a/src/qml/qml/qqmlrewrite.cpp
+++ b/src/qml/qml/qqmlrewrite.cpp
@@ -51,6 +51,8 @@ DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP);
namespace QQmlRewrite {
+QString SharedBindingTester::evalString("eval");
+
static void rewriteStringLiteral(AST::StringLiteral *ast, const QString *code, int startPosition, TextWriter *writer)
{
const unsigned position = ast->firstSourceLocation().begin() - startPosition + 1;
@@ -419,6 +421,21 @@ QString RewriteSignalHandler::operator()(QQmlJS::AST::Node *node, const QString
return rewritten;
}
+QString RewriteSignalHandler::operator()(const QString &code, const QString &name, bool *ok)
+{
+ Engine engine;
+ Lexer lexer(&engine);
+ Parser parser(&engine);
+ lexer.setCode(code, 0);
+ parser.parseStatement();
+ if (!parser.statement()) {
+ if (ok) *ok = false;
+ return QString();
+ }
+ if (ok) *ok = true;
+ return operator()(parser.statement(), code, name);
+}
+
} // namespace QQmlRewrite
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlrewrite_p.h b/src/qml/qml/qqmlrewrite_p.h
index 1d69839878..efa10ce316 100644
--- a/src/qml/qml/qqmlrewrite_p.h
+++ b/src/qml/qml/qqmlrewrite_p.h
@@ -70,9 +70,11 @@ public:
bool isSharable(const QString &code);
bool isSharable(AST::Node *Node);
- virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; }
- virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; }
- virtual bool visit(AST::CallExpression *) { _sharable = false; return false; }
+ inline virtual bool visit(AST::FunctionDeclaration *);
+ inline virtual bool visit(AST::FunctionExpression *);
+ inline virtual bool visit(AST::IdentifierExpression *);
+
+ static QString evalString;
};
class RewriteBinding: protected AST::Visitor
@@ -133,6 +135,7 @@ class RewriteSignalHandler: protected AST::Visitor
public:
RewriteSignalHandler();
QString operator()(QQmlJS::AST::Node *node, const QString &code, const QString &name);
+ QString operator()(const QString &code, const QString &name, bool *ok = 0);
protected:
void rewriteMultilineStrings(QString &code);
@@ -142,6 +145,26 @@ protected:
virtual bool visit(AST::StringLiteral *ast);
};
+bool SharedBindingTester::visit(AST::FunctionDeclaration *)
+{
+ _sharable = false;
+ return false;
+}
+
+bool SharedBindingTester::visit(AST::FunctionExpression *)
+{
+ _sharable = false;
+ return false;
+}
+
+bool SharedBindingTester::visit(AST::IdentifierExpression *e)
+{
+ if (e->name == evalString)
+ _sharable = false;
+
+ return false; // IdentifierExpression is a leaf node anyway
+}
+
} // namespace QQmlRewrite
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlscript.cpp b/src/qml/qml/qqmlscript.cpp
index e1925eb238..37c0fb44a4 100644
--- a/src/qml/qml/qqmlscript.cpp
+++ b/src/qml/qml/qqmlscript.cpp
@@ -66,6 +66,11 @@ QQmlScript::Object::Object()
: type(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1),
componentCompileState(0), nextAliasingObject(0), nextIdObject(0)
{
+ // initialize the members in the meta object
+ extObject.d.superdata = 0;
+ extObject.d.stringdata = 0;
+ extObject.d.data = 0;
+ extObject.d.extradata = 0;
}
QQmlScript::Object::~Object()
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 5412315d31..985d291a8e 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -204,13 +204,19 @@ inline bool fastHasBinding(QObject *o, int index)
{
QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(o)->declarativeData);
+ index &= 0xFFFFFF; // To handle value types
+
return ddata && (ddata->bindingBitsSize > index) &&
(ddata->bindingBits[index / 32] & (1 << (index % 32)));
}
static void removeBindingOnProperty(QObject *o, int index)
{
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, index, -1, 0);
+ int coreIndex = index & 0xFFFFFF;
+ int valueTypeIndex = index & 0xFF000000;
+ if (!valueTypeIndex) valueTypeIndex = -1;
+
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
if (binding) binding->destroy();
}
@@ -724,15 +730,10 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
- QQmlAbstractBoundSignal *bs = 0;
- if (signal.parameterTypes().count())
- bs = new QQmlBoundSignal(target, signal, target);
- else
- bs = new QQmlBoundSignalNoParams(target, signal, target);
- QQmlExpression *expr =
- new QQmlExpression(CTXT, context, DATAS.at(instr.value), true, COMP->name, instr.line, instr.column, *new QQmlExpressionPrivate);
+ QQmlBoundSignal *bs = new QQmlBoundSignal(target, signal, target);
+ QQmlBoundSignalExpression *expr =
+ new QQmlBoundSignalExpression(CTXT, context, DATAS.at(instr.value), true, COMP->name, instr.line, instr.column);
bs->setExpression(expr);
- bs->addToObject();
QML_END_INSTR(StoreSignal)
QML_BEGIN_INSTR(StoreImportedScript)
@@ -788,35 +789,23 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
bind->m_mePtr = &bindValues.top();
bind->setTarget(target, instr.property, CTXT);
- typedef QQmlPropertyPrivate QDPP;
- Q_ASSERT(bind->propertyIndex() == QDPP::bindingIndex(instr.property));
- Q_ASSERT(bind->object() == target);
-
- bind->addToObject();
- QML_END_INSTR(StoreBinding)
-
- QML_BEGIN_INSTR(StoreBindingOnAlias)
- QObject *target =
- objects.at(objects.count() - 1 - instr.owner);
- QObject *context =
- objects.at(objects.count() - 1 - instr.context);
+ if (instr.isAlias) {
+ QQmlAbstractBinding *old =
+ QQmlPropertyPrivate::setBindingNoEnable(target,
+ instr.property.coreIndex,
+ instr.property.getValueTypeCoreIndex(),
+ bind);
+ if (old) { old->destroy(); }
+ } else {
+ typedef QQmlPropertyPrivate QDPP;
+ Q_ASSERT(bind->propertyIndex() == QDPP::bindingIndex(instr.property));
+ Q_ASSERT(bind->object() == target);
- if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
- QML_NEXT_INSTR(StoreBindingOnAlias);
+ CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property));
- QQmlBinding *bind = new QQmlBinding(PRIMITIVES.at(instr.value), true,
- context, CTXT, COMP->name, instr.line,
- instr.column);
- bindValues.push(bind);
- bind->m_mePtr = &bindValues.top();
- bind->setTarget(target, instr.property, CTXT);
-
- QQmlAbstractBinding *old =
- QQmlPropertyPrivate::setBindingNoEnable(target, instr.property.coreIndex,
- instr.property.getValueTypeCoreIndex(),
- bind);
- if (old) { old->destroy(); }
- QML_END_INSTR(StoreBindingOnAlias)
+ bind->addToObject();
+ }
+ QML_END_INSTR(StoreBinding)
QML_BEGIN_INSTR(StoreV4Binding)
QObject *target =
@@ -837,6 +826,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
Q_ASSERT(binding->propertyIndex() == (property & 0xFF00FFFF));
Q_ASSERT(binding->object() == target);
+ CLEAN_PROPERTY(target, property & 0xFF00FFFF);
+
binding->addToObject();
QML_END_INSTR(StoreV4Binding)
@@ -855,11 +846,22 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
bindValues.push(binding);
binding->m_mePtr = &bindValues.top();
- typedef QQmlPropertyPrivate QDPP;
- Q_ASSERT(binding->propertyIndex() == QDPP::bindingIndex(instr.property));
- Q_ASSERT(binding->object() == target);
+ if (instr.isAlias) {
+ QQmlAbstractBinding *old =
+ QQmlPropertyPrivate::setBindingNoEnable(target,
+ instr.property.coreIndex,
+ instr.property.getValueTypeCoreIndex(),
+ binding);
+ if (old) { old->destroy(); }
+ } else {
+ typedef QQmlPropertyPrivate QDPP;
+ Q_ASSERT(binding->propertyIndex() == QDPP::bindingIndex(instr.property));
+ Q_ASSERT(binding->object() == target);
+
+ CLEAN_PROPERTY(target, QDPP::bindingIndex(instr.property));
- binding->addToObject();
+ binding->addToObject();
+ }
}
QML_END_INSTR(StoreV8Binding)
@@ -1242,9 +1244,9 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
while (!bindValues.isEmpty()) {
QQmlAbstractBinding *b = bindValues.pop();
- if(b) {
+ if (b) {
b->m_mePtr = 0;
- b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
+ b->setEnabled(true, QQmlPropertyPrivate::BypassInterceptor |
QQmlPropertyPrivate::DontRemoveBinding);
}
diff --git a/src/qml/qml/v4/qv4bindings.cpp b/src/qml/qml/v4/qv4bindings.cpp
index 0cd6ffd082..4c92598c32 100644
--- a/src/qml/qml/v4/qv4bindings.cpp
+++ b/src/qml/qml/v4/qv4bindings.cpp
@@ -52,6 +52,7 @@
#include <private/qqmlmetatype_p.h>
#include <private/qqmltrace_p.h>
#include <private/qqmlstringconverters_p.h>
+#include <private/qqmlproperty_p.h>
#include <QtQml/qqmlinfo.h>
#include <QtCore/qnumeric.h>
@@ -66,46 +67,53 @@ namespace {
struct Register {
typedef QQmlRegisterType Type;
- void setUndefined() { dataType = UndefinedType; }
- void setNull() { dataType = NullType; }
- void setNaN() { setqreal(qSNaN()); }
- bool isUndefined() const { return dataType == UndefinedType; }
+ inline void setUndefined() { dataType = UndefinedType; }
+ inline void setNull() { dataType = NullType; }
+ inline void setNaN() { setnumber(qSNaN()); }
+ inline bool isUndefined() const { return dataType == UndefinedType; }
- void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
- QObject *getQObject() const { return qobjectValue; }
+ inline void setQObject(QObject *o) { qobjectValue = o; dataType = QObjectStarType; }
+ inline QObject *getQObject() const { return qobjectValue; }
- void setqreal(qreal v) { qrealValue = v; dataType = QRealType; }
- qreal getqreal() const { return qrealValue; }
- qreal &getqrealref() { return qrealValue; }
+ inline void setnumber(double v) { numberValue = v; dataType = NumberType; }
+ inline double getnumber() const { return numberValue; }
+ inline double &getnumberref() { return numberValue; }
- void setint(int v) { intValue = v; dataType = IntType; }
- int getint() const { return intValue; }
- int &getintref() { return intValue; }
+ inline void setfloat(float v) { floatValue = v; dataType = FloatType; }
+ inline float getfloat() const { return floatValue; }
+ inline float &getfloatref() { return floatValue; }
- void setbool(bool v) { boolValue = v; dataType = BoolType; }
- bool getbool() const { return boolValue; }
- bool &getboolref() { return boolValue; }
+ inline void setint(int v) { intValue = v; dataType = IntType; }
+ inline int getint() const { return intValue; }
+ inline int &getintref() { return intValue; }
- QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
- QString *getstringptr() { return (QString *)typeDataPtr(); }
- QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
- const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
- const QString *getstringptr() const { return (QString *)typeDataPtr(); }
- const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
+ inline void setbool(bool v) { boolValue = v; dataType = BoolType; }
+ inline bool getbool() const { return boolValue; }
+ inline bool &getboolref() { return boolValue; }
+
+ inline QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
+ inline QString *getstringptr() { return (QString *)typeDataPtr(); }
+ inline QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
+ inline QColor *getcolorptr() { return (QColor *)typeDataPtr(); }
+ inline const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
+ inline const QString *getstringptr() const { return (QString *)typeDataPtr(); }
+ inline const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
+ inline const QColor *getcolorptr() const { return (QColor *)typeDataPtr(); }
size_t dataSize() { return sizeof(data); }
- void *typeDataPtr() { return (void *)&data; }
- void *typeMemory() { return (void *)data; }
- const void *typeDataPtr() const { return (void *)&data; }
- const void *typeMemory() const { return (void *)data; }
+ inline void *typeDataPtr() { return (void *)&data; }
+ inline void *typeMemory() { return (void *)data; }
+ inline const void *typeDataPtr() const { return (void *)&data; }
+ inline const void *typeMemory() const { return (void *)data; }
- Type gettype() const { return dataType; }
- void settype(Type t) { dataType = t; }
+ inline Type gettype() const { return dataType; }
+ inline void settype(Type t) { dataType = t; }
Type dataType; // Type of data
union {
QObject *qobjectValue;
- qreal qrealValue;
+ double numberValue;
+ float floatValue;
int intValue;
bool boolValue;
void *data[sizeof(QVariant)];
@@ -387,85 +395,6 @@ void QV4Bindings::subscribe(QObject *o, int notifyIndex, int subIndex)
sub->disconnect();
}
-// Conversion functions - these MUST match the QtScript expression path
-inline static qreal toReal(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::QReal) {
- return reg->getqreal();
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toReal();
- } else {
- if (ok) *ok = false;
- return 0;
- }
-}
-
-inline static QString toString(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::QReal) {
- return QString::number(reg->getqreal());
- } else if (type == QMetaType::Int) {
- return QString::number(reg->getint());
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toString();
- } else if (type == QMetaType::QString) {
- return *reg->getstringptr();
- } else {
- if (ok) *ok = false;
- return QString();
- }
-}
-
-inline static bool toBool(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::Bool) {
- return reg->getbool();
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toBool();
- } else {
- if (ok) *ok = false;
- return false;
- }
-}
-
-inline static QUrl toUrl(Register *reg, int type, QQmlContextData *context, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- QUrl base;
- if (type == qMetaTypeId<QVariant>()) {
- QVariant *var = reg->getvariantptr();
- int vt = var->type();
- if (vt == QVariant::Url) {
- base = var->toUrl();
- } else if (vt == QVariant::ByteArray) {
- // Preserve any valid percent-encoded octets supplied by the source
- base.setEncodedUrl(var->toByteArray(), QUrl::TolerantMode);
- } else if (vt == QVariant::String) {
- base.setEncodedUrl(var->toString().toUtf8(), QUrl::TolerantMode);
- } else {
- if (ok) *ok = false;
- return QUrl();
- }
- } else if (type == QMetaType::QString) {
- base.setEncodedUrl(reg->getstringptr()->toUtf8(), QUrl::TolerantMode);
- } else {
- if (ok) *ok = false;
- return QUrl();
- }
-
- if (!base.isEmpty() && base.isRelative())
- return context->url.resolved(base);
- else
- return base;
-}
-
static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
{
QVariant qtscript = qtscriptRaw;
@@ -529,10 +458,29 @@ static void testBindingResult(const QString &binding, int line, int column,
if (expression.hasError()) {
iserror = true;
qtscriptResult = "exception";
- } else {
- qtscriptResult = testResultToString(value, isUndefined);
+ } else if (value.userType() != resultType) {
+ // Override the QMetaType conversions to make them more JS friendly.
+ if (value.userType() == QMetaType::Double && (resultType == QMetaType::QString ||
+ resultType == QMetaType::QUrl)) {
+ // number to string-like conversion.
+ value = QVariant::fromValue<QString>(QString::number(value.toDouble(), 'g', 16));
+ } else if (value.userType() == QMetaType::QUrl && resultType == QMetaType::Bool) {
+ // url to bool conversion
+ value = QVariant::fromValue<bool>(!value.toUrl().isEmpty());
+ }
+
+ if (!value.isNull() && !value.convert(resultType)) {
+ iserror = true;
+ qtscriptResult = "exception";
+ } else if (resultType == QMetaType::QUrl) {
+ // a V8 value was converted to QUrl.
+ value = QVariant::fromValue<QUrl>(context->resolvedUrl(value.toUrl()));
+ }
}
+ if (! iserror)
+ qtscriptResult = testResultToString(value, isUndefined);
+
if (isUndefined && result.isUndefined()) {
return;
} else if(isUndefined != result.isUndefined()) {
@@ -557,8 +505,8 @@ static void testBindingResult(const QString &binding, int line, int column,
case QMetaType::Int:
v4value = result.getint();
break;
- case QMetaType::QReal:
- v4value = result.getqreal();
+ case QMetaType::Double:
+ v4value = result.getnumber();
break;
default:
if (resultType == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
@@ -621,15 +569,15 @@ static void throwException(int id, QQmlDelayedError *error,
QQmlEnginePrivate::warning(context->engine, error->error);
}
-const qreal QV4Bindings::D32 = 4294967296.0;
+const double QV4Bindings::D32 = 4294967296.0;
-qint32 QV4Bindings::toInt32(qreal n)
+qint32 QV4Bindings::toInt32(double n)
{
if (qIsNaN(n) || qIsInf(n) || (n == 0))
return 0;
double sign = (n < 0) ? -1.0 : 1.0;
- qreal abs_n = fabs(n);
+ double abs_n = fabs(n);
n = ::fmod(sign * ::floor(abs_n), D32);
const double D31 = D32 / 2.0;
@@ -643,13 +591,13 @@ qint32 QV4Bindings::toInt32(qreal n)
return qint32 (n);
}
-inline quint32 QV4Bindings::toUint32(qreal n)
+inline quint32 QV4Bindings::toUint32(double n)
{
if (qIsNaN(n) || qIsInf(n) || (n == 0))
return 0;
double sign = (n < 0) ? -1.0 : 1.0;
- qreal abs_n = fabs(n);
+ double abs_n = fabs(n);
n = ::fmod(sign * ::floor(abs_n), D32);
@@ -665,6 +613,11 @@ inline quint32 QV4Bindings::toUint32(qreal n)
goto exceptionExit; \
}
+#define THROW_VALUE_EXCEPTION_STR(id, str) { \
+ throwException((id), error, program, context, (str)); \
+ goto exceptionExit; \
+}
+
#define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
#define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
@@ -791,13 +744,21 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
sub->bindings = this;
sub->method = subIdx;
}
- reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
+
+ const Register::Type valueType = (Register::Type)instr->fetchAndSubscribe.valueType;
+ reg.init(valueType);
if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
MARK_REGISTER(instr->fetchAndSubscribe.reg);
QQmlAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
reg.typeDataPtr());
+ if (valueType == FloatType) {
+ // promote floats
+ const double v = reg.getfloat();
+ reg.setnumber(v);
+ }
+
if (accessors->notifier) {
QQmlNotifier *notifier = 0;
accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, &notifier);
@@ -868,11 +829,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(UnaryNot, unaryop)
- QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop)
+ QML_V4_BEGIN_INSTR(UnaryMinusNumber, unaryop)
{
- registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal());
+ registers[instr->unaryop.output].setnumber(-registers[instr->unaryop.src].getnumber());
}
- QML_V4_END_INSTR(UnaryMinusReal, unaryop)
+ QML_V4_END_INSTR(UnaryMinusNumber, unaryop)
QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop)
{
@@ -880,11 +841,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(UnaryMinusInt, unaryop)
- QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop)
+ QML_V4_BEGIN_INSTR(UnaryPlusNumber, unaryop)
{
- registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal());
+ registers[instr->unaryop.output].setnumber(+registers[instr->unaryop.src].getnumber());
}
- QML_V4_END_INSTR(UnaryPlusReal, unaryop)
+ QML_V4_END_INSTR(UnaryPlusNumber, unaryop)
QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop)
{
@@ -901,14 +862,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertBoolToInt, unaryop)
- QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertBoolToNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(src.getbool());
+ else output.setnumber(src.getbool());
}
- QML_V4_END_INSTR(ConvertBoolToReal, unaryop)
+ QML_V4_END_INSTR(ConvertBoolToNumber, unaryop)
QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop)
{
@@ -932,14 +893,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertIntToBool, unaryop)
- QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertIntToNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qreal(src.getint()));
+ else output.setnumber(double(src.getint()));
}
- QML_V4_END_INSTR(ConvertIntToReal, unaryop)
+ QML_V4_END_INSTR(ConvertIntToNumber, unaryop)
QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop)
{
@@ -954,25 +915,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertIntToString, unaryop)
- QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNumberToBool, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setbool(src.getqreal() != 0);
+ else output.setbool(src.getnumber() != 0);
}
- QML_V4_END_INSTR(ConvertRealToBool, unaryop)
+ QML_V4_END_INSTR(ConvertNumberToBool, unaryop)
- QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNumberToInt, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(toInt32(src.getqreal()));
+ else output.setint(toInt32(src.getnumber()));
}
- QML_V4_END_INSTR(ConvertRealToInt, unaryop)
+ QML_V4_END_INSTR(ConvertNumberToInt, unaryop)
- QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertNumberToString, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
@@ -980,11 +941,11 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
if (src.isUndefined()) {
output.setUndefined();
} else {
- new (output.getstringptr()) QString(QString::number(src.getqreal()));
+ new (output.getstringptr()) QString(QString::number(src.getnumber(), 'g', 16));
STRING_REGISTER(instr->unaryop.output);
}
}
- QML_V4_END_INSTR(ConvertRealToString, unaryop)
+ QML_V4_END_INSTR(ConvertNumberToString, unaryop)
QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
{
@@ -1026,7 +987,7 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ConvertStringToInt, unaryop)
- QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop)
+ QML_V4_BEGIN_INSTR(ConvertStringToNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
@@ -1041,10 +1002,10 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
output.cleanupString();
MARK_CLEAN_REGISTER(instr->unaryop.output);
}
- output.setqreal(tmp.toNumber());
+ output.setnumber(tmp.toNumber());
}
}
- QML_V4_END_INSTR(ConvertStringToReal, unaryop)
+ QML_V4_END_INSTR(ConvertStringToNumber, unaryop)
QML_V4_BEGIN_INSTR(ConvertStringToUrl, unaryop)
{
@@ -1190,75 +1151,75 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(ResolveUrl, unaryop)
- QML_V4_BEGIN_INSTR(MathSinReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathSinNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qSin(src.getqreal()));
+ else output.setnumber(qSin(src.getnumber()));
}
- QML_V4_END_INSTR(MathSinReal, unaryop)
+ QML_V4_END_INSTR(MathSinNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathCosReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathCosNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qCos(src.getqreal()));
+ else output.setnumber(qCos(src.getnumber()));
}
- QML_V4_END_INSTR(MathCosReal, unaryop)
+ QML_V4_END_INSTR(MathCosNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathAbsReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathAbsNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setqreal(qAbs(src.getqreal()));
+ else output.setnumber(qAbs(src.getnumber()));
}
- QML_V4_END_INSTR(MathAbsReal, unaryop)
+ QML_V4_END_INSTR(MathAbsNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathRoundReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathRoundNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(qRound(src.getqreal()));
+ else output.setint(qRound(src.getnumber()));
}
- QML_V4_END_INSTR(MathRoundReal, unaryop)
+ QML_V4_END_INSTR(MathRoundNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathFloorReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathFloorNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(qFloor(src.getqreal()));
+ else output.setint(qFloor(src.getnumber()));
}
- QML_V4_END_INSTR(MathFloorReal, unaryop)
+ QML_V4_END_INSTR(MathFloorNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathCeilReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathCeilNumber, unaryop)
{
const Register &src = registers[instr->unaryop.src];
Register &output = registers[instr->unaryop.output];
if (src.isUndefined()) output.setUndefined();
- else output.setint(qCeil(src.getqreal()));
+ else output.setint(qCeil(src.getnumber()));
}
- QML_V4_END_INSTR(MathCeilReal, unaryop)
+ QML_V4_END_INSTR(MathCeilNumber, unaryop)
- QML_V4_BEGIN_INSTR(MathPIReal, unaryop)
+ QML_V4_BEGIN_INSTR(MathPINumber, unaryop)
{
- static const qreal qmlPI = 2.0 * qAsin(1.0);
+ static const double qmlPI = 2.0 * qAsin(1.0);
Register &output = registers[instr->unaryop.output];
- output.setqreal(qmlPI);
+ output.setnumber(qmlPI);
}
- QML_V4_END_INSTR(MathPIReal, unaryop)
+ QML_V4_END_INSTR(MathPINumber, unaryop)
QML_V4_BEGIN_INSTR(LoadNull, null_value)
registers[instr->null_value.reg].setNull();
QML_V4_END_INSTR(LoadNull, null_value)
- QML_V4_BEGIN_INSTR(LoadReal, real_value)
- registers[instr->real_value.reg].setqreal(instr->real_value.value);
- QML_V4_END_INSTR(LoadReal, real_value)
+ QML_V4_BEGIN_INSTR(LoadNumber, number_value)
+ registers[instr->number_value.reg].setnumber(instr->number_value.value);
+ QML_V4_END_INSTR(LoadNumber, number_value)
QML_V4_BEGIN_INSTR(LoadInt, int_value)
registers[instr->int_value.reg].setint(instr->int_value.value);
@@ -1305,12 +1266,12 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(BitXorInt, binaryop)
- QML_V4_BEGIN_INSTR(AddReal, binaryop)
+ QML_V4_BEGIN_INSTR(AddNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() +
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() +
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(AddReal, binaryop)
+ QML_V4_END_INSTR(AddNumber, binaryop)
QML_V4_BEGIN_INSTR(AddString, binaryop)
{
@@ -1324,36 +1285,33 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(AddString, binaryop)
- QML_V4_BEGIN_INSTR(SubReal, binaryop)
+ QML_V4_BEGIN_INSTR(SubNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() -
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() -
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(SubReal, binaryop)
+ QML_V4_END_INSTR(SubNumber, binaryop)
- QML_V4_BEGIN_INSTR(MulReal, binaryop)
+ QML_V4_BEGIN_INSTR(MulNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() *
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() *
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(MulReal, binaryop)
+ QML_V4_END_INSTR(MulNumber, binaryop)
- QML_V4_BEGIN_INSTR(DivReal, binaryop)
+ QML_V4_BEGIN_INSTR(DivNumber, binaryop)
{
- registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() /
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setnumber(registers[instr->binaryop.left].getnumber() /
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(DivReal, binaryop)
+ QML_V4_END_INSTR(DivNumber, binaryop)
- QML_V4_BEGIN_INSTR(ModReal, binaryop)
+ QML_V4_BEGIN_INSTR(ModNumber, binaryop)
{
Register &target = registers[instr->binaryop.output];
const Register &left = registers[instr->binaryop.left];
const Register &right = registers[instr->binaryop.right];
- if (QMetaType::QReal == QMetaType::Float)
- target.setqreal(::fmodf(left.getqreal(), right.getqreal()));
- else
- target.setqreal(::fmod(left.getqreal(), right.getqreal()));
+ target.setnumber(::fmod(left.getnumber(), right.getnumber()));
}
QML_V4_END_INSTR(ModInt, binaryop)
@@ -1378,61 +1336,61 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(URShiftInt, binaryop)
- QML_V4_BEGIN_INSTR(GtReal, binaryop)
+ QML_V4_BEGIN_INSTR(GtNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(GtReal, binaryop)
+ QML_V4_END_INSTR(GtNumber, binaryop)
- QML_V4_BEGIN_INSTR(LtReal, binaryop)
+ QML_V4_BEGIN_INSTR(LtNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(LtReal, binaryop)
+ QML_V4_END_INSTR(LtNumber, binaryop)
- QML_V4_BEGIN_INSTR(GeReal, binaryop)
+ QML_V4_BEGIN_INSTR(GeNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() >=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(GeReal, binaryop)
+ QML_V4_END_INSTR(GeNumber, binaryop)
- QML_V4_BEGIN_INSTR(LeReal, binaryop)
+ QML_V4_BEGIN_INSTR(LeNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() <=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(LeReal, binaryop)
+ QML_V4_END_INSTR(LeNumber, binaryop)
- QML_V4_BEGIN_INSTR(EqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(EqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(EqualReal, binaryop)
+ QML_V4_END_INSTR(EqualNumber, binaryop)
- QML_V4_BEGIN_INSTR(NotEqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(NotEqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(NotEqualReal, binaryop)
+ QML_V4_END_INSTR(NotEqualNumber, binaryop)
- QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(StrictEqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() ==
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(StrictEqualReal, binaryop)
+ QML_V4_END_INSTR(StrictEqualNumber, binaryop)
- QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop)
+ QML_V4_BEGIN_INSTR(StrictNotEqualNumber, binaryop)
{
- registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
- registers[instr->binaryop.right].getqreal());
+ registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getnumber() !=
+ registers[instr->binaryop.right].getnumber());
}
- QML_V4_END_INSTR(StrictNotEqualReal, binaryop)
+ QML_V4_END_INSTR(StrictNotEqualNumber, binaryop)
QML_V4_BEGIN_INSTR(GtString, binaryop)
{
@@ -1578,25 +1536,25 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
}
QML_V4_END_INSTR(StrictNotEqualObject, binaryop)
- QML_V4_BEGIN_INSTR(MathMaxReal, binaryop)
+ QML_V4_BEGIN_INSTR(MathMaxNumber, binaryop)
{
const Register &left = registers[instr->binaryop.left];
const Register &right = registers[instr->binaryop.right];
Register &output = registers[instr->binaryop.output];
if (left.isUndefined() || right.isUndefined()) output.setUndefined();
- else output.setqreal(qMax(left.getqreal(), right.getqreal()));
+ else output.setnumber(qMax(left.getnumber(), right.getnumber()));
}
- QML_V4_END_INSTR(MathMaxReal, binaryop)
+ QML_V4_END_INSTR(MathMaxNumber, binaryop)
- QML_V4_BEGIN_INSTR(MathMinReal, binaryop)
+ QML_V4_BEGIN_INSTR(MathMinNumber, binaryop)
{
const Register &left = registers[instr->binaryop.left];
const Register &right = registers[instr->binaryop.right];
Register &output = registers[instr->binaryop.output];
if (left.isUndefined() || right.isUndefined()) output.setUndefined();
- else output.setqreal(qMin(left.getqreal(), right.getqreal()));
+ else output.setnumber(qMin(left.getnumber(), right.getnumber()));
}
- QML_V4_END_INSTR(MathMinReal, binaryop)
+ QML_V4_END_INSTR(MathMinNumber, binaryop)
QML_V4_BEGIN_INSTR(NewString, construct)
{
@@ -1625,11 +1583,17 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
if (!object) {
THROW_EXCEPTION(instr->fetch.exceptionId);
} else {
- reg.init((Register::Type)instr->fetch.valueType);
+ const Register::Type valueType = (Register::Type)instr->fetch.valueType;
+ reg.init(valueType);
if (instr->fetch.valueType >= FirstCleanupType)
MARK_REGISTER(instr->fetch.reg);
void *argv[] = { reg.typeDataPtr(), 0 };
QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
+ if (valueType == FloatType) {
+ // promote floats
+ const double v = reg.getfloat();
+ reg.setnumber(v);
+ }
}
}
QML_V4_END_INSTR(Fetch, fetch)
@@ -1649,6 +1613,30 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
if (data.isUndefined())
THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value"));
+ if (data.gettype() == QObjectStarType) {
+ if (QObject *dataObject = data.getQObject()) {
+ const QMetaObject *dataMo = dataObject->metaObject();
+
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine);
+ QMetaProperty receiver = output->metaObject()->property(instr->store.index);
+ const QMetaObject *receiverMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, receiver.userType());
+
+ // Verify that these types are compatible
+ if (!QQmlPropertyPrivate::canConvert(dataMo, receiverMo)) {
+ THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign ") +
+ QLatin1String(dataMo->className()) +
+ QLatin1String(" to ") +
+ QLatin1String(receiverMo->className()));
+ }
+ }
+ }
+
+ if (instr->store.valueType == FloatType) {
+ // cast numbers to floats
+ const float v = (float) data.getnumber();
+ data.setfloat(v);
+ }
+
int status = -1;
void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
QMetaObject::metacall(output, QMetaObject::WriteProperty,
@@ -1687,22 +1675,14 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
executedBlocks |= instr->blockop.block;
QML_V4_END_INSTR(Block, blockop)
- // XXX not applicable in v8
- QML_V4_BEGIN_INSTR(InitString, initstring)
-// if (!identifiers[instr->initstring.offset].identifier) {
-// quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
-// QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
-
-// QString str = QString::fromRawData(strdata, len);
-
-// // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
-// }
- QML_V4_END_INSTR(InitString, initstring)
-
QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
registers[instr->cleanup.reg].cleanup();
QML_V4_END_INSTR(CleanupRegister, cleanup)
+ QML_V4_BEGIN_INSTR(Throw, throwop)
+ THROW_VALUE_EXCEPTION_STR(instr->throwop.exceptionId, *registers[instr->throwop.message].getstringptr());
+ QML_V4_END_INSTR(Throw, throwop)
+
#ifdef QML_THREADED_INTERPRETER
// nothing to do
#else
diff --git a/src/qml/qml/v4/qv4bindings_p.h b/src/qml/qml/v4/qv4bindings_p.h
index 1824fa4ee9..3a7d175d7b 100644
--- a/src/qml/qml/v4/qv4bindings_p.h
+++ b/src/qml/qml/v4/qv4bindings_p.h
@@ -141,9 +141,9 @@ private:
inline void subscribeId(QQmlContextData *p, int idIndex, int subIndex);
inline void subscribe(QObject *o, int notifyIndex, int subIndex);
- inline static qint32 toInt32(qreal n);
- static const qreal D32;
- static quint32 toUint32(qreal n);
+ inline static qint32 toInt32(double n);
+ static const double D32;
+ static quint32 toUint32(double n);
};
diff --git a/src/qml/qml/v4/qv4compiler.cpp b/src/qml/qml/v4/qv4compiler.cpp
index c9495e8987..045a14fbb5 100644
--- a/src/qml/qml/v4/qv4compiler.cpp
+++ b/src/qml/qml/v4/qv4compiler.cpp
@@ -62,7 +62,9 @@ static bool qmlEnableV4 = true;
using namespace QQmlJS;
QV4CompilerPrivate::QV4CompilerPrivate()
- : _function(0) , _block(0) , _discarded(false), registerCount(0)
+ : subscriptionOffset(0)
+ , _function(0) , _block(0) , _discarded(false), registerCount(0)
+ , bindingLine(0), bindingColumn(0)
{
}
@@ -73,6 +75,8 @@ void QV4CompilerPrivate::trace(int line, int column)
{
bytecode.clear();
+ this->bindingLine = line;
+ this->bindingColumn = column;
this->currentReg = _function->tempCount;
this->registerCount = qMax(this->registerCount, this->currentReg);
@@ -226,8 +230,9 @@ void QV4CompilerPrivate::visitConst(IR::Const *e)
gen(i);
} break;
- case IR::RealType: {
- Instr::LoadReal i;
+ case IR::FloatType:
+ case IR::NumberType: {
+ Instr::LoadNumber i;
i.reg = currentReg;
i.value = e->value;
gen(i);
@@ -316,7 +321,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
Instr::LoadAttached attached;
attached.output = currentReg;
attached.reg = currentReg;
- attached.exceptionId = exceptionId(e->line, e->column);
+ attached.exceptionId = exceptionId(bindingLine, bindingColumn);
if (e->declarativeType->attachedPropertiesId() == -1)
discard();
attached.id = e->declarativeType->attachedPropertiesId();
@@ -351,8 +356,11 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
QQmlRegisterType regType;
switch (propTy) {
- case QMetaType::QReal:
- regType = QRealType;
+ case QMetaType::Float:
+ regType = FloatType;
+ break;
+ case QMetaType::Double:
+ regType = NumberType;
break;
case QMetaType::Bool:
regType = BoolType;
@@ -373,7 +381,7 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
default:
if (propTy == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
regType = PODValueType;
- } else if (QQmlMetaType::isQObject(propTy)) {
+ } else if (engine->metaObjectForType(propTy)) {
regType = QObjectStarType;
} else {
if (qmlVerboseCompiler())
@@ -458,14 +466,14 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e)
} break;
case IR::OpUMinus:
- if (e->expr->type == IR::RealType) {
- Instr::UnaryMinusReal i;
+ if (IR::isRealType(e->expr->type)) {
+ Instr::UnaryMinusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
} else if (e->expr->type == IR::IntType) {
- convertToReal(e->expr, currentReg);
- Instr::UnaryMinusReal i;
+ convertToNumber(e->expr, currentReg);
+ Instr::UnaryMinusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
@@ -475,14 +483,14 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e)
break;
case IR::OpUPlus:
- if (e->expr->type == IR::RealType) {
- Instr::UnaryPlusReal i;
+ if (IR::isRealType(e->expr->type)) {
+ Instr::UnaryPlusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
} else if (e->expr->type == IR::IntType) {
- convertToReal(e->expr, currentReg);
- Instr::UnaryPlusReal i;
+ convertToNumber(e->expr, currentReg);
+ Instr::UnaryPlusNumber i;
i.output = currentReg;
i.src = src;
gen(i);
@@ -522,25 +530,26 @@ void QV4CompilerPrivate::visitUnop(IR::Unop *e)
} // switch
}
-void QV4CompilerPrivate::convertToReal(IR::Expr *expr, int reg)
+void QV4CompilerPrivate::convertToNumber(IR::Expr *expr, int reg)
{
- if (expr->type == IR::RealType)
+ if (expr->type == IR::NumberType)
return;
switch (expr->type) {
case IR::BoolType: {
- Instr::ConvertBoolToReal i;
+ Instr::ConvertBoolToNumber i;
i.output = i.src = reg;
gen(i);
} break;
case IR::IntType: {
- Instr::ConvertIntToReal i;
+ Instr::ConvertIntToNumber i;
i.output = i.src = reg;
gen(i);
} break;
- case IR::RealType:
+ case IR::FloatType:
+ case IR::NumberType:
// nothing to do
return;
@@ -566,8 +575,9 @@ void QV4CompilerPrivate::convertToInt(IR::Expr *expr, int reg)
// nothing to do
return;
- case IR::RealType: {
- Instr::ConvertRealToInt i;
+ case IR::FloatType:
+ case IR::NumberType: {
+ Instr::ConvertNumberToInt i;
i.output = i.src = reg;
gen(i);
} break;
@@ -594,8 +604,9 @@ void QV4CompilerPrivate::convertToBool(IR::Expr *expr, int reg)
gen(i);
} break;
- case IR::RealType: {
- Instr::ConvertRealToBool i;
+ case IR::FloatType:
+ case IR::NumberType: {
+ Instr::ConvertNumberToBool i;
i.output = i.src = reg;
gen(i);
} return;
@@ -643,19 +654,19 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e)
case IR::OpAdd:
if (e->type == IR::StringType)
return V4Instr::AddString;
- return V4Instr::AddReal;
+ return V4Instr::AddNumber;
case IR::OpSub:
- return V4Instr::SubReal;
+ return V4Instr::SubNumber;
case IR::OpMul:
- return V4Instr::MulReal;
+ return V4Instr::MulNumber;
case IR::OpDiv:
- return V4Instr::DivReal;
+ return V4Instr::DivNumber;
case IR::OpMod:
- return V4Instr::ModReal;
+ return V4Instr::ModNumber;
case IR::OpLShift:
return V4Instr::LShiftInt;
@@ -669,50 +680,50 @@ quint8 QV4CompilerPrivate::instructionOpcode(IR::Binop *e)
case IR::OpGt:
if (e->left->type == IR::StringType)
return V4Instr::GtString;
- return V4Instr::GtReal;
+ return V4Instr::GtNumber;
case IR::OpLt:
if (e->left->type == IR::StringType)
return V4Instr::LtString;
- return V4Instr::LtReal;
+ return V4Instr::LtNumber;
case IR::OpGe:
if (e->left->type == IR::StringType)
return V4Instr::GeString;
- return V4Instr::GeReal;
+ return V4Instr::GeNumber;
case IR::OpLe:
if (e->left->type == IR::StringType)
return V4Instr::LeString;
- return V4Instr::LeReal;
+ return V4Instr::LeNumber;
case IR::OpEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::EqualObject;
if (e->left->type == IR::StringType)
return V4Instr::EqualString;
- return V4Instr::EqualReal;
+ return V4Instr::EqualNumber;
case IR::OpNotEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::NotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::NotEqualString;
- return V4Instr::NotEqualReal;
+ return V4Instr::NotEqualNumber;
case IR::OpStrictEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::StrictEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictEqualString;
- return V4Instr::StrictEqualReal;
+ return V4Instr::StrictEqualNumber;
case IR::OpStrictNotEqual:
if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
return V4Instr::StrictNotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictNotEqualString;
- return V4Instr::StrictNotEqualReal;
+ return V4Instr::StrictNotEqualNumber;
case IR::OpAnd:
case IR::OpOr:
@@ -733,12 +744,26 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
int left = currentReg;
int right = currentReg + 1;
- traceExpression(e->left, left);
- traceExpression(e->right, right);
+ if (e->left->asTemp() && e->type != IR::StringType)
+ left = e->left->asTemp()->index;
+ else
+ traceExpression(e->left, left);
- // At this point it is possible that the type of the
- // subexpressions is different. This can happen because
- // we keep BINOP expressions in HIR.
+ if (IR::Temp *t = e->right->asTemp())
+ right = t->index;
+ else
+ traceExpression(e->right, right);
+
+ if (e->left->type != e->right->type) {
+ if (qmlVerboseCompiler())
+ qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op)
+ << "(`" << IR::binaryOperator(e->left->type)
+ << "' and `"
+ << IR::binaryOperator(e->right->type)
+ << "'";
+ discard();
+ return;
+ }
switch (e->op) {
case IR::OpInvalid:
@@ -766,8 +791,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
case IR::OpAdd:
if (e->type != IR::StringType) {
- convertToReal(e->left, left);
- convertToReal(e->right, right);
+ convertToNumber(e->left, left);
+ convertToNumber(e->right, right);
}
break;
@@ -775,8 +800,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
case IR::OpMul:
case IR::OpDiv:
case IR::OpMod:
- convertToReal(e->left, left);
- convertToReal(e->right, right);
+ convertToNumber(e->left, left);
+ convertToNumber(e->right, right);
break;
case IR::OpGt:
@@ -788,8 +813,8 @@ void QV4CompilerPrivate::visitBinop(IR::Binop *e)
case IR::OpStrictEqual:
case IR::OpStrictNotEqual:
if (e->left->type >= IR::FirstNumberType) {
- convertToReal(e->left, left);
- convertToReal(e->right, right);
+ convertToNumber(e->left, left);
+ convertToNumber(e->right, right);
}
break;
@@ -813,7 +838,7 @@ void QV4CompilerPrivate::visitCall(IR::Call *call)
{
if (IR::Name *name = call->base->asName()) {
IR::Expr *arg = call->onlyArgument();
- if (arg != 0 && arg->type == IR::RealType) {
+ if (arg != 0 && IR::isRealType(arg->type)) {
traceExpression(arg, currentReg);
switch (name->builtin) {
@@ -821,37 +846,37 @@ void QV4CompilerPrivate::visitCall(IR::Call *call)
break;
case IR::MathSinBultinFunction: {
- Instr::MathSinReal i;
+ Instr::MathSinNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathCosBultinFunction: {
- Instr::MathCosReal i;
+ Instr::MathCosNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathAbsBuiltinFunction: {
- Instr::MathAbsReal i;
+ Instr::MathAbsNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathRoundBultinFunction: {
- Instr::MathRoundReal i;
+ Instr::MathRoundNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathFloorBultinFunction: {
- Instr::MathFloorReal i;
+ Instr::MathFloorNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
case IR::MathCeilBuiltinFunction: {
- Instr::MathCeilReal i;
+ Instr::MathCeilNumber i;
i.output = i.src = currentReg;
gen(i);
} return;
@@ -869,21 +894,21 @@ void QV4CompilerPrivate::visitCall(IR::Call *call)
IR::Expr *arg1 = call->args->expr;
IR::Expr *arg2 = call->args->next->expr;
- if (arg1 != 0 && arg1->type == IR::RealType &&
- arg2 != 0 && arg2->type == IR::RealType) {
+ if (arg1 != 0 && IR::isRealType(arg1->type) &&
+ arg2 != 0 && IR::isRealType(arg2->type)) {
traceExpression(arg1, currentReg);
traceExpression(arg2, currentReg + 1);
if (name->builtin == IR::MathMaxBuiltinFunction) {
- Instr::MathMaxReal i;
+ Instr::MathMaxNumber i;
i.left = currentReg;
i.right = currentReg + 1;
i.output = currentReg;
gen(i);
return;
} else if (name->builtin == IR::MathMinBuiltinFunction) {
- Instr::MathMinReal i;
+ Instr::MathMinNumber i;
i.left = currentReg;
i.right = currentReg + 1;
i.output = currentReg;
@@ -917,7 +942,17 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
quint8 dest = target->index;
- if (target->type != s->source->type) {
+ IR::Type targetTy = s->target->type;
+ IR::Type sourceTy = s->source->type;
+
+ // promote the floats
+ if (sourceTy == IR::FloatType)
+ sourceTy = IR::NumberType;
+
+ if (targetTy == IR::FloatType)
+ targetTy = IR::NumberType;
+
+ if (sourceTy != targetTy) {
quint8 src = dest;
if (IR::Temp *t = s->source->asTemp())
@@ -926,8 +961,6 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
traceExpression(s->source, dest);
V4Instr::Type opcode = V4Instr::Noop;
- IR::Type targetTy = s->target->type;
- IR::Type sourceTy = s->source->type;
if (sourceTy == IR::UrlType) {
switch (targetTy) {
@@ -937,13 +970,22 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
// url-to-xxx conversions.
break;
default: {
+ if (s->isMoveForReturn) {
+ V4Instr instr;
+ instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn);
+ registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2")
+ .arg(QLatin1String(IR::typeName(sourceTy)))
+ .arg(QLatin1String(IR::typeName(targetTy)))));
+ instr.throwop.message = dest;
+ gen(V4Instr::Throw, instr);
+ return;
+ }
// generate a UrlToString conversion and fix
// the type of the source expression.
V4Instr conv;
- conv.unaryop.output = V4Instr::ConvertUrlToString;
+ conv.unaryop.output = src;
conv.unaryop.src = src;
- gen(opcode, conv);
-
+ gen(V4Instr::ConvertUrlToString, conv);
sourceTy = IR::StringType;
break;
}
@@ -953,7 +995,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
if (targetTy == IR::BoolType) {
switch (sourceTy) {
case IR::IntType: opcode = V4Instr::ConvertIntToBool; break;
- case IR::RealType: opcode = V4Instr::ConvertRealToBool; break;
+ case IR::NumberType: opcode = V4Instr::ConvertNumberToBool; break;
case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break;
case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break;
@@ -963,33 +1005,44 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
} else if (targetTy == IR::IntType) {
switch (sourceTy) {
case IR::BoolType: opcode = V4Instr::ConvertBoolToInt; break;
- case IR::RealType: {
+ case IR::NumberType: {
if (s->isMoveForReturn)
- opcode = V4Instr::MathRoundReal;
+ opcode = V4Instr::MathRoundNumber;
else
- opcode = V4Instr::ConvertRealToInt;
+ opcode = V4Instr::ConvertNumberToInt;
break;
}
case IR::StringType: opcode = V4Instr::ConvertStringToInt; break;
default: break;
} // switch
- } else if (targetTy == IR::RealType) {
+ } else if (IR::isRealType(targetTy)) {
switch (sourceTy) {
- case IR::BoolType: opcode = V4Instr::ConvertBoolToReal; break;
- case IR::IntType: opcode = V4Instr::ConvertIntToReal; break;
- case IR::StringType: opcode = V4Instr::ConvertStringToReal; break;
+ case IR::BoolType: opcode = V4Instr::ConvertBoolToNumber; break;
+ case IR::IntType: opcode = V4Instr::ConvertIntToNumber; break;
+ case IR::StringType: opcode = V4Instr::ConvertStringToNumber; break;
default: break;
} // switch
} else if (targetTy == IR::StringType) {
switch (sourceTy) {
case IR::BoolType: opcode = V4Instr::ConvertBoolToString; break;
case IR::IntType: opcode = V4Instr::ConvertIntToString; break;
- case IR::RealType: opcode = V4Instr::ConvertRealToString; break;
+ case IR::NumberType: opcode = V4Instr::ConvertNumberToString; break;
case IR::UrlType: opcode = V4Instr::ConvertUrlToString; break;
case IR::ColorType: opcode = V4Instr::ConvertColorToString; break;
default: break;
} // switch
} else if (targetTy == IR::UrlType) {
+ if (s->isMoveForReturn && sourceTy != IR::StringType) {
+ V4Instr instr;
+ instr.throwop.exceptionId = exceptionId(bindingLine, bindingColumn);
+ registerLiteralString(dest, _function->newString(QString::fromUtf8("Unable to assign %1 to %2")
+ .arg(QLatin1String(IR::typeName(sourceTy)))
+ .arg(QLatin1String(IR::typeName(targetTy)))));
+ instr.throwop.message = dest;
+ gen(V4Instr::Throw, instr);
+ return;
+ }
+
V4Instr convToString;
convToString.unaryop.output = dest;
convToString.unaryop.src = src;
@@ -998,7 +1051,7 @@ void QV4CompilerPrivate::visitMove(IR::Move *s)
switch (sourceTy) {
case IR::BoolType: gen(V4Instr::ConvertBoolToString, convToString); sourceTy = IR::StringType; break;
case IR::IntType: gen(V4Instr::ConvertIntToString, convToString); sourceTy = IR::StringType; break;
- case IR::RealType: gen(V4Instr::ConvertRealToString, convToString); sourceTy = IR::StringType; break;
+ case IR::NumberType: gen(V4Instr::ConvertNumberToString, convToString); sourceTy = IR::StringType; break;
case IR::ColorType: gen(V4Instr::ConvertColorToString, convToString); sourceTy = IR::StringType; break;
default: break;
} // switch
@@ -1094,8 +1147,9 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s)
case IR::IntType:
test.regType = QMetaType::Int;
break;
- case IR::RealType:
- test.regType = QMetaType::QReal;
+ case IR::FloatType:
+ case IR::NumberType:
+ test.regType = QMetaType::Double;
break;
default:
discard();
@@ -1108,6 +1162,7 @@ void QV4CompilerPrivate::visitRet(IR::Ret *s)
store.output = 0;
store.index = expression->property->index;
store.reg = storeReg;
+ store.valueType = s->type == IR::FloatType ? FloatType : 0;
store.exceptionId = exceptionId(s->line, s->column);
gen(store);
}
@@ -1119,7 +1174,6 @@ void QV4Compiler::dump(const QByteArray &programData)
qWarning() << "Program.bindings:" << program->bindings;
qWarning() << "Program.dataLength:" << program->dataLength;
qWarning() << "Program.subscriptions:" << program->subscriptions;
- qWarning() << "Program.indentifiers:" << program->identifiers;
const int programSize = program->instructionCount;
const char *start = program->instructions();
@@ -1137,8 +1191,8 @@ void QV4CompilerPrivate::resetInstanceState()
data = committed.data;
exceptions = committed.exceptions;
usedSubscriptionIds.clear();
- subscriptionIds = committed.subscriptionIds;
- registeredStrings = committed.registeredStrings;
+ subscriptionIds.clear();
+ subscriptionOffset = committed.subscriptionCount;
bytecode.clear();
patches.clear();
pool.clear();
@@ -1159,8 +1213,9 @@ int QV4CompilerPrivate::commitCompile()
committed.bytecode.append(bytecode.constData(), bytecode.size());
committed.data = data;
committed.exceptions = exceptions;
- committed.subscriptionIds = subscriptionIds;
- committed.registeredStrings = registeredStrings;
+ committed.subscriptionCount = subscriptionOffset + subscriptionIds.count();
+ if (bindingsDump())
+ committed.subscriptions.append(subscriptionIds);
return rv;
}
@@ -1212,7 +1267,7 @@ bool QV4CompilerPrivate::compile(QQmlJS::AST::Node *node)
qerr << endl;
}
- if (discarded || subscriptionIds.count() > 0xFFFF || registeredStrings.count() > 0xFFFF || registerCount > 31)
+ if (discarded || subscriptionIds.count() > 0xFFFF || registerCount > 31)
return false;
return true;
@@ -1236,32 +1291,6 @@ int QV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str)
return reg;
}
-// Returns an identifier offset
-int QV4CompilerPrivate::registerString(const QString &string)
-{
- Q_ASSERT(!string.isEmpty());
-
- QPair<int, int> *iter = registeredStrings.value(string);
-
- if (!iter) {
- quint32 len = string.length();
- QByteArray lendata((const char *)&len, sizeof(quint32));
- QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar));
- strdata.prepend(lendata);
- int rv = data.count();
- data += strdata;
-
- iter = &registeredStrings[string];
- *iter = qMakePair(registeredStrings.count(), rv);
- }
-
- Instr::InitString reg;
- reg.offset = iter->first;
- reg.dataIdx = iter->second;
- gen(reg);
- return reg.offset;
-}
-
/*!
Returns true if the current expression has not already subscribed to \a sub in currentBlockMask.
*/
@@ -1285,7 +1314,7 @@ int QV4CompilerPrivate::subscriptionIndex(const QStringList &sub)
QString str = sub.join(QLatin1String("."));
int *iter = subscriptionIds.value(str);
if (!iter) {
- int count = subscriptionIds.count();
+ int count = subscriptionOffset + subscriptionIds.count();
iter = &subscriptionIds[str];
*iter = count;
}
@@ -1384,8 +1413,8 @@ QByteArray QV4CompilerPrivate::buildSignalTable() const
QVector<quint32> header;
QVector<quint32> data;
- for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) {
- header.append(committed.subscriptionIds.count() + data.count());
+ for (int ii = 0; ii < committed.subscriptionCount; ++ii) {
+ header.append(committed.subscriptionCount + data.count());
const QList<QPair<int, quint32> > &bindings = table[ii];
data.append(bindings.count());
for (int jj = 0; jj < bindings.count(); ++jj) {
@@ -1443,8 +1472,7 @@ QByteArray QV4Compiler::program() const
data += d->buildExceptionData();
prog.dataLength = 4 * ((data.size() + 3) / 4);
- prog.subscriptions = d->committed.subscriptionIds.count();
- prog.identifiers = d->committed.registeredStrings.count();
+ prog.subscriptions = d->committed.subscriptionCount;
prog.instructionCount = bytecode.count();
int size = sizeof(QV4Program) + bytecode.count();
size += prog.dataLength;
@@ -1461,12 +1489,13 @@ QByteArray QV4Compiler::program() const
if (bindingsDump()) {
qWarning().nospace() << "Subscription slots:";
- for (QQmlAssociationList<QString, int>::ConstIterator iter = d->committed.subscriptionIds.begin();
- iter != d->committed.subscriptionIds.end();
- ++iter) {
- qWarning().nospace() << " " << iter->first << "\t-> " << iter->second;
+ QQmlAssociationList<QString, int> subscriptionIds;
+ foreach (subscriptionIds, d->committed.subscriptions) {
+ for (QQmlAssociationList<QString, int>::ConstIterator iter = subscriptionIds.begin();
+ iter != subscriptionIds.end(); ++iter) {
+ qWarning().nospace() << " " << iter->first << "\t-> " << iter->second;
+ }
}
-
QV4Compiler::dump(programData);
}
diff --git a/src/qml/qml/v4/qv4compiler_p_p.h b/src/qml/qml/v4/qv4compiler_p_p.h
index a9209d978f..0c06ade87f 100644
--- a/src/qml/qml/v4/qv4compiler_p_p.h
+++ b/src/qml/qml/v4/qv4compiler_p_p.h
@@ -128,8 +128,6 @@ public:
bool compile(QQmlJS::AST::Node *);
int registerLiteralString(quint8 reg, const QStringRef &);
- int registerString(const QString &);
- QQmlAssociationList<QString, QPair<int, int> > registeredStrings;
QByteArray data;
bool blockNeedsSubscription(const QStringList &);
@@ -141,7 +139,7 @@ public:
QVector<quint64> exceptions;
QQmlAssociationList<int, quint32> usedSubscriptionIds;
-
+ int subscriptionOffset;
QQmlAssociationList<QString, int> subscriptionIds;
QQmlJS::Bytecode bytecode;
@@ -156,17 +154,17 @@ public:
QQmlPool pool;
// Committed binding data
- struct {
+ struct Committed {
+ Committed(): subscriptionCount(0) {}
QList<int> offsets;
QList<QQmlAssociationList<int, quint32> > dependencies;
//QQmlJS::Bytecode bytecode;
QByteArray bytecode;
QByteArray data;
- QQmlAssociationList<QString, int> subscriptionIds;
QVector<quint64> exceptions;
-
- QQmlAssociationList<QString, QPair<int, int> > registeredStrings;
+ int subscriptionCount;
+ QList<QQmlAssociationList<QString, int> > subscriptions;
int count() const { return offsets.count(); }
} committed;
@@ -174,7 +172,7 @@ public:
QByteArray buildSignalTable() const;
QByteArray buildExceptionData() const;
- void convertToReal(QQmlJS::IR::Expr *expr, int reg);
+ void convertToNumber(QQmlJS::IR::Expr *expr, int reg);
void convertToInt(QQmlJS::IR::Expr *expr, int reg);
void convertToBool(QQmlJS::IR::Expr *expr, int reg);
quint8 instructionOpcode(QQmlJS::IR::Binop *e);
@@ -235,6 +233,8 @@ private:
bool usedSubscriptionIdsChanged;
quint32 currentBlockMask;
+ int bindingLine;
+ int bindingColumn;
};
diff --git a/src/qml/qml/v4/qv4instruction.cpp b/src/qml/qml/v4/qv4instruction.cpp
index cb6ff40589..ecd4f01ef3 100644
--- a/src/qml/qml/v4/qv4instruction.cpp
+++ b/src/qml/qml/v4/qv4instruction.cpp
@@ -123,14 +123,14 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::UnaryNot:
INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::UnaryMinusReal:
- INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::UnaryMinusNumber:
+ INSTR_DUMP << "\t" << "UnaryMinusNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::UnaryMinusInt:
INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::UnaryPlusReal:
- INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::UnaryPlusNumber:
+ INSTR_DUMP << "\t" << "UnaryPlusNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::UnaryPlusInt:
INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -138,8 +138,8 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertBoolToInt:
INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertBoolToReal:
- INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertBoolToNumber:
+ INSTR_DUMP << "\t" << "ConvertBoolToNumber" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertBoolToString:
INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -147,20 +147,20 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertIntToBool:
INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertIntToReal:
- INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertIntToNumber:
+ INSTR_DUMP << "\t" << "ConvertIntToNumber" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertIntToString:
INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertRealToBool:
- INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertNumberToBool:
+ INSTR_DUMP << "\t" << "ConvertNumberToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertRealToInt:
- INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertNumberToInt:
+ INSTR_DUMP << "\t" << "ConvertNumberToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertRealToString:
- INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertNumberToString:
+ INSTR_DUMP << "\t" << "ConvertNumberToString" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertStringToBool:
INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -168,8 +168,8 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ConvertStringToInt:
INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::ConvertStringToReal:
- INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::ConvertStringToNumber:
+ INSTR_DUMP << "\t" << "ConvertStringToNumber" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::ConvertStringToUrl:
INSTR_DUMP << "\t" << "ConvertStringToUrl" << "\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
@@ -198,32 +198,32 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::ResolveUrl:
INSTR_DUMP << "\t" << "ResolveUrl" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathSinReal:
- INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathSinNumber:
+ INSTR_DUMP << "\t" << "MathSinNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathCosReal:
- INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathCosNumber:
+ INSTR_DUMP << "\t" << "MathCosNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathAbsReal:
- INSTR_DUMP << "\t" << "MathAbsReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathAbsNumber:
+ INSTR_DUMP << "\t" << "MathAbsNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathRoundReal:
- INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathRoundNumber:
+ INSTR_DUMP << "\t" << "MathRoundNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathFloorReal:
- INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathFloorNumber:
+ INSTR_DUMP << "\t" << "MathFloorNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathCeilReal:
- INSTR_DUMP << "\t" << "MathCeilReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathCeilNumber:
+ INSTR_DUMP << "\t" << "MathCeilNumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
- case V4Instr::MathPIReal:
- INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
+ case V4Instr::MathPINumber:
+ INSTR_DUMP << "\t" << "MathPINumber" << "\t\t" << "Input_Reg(" << i->unaryop.src << ") -> Output_Reg(" << i->unaryop.output << ")";
break;
case V4Instr::LoadNull:
INSTR_DUMP << "\t" << "LoadNull" << "\t\t" << "Constant(null) -> Output_Reg(" << i->null_value.reg << ")";
break;
- case V4Instr::LoadReal:
- INSTR_DUMP << "\t" << "LoadReal" << "\t\t" << "Constant(" << i->real_value.value << ") -> Output_Reg(" << i->real_value.reg << ")";
+ case V4Instr::LoadNumber:
+ INSTR_DUMP << "\t" << "LoadNumber" << "\t\t" << "Constant(" << i->number_value.value << ") -> Output_Reg(" << i->number_value.reg << ")";
break;
case V4Instr::LoadInt:
INSTR_DUMP << "\t" << "LoadInt" << "\t\t\t" << "Constant(" << i->int_value.value << ") -> Output_Reg(" << i->int_value.reg << ")";
@@ -249,23 +249,23 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::BitXorInt:
INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::AddReal:
- INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::AddNumber:
+ INSTR_DUMP << "\t" << "AddNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::AddString:
INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::SubReal:
- INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::SubNumber:
+ INSTR_DUMP << "\t" << "SubNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::MulReal:
- INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::MulNumber:
+ INSTR_DUMP << "\t" << "MulNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::DivReal:
- INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::DivNumber:
+ INSTR_DUMP << "\t" << "DivNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::ModReal:
- INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::ModNumber:
+ INSTR_DUMP << "\t" << "ModNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::LShiftInt:
INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
@@ -276,29 +276,29 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::URShiftInt:
INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::GtReal:
- INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::GtNumber:
+ INSTR_DUMP << "\t" << "GtNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::LtReal:
- INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::LtNumber:
+ INSTR_DUMP << "\t" << "LtNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::GeReal:
- INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::GeNumber:
+ INSTR_DUMP << "\t" << "GeNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::LeReal:
- INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::LeNumber:
+ INSTR_DUMP << "\t" << "LeNumber" << "\t\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::EqualReal:
- INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::EqualNumber:
+ INSTR_DUMP << "\t" << "EqualNumber" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::NotEqualReal:
- INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::NotEqualNumber:
+ INSTR_DUMP << "\t" << "NotEqualNumber" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::StrictEqualReal:
- INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::StrictEqualNumber:
+ INSTR_DUMP << "\t" << "StrictEqualNumber" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::StrictNotEqualReal:
- INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::StrictNotEqualNumber:
+ INSTR_DUMP << "\t" << "StrictNotEqualNumber" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::GtString:
INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
@@ -336,11 +336,11 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::StrictNotEqualObject:
INSTR_DUMP << "\t" << "StrictNotEqualObject" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::MathMaxReal:
- INSTR_DUMP << "\t" << "MathMaxReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::MathMaxNumber:
+ INSTR_DUMP << "\t" << "MathMaxNumber" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
- case V4Instr::MathMinReal:
- INSTR_DUMP << "\t" << "MathMinReal" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
+ case V4Instr::MathMinNumber:
+ INSTR_DUMP << "\t" << "MathMinNumber" << "\t" << "Input_Reg(" << i->binaryop.left << ") Input_Reg(" << i->binaryop.right << ") -> Output_Reg(" << i->binaryop.output << ")";
break;
case V4Instr::NewString:
INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << i->construct.reg << ")";
@@ -376,12 +376,12 @@ void Bytecode::dump(const V4Instr *i, int address) const
case V4Instr::Branch:
INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + i->branchop.offset) << ")";
break;
- case V4Instr::InitString:
- INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << i->initstring.dataIdx << ") -> String_Slot(" << i->initstring.offset << ")";
- break;
case V4Instr::Block:
INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(i->blockop.block, 16).constData() << ")";
break;
+ case V4Instr::Throw:
+ INSTR_DUMP << "\t" << "Throw" << "\t\t\t" << "InputReg(" << i->throwop.message << ")";
+ break;
default:
INSTR_DUMP << "\t" << "Unknown";
break;
diff --git a/src/qml/qml/v4/qv4instruction_p.h b/src/qml/qml/v4/qv4instruction_p.h
index 239cb362cc..310bfbaff5 100644
--- a/src/qml/qml/v4/qv4instruction_p.h
+++ b/src/qml/qml/v4/qv4instruction_p.h
@@ -76,22 +76,22 @@ QT_BEGIN_NAMESPACE
F(LoadModuleObject, load) \
F(LoadAttached, attached) \
F(UnaryNot, unaryop) \
- F(UnaryMinusReal, unaryop) \
+ F(UnaryMinusNumber, unaryop) \
F(UnaryMinusInt, unaryop) \
- F(UnaryPlusReal, unaryop) \
+ F(UnaryPlusNumber, unaryop) \
F(UnaryPlusInt, unaryop) \
F(ConvertBoolToInt, unaryop) \
- F(ConvertBoolToReal, unaryop) \
+ F(ConvertBoolToNumber, unaryop) \
F(ConvertBoolToString, unaryop) \
F(ConvertIntToBool, unaryop) \
- F(ConvertIntToReal, unaryop) \
+ F(ConvertIntToNumber, unaryop) \
F(ConvertIntToString, unaryop) \
- F(ConvertRealToBool, unaryop) \
- F(ConvertRealToInt, unaryop) \
- F(ConvertRealToString, unaryop) \
+ F(ConvertNumberToBool, unaryop) \
+ F(ConvertNumberToInt, unaryop) \
+ F(ConvertNumberToString, unaryop) \
F(ConvertStringToBool, unaryop) \
F(ConvertStringToInt, unaryop) \
- F(ConvertStringToReal, unaryop) \
+ F(ConvertStringToNumber, unaryop) \
F(ConvertStringToUrl, unaryop) \
F(ConvertStringToColor, unaryop) \
F(ConvertUrlToBool, unaryop) \
@@ -101,15 +101,15 @@ QT_BEGIN_NAMESPACE
F(ConvertObjectToBool, unaryop) \
F(ConvertNullToObject, unaryop) \
F(ResolveUrl, unaryop) \
- F(MathSinReal, unaryop) \
- F(MathCosReal, unaryop) \
- F(MathAbsReal, unaryop) \
- F(MathRoundReal, unaryop) \
- F(MathFloorReal, unaryop) \
- F(MathCeilReal, unaryop) \
- F(MathPIReal, unaryop) \
+ F(MathSinNumber, unaryop) \
+ F(MathCosNumber, unaryop) \
+ F(MathAbsNumber, unaryop) \
+ F(MathRoundNumber, unaryop) \
+ F(MathFloorNumber, unaryop) \
+ F(MathCeilNumber, unaryop) \
+ F(MathPINumber, unaryop) \
F(LoadNull, null_value) \
- F(LoadReal, real_value) \
+ F(LoadNumber, number_value) \
F(LoadInt, int_value) \
F(LoadBool, bool_value) \
F(LoadString, string_value) \
@@ -118,23 +118,23 @@ QT_BEGIN_NAMESPACE
F(BitAndInt, binaryop) \
F(BitOrInt, binaryop) \
F(BitXorInt, binaryop) \
- F(AddReal, binaryop) \
+ F(AddNumber, binaryop) \
F(AddString, binaryop) \
- F(SubReal, binaryop) \
- F(MulReal, binaryop) \
- F(DivReal, binaryop) \
- F(ModReal, binaryop) \
+ F(SubNumber, binaryop) \
+ F(MulNumber, binaryop) \
+ F(DivNumber, binaryop) \
+ F(ModNumber, binaryop) \
F(LShiftInt, binaryop) \
F(RShiftInt, binaryop) \
F(URShiftInt, binaryop) \
- F(GtReal, binaryop) \
- F(LtReal, binaryop) \
- F(GeReal, binaryop) \
- F(LeReal, binaryop) \
- F(EqualReal, binaryop) \
- F(NotEqualReal, binaryop) \
- F(StrictEqualReal, binaryop) \
- F(StrictNotEqualReal, binaryop) \
+ F(GtNumber, binaryop) \
+ F(LtNumber, binaryop) \
+ F(GeNumber, binaryop) \
+ F(LeNumber, binaryop) \
+ F(EqualNumber, binaryop) \
+ F(NotEqualNumber, binaryop) \
+ F(StrictEqualNumber, binaryop) \
+ F(StrictNotEqualNumber, binaryop) \
F(GtString, binaryop) \
F(LtString, binaryop) \
F(GeString, binaryop) \
@@ -147,8 +147,8 @@ QT_BEGIN_NAMESPACE
F(NotEqualObject, binaryop) \
F(StrictEqualObject, binaryop) \
F(StrictNotEqualObject, binaryop) \
- F(MathMaxReal, binaryop) \
- F(MathMinReal, binaryop) \
+ F(MathMaxNumber, binaryop) \
+ F(MathMinNumber, binaryop) \
F(NewString, construct) \
F(NewUrl, construct) \
F(CleanupRegister, cleanup) \
@@ -160,8 +160,7 @@ QT_BEGIN_NAMESPACE
F(BranchFalse, branchop) \
F(Branch, branchop) \
F(Block, blockop) \
- /* Speculative property resolution */ \
- F(InitString, initstring)
+ F(Throw, throwop)
#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
# define QML_THREADED_INTERPRETER
@@ -192,7 +191,7 @@ class QQmlNotifier;
namespace QQmlJS {
-union V4Instr {
+union Q_AUTOTEST_EXPORT V4Instr {
enum Type {
FOR_EACH_V4_INSTR(QML_V4_INSTR_ENUM)
};
@@ -241,6 +240,7 @@ union V4Instr {
qint8 output;
qint8 reg;
quint8 exceptionId;
+ quint8 valueType;
quint32 index;
};
@@ -283,10 +283,10 @@ union V4Instr {
qint8 reg;
};
- struct instr_real_value {
+ struct instr_number_value {
QML_V4_INSTR_HEADER
qint8 reg;
- qreal value; // XXX Makes the instruction 12 bytes
+ double value; // XXX Makes the instruction 12 bytes
};
struct instr_int_value {
@@ -358,6 +358,12 @@ union V4Instr {
quint32 block;
};
+ struct instr_throwop {
+ QML_V4_INSTR_HEADER
+ quint8 exceptionId;
+ quint32 message;
+ };
+
instr_common common;
instr_id id;
instr_init init;
@@ -371,7 +377,7 @@ union V4Instr {
instr_copy copy;
instr_construct construct;
instr_null_value null_value;
- instr_real_value real_value;
+ instr_number_value number_value;
instr_int_value int_value;
instr_bool_value bool_value;
instr_string_value string_value;
@@ -383,6 +389,7 @@ union V4Instr {
instr_initstring initstring;
instr_branchop branchop;
instr_blockop blockop;
+ instr_throwop throwop;
};
template<int N>
@@ -400,11 +407,11 @@ FOR_EACH_V4_INSTR(QML_V4_INSTR_META_TEMPLATE);
#undef QML_V4_INSTR_META_TEMPLATE
template<int Instr>
-class V4InstrData : public V4InstrMeta<Instr>::DataType
+class Q_AUTOTEST_EXPORT V4InstrData : public V4InstrMeta<Instr>::DataType
{
};
-class Bytecode
+class Q_AUTOTEST_EXPORT Bytecode
{
Q_DISABLE_COPY(Bytecode)
diff --git a/src/qml/qml/v4/qv4ir.cpp b/src/qml/qml/v4/qv4ir.cpp
index 34245f5bf4..ba0faec80e 100644
--- a/src/qml/qml/v4/qv4ir.cpp
+++ b/src/qml/qml/v4/qv4ir.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace IR {
-inline const char *typeName(Type t)
+const char *typeName(Type t)
{
switch (t) {
case InvalidType: return "invalid";
@@ -58,15 +58,15 @@ inline const char *typeName(Type t)
case NullType: return "null";
case VoidType: return "void";
case StringType: return "string";
- case UrlType: return "url";
- case ColorType: return "color";
+ case UrlType: return "QUrl";
+ case ColorType: return "QColor";
case SGAnchorLineType: return "SGAnchorLine";
case AttachType: return "AttachType";
case ObjectType: return "object";
case BoolType: return "bool";
case IntType: return "int";
- case RealType: return "qreal";
- case RealNaNType: return "NaN";
+ case FloatType: return "float";
+ case NumberType: return "number";
default: return "invalid";
}
}
@@ -91,15 +91,20 @@ IR::Type maxType(IR::Type left, IR::Type right)
return IR::StringType;
} else if (left == right)
return left;
- else if (isNumberType(left) && isNumberType(right))
- return qMax(left, right);
- else if ((isNumberType(left) && isStringType(right)) ||
+ else if (isNumberType(left) && isNumberType(right)) {
+ IR::Type ty = qMax(left, right);
+ return ty == FloatType ? NumberType : ty; // promote floats
+ } else if ((isNumberType(left) && isStringType(right)) ||
(isNumberType(right) && isStringType(left)))
return IR::StringType;
else
return IR::InvalidType;
}
+bool isRealType(IR::Type type)
+{
+ return type == IR::NumberType || type == IR::FloatType;
+}
const char *opname(AluOp op)
{
@@ -233,7 +238,7 @@ void Name::init(Name *base, Type type, const QString *id, Symbol symbol, quint32
builtin = MathMinBuiltinFunction;
} else if (id->length() == 7 && *id == QLatin1String("Math.PI")) {
builtin = MathPIBuiltinConstant;
- this->type = RealType;
+ this->type = NumberType;
}
}
@@ -267,7 +272,7 @@ Type Unop::typeForOp(AluOp op, Expr *expr)
case OpUMinus:
case OpUPlus:
case OpCompl:
- return maxType(expr->type, RealType);
+ return maxType(expr->type, NumberType);
default:
break;
@@ -309,13 +314,13 @@ Type Binop::typeForOp(AluOp op, Expr *left, Expr *right)
case OpAdd:
if (left->type == StringType)
return StringType;
- return RealType;
+ return NumberType;
case OpSub:
case OpMul:
case OpDiv:
case OpMod:
- return RealType;
+ return NumberType;
case OpLShift:
case OpRShift:
@@ -364,7 +369,7 @@ Type Call::typeForFunction(Expr *base)
case MathAbsBuiltinFunction: //### type could also be Int if input was Int
case MathMaxBuiltinFunction:
case MathMinBuiltinFunction:
- return RealType;
+ return NumberType;
case MathRoundBultinFunction:
case MathFloorBultinFunction:
@@ -601,6 +606,12 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
break;
}
}
+ } else if (op == OpAdd) {
+ if (String *s1 = left->asString()) {
+ if (String *s2 = right->asString()) {
+ return STRING(function->newString(s1->value.toString() + s2->value));
+ }
+ }
}
}
diff --git a/src/qml/qml/v4/qv4ir_p.h b/src/qml/qml/v4/qv4ir_p.h
index 4e9f9faacd..26bd43c406 100644
--- a/src/qml/qml/v4/qv4ir_p.h
+++ b/src/qml/qml/v4/qv4ir_p.h
@@ -150,10 +150,12 @@ enum Type {
FirstNumberType,
BoolType = FirstNumberType,
IntType,
- RealType,
- RealNaNType
+ FloatType,
+ NumberType
};
Type maxType(IR::Type left, IR::Type right);
+bool isRealType(IR::Type type);
+const char *typeName(IR::Type t);
struct ExprVisitor {
virtual ~ExprVisitor() {}
diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp
index 453120c6c7..31ed9a5a6a 100644
--- a/src/qml/qml/v4/qv4irbuilder.cpp
+++ b/src/qml/qml/v4/qv4irbuilder.cpp
@@ -61,8 +61,11 @@ static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine, const QM
case QMetaType::Int:
return IR::IntType;
- case QMetaType::QReal:
- return IR::RealType;
+ case QMetaType::Float:
+ return IR::FloatType;
+
+ case QMetaType::Double:
+ return IR::NumberType;
case QMetaType::QString:
return IR::StringType;
@@ -542,7 +545,7 @@ bool QV4IRBuilder::visit(AST::NumericLiteral *ast)
_expr.format = ExprResult::cx;
_block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
} else {
- _expr.code = _block->CONST(IR::RealType, ast->value);
+ _expr.code = _block->CONST(IR::NumberType, ast->value);
}
return false;
}
@@ -889,7 +892,14 @@ void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult
_expr.format = ExprResult::cx;
_block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
} else {
- _expr.code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
+ IR::Expr *e = _block->BINOP(IR::binaryOperator(ast->op), left, right);
+ if (e->asConst() != 0 || e->asString() != 0)
+ _expr.code = e;
+ else {
+ IR::Temp *t = _block->TEMP(e->type);
+ _block->MOVE(t, e);
+ _expr.code = t;
+ }
}
}
@@ -977,8 +987,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
if (left.type() == IR::StringType && right.type() == IR::StringType) {
binop(ast, left, right);
} else if (left.isValid() && right.isValid()) {
- implicitCvt(left, IR::RealType);
- implicitCvt(right, IR::RealType);
+ implicitCvt(left, IR::NumberType);
+ implicitCvt(right, IR::NumberType);
binop(ast, left, right);
}
} break;
@@ -998,8 +1008,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
}
} else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
(left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
- implicitCvt(left, IR::RealType);
- implicitCvt(right, IR::RealType);
+ implicitCvt(left, IR::NumberType);
+ implicitCvt(right, IR::NumberType);
binop(ast, left, right);
} else if (left.isValid() && right.isValid()) {
binop(ast, left, right);
@@ -1086,8 +1096,8 @@ bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
IR::Type t = maxType(left.type(), right.type());
if (t >= IR::FirstNumberType) {
- implicitCvt(left, IR::RealType);
- implicitCvt(right, IR::RealType);
+ implicitCvt(left, IR::NumberType);
+ implicitCvt(right, IR::NumberType);
IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
_expr.code = _block->TEMP(code->type);
diff --git a/src/qml/qml/v4/qv4irbuilder_p.h b/src/qml/qml/v4/qv4irbuilder_p.h
index 2b338c0778..e73ec22750 100644
--- a/src/qml/qml/v4/qv4irbuilder_p.h
+++ b/src/qml/qml/v4/qv4irbuilder_p.h
@@ -95,8 +95,8 @@ protected:
case QQmlJS::IR::StringType:
case QQmlJS::IR::BoolType:
case QQmlJS::IR::IntType:
- case QQmlJS::IR::RealType:
- case QQmlJS::IR::RealNaNType:
+ case QQmlJS::IR::FloatType:
+ case QQmlJS::IR::NumberType:
return true;
default:
diff --git a/src/qml/qml/v4/qv4program_p.h b/src/qml/qml/v4/qv4program_p.h
index 60e7403786..c1dc39279d 100644
--- a/src/qml/qml/v4/qv4program_p.h
+++ b/src/qml/qml/v4/qv4program_p.h
@@ -65,7 +65,6 @@ struct QV4Program {
quint32 signalTableOffset;
quint32 exceptionDataOffset;
quint16 subscriptions;
- quint16 identifiers;
quint16 instructionCount;
struct BindingReference {
@@ -87,7 +86,8 @@ enum QQmlRegisterType {
UndefinedType,
NullType,
QObjectStarType,
- QRealType,
+ NumberType,
+ FloatType,
IntType,
BoolType,
diff --git a/src/qml/qml/v8/qjsvalue_p.h b/src/qml/qml/v8/qjsvalue_p.h
index acfe958cb6..099d53ee7a 100644
--- a/src/qml/qml/v8/qjsvalue_p.h
+++ b/src/qml/qml/v8/qjsvalue_p.h
@@ -177,7 +177,7 @@ private:
CBool,
CNull,
CUndefined,
- JSValue = 0x2000, // V8 values are equal or higher then this value.
+ JSValue = 0x2000 // V8 values are equal or higher then this value.
// JSPrimitive,
// JSObject
} m_state;
diff --git a/src/qml/qml/v8/qv8bindings.cpp b/src/qml/qml/v8/qv8bindings.cpp
index 4b96679cf3..025854f1ac 100644
--- a/src/qml/qml/v8/qv8bindings.cpp
+++ b/src/qml/qml/v8/qv8bindings.cpp
@@ -58,7 +58,7 @@ static QQmlJavaScriptExpression::VTable QV8Bindings_Binding_jsvtable = {
};
QV8Bindings::Binding::Binding()
-: QQmlJavaScriptExpression(&QV8Bindings_Binding_jsvtable), target(0), parent(0)
+: QQmlJavaScriptExpression(&QV8Bindings_Binding_jsvtable), parent(0)
{
}
@@ -85,12 +85,20 @@ void QV8Bindings::Binding::refresh()
int QV8Bindings::Binding::propertyIndex() const
{
- return instruction->property.encodedIndex();
+ if (target.hasValue()) return target.constValue()->targetProperty;
+ else return instruction->property.encodedIndex();
}
QObject *QV8Bindings::Binding::object() const
{
- return target;
+ if (target.hasValue()) return target.constValue()->target;
+ else return *target;
+}
+
+void QV8Bindings::Binding::retargetBinding(QObject *t, int i)
+{
+ target.value().target = t;
+ target.value().targetProperty = i;
}
void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
@@ -127,13 +135,13 @@ void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
trace.event("writing V8 result");
bool needsErrorData = false;
- if (!watcher.wasDeleted() && !hasError()) {
+ if (!watcher.wasDeleted() && !destroyedFlag() && !hasError()) {
typedef QQmlPropertyPrivate PP;
- needsErrorData = !PP::writeBinding(target, instruction->property, context, this, result,
+ needsErrorData = !PP::writeBinding(*target, instruction->property, context, this, result,
isUndefined, flags);
}
- if (!watcher.wasDeleted()) {
+ if (!watcher.wasDeleted() && !destroyedFlag()) {
if (needsErrorData) {
QUrl url = parent->url();
@@ -156,7 +164,7 @@ void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags)
ep->dereferenceScarceResources();
} else {
- QQmlProperty p = QQmlPropertyPrivate::restore(target, instruction->property, context);
+ QQmlProperty p = QQmlPropertyPrivate::restore(*target, instruction->property, context);
QQmlAbstractBinding::printBindingLoopError(p);
}
}
@@ -177,6 +185,7 @@ void QV8Bindings::Binding::expressionChanged(QQmlJavaScriptExpression *e)
void QV8Bindings::Binding::destroy()
{
setEnabledFlag(false);
+ setDestroyedFlag(true);
removeFromObject();
clear();
clearError();
diff --git a/src/qml/qml/v8/qv8bindings_p.h b/src/qml/qml/v8/qv8bindings_p.h
index ad5b2cb8b0..7cc1cc9c21 100644
--- a/src/qml/qml/v8/qv8bindings_p.h
+++ b/src/qml/qml/v8/qv8bindings_p.h
@@ -53,12 +53,13 @@
// We mean it.
//
+#include <private/qpointervaluepair_p.h>
#include <private/qqmlpropertycache_p.h>
#include <private/qqmlinstruction_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlcompiler_p.h>
-#include <private/qqmlbinding_p.h>
#include <private/qflagpointer_p.h>
+#include <private/qqmlbinding_p.h>
QT_BEGIN_HEADER
@@ -96,17 +97,26 @@ public:
virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags);
virtual void update(QQmlPropertyPrivate::WriteFlags flags);
virtual void destroy();
- virtual int propertyIndex() const;
virtual QObject *object() const;
+ virtual int propertyIndex() const;
+ virtual void retargetBinding(QObject *, int);
- QObject *target;
QV8Bindings *parent;
+ struct Retarget {
+ QObject *target;
+ int targetProperty;
+ };
+
// To save memory, we store flags inside the instruction pointer.
- // flag1: enabled
- // flag2: updating
+ // target.flag1: destroyed
+ // instruction.flag1: enabled
+ // instruction.flag2: updating
+ QPointerValuePair<QObject, Retarget> target;
QFlagPointer<const QQmlInstruction::instr_assignBinding> instruction;
+ inline bool destroyedFlag() const { return target.flag(); }
+ inline void setDestroyedFlag(bool v) { return target.setFlagValue(v); }
inline bool enabledFlag() const { return instruction.flag(); }
inline void setEnabledFlag(bool v) { instruction.setFlagValue(v); }
inline bool updatingFlag() const { return instruction.flag2(); }
diff --git a/src/qml/qml/v8/qv8contextwrapper.cpp b/src/qml/qml/v8/qv8contextwrapper.cpp
index 39392b8984..8a98727205 100644
--- a/src/qml/qml/v8/qv8contextwrapper.cpp
+++ b/src/qml/qml/v8/qv8contextwrapper.cpp
@@ -327,7 +327,7 @@ v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
const QVariant &value = cp->propertyValues.at(propertyIdx);
if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
- QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*)propertyIdx,
+ QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx),
0,
QQmlContextPrivate::context_count,
QQmlContextPrivate::context_at);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 678f9aa3ee..2302d0e369 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -46,7 +46,6 @@
#include "qv8sequencewrapper_p.h"
#include "qv8include_p.h"
#include "qjsengine_p.h"
-#include "../../../3rdparty/javascriptcore/DateMath.h"
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmllist_p.h>
@@ -765,23 +764,19 @@ void QV8Engine::setExtensionData(int index, Deletable *data)
double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt)
{
- // from QScriptEngine::DateTimeToMs()
if (!dt.isValid()) {
return qSNaN();
}
- QDateTime utc = dt.toUTC();
- QDate date = utc.date();
- QTime time = utc.time();
- QV8DateConverter::JSC::GregorianDateTime tm;
- tm.year = date.year() - 1900;
- tm.month = date.month() - 1;
- tm.monthDay = date.day();
- tm.weekDay = date.dayOfWeek();
- tm.yearDay = date.dayOfYear();
- tm.hour = time.hour();
- tm.minute = time.minute();
- tm.second = time.second();
- return QV8DateConverter::JSC::gregorianDateTimeToMS(tm, time.msec());
+
+ return dt.toMSecsSinceEpoch();
+}
+
+QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate)
+{
+ if (qIsNaN(jsDate))
+ return QDateTime();
+
+ return QDateTime::fromMSecsSinceEpoch(jsDate);
}
v8::Persistent<v8::Object> *QV8Engine::findOwnerAndStrength(QObject *object, bool *shouldBeStrong)
@@ -815,24 +810,6 @@ v8::Persistent<v8::Object> *QV8Engine::findOwnerAndStrength(QObject *object, boo
}
}
-QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate)
-{
- // from QScriptEngine::MsToDateTime()
- if (qIsNaN(jsDate))
- return QDateTime();
- QV8DateConverter::JSC::GregorianDateTime tm;
- QV8DateConverter::JSC::msToGregorianDateTime(jsDate, tm);
-
- // from QScriptEngine::MsFromTime()
- int ms = int(::fmod(jsDate, 1000.0));
- if (ms < 0)
- ms += int(1000.0);
-
- QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
- QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
- return convertedUTC.toLocalTime();
-}
-
void QV8Engine::addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle)
{
if (handle.IsEmpty())
diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp
index 2350b9dc2c..ce85725642 100644
--- a/src/qml/qml/v8/qv8qobjectwrapper.cpp
+++ b/src/qml/qml/v8/qv8qobjectwrapper.cpp
@@ -63,7 +63,7 @@ Q_DECLARE_METATYPE(QQmlV8Handle);
QT_BEGIN_NAMESPACE
-#if defined(__GNUC__)
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
// The code in this file does not violate strict aliasing, but GCC thinks it does
// so turn off the warnings for us to have a clean build
@@ -269,7 +269,7 @@ static v8::Handle<v8::Value> GenericValueGetter(v8::Local<v8::String>, const v8:
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This);
QObject *object = resource->object;
- if (!object) return v8::Undefined();
+ if (QQmlData::wasDeleted(object)) return v8::Undefined();
QQmlPropertyData *property =
(QQmlPropertyData *)v8::External::Unwrap(info.Data());
@@ -476,6 +476,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
objectHandle?*objectHandle:engine->newQObject(object),
v8::Integer::New(index)
};
+ Q_ASSERT(argv[0]->IsObject());
return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 2, argv);
}
static v8::Handle<v8::Value> createWithGlobal(QV8Engine *engine, QObject *object,
@@ -486,10 +487,14 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
v8::Integer::New(index),
v8::Context::GetCallingQmlGlobal()
};
+ Q_ASSERT(argv[0]->IsObject());
return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 3, argv);
}
};
+ if (QQmlData::wasDeleted(object))
+ return v8::Handle<v8::Value>();
+
{
// Comparing the hash first actually makes a measurable difference here, at least on x86
quint32 hash = property.hash();
@@ -705,6 +710,9 @@ bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QH
engine->qobjectWrapper()->m_destroyString == property)
return true;
+ if (QQmlData::wasDeleted(object))
+ return false;
+
QQmlPropertyData local;
QQmlPropertyData *result = 0;
result = QQmlPropertyCache::property(engine->engine(), object, property, local);
@@ -735,7 +743,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property,
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return v8::Handle<v8::Value>();
QObject *object = resource->object;
@@ -779,7 +787,7 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property,
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return value;
QObject *object = resource->object;
@@ -873,7 +881,7 @@ static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return;
QObject *object = resource->object;
@@ -900,7 +908,7 @@ static void FastValueSetterReadOnly(v8::Local<v8::String> property, v8::Local<v8
{
QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This());
- if (resource->object.isNull())
+ if (QQmlData::wasDeleted(resource->object))
return;
QV8Engine *v8engine = resource->engine;
@@ -1080,20 +1088,13 @@ released the handle.
*/
v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
{
- if (!object)
+ if (QQmlData::wasDeleted(object))
return v8::Null();
- if (QObjectPrivate::get(object)->wasDeleted)
- return v8::Null();
-
QQmlData *ddata = QQmlData::get(object, true);
-
if (!ddata)
return v8::Undefined();
- if (ddata->isQueuedForDeletion)
- return v8::Null();
-
if (ddata->v8objectid == m_id && !ddata->v8object.IsEmpty()) {
// We own the v8object
return v8::Local<v8::Object>::New(ddata->v8object);
diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri
index de492a8ce5..7816c84b79 100644
--- a/src/qml/qml/v8/v8.pri
+++ b/src/qml/qml/v8/v8.pri
@@ -1,5 +1,3 @@
-INCLUDEPATH += $$PWD/../../../3rdparty/javascriptcore
-
include(script.pri)
HEADERS += \
@@ -20,7 +18,6 @@ HEADERS += \
$$PWD/qv8include_p.h \
$$PWD/qv8worker_p.h \
$$PWD/qv8bindings_p.h \
- $$PWD/../../../3rdparty/javascriptcore/DateMath.h \
$$PWD/qv8engine_impl_p.h \
$$PWD/qv8domerrors_p.h \
$$PWD/qv8sqlerrors_p.h \
@@ -39,7 +36,6 @@ SOURCES += \
$$PWD/qv8include.cpp \
$$PWD/qv8worker.cpp \
$$PWD/qv8bindings.cpp \
- $$PWD/../../../3rdparty/javascriptcore/DateMath.cpp \
$$PWD/qv8domerrors.cpp \
$$PWD/qv8sqlerrors.cpp \
- $$PWD/qqmlbuiltinfunctions.cpp \ No newline at end of file
+ $$PWD/qqmlbuiltinfunctions.cpp
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index 6df36d20cb..157cfe97c0 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -4,7 +4,7 @@ TARGET = QtQuickTest
QPRO_PWD = $$PWD
CONFIG += module
-CONFIG += dll warn_on
+CONFIG += dll warn_on declarative_debug
MODULE_PRI += ../../modules/qt_qmltest.pri
QT += testlib testlib-private qml quick gui
@@ -33,4 +33,4 @@ HEADERS += \
$$PWD/qtestoptions_p.h
-DEFINES += QT_BUILD_QUICK_TEST_LIB
+DEFINES += QT_BUILD_QUICK_TEST_LIB \ No newline at end of file
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 1c69cee456..3a2103afb6 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -100,10 +100,10 @@ static inline QString stripQuotes(const QString &s)
return s;
}
-template <class View> void handleCompileErrors(const QFileInfo &fi, const View &view)
+void handleCompileErrors(const QFileInfo &fi, QQuickView *view)
{
// Error compiling the test - flag failure in the log and continue.
- const QList<QQmlError> errors = view.errors();
+ const QList<QQmlError> errors = view->errors();
QuickTestResult results;
results.setTestCaseName(fi.baseName());
results.startLogging();
@@ -125,8 +125,8 @@ template <class View> void handleCompileErrors(const QFileInfo &fi, const View &
str << ": " << e.description() << '\n';
}
str << " Working directory: " << QDir::toNativeSeparators(QDir::current().absolutePath()) << '\n';
- if (QQmlEngine *engine = view.engine()) {
- str << " View: " << view.metaObject()->className() << ", import paths:\n";
+ if (QQmlEngine *engine = view->engine()) {
+ str << " View: " << view->metaObject()->className() << ", import paths:\n";
foreach (const QString &i, engine->importPathList())
str << " '" << QDir::toNativeSeparators(i) << "'\n";
const QStringList pluginPaths = engine->pluginPathList();
@@ -249,17 +249,17 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport
// Scan through all of the "tst_*.qml" files and run each of them
// in turn with a QQuickView.
- QQuickView view;
+ QQuickView *view = new QQuickView;
QTestRootObject rootobj;
QEventLoop eventLoop;
- QObject::connect(view.engine(), SIGNAL(quit()),
+ QObject::connect(view->engine(), SIGNAL(quit()),
&rootobj, SLOT(quit()));
- QObject::connect(view.engine(), SIGNAL(quit()),
+ QObject::connect(view->engine(), SIGNAL(quit()),
&eventLoop, SLOT(quit()));
- view.rootContext()->setContextProperty
+ view->rootContext()->setContextProperty
(QLatin1String("qtest"), &rootobj);
foreach (const QString &path, imports)
- view.engine()->addImportPath(path);
+ view->engine()->addImportPath(path);
foreach (QString file, files) {
QFileInfo fi(file);
@@ -271,13 +271,13 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport
rootobj.hasQuit = false;
QString path = fi.absoluteFilePath();
if (path.startsWith(QLatin1String(":/")))
- view.setSource(QUrl(QLatin1String("qrc:") + path.mid(2)));
+ view->setSource(QUrl(QLatin1String("qrc:") + path.mid(2)));
else
- view.setSource(QUrl::fromLocalFile(path));
+ view->setSource(QUrl::fromLocalFile(path));
if (QTest::printAvailableFunctions)
continue;
- if (view.status() == QQuickView::Error) {
+ if (view->status() == QQuickView::Error) {
handleCompileErrors(fi, view);
continue;
}
@@ -286,8 +286,8 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport
// synchronously during setSource(). Otherwise it is
// an asynchronous test and we need to show the window
// and wait for the quit indication.
- view.show();
- QTest::qWaitForWindowShown(&view);
+ view->show();
+ QTest::qWaitForWindowShown(view);
rootobj.setWindowShown(true);
if (!rootobj.hasQuit && rootobj.hasTestCase())
eventLoop.exec();
@@ -296,10 +296,8 @@ int quick_test_main(int argc, char **argv, const char *name, quick_test_viewport
// Flush the current logging stream.
QuickTestResult::setProgramName(0);
-
- //Sometimes delete app cause crash here with some qpa plugins,
- //so we comment the follow line out to make them happy.
- //delete app;
+ delete view;
+ delete app;
// Return the number of failures as the exit code.
return QuickTestResult::exitCode();
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index a605b9ce6d..6d8d9b852b 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -47,7 +47,6 @@
#include <QtQuick/private/qquickshadereffectsource_p.h>
#include <QtGui/qopenglframebufferobject.h>
-#include <QtCore/qdebug.h>
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qquicksvgparser_p.h>
#include <private/qquickpath_p.h>
@@ -185,7 +184,7 @@ QColor qt_color_from_string(v8::Local<v8::Value> name)
if (*p != ')') return QColor();
if (isRgb)
return QColor::fromRgba(qRgba(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255)));
- else
+ else if (isHsl)
return QColor::fromHsl(qClamp(rh, 0, 255), qClamp(gs, 0, 255), qClamp(bl, 0, 255), qClamp(alpha, 0, 255));
}
return QColor();
@@ -484,8 +483,6 @@ static v8::Handle<v8::Value> ctx2d_reset(const v8::Arguments &args)
CHECK_CONTEXT(r)
r->context->reset();
- r->context->m_path = QPainterPath();
- r->context->m_path.setFillRule(Qt::WindingFill);
return args.This();
}
@@ -551,15 +548,8 @@ static v8::Handle<v8::Value> ctx2d_rotate(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
- if (args.Length() == 1) {
- qreal angle = args[0]->NumberValue();
- if (!qIsFinite(angle))
- return args.This();
-
- r->context->state.matrix.rotate(DEGREES(angle));
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
+ if (args.Length() == 1)
+ r->context->rotate(args[0]->NumberValue());
return args.This();
}
@@ -583,17 +573,8 @@ static v8::Handle<v8::Value> ctx2d_scale(const v8::Arguments &args)
CHECK_CONTEXT(r)
- if (args.Length() == 2) {
- qreal x, y;
- x = args[0]->NumberValue();
- y = args[1]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
-
- r->context->state.matrix.scale(x, y);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
+ if (args.Length() == 2)
+ r->context->scale(args[0]->NumberValue(), args[1]->NumberValue());
return args.This();
}
@@ -636,25 +617,13 @@ static v8::Handle<v8::Value> ctx2d_setTransform(const v8::Arguments &args)
CHECK_CONTEXT(r)
- if (args.Length() == 6) {
- qreal a = args[0]->NumberValue();
- qreal b = args[1]->NumberValue();
- qreal c = args[2]->NumberValue();
- qreal d = args[3]->NumberValue();
- qreal e = args[4]->NumberValue();
- qreal f = args[5]->NumberValue();
-
- if (!qIsFinite(a)
- || !qIsFinite(b)
- || !qIsFinite(c)
- || !qIsFinite(d)
- || !qIsFinite(e)
- || !qIsFinite(f))
- return args.This();
-
- r->context->state.matrix = QTransform(a, b, c, d, e, f);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
+ if (args.Length() == 6)
+ r->context->setTransform( args[0]->NumberValue()
+ , args[1]->NumberValue()
+ , args[2]->NumberValue()
+ , args[3]->NumberValue()
+ , args[4]->NumberValue()
+ , args[5]->NumberValue());
return args.This();
}
@@ -675,25 +644,13 @@ static v8::Handle<v8::Value> ctx2d_transform(const v8::Arguments &args)
CHECK_CONTEXT(r)
- if (args.Length() == 6) {
- qreal a = args[0]->NumberValue();
- qreal b = args[1]->NumberValue();
- qreal c = args[2]->NumberValue();
- qreal d = args[3]->NumberValue();
- qreal e = args[4]->NumberValue();
- qreal f = args[5]->NumberValue();
-
- if (!qIsFinite(a)
- || !qIsFinite(b)
- || !qIsFinite(c)
- || !qIsFinite(d)
- || !qIsFinite(e)
- || !qIsFinite(f))
- return args.This();
-
- r->context->state.matrix *= QTransform(a, b, c, d, e, f);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
+ if (args.Length() == 6)
+ r->context->transform( args[0]->NumberValue()
+ , args[1]->NumberValue()
+ , args[2]->NumberValue()
+ , args[3]->NumberValue()
+ , args[4]->NumberValue()
+ , args[5]->NumberValue());
return args.This();
}
@@ -713,17 +670,8 @@ static v8::Handle<v8::Value> ctx2d_translate(const v8::Arguments &args)
CHECK_CONTEXT(r)
- if (args.Length() == 2) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
-
- r->context->state.matrix.translate(x, y);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
-
+ if (args.Length() == 2)
+ r->context->translate(args[0]->NumberValue(), args[1]->NumberValue());
return args.This();
}
@@ -739,8 +687,7 @@ static v8::Handle<v8::Value> ctx2d_resetTransform(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
- r->context->state.matrix = QTransform();
- r->context->buffer()->updateMatrix(r->context->state.matrix);
+ r->context->setTransform(1, 0, 0, 1, 0, 0);
return args.This();
}
@@ -755,16 +702,9 @@ static v8::Handle<v8::Value> ctx2d_shear(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
- if (args.Length() == 2) {
- qreal sh = args[0]->NumberValue();
- qreal sv = args[1]->NumberValue();
+ if (args.Length() == 2)
+ r->context->shear(args[0]->NumberValue(), args[1]->NumberValue());
- if (!qIsFinite(sh) || !qIsFinite(sv))
- return args.This();
-
- r->context->state.matrix.shear(sh, sv);
- r->context->buffer()->updateMatrix(r->context->state.matrix);
- }
return args.This();
}
// compositing
@@ -1596,17 +1536,11 @@ static v8::Handle<v8::Value> ctx2d_clearRect(const v8::Arguments &args)
CHECK_CONTEXT(r)
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->buffer()->clearRect(x, y, w, h);
- }
+ if (args.Length() == 4)
+ r->context->clearRect(args[0]->NumberValue(),
+ args[1]->NumberValue(),
+ args[2]->NumberValue(),
+ args[3]->NumberValue());
return args.This();
}
@@ -1621,18 +1555,8 @@ static v8::Handle<v8::Value> ctx2d_fillRect(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->buffer()->fillRect(x, y, w, h);
- }
-
+ if (args.Length() == 4)
+ r->context->fillRect(args[0]->NumberValue(), args[1]->NumberValue(), args[2]->NumberValue(), args[3]->NumberValue());
return args.This();
}
@@ -1651,18 +1575,8 @@ static v8::Handle<v8::Value> ctx2d_strokeRect(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
-
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->buffer()->strokeRect(x, y, w, h);
- }
+ if (args.Length() == 4)
+ r->context->strokeRect(args[0]->NumberValue(), args[1]->NumberValue(), args[2]->NumberValue(), args[3]->NumberValue());
return args.This();
}
@@ -1687,15 +1601,8 @@ static v8::Handle<v8::Value> ctx2d_arc(const v8::Arguments &args)
antiClockwise = args[5]->BooleanValue();
qreal radius = args[2]->NumberValue();
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal sa = args[3]->NumberValue();
- qreal ea = args[4]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(sa) || !qIsFinite(ea))
- return args.This();
- if (radius < 0)
+ if (qIsFinite(radius) && radius < 0)
V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
r->context->arc(args[0]->NumberValue(),
@@ -1734,25 +1641,17 @@ static v8::Handle<v8::Value> ctx2d_arcTo(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
-
-
if (args.Length() == 5) {
- qreal x1 = args[0]->NumberValue();
- qreal y1 = args[1]->NumberValue();
- qreal x2 = args[2]->NumberValue();
- qreal y2 = args[3]->NumberValue();
-
- if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2))
- return args.This();
-
qreal radius = args[4]->NumberValue();
- if (radius < 0)
+
+ if (qIsFinite(radius) && radius < 0)
V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
+
r->context->arcTo(args[0]->NumberValue(),
args[1]->NumberValue(),
args[2]->NumberValue(),
args[3]->NumberValue(),
- args[4]->NumberValue());
+ radius);
}
return args.This();
@@ -1845,14 +1744,7 @@ static v8::Handle<v8::Value> ctx2d_clip(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
- QPainterPath clipPath = r->context->m_path;
- clipPath.closeSubpath();
- if (!r->context->state.clipPath.isEmpty())
- r->context->state.clipPath = clipPath.intersected(r->context->state.clipPath);
- else
- r->context->state.clipPath = clipPath;
- r->context->buffer()->clip(r->context->state.clipPath);
-
+ r->context->clip();
return args.This();
}
@@ -1887,9 +1779,7 @@ static v8::Handle<v8::Value> ctx2d_fill(const v8::Arguments &args)
{
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r);
-
- r->context->buffer()->fill(r->context->m_path);
-
+ r->context->fill();
return args.This();
}
@@ -1975,19 +1865,8 @@ static v8::Handle<v8::Value> ctx2d_rect(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
-
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- r->context->rect(x, y, w, h);
- }
-
+ if (args.Length() == 4)
+ r->context->rect(args[0]->NumberValue(), args[1]->NumberValue(), args[2]->NumberValue(), args[3]->NumberValue());
return args.This();
}
@@ -2002,23 +1881,13 @@ static v8::Handle<v8::Value> ctx2d_roundedRect(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
- if (args.Length() == 6) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
- qreal xr = args[4]->NumberValue();
- qreal yr = args[5]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
- if (!qIsFinite(xr) || !qIsFinite(yr))
- V8THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "roundedRect(): Invalid arguments");
-
- r->context->roundedRect(x, y, w, h, xr, yr);
- }
-
+ if (args.Length() == 6)
+ r->context->roundedRect(args[0]->NumberValue()
+ , args[1]->NumberValue()
+ , args[2]->NumberValue()
+ , args[3]->NumberValue()
+ , args[4]->NumberValue()
+ , args[5]->NumberValue());
return args.This();
}
@@ -2036,18 +1905,8 @@ static v8::Handle<v8::Value> ctx2d_ellipse(const v8::Arguments &args)
CHECK_CONTEXT(r)
- if (args.Length() == 4) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- qreal w = args[2]->NumberValue();
- qreal h = args[3]->NumberValue();
-
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
- return args.This();
-
-
- r->context->ellipse(x, y, w, h);
- }
+ if (args.Length() == 4)
+ r->context->ellipse(args[0]->NumberValue(), args[1]->NumberValue(), args[2]->NumberValue(), args[3]->NumberValue());
return args.This();
}
@@ -2089,9 +1948,7 @@ static v8::Handle<v8::Value> ctx2d_stroke(const v8::Arguments &args)
QV8Context2DResource *r = v8_resource_cast<QV8Context2DResource>(args.This());
CHECK_CONTEXT(r)
-
- r->context->buffer()->stroke(r->context->m_path);
-
+ r->context->stroke();
return args.This();
}
@@ -2108,13 +1965,8 @@ static v8::Handle<v8::Value> ctx2d_isPointInPath(const v8::Arguments &args)
CHECK_CONTEXT(r)
bool pointInPath = false;
- if (args.Length() == 2) {
- qreal x = args[0]->NumberValue();
- qreal y = args[1]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y))
- return v8::Boolean::New(false);
- pointInPath = r->context->isPointInPath(x, y);
- }
+ if (args.Length() == 2)
+ pointInPath = r->context->isPointInPath(args[0]->NumberValue(), args[1]->NumberValue());
return v8::Boolean::New(pointInPath);
}
@@ -2331,14 +2183,8 @@ static v8::Handle<v8::Value> ctx2d_strokeText(const v8::Arguments &args)
CHECK_CONTEXT(r)
QV8Engine *engine = V8ENGINE();
- if (args.Length() == 3) {
- qreal x = args[1]->NumberValue();
- qreal y = args[2]->NumberValue();
- if (!qIsFinite(x) || !qIsFinite(y))
- return args.This();
- QPainterPath textPath = r->context->createTextGlyphs(x, y, engine->toString(args[0]));
- r->context->buffer()->stroke(textPath);
- }
+ if (args.Length() == 3)
+ r->context->drawText(engine->toString(args[0]), args[1]->NumberValue(), args[2]->NumberValue(), false);
return args.This();
}
/*!
@@ -2450,6 +2296,10 @@ static v8::Handle<v8::Value> ctx2d_drawImage(const v8::Arguments &args)
if (!args.Length())
return args.This();
+ //FIXME:This function should be moved to QQuickContext2D::drawImage(...)
+ if (!r->context->state.invertibleCTM)
+ return args.This();
+
QImage image;
if (args[0]->IsString()) {
QUrl url(engine->toString(args[0]->ToString()));
@@ -2868,16 +2718,221 @@ static v8::Handle<v8::Value> ctx2d_gradient_addColorStop(const v8::Arguments &ar
return args.This();
}
+void QQuickContext2D::scale(qreal x, qreal y)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return;
+
+ QTransform newTransform = state.matrix;
+ newTransform.scale(x, y);
+
+ if (!newTransform.isInvertible()) {
+ state.invertibleCTM = false;
+ return;
+ }
+
+ state.matrix = newTransform;
+ buffer()->updateMatrix(state.matrix);
+ m_path = QTransform().scale(1.0 / x, 1.0 / y).map(m_path);
+}
+
+void QQuickContext2D::rotate(qreal angle)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(angle))
+ return;
+
+ QTransform newTransform =state.matrix;
+ newTransform.rotate(DEGREES(angle));
+
+ if (!newTransform.isInvertible()) {
+ state.invertibleCTM = false;
+ return;
+ }
+
+ state.matrix = newTransform;
+ buffer()->updateMatrix(state.matrix);
+ m_path = QTransform().rotate(-DEGREES(angle)).map(m_path);
+}
+
+void QQuickContext2D::shear(qreal h, qreal v)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(h) || !qIsFinite(v))
+ return ;
+
+ QTransform newTransform = state.matrix;
+ newTransform.shear(h, v);
+
+ if (!newTransform.isInvertible()) {
+ state.invertibleCTM = false;
+ return;
+ }
+
+ state.matrix = newTransform;
+ buffer()->updateMatrix(state.matrix);
+ m_path = QTransform().shear(-h, -v).map(m_path);
+}
+
+void QQuickContext2D::translate(qreal x, qreal y)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return ;
+
+ QTransform newTransform = state.matrix;
+ newTransform.translate(x, y);
+
+ if (!newTransform.isInvertible()) {
+ state.invertibleCTM = false;
+ return;
+ }
+
+ state.matrix = newTransform;
+ buffer()->updateMatrix(state.matrix);
+ m_path = QTransform().translate(-x, -y).map(m_path);
+}
+
+void QQuickContext2D::transform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f))
+ return;
+
+ QTransform transform(a, b, c, d, e, f);
+ QTransform newTransform = state.matrix * transform;
+
+ if (!newTransform.isInvertible()) {
+ state.invertibleCTM = false;
+ return;
+ }
+ state.matrix = newTransform;
+ buffer()->updateMatrix(state.matrix);
+ m_path = transform.inverted().map(m_path);
+}
+
+void QQuickContext2D::setTransform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f)
+{
+ if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f))
+ return;
+
+ QTransform ctm = state.matrix;
+ if (!ctm.isInvertible())
+ return;
+
+ state.matrix = ctm.inverted() * state.matrix;
+ m_path = ctm.map(m_path);
+ state.invertibleCTM = true;
+ transform(a, b, c, d, e, f);
+}
+
+void QQuickContext2D::fill()
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!m_path.elementCount())
+ return;
+
+ m_path.setFillRule(state.fillRule);
+ buffer()->fill(m_path);
+}
+
+void QQuickContext2D::clip()
+{
+ if (!state.invertibleCTM)
+ return;
+
+ QPainterPath clipPath = m_path;
+ clipPath.closeSubpath();
+ if (!state.clipPath.isEmpty())
+ state.clipPath = clipPath.intersected(state.clipPath);
+ else
+ state.clipPath = clipPath;
+ buffer()->clip(state.clipPath);
+}
+
+void QQuickContext2D::stroke()
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!m_path.elementCount())
+ return;
+
+ buffer()->stroke(m_path);
+}
+
+void QQuickContext2D::fillRect(qreal x, qreal y, qreal w, qreal h)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return;
+
+ buffer()->fillRect(x, y, w, h);
+}
+
+void QQuickContext2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return;
+
+ buffer()->strokeRect(x, y, w, h);
+}
+
+void QQuickContext2D::clearRect(qreal x, qreal y, qreal w, qreal h)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return;
+
+ buffer()->clearRect(x, y, w, h);
+}
+
+void QQuickContext2D::drawText(const QString& text, qreal x, qreal y, bool fill)
+{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return;
+
+ QPainterPath textPath = createTextGlyphs(x, y, text);
+ if (fill)
+ buffer()->fill(textPath);
+ else
+ buffer()->stroke(textPath);
+}
+
void QQuickContext2D::beginPath()
{
+ if (!m_path.elementCount())
+ return;
m_path = QPainterPath();
- m_path.setFillRule(state.fillRule);
}
void QQuickContext2D::closePath()
{
- if (m_path.isEmpty())
+ if (!m_path.elementCount())
return;
QRectF boundRect = m_path.boundingRect();
@@ -2889,29 +2944,53 @@ void QQuickContext2D::closePath()
void QQuickContext2D::moveTo( qreal x, qreal y)
{
+ if (!state.invertibleCTM)
+ return;
+
//FIXME: moveTo should not close the previous subpath
- m_path.moveTo(state.matrix.map(QPointF(x, y)));
+ m_path.moveTo(QPointF(x, y));
}
void QQuickContext2D::lineTo( qreal x, qreal y)
{
- m_path.lineTo(state.matrix.map(QPointF(x, y)));
+ if (!state.invertibleCTM)
+ return;
+
+ QPointF pt(x, y);
+
+ if (!m_path.elementCount())
+ m_path.moveTo(pt);
+ else if (m_path.currentPosition() != pt)
+ m_path.lineTo(pt);
}
void QQuickContext2D::quadraticCurveTo(qreal cpx, qreal cpy,
qreal x, qreal y)
{
- m_path.quadTo(state.matrix.map(QPointF(cpx, cpy)),
- state.matrix.map(QPointF(x, y)));
+ if (!state.invertibleCTM)
+ return;
+
+ if (!m_path.elementCount())
+ m_path.moveTo(QPointF(cpx, cpy));
+
+ QPointF pt(x, y);
+ if (m_path.currentPosition() != pt)
+ m_path.quadTo(QPointF(cpx, cpy), pt);
}
void QQuickContext2D::bezierCurveTo(qreal cp1x, qreal cp1y,
qreal cp2x, qreal cp2y,
qreal x, qreal y)
{
- m_path.cubicTo(state.matrix.map(QPointF(cp1x, cp1y)),
- state.matrix.map(QPointF(cp2x, cp2y)),
- state.matrix.map(QPointF(x, y)));
+ if (!state.invertibleCTM)
+ return;
+
+ if (!m_path.elementCount())
+ m_path.moveTo(QPointF(cp1x, cp1y));
+
+ QPointF pt(x, y);
+ if (m_path.currentPosition() != pt)
+ m_path.cubicTo(QPointF(cp1x, cp1y), QPointF(cp2x, cp2y), pt);
}
void QQuickContext2D::addArcTo(const QPointF& p1, const QPointF& p2, float radius)
@@ -2969,69 +3048,100 @@ void QQuickContext2D::addArcTo(const QPointF& p1, const QPointF& p2, float radiu
if ((sa < ea) && ((ea - sa) > Q_PI))
anticlockwise = true;
- arc(p.x(), p.y(), radius, sa, ea, anticlockwise, false);
+ arc(p.x(), p.y(), radius, sa, ea, anticlockwise);
}
void QQuickContext2D::arcTo(qreal x1, qreal y1,
qreal x2, qreal y2,
qreal radius)
{
- QPointF st = state.matrix.map(QPointF(x1, y1));
- QPointF end = state.matrix.map(QPointF(x2, y2));
+ if (!state.invertibleCTM)
+ return;
- if (!m_path.elementCount()) {
+ if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2) || !qIsFinite(radius))
+ return;
+
+ QPointF st(x1, y1);
+ QPointF end(x2, y2);
+
+ if (!m_path.elementCount())
m_path.moveTo(st);
- } else if (st == m_path.currentPosition() || st == end || !radius) {
- m_path.lineTo(st);
- } else {
+ else if (st == m_path.currentPosition() || st == end || !radius)
+ lineTo(x1, y1);
+ else
addArcTo(st, end, radius);
- }
-}
+ }
-void QQuickContext2D::rect(qreal x, qreal y,
- qreal w, qreal h)
+void QQuickContext2D::rect(qreal x, qreal y, qreal w, qreal h)
{
- m_path.addPolygon(state.matrix.map(QRectF(x, y, w, h)));
+ if (!state.invertibleCTM)
+ return;
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return;
+
+ if (!w && !h) {
+ m_path.moveTo(x, y);
+ return;
+ }
+ m_path.addRect(x, y, w, h);
}
void QQuickContext2D::roundedRect(qreal x, qreal y,
qreal w, qreal h,
qreal xr, qreal yr)
{
- QPainterPath path;
- path.addRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::AbsoluteSize);
- m_path.addPath(state.matrix.map(path));
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h) || !qIsFinite(xr) || !qIsFinite(yr))
+ return;
+
+ if (!w && !h) {
+ m_path.moveTo(x, y);
+ return;
+ }
+ m_path.addRoundedRect(QRectF(x, y, w, h), xr, yr, Qt::AbsoluteSize);
}
void QQuickContext2D::ellipse(qreal x, qreal y,
qreal w, qreal h)
{
- QPainterPath path;
- path.addEllipse(x, y, w, h);
- m_path.addPath(state.matrix.map(path));
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ return;
+
+ if (!w && !h) {
+ m_path.moveTo(x, y);
+ return;
+ }
+
+ m_path.addEllipse(x, y, w, h);
}
void QQuickContext2D::text(const QString& str, qreal x, qreal y)
{
+ if (!state.invertibleCTM)
+ return;
+
QPainterPath path;
path.addText(x, y, state.font, str);
- m_path.addPath(state.matrix.map(path));
+ m_path.addPath(path);
}
-void QQuickContext2D::arc(qreal xc,
- qreal yc,
- qreal radius,
- qreal sar,
- qreal ear,
- bool antiClockWise,
- bool transform)
+void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear, bool antiClockWise)
{
+ if (!state.invertibleCTM)
+ return;
+
+ if (!qIsFinite(xc) || !qIsFinite(yc) || !qIsFinite(sar) || !qIsFinite(ear) || !qIsFinite(radius))
+ return;
+
+ if (sar == ear)
+ return;
+
- if (transform) {
- QPointF point = state.matrix.map(QPointF(xc, yc));
- xc = point.x();
- yc = point.y();
- }
//### HACK
// In Qt we don't switch the coordinate system for degrees
@@ -3068,17 +3178,14 @@ void QQuickContext2D::arc(qreal xc,
qFuzzyCompare(qAbs(span), 360))) {
span += ea - sa;
}
- if (!m_path.elementCount())
- m_path.moveTo(xs, ys);
}
-
- if (transform) {
- QPointF currentPos = m_path.currentPosition();
- QPointF startPos = QPointF(xc + radius * qCos(sar),
- yc - radius * qSin(sar));
- if (currentPos != startPos)
- m_path.lineTo(startPos);
+ // If the path is empty, move to where the arc will start to avoid painting a line from (0,0)
+ if (!m_path.elementCount())
+ m_path.arcMoveTo(xs, ys, width, height, sa);
+ else if (!radius) {
+ m_path.lineTo(xc, yc);
+ return;
}
m_path.arcTo(xs, ys, width, height, sa, span);
@@ -3142,9 +3249,59 @@ QPainterPath QQuickContext2D::createTextGlyphs(qreal x, qreal y, const QString&
}
+static inline bool areCollinear(const QPointF& a, const QPointF& b, const QPointF& c)
+{
+ // Solved from comparing the slopes of a to b and b to c: (ay-by)/(ax-bx) == (cy-by)/(cx-bx)
+ return qFuzzyCompare((c.y() - b.y()) * (a.x() - b.x()), (a.y() - b.y()) * (c.x() - b.x()));
+}
+
+static inline bool withinRange(qreal p, qreal a, qreal b)
+{
+ return (p >= a && p <= b) || (p >= b && p <= a);
+}
+
bool QQuickContext2D::isPointInPath(qreal x, qreal y) const
{
- return m_path.contains(QPointF(x, y));
+ if (!state.invertibleCTM)
+ return false;
+
+ if (!m_path.elementCount())
+ return false;
+
+ if (!qIsFinite(x) || !qIsFinite(y))
+ return false;
+
+ QPointF point(x, y);
+ QTransform ctm = state.matrix;
+ QPointF p = ctm.inverted().map(point);
+ if (!qIsFinite(p.x()) || !qIsFinite(p.y()))
+ return false;
+
+ const_cast<QQuickContext2D *>(this)->m_path.setFillRule(state.fillRule);
+
+ bool contains = m_path.contains(p);
+
+ if (!contains) {
+ // check whether the point is on the border
+ QPolygonF border = m_path.toFillPolygon();
+
+ QPointF p1 = border.at(0);
+ QPointF p2;
+
+ for (int i = 1; i < border.size(); ++i) {
+ p2 = border.at(i);
+ if (areCollinear(p, p1, p2)
+ // Once we know that the points are collinear we
+ // only need to check one of the coordinates
+ && (qAbs(p2.x() - p1.x()) > qAbs(p2.y() - p1.y()) ?
+ withinRange(p.x(), p1.x(), p2.x()) :
+ withinRange(p.y(), p1.y(), p2.y()))) {
+ return true;
+ }
+ p1 = p2;
+ }
+ }
+ return contains;
}
QQuickContext2D::QQuickContext2D(QObject *parent)
@@ -3405,7 +3562,9 @@ void QQuickContext2D::popState()
if (newState.shadowOffsetY != state.shadowOffsetY)
buffer()->setShadowOffsetY(newState.shadowOffsetY);
+ m_path = state.matrix.map(m_path);
state = newState;
+ m_path = state.matrix.inverted().map(m_path);
}
void QQuickContext2D::pushState()
{
@@ -3417,6 +3576,8 @@ void QQuickContext2D::reset()
QQuickContext2D::State newState;
newState.matrix = QTransform();
+ m_path = QPainterPath();
+
QPainterPath defaultClipPath;
QRect r(0, 0, m_canvas->canvasSize().width(), m_canvas->canvasSize().height());
@@ -3431,6 +3592,7 @@ void QQuickContext2D::reset()
newState.fillPatternRepeatY = false;
newState.strokePatternRepeatX = false;
newState.strokePatternRepeatY = false;
+ newState.invertibleCTM = true;
newState.fillRule = Qt::WindingFill;
newState.globalAlpha = 1.0;
newState.lineWidth = 1;
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index 3230881134..4112d4ebf0 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -116,6 +116,7 @@ public:
, fillPatternRepeatY(false)
, strokePatternRepeatX(false)
, strokePatternRepeatY(false)
+ , invertibleCTM(true)
, fillRule(Qt::WindingFill)
, globalAlpha(1.0)
, lineWidth(1)
@@ -141,6 +142,7 @@ public:
bool fillPatternRepeatY:1;
bool strokePatternRepeatX:1;
bool strokePatternRepeatY:1;
+ bool invertibleCTM:1;
Qt::FillRule fillRule;
qreal globalAlpha;
qreal lineWidth;
@@ -180,7 +182,23 @@ public:
void pushState();
void reset();
- // path API
+ void fill();
+ void clip();
+ void stroke();
+ void fillRect(qreal x, qreal y, qreal w, qreal h);
+ void strokeRect(qreal x, qreal y, qreal w, qreal h);
+ void clearRect(qreal x, qreal y, qreal w, qreal h);
+ void drawText(const QString& text, qreal x, qreal y, bool fill);
+
+ //Transform APIs
+ void scale(qreal x, qreal y);
+ void rotate(qreal angle);
+ void shear(qreal h, qreal v);
+ void translate(qreal x, qreal y);
+ void transform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f);
+ void setTransform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f);
+
+ // Path APIs
void beginPath();
void closePath();
void moveTo(qreal x, qreal y);
@@ -195,7 +213,7 @@ public:
void text(const QString& str, qreal x, qreal y);
void arc(qreal x, qreal y, qreal radius,
qreal startAngle, qreal endAngle,
- bool anticlockwise, bool transform=true);
+ bool anticlockwise);
void addArcTo(const QPointF& p1, const QPointF& p2, float radius);
bool isPointInPath(qreal x, qreal y) const;
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index 591fc216a4..f6b9a1afeb 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -236,7 +236,7 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
reset();
- QTransform originMatrix = p->transform();
+ QTransform originMatrix = p->worldTransform();
QPen pen = makePen(state);
setPainterState(p, state, pen);
@@ -247,7 +247,7 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
case QQuickContext2D::UpdateMatrix:
{
state.matrix = takeMatrix();
- p->setTransform(state.matrix * originMatrix);
+ p->setWorldTransform(state.matrix * originMatrix);
break;
}
case QQuickContext2D::ClearRect:
@@ -303,36 +303,42 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
state.strokeStyle = takeStrokeStyle();
state.strokePatternRepeatX = takeBool();
state.strokePatternRepeatY = takeBool();
- pen.setBrush(state.strokeStyle);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setBrush(state.strokeStyle);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::LineWidth:
{
state.lineWidth = takeLineWidth();
- pen.setWidth(state.lineWidth);
- p->setPen(pen);
+ QPen nPen = p->pen();
+
+ nPen.setWidthF(state.lineWidth);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::LineCap:
{
state.lineCap = takeLineCap();
- pen.setCapStyle(state.lineCap);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setCapStyle(state.lineCap);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::LineJoin:
{
state.lineJoin = takeLineJoin();
- pen.setJoinStyle(state.lineJoin);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setJoinStyle(state.lineJoin);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::MiterLimit:
{
state.miterLimit = takeMiterLimit();
- pen.setMiterLimit(state.miterLimit);
- p->setPen(pen);
+ QPen nPen = p->pen();
+ nPen.setMiterLimit(state.miterLimit);
+ p->setPen(nPen);
break;
}
case QQuickContext2D::TextAlign:
diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp
index 2e2c8725aa..3f08c8f056 100644
--- a/src/quick/items/qquickcanvas.cpp
+++ b/src/quick/items/qquickcanvas.cpp
@@ -55,7 +55,6 @@
#include <private/qguiapplication_p.h>
#include <QtGui/QInputMethod>
-#include <QtGui/QCursor>
#include <private/qabstractanimation_p.h>
@@ -123,10 +122,12 @@ private:
bool m_eventSent;
};
+#ifndef QT_NO_ACCESSIBILITY
QAccessibleInterface *QQuickCanvas::accessibleRoot() const
{
return QAccessible::queryAccessibleInterface(const_cast<QQuickCanvas*>(this));
}
+#endif
/*
@@ -154,6 +155,10 @@ have a scope focused item), and the other items will have their focus cleared.
// #define TOUCH_DEBUG
// #define DIRTY_DEBUG
+#ifdef FOCUS_DEBUG
+void printFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1);
+#endif
+
QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData()
: transformNode(0)
{
@@ -952,7 +957,7 @@ bool QQuickCanvasPrivate::clearHover()
if (hoverItems.isEmpty())
return false;
- QPointF pos = QCursor::pos(); // ### refactor: q->mapFromGlobal(QCursor::pos());
+ QPointF pos = QGuiApplicationPrivate::lastCursorPosition;; // ### refactor: q->mapFromGlobal(QCursor::pos());
bool accepted = false;
foreach (QQuickItem* item, hoverItems)
@@ -1087,8 +1092,12 @@ bool QQuickCanvasPrivate::deliverMouseEvent(QMouseEvent *event)
QQuickMouseEventEx me(event->type(), transform.map(event->windowPos()),
event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers());
- if (QQuickMouseEventEx::extended(event))
- me.setVelocity(QQuickMouseEventEx::extended(event)->velocity());
+ QQuickMouseEventEx *eventEx = QQuickMouseEventEx::extended(event);
+ if (eventEx) {
+ me.setVelocity(eventEx->velocity());
+ me.setCapabilities(eventEx->capabilities());
+ }
+ me.setTimestamp(event->timestamp());
me.accept();
q->sendEvent(mouseGrabberItem, &me);
event->setAccepted(me.isAccepted());
diff --git a/src/quick/items/qquickcanvas.h b/src/quick/items/qquickcanvas.h
index 787bb7e3c7..396bc2b8ff 100644
--- a/src/quick/items/qquickcanvas.h
+++ b/src/quick/items/qquickcanvas.h
@@ -102,7 +102,9 @@ public:
QQmlIncubationController *incubationController() const;
+#ifndef QT_NO_ACCESSIBILITY
virtual QAccessibleInterface *accessibleRoot() const;
+#endif
// Scene graph specific functions
QSGTexture *createTextureFromImage(const QImage &image) const;
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 62d0e4aa41..75c9919e34 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1108,7 +1108,8 @@ void QQuickFlickable::mouseReleaseEvent(QMouseEvent *event)
d->clearDelayedPress();
d->handleMouseReleaseEvent(event);
event->accept();
- ungrabMouse();
+ if (canvas() && canvas()->mouseGrabberItem() == this)
+ ungrabMouse();
} else {
QQuickItem::mouseReleaseEvent(event);
}
diff --git a/src/quick/items/qquickimplicitsizeitem.cpp b/src/quick/items/qquickimplicitsizeitem.cpp
index 427be42312..1de8e0ab73 100644
--- a/src/quick/items/qquickimplicitsizeitem.cpp
+++ b/src/quick/items/qquickimplicitsizeitem.cpp
@@ -47,12 +47,24 @@ QT_BEGIN_NAMESPACE
void QQuickImplicitSizeItemPrivate::implicitWidthChanged()
{
Q_Q(QQuickImplicitSizeItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitWidth) {
+ change.listener->itemImplicitWidthChanged(q);
+ }
+ }
emit q->implicitWidthChanged();
}
void QQuickImplicitSizeItemPrivate::implicitHeightChanged()
{
Q_Q(QQuickImplicitSizeItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitHeight) {
+ change.listener->itemImplicitHeightChanged(q);
+ }
+ }
emit q->implicitHeightChanged();
}
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 1cf10df2f7..ffaec540a2 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -52,8 +52,8 @@
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlinfo.h>
#include <QtGui/qpen.h>
-#include <QtGui/qcursor.h>
#include <QtGui/qguiapplication.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qinputmethod.h>
#include <QtCore/qdebug.h>
#include <QtCore/qcoreevent.h>
@@ -75,6 +75,26 @@
QT_BEGIN_NAMESPACE
+#ifdef FOCUS_DEBUG
+void printFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1);
+void printFocusTree(QQuickItem *item, QQuickItem *scope, int depth)
+{
+ qWarning()
+ << QByteArray(depth, '\t').constData()
+ << (scope && QQuickItemPrivate::get(scope)->subFocusItem == item ? '*' : ' ')
+ << item->hasFocus()
+ << item->hasActiveFocus()
+ << item->isFocusScope()
+ << item;
+ foreach (QQuickItem *child, item->childItems()) {
+ printFocusTree(
+ child,
+ item->isFocusScope() || !scope ? item : scope,
+ item->isFocusScope() || !scope ? depth + 1 : depth);
+ }
+}
+#endif
+
static void QQuickItem_parentNotifier(QObject *o, intptr_t, QQmlNotifier **n)
{
QQuickItemPrivate *d = QQuickItemPrivate::get(static_cast<QQuickItem *>(o));
@@ -1613,9 +1633,6 @@ void QQuickItemPrivate::setAccessibleFlagAndListener()
if (item->d_func()->isAccessible)
break; // already set - grandparents should have the flag set as well.
- if (item->canvas() && item->canvas()->rootItem() == item)
- break; // don't add a listener to the canvas root item
-
item->d_func()->isAccessible = true;
item = item->d_func()->parentItem;
}
@@ -1939,6 +1956,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
if (d->canvas) {
QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem,
QQuickCanvasPrivate::DontChangeFocusProperty);
+ if (scopeFocusedItem != this)
+ QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, true);
} else {
QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, false);
}
@@ -1990,7 +2009,10 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
while (!scopeItem->isFocusScope() && scopeItem->parentItem())
scopeItem = scopeItem->parentItem();
- if (scopeItem->scopedFocusItem()) {
+ if (QQuickItemPrivate::get(scopeItem)->subFocusItem
+ || (!scopeItem->isFocusScope() && scopeItem->hasFocus())) {
+ if (scopeFocusedItem != this)
+ QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, false);
QQuickItemPrivate::get(scopeFocusedItem)->focus = false;
emit scopeFocusedItem->focusChanged(false);
} else {
@@ -4145,7 +4167,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
for (int ii = 0; ii < childItems.count(); ++ii) {
QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(
- flags & QQuickItem::ItemIsFocusScope ? q : scope, newEffectiveEnable);
+ (flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable);
}
if (canvas && scope && effectiveEnable && focus) {
@@ -4509,6 +4531,12 @@ void QQuickItem::resetWidth()
void QQuickItemPrivate::implicitWidthChanged()
{
Q_Q(QQuickItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitWidth) {
+ change.listener->itemImplicitWidthChanged(q);
+ }
+ }
emit q->implicitWidthChanged();
}
@@ -4631,6 +4659,12 @@ void QQuickItem::resetHeight()
void QQuickItemPrivate::implicitHeightChanged()
{
Q_Q(QQuickItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitHeight) {
+ change.listener->itemImplicitHeightChanged(q);
+ }
+ }
emit q->implicitHeightChanged();
}
@@ -4781,6 +4815,7 @@ void QQuickItem::setFocus(bool focus)
QVarLengthArray<QQuickItem *, 20> changed;
QQuickItem *oldSubFocusItem = QQuickItemPrivate::get(scope)->subFocusItem;
if (oldSubFocusItem) {
+ QQuickItemPrivate::get(oldSubFocusItem)->updateSubFocusItem(scope, false);
QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
changed << oldSubFocusItem;
}
@@ -4850,7 +4885,7 @@ bool QQuickItem::isUnderMouse() const
if (!d->canvas)
return false;
- QPoint cursorPos = QCursor::pos();
+ QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition;
if (QRectF(0, 0, width(), height()).contains(mapFromScene(cursorPos))) // ### refactor: d->canvas->mapFromGlobal(cursorPos))))
return true;
return false;
@@ -5669,10 +5704,11 @@ void QQuickItemLayer::activateEffect()
Q_ASSERT(m_effectComponent);
Q_ASSERT(!m_effect);
- QObject *created = m_effectComponent->create();
+ QObject *created = m_effectComponent->beginCreate(m_effectComponent->creationContext());
m_effect = qobject_cast<QQuickItem *>(created);
if (!m_effect) {
qWarning("Item: layer.effect is not a QML Item.");
+ m_effectComponent->completeCreate();
delete created;
return;
}
@@ -5683,6 +5719,7 @@ void QQuickItemLayer::activateEffect()
}
m_effect->setVisible(m_item->isVisible());
m_effect->setProperty(m_name, qVariantFromValue<QObject *>(m_effectSource));
+ m_effectComponent->completeCreate();
}
void QQuickItemLayer::deactivateEffect()
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 01e8b4d335..89c09ed015 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -302,6 +302,8 @@ public:
Parent = 0x20,
Children = 0x40,
Rotation = 0x80,
+ ImplicitWidth = 0x100,
+ ImplicitHeight = 0x200
};
Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
diff --git a/src/quick/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h
index 3a5c25f5f5..cbdfb2b18b 100644
--- a/src/quick/items/qquickitemchangelistener_p.h
+++ b/src/quick/items/qquickitemchangelistener_p.h
@@ -74,6 +74,8 @@ public:
virtual void itemChildRemoved(QQuickItem *, QQuickItem *) {}
virtual void itemParentChanged(QQuickItem *, QQuickItem *) {}
virtual void itemRotationChanged(QQuickItem *) {}
+ virtual void itemImplicitWidthChanged(QQuickItem *) {}
+ virtual void itemImplicitHeightChanged(QQuickItem *) {}
virtual QQuickAnchorsPrivate *anchorPrivate() { return 0; }
};
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 6f33545185..1cc2637fe6 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -577,7 +577,7 @@ void QQuickListViewPrivate::initializeViewItem(FxViewItem *item)
itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
if (sectionCriteria && sectionCriteria->delegate()) {
- if (item->attached->m_prevSection != item->attached->m_section)
+ if (QString::compare(item->attached->m_prevSection, item->attached->m_section, Qt::CaseInsensitive))
updateInlineSection(static_cast<FxListItemSG*>(item));
}
}
@@ -962,7 +962,7 @@ void QQuickListViewPrivate::updateInlineSection(FxListItemSG *listItem)
{
if (!sectionCriteria || !sectionCriteria->delegate())
return;
- if (listItem->attached->m_prevSection != listItem->attached->m_section
+ if (QString::compare(listItem->attached->m_prevSection, listItem->attached->m_section, Qt::CaseInsensitive)
&& (sectionCriteria->labelPositioning() & QQuickViewSection::InlineLabels
|| (listItem->index == 0 && sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart))) {
if (!listItem->section()) {
@@ -1022,7 +1022,7 @@ void QQuickListViewPrivate::updateStickySections()
if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart && isValid() && visibleItems.count()) {
if (!currentSectionItem) {
currentSectionItem = getSectionItem(currentSection);
- } else if (currentStickySection != currentSection) {
+ } else if (QString::compare(currentStickySection, currentSection, Qt::CaseInsensitive)) {
QQmlContext *context = QQmlEngine::contextForObject(currentSectionItem)->parentContext();
context->setContextProperty(QLatin1String("section"), currentSection);
}
@@ -1055,7 +1055,7 @@ void QQuickListViewPrivate::updateStickySections()
if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd && isValid() && visibleItems.count()) {
if (!nextSectionItem) {
nextSectionItem = getSectionItem(nextSection);
- } else if (nextStickySection != nextSection) {
+ } else if (QString::compare(nextStickySection, nextSection, Qt::CaseInsensitive)) {
QQmlContext *context = QQmlEngine::contextForObject(nextSectionItem)->parentContext();
context->setContextProperty(QLatin1String("section"), nextSection);
}
@@ -2040,6 +2040,9 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation)
sections, etc. for an address book)
\endlist
+ A case insensitive comparison is used when determining section
+ boundaries.
+
\c section.delegate holds the delegate component for each section.
\c section.labelPositioning determines whether the current and/or
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index f41ba44943..864e03bf43 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -52,9 +52,11 @@
QT_BEGIN_NAMESPACE
+static const QQuickItemPrivate::ChangeTypes watchedChanges
+ = QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
+
QQuickLoaderPrivate::QQuickLoaderPrivate()
: item(0), component(0), itemContext(0), incubator(0), updatingSize(false),
- itemWidthValid(false), itemHeightValid(false),
active(true), loadingFromSource(false), asynchronous(false)
{
}
@@ -69,16 +71,23 @@ QQuickLoaderPrivate::~QQuickLoaderPrivate()
void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
{
- if (resizeItem == item) {
- if (!updatingSize && newGeometry.width() != oldGeometry.width())
- itemWidthValid = true;
- if (!updatingSize && newGeometry.height() != oldGeometry.height())
- itemHeightValid = true;
+ if (resizeItem == item)
_q_updateSize(false);
- }
QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
}
+void QQuickLoaderPrivate::itemImplicitWidthChanged(QQuickItem *)
+{
+ Q_Q(QQuickLoader);
+ q->setImplicitWidth(getImplicitWidth());
+}
+
+void QQuickLoaderPrivate::itemImplicitHeightChanged(QQuickItem *)
+{
+ Q_Q(QQuickLoader);
+ q->setImplicitHeight(getImplicitHeight());
+}
+
void QQuickLoaderPrivate::clear()
{
Q_Q(QQuickLoader);
@@ -103,7 +112,7 @@ void QQuickLoaderPrivate::clear()
if (item) {
QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- p->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ p->removeItemChangeListener(this, watchedChanges);
// We can't delete immediately because our item may have triggered
// the Loader to load a different item.
@@ -117,14 +126,32 @@ void QQuickLoaderPrivate::clear()
void QQuickLoaderPrivate::initResize()
{
QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- p->addItemChangeListener(this, QQuickItemPrivate::Geometry);
- // We may override the item's size, so we need to remember
- // whether the item provided its own valid size.
- itemWidthValid = p->widthValid;
- itemHeightValid = p->heightValid;
+ p->addItemChangeListener(this, watchedChanges);
_q_updateSize();
}
+qreal QQuickLoaderPrivate::getImplicitWidth() const
+{
+ Q_Q(const QQuickLoader);
+ // If the Loader has a valid width then Loader has set an explicit width on the
+ // item, and we want the item's implicitWidth. If the Loader's width has
+ // not been set then its implicitWidth is the width of the item.
+ if (item)
+ return q->widthValid() ? item->implicitWidth() : item->width();
+ return QQuickImplicitSizeItemPrivate::getImplicitWidth();
+}
+
+qreal QQuickLoaderPrivate::getImplicitHeight() const
+{
+ Q_Q(const QQuickLoader);
+ // If the Loader has a valid height then Loader has set an explicit height on the
+ // item, and we want the item's implicitHeight. If the Loader's height has
+ // not been set then its implicitHeight is the height of the item.
+ if (item)
+ return q->heightValid() ? item->implicitHeight() : item->height();
+ return QQuickImplicitSizeItemPrivate::getImplicitHeight();
+}
+
/*!
\qmlclass Loader QQuickLoader
\inqmlmodule QtQuick 2
@@ -245,7 +272,7 @@ QQuickLoader::~QQuickLoader()
Q_D(QQuickLoader);
if (d->item) {
QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
- p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ p->removeItemChangeListener(d, watchedChanges);
}
}
@@ -282,9 +309,16 @@ void QQuickLoader::setActive(bool newVal)
loadFromSourceComponent();
}
} else {
+ // cancel any current incubation
+ if (d->incubator) {
+ d->incubator->clear();
+ delete d->itemContext;
+ d->itemContext = 0;
+ }
+
if (d->item) {
QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
- p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ p->removeItemChangeListener(d, watchedChanges);
// We can't delete immediately because our item may have triggered
// the Loader to load a different item.
@@ -553,6 +587,14 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
QQuickItem *item = qobject_cast<QQuickItem*>(obj);
if (item) {
+ // If the item doesn't have an explicit size, but the Loader
+ // does, then set the item's size now before bindings are
+ // evaluated, otherwise we will end up resizing the item
+ // later and triggering any affected bindings/anchors.
+ if (widthValid && !QQuickItemPrivate::get(item)->widthValid)
+ item->setWidth(q->width());
+ if (heightValid && !QQuickItemPrivate::get(item)->heightValid)
+ item->setHeight(q->height());
QQml_setParent_noEvent(itemContext, obj);
QQml_setParent_noEvent(item, q);
item->setParentItem(q);
@@ -607,7 +649,8 @@ void QQuickLoaderPrivate::incubatorStateChanged(QQmlIncubator::Status status)
emit q->sourceComponentChanged();
emit q->statusChanged();
emit q->progressChanged();
- emit q->loaded();
+ if (status == QQmlIncubator::Ready)
+ emit q->loaded();
disposeInitialPropertyValues(); // cleanup
}
@@ -812,15 +855,13 @@ void QQuickLoaderPrivate::_q_updateSize(bool loaderGeometryChanged)
updatingSize = true;
- qreal iWidth = !itemWidthValid ? item->implicitWidth() : item->width();
- qreal iHeight = !itemHeightValid ? item->implicitHeight() : item->height();
- q->setImplicitSize(iWidth, iHeight);
-
if (loaderGeometryChanged && q->widthValid())
item->setWidth(q->width());
if (loaderGeometryChanged && q->heightValid())
item->setHeight(q->height());
+ q->setImplicitSize(getImplicitWidth(), getImplicitHeight());
+
updatingSize = false;
}
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 1ad7756ed8..0978911315 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -87,6 +87,8 @@ public:
~QQuickLoaderPrivate();
void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void itemImplicitWidthChanged(QQuickItem *);
+ void itemImplicitHeightChanged(QQuickItem *);
void clear();
void initResize();
void load();
@@ -97,6 +99,9 @@ public:
QUrl resolveSourceUrl(QQmlV8Function *args);
v8::Handle<v8::Object> extractInitialPropertyValues(QQmlV8Function *args, QObject *loader, bool *error);
+ virtual qreal getImplicitWidth() const;
+ virtual qreal getImplicitHeight() const;
+
QUrl source;
QQuickItem *item;
QQmlComponent *component;
@@ -105,8 +110,6 @@ public:
v8::Persistent<v8::Object> initialPropertyValues;
v8::Persistent<v8::Object> qmlGlobalForIpv;
bool updatingSize: 1;
- bool itemWidthValid : 1;
- bool itemHeightValid : 1;
bool active : 1;
bool loadingFromSource : 1;
bool asynchronous : 1;
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index 110cc6ad7a..2ba7b80748 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -236,7 +236,7 @@ void QQuickTouchPoint::setSceneY(qreal sceneY)
\list
\li setting \c touchPoints to provide touch point objects with properties that can be bound to
- \li using the onTouchUpdated or onTouchPointsPressed, onTouchPointsUpdated and onTouchPointsReleased handlers
+ \li using the onTouchUpdated or onPressed, onUpdated and onReleased handlers
\endlist
While a MultiPointTouchArea \e can take exclusive ownership of certain touch points, it is also possible to have
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index 962dddafc9..836943c478 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -58,13 +58,13 @@
// The number of samples to use in calculating the velocity of a flick
#ifndef QML_FLICK_SAMPLEBUFFER
-#define QML_FLICK_SAMPLEBUFFER 3
+#define QML_FLICK_SAMPLEBUFFER 1
#endif
// The number of samples to discard when calculating the flick velocity.
// Touch panels often produce inaccurate results as the finger is lifted.
#ifndef QML_FLICK_DISCARDSAMPLES
-#define QML_FLICK_DISCARDSAMPLES 1
+#define QML_FLICK_DISCARDSAMPLES 0
#endif
// The default maximum velocity of a flick.
@@ -114,8 +114,8 @@ void QQuickPathViewAttached::setValue(const QByteArray &name, const QVariant &va
}
QQuickPathViewPrivate::QQuickPathViewPrivate()
- : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0), lastDist(0)
- , lastElapsed(0), offset(0.0), offsetAdj(0.0), mappedRange(1.0)
+ : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0)
+ , offset(0.0), offsetAdj(0.0), mappedRange(1.0)
, stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true)
, autoHighlight(true), highlightUp(false), layoutScheduled(false)
, moving(false), flicking(false), requestedOnPath(false), inRequest(false)
@@ -127,7 +127,7 @@ QQuickPathViewPrivate::QQuickPathViewPrivate()
, highlightPosition(0)
, highlightRangeStart(0), highlightRangeEnd(0)
, highlightRangeMode(QQuickPathView::StrictlyEnforceRange)
- , highlightMoveDuration(300), modelCount(0)
+ , highlightMoveDuration(300), modelCount(0), snapMode(QQuickPathView::NoSnap)
{
}
@@ -139,7 +139,7 @@ void QQuickPathViewPrivate::init()
q->setFlag(QQuickItem::ItemIsFocusScope);
q->setFiltersChildMouseEvents(true);
FAST_CONNECT(&tl, SIGNAL(updated()), q, SLOT(ticked()))
- lastPosTime.invalidate();
+ timer.invalidate();
FAST_CONNECT(&tl, SIGNAL(completed()), q, SLOT(movementEnding()))
}
@@ -266,7 +266,8 @@ qreal QQuickPathViewPrivate::positionOfIndex(qreal index) const
if (model && index >= 0 && index < modelCount) {
qreal start = 0.0;
- if (haveHighlightRange && highlightRangeMode != QQuickPathView::NoHighlightRange)
+ if (haveHighlightRange && (highlightRangeMode != QQuickPathView::NoHighlightRange
+ || snapMode != QQuickPathView::NoSnap))
start = highlightRangeStart;
qreal globalPos = index + offset;
globalPos = qmlMod(globalPos, qreal(modelCount)) / modelCount;
@@ -698,7 +699,7 @@ void QQuickPathView::setCurrentIndex(int idx)
if (d->modelCount) {
d->createCurrentItem();
if (d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange)
- d->snapToCurrent();
+ d->snapToIndex(d->currentIndex);
d->currentItemOffset = d->positionOfIndex(d->currentIndex);
d->updateHighlight();
}
@@ -889,7 +890,7 @@ void QQuickPathView::setPreferredHighlightBegin(qreal start)
if (d->highlightRangeStart == start || start < 0 || start > 1.0)
return;
d->highlightRangeStart = start;
- d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ d->haveHighlightRange = d->highlightRangeStart <= d->highlightRangeEnd;
refill();
emit preferredHighlightBeginChanged();
}
@@ -906,7 +907,7 @@ void QQuickPathView::setPreferredHighlightEnd(qreal end)
if (d->highlightRangeEnd == end || end < 0 || end > 1.0)
return;
d->highlightRangeEnd = end;
- d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ d->haveHighlightRange = d->highlightRangeStart <= d->highlightRangeEnd;
refill();
emit preferredHighlightEndChanged();
}
@@ -923,10 +924,12 @@ void QQuickPathView::setHighlightRangeMode(HighlightRangeMode mode)
if (d->highlightRangeMode == mode)
return;
d->highlightRangeMode = mode;
- d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ d->haveHighlightRange = d->highlightRangeStart <= d->highlightRangeEnd;
if (d->haveHighlightRange) {
d->regenerate();
- d->snapToCurrent();
+ int index = d->highlightRangeMode != NoHighlightRange ? d->currentIndex : d->calcCurrentIndex();
+ if (index >= 0)
+ d->snapToIndex(index);
}
emit highlightRangeModeChanged();
}
@@ -1175,6 +1178,41 @@ void QQuickPathView::setPathItemCount(int i)
emit pathItemCountChanged();
}
+/*!
+ \qmlproperty enumeration QtQuick2::PathView::snapMode
+
+ This property determines how the items will settle following a drag or flick.
+ The possible values are:
+
+ \list
+ \li PathView.NoSnap (default) - the items stop anywhere along the path.
+ \li PathView.SnapToItem - the items settle with an item aligned with the \l preferredHighlightBegin.
+ \li PathView.SnapOneItem - the items settle no more than one item away from the item nearest
+ \l preferredHighlightBegin at the time the press is released. This mode is particularly
+ useful for moving one page at a time.
+ \endlist
+
+ \c snapMode does not affect the \l currentIndex. To update the
+ \l currentIndex as the view is moved, set \l highlightRangeMode
+ to \c PathView.StrictlyEnforceRange (default for PathView).
+
+ \sa highlightRangeMode
+*/
+QQuickPathView::SnapMode QQuickPathView::snapMode() const
+{
+ Q_D(const QQuickPathView);
+ return d->snapMode;
+}
+
+void QQuickPathView::setSnapMode(SnapMode mode)
+{
+ Q_D(QQuickPathView);
+ if (mode == d->snapMode)
+ return;
+ d->snapMode = mode;
+ emit snapModeChanged();
+}
+
QPointF QQuickPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
{
qreal samples = qMin(path->path().length()/5, qreal(500.0));
@@ -1236,6 +1274,15 @@ qreal QQuickPathViewPrivate::calcVelocity() const
return velocity;
}
+qint64 QQuickPathViewPrivate::computeCurrentTime(QInputEvent *event)
+{
+ if (0 != event->timestamp() && QQuickItemPrivate::consistentTime == -1) {
+ return event->timestamp();
+ }
+
+ return QQuickItemPrivate::elapsed(timer);
+}
+
void QQuickPathView::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickPathView);
@@ -1277,9 +1324,8 @@ void QQuickPathViewPrivate::handleMousePressEvent(QMouseEvent *event)
else
stealMouse = false;
- lastElapsed = 0;
- lastDist = 0;
- QQuickItemPrivate::start(lastPosTime);
+ QQuickItemPrivate::start(timer);
+ lastPosTime = computeCurrentTime(event);
tl.clear();
}
@@ -1299,7 +1345,7 @@ void QQuickPathView::mouseMoveEvent(QMouseEvent *event)
void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
{
Q_Q(QQuickPathView);
- if (!interactive || !lastPosTime.isValid() || !model || !modelCount)
+ if (!interactive || !timer.isValid() || !model || !modelCount)
return;
qreal newPc;
@@ -1308,10 +1354,10 @@ void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
QPointF delta = pathPoint - startPoint;
if (qAbs(delta.x()) > qApp->styleHints()->startDragDistance() || qAbs(delta.y()) > qApp->styleHints()->startDragDistance()) {
stealMouse = true;
- startPc = newPc;
}
}
+ qint64 currentTimestamp = computeCurrentTime(event);
if (stealMouse) {
moveReason = QQuickPathViewPrivate::Mouse;
qreal diff = (newPc - startPc)*modelCount*mappedRange;
@@ -1323,10 +1369,9 @@ void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
else if (diff < -modelCount/2)
diff += modelCount;
- lastElapsed = QQuickItemPrivate::restart(lastPosTime);
- lastDist = diff;
- startPc = newPc;
- addVelocitySample(diff / (qreal(lastElapsed) / 1000.));
+ qint64 elapsed = currentTimestamp - lastPosTime;
+ if (elapsed > 0)
+ addVelocitySample(diff / (qreal(elapsed) / 1000.));
}
if (!moving) {
moving = true;
@@ -1334,6 +1379,8 @@ void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event)
emit q->movementStarted();
}
}
+ startPc = newPc;
+ lastPosTime = currentTimestamp;
}
void QQuickPathView::mouseReleaseEvent(QMouseEvent *event)
@@ -1353,8 +1400,8 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
Q_Q(QQuickPathView);
stealMouse = false;
q->setKeepMouseGrab(false);
- if (!interactive || !lastPosTime.isValid() || !model || !modelCount) {
- lastPosTime.invalidate();
+ if (!interactive || !timer.isValid() || !model || !modelCount) {
+ timer.invalidate();
if (!tl.isActive())
q->movementEnding();
return;
@@ -1364,7 +1411,7 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
qreal count = modelCount*mappedRange;
qreal pixelVelocity = (path->path().length()/count) * velocity;
if (qAbs(pixelVelocity) > MinimumFlickVelocity) {
- if (qAbs(pixelVelocity) > maximumFlickVelocity) {
+ if (qAbs(pixelVelocity) > maximumFlickVelocity || snapMode == QQuickPathView::SnapOneItem) {
// limit velocity
qreal maxVel = velocity < 0 ? -maximumFlickVelocity : maximumFlickVelocity;
velocity = maxVel / (path->path().length()/count);
@@ -1373,14 +1420,24 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
qreal v2 = velocity*velocity;
qreal accel = deceleration/10;
qreal dist = 0;
- if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
- // + 0.25 to encourage moving at least one item in the flick direction
- dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0) + 0.25));
- // round to nearest item.
- if (velocity > 0.)
- dist = qRound(dist + offset) - offset;
- else
- dist = qRound(dist - offset) + offset;
+ if (haveHighlightRange && (highlightRangeMode == QQuickPathView::StrictlyEnforceRange
+ || snapMode != QQuickPathView::NoSnap)) {
+ if (snapMode == QQuickPathView::SnapOneItem) {
+ // encourage snapping one item in direction of motion
+ if (velocity > 0.)
+ dist = qRound(0.5 + offset) - offset;
+ else
+ dist = qRound(0.5 - offset) + offset;
+ } else {
+ // + 0.25 to encourage moving at least one item in the flick direction
+ dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0) + 0.25));
+
+ // round to nearest item.
+ if (velocity > 0.)
+ dist = qRound(dist + offset) - offset;
+ else
+ dist = qRound(dist - offset) + offset;
+ }
// Calculate accel required to stop on item boundary
if (dist <= 0.) {
dist = 0.;
@@ -1405,7 +1462,7 @@ void QQuickPathViewPrivate::handleMouseReleaseEvent(QMouseEvent *)
fixOffset();
}
- lastPosTime.invalidate();
+ timer.invalidate();
if (!tl.isActive())
q->movementEnding();
}
@@ -1441,8 +1498,8 @@ bool QQuickPathView::sendMouseEvent(QMouseEvent *event)
grabMouse();
return d->stealMouse;
- } else if (d->lastPosTime.isValid()) {
- d->lastPosTime.invalidate();
+ } else if (d->timer.isValid()) {
+ d->timer.invalidate();
d->fixOffset();
}
if (event->type() == QEvent::MouseButtonRelease)
@@ -1476,7 +1533,7 @@ void QQuickPathView::mouseUngrabEvent()
// fix our state
d->stealMouse = false;
setKeepMouseGrab(false);
- d->lastPosTime.invalidate();
+ d->timer.invalidate();
d->fixOffset();
if (!d->tl.isActive())
movementEnding();
@@ -1557,7 +1614,8 @@ void QQuickPathView::refill()
if (d->items.count() < count) {
int idx = qRound(d->modelCount - d->offset) % d->modelCount;
qreal startPos = 0.0;
- if (d->haveHighlightRange && d->highlightRangeMode != QQuickPathView::NoHighlightRange)
+ if (d->haveHighlightRange && (d->highlightRangeMode != QQuickPathView::NoHighlightRange
+ || d->snapMode != QQuickPathView::NoSnap))
startPos = d->highlightRangeStart;
if (d->firstIndex >= 0) {
startPos = d->positionOfIndex(d->firstIndex);
@@ -1833,22 +1891,23 @@ void QQuickPathViewPrivate::fixOffset()
{
Q_Q(QQuickPathView);
if (model && items.count()) {
- if (haveHighlightRange && highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+ if (haveHighlightRange && (highlightRangeMode == QQuickPathView::StrictlyEnforceRange
+ || snapMode != QQuickPathView::NoSnap)) {
int curr = calcCurrentIndex();
- if (curr != currentIndex)
+ if (curr != currentIndex && highlightRangeMode == QQuickPathView::StrictlyEnforceRange)
q->setCurrentIndex(curr);
else
- snapToCurrent();
+ snapToIndex(curr);
}
}
}
-void QQuickPathViewPrivate::snapToCurrent()
+void QQuickPathViewPrivate::snapToIndex(int index)
{
if (!model || modelCount <= 0)
return;
- qreal targetOffset = qmlMod(modelCount - currentIndex, modelCount);
+ qreal targetOffset = qmlMod(modelCount - index, modelCount);
if (offset == targetOffset)
return;
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
index 8b15e85b8a..2c0c106113 100644
--- a/src/quick/items/qquickpathview_p.h
+++ b/src/quick/items/qquickpathview_p.h
@@ -83,8 +83,10 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount NOTIFY pathItemCountChanged)
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
Q_ENUMS(HighlightRangeMode)
+ Q_ENUMS(SnapMode)
public:
QQuickPathView(QQuickItem *parent=0);
@@ -144,6 +146,10 @@ public:
int pathItemCount() const;
void setPathItemCount(int);
+ enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
static QQuickPathViewAttached *qmlAttachedProperties(QObject *);
public Q_SLOTS:
@@ -176,6 +182,7 @@ Q_SIGNALS:
void movementEnded();
void flickStarted();
void flickEnded();
+ void snapModeChanged();
protected:
virtual void updatePolish();
diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index ac74e9a568..3285b40036 100644
--- a/src/quick/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
@@ -122,10 +122,11 @@ public:
void setAdjustedOffset(qreal offset);
void regenerate();
void updateItem(QQuickItem *, qreal);
- void snapToCurrent();
+ void snapToIndex(int index);
QPointF pointNear(const QPointF &point, qreal *nearPercent=0) const;
void addVelocitySample(qreal v);
qreal calcVelocity() const;
+ qint64 computeCurrentTime(QInputEvent *event);
QQuickPath *path;
int currentIndex;
@@ -133,8 +134,6 @@ public:
qreal currentItemOffset;
qreal startPc;
QPointF startPoint;
- qreal lastDist;
- int lastElapsed;
qreal offset;
qreal offsetAdj;
qreal mappedRange;
@@ -149,7 +148,8 @@ public:
bool flicking : 1;
bool requestedOnPath : 1;
bool inRequest : 1;
- QElapsedTimer lastPosTime;
+ QElapsedTimer timer;
+ qint64 lastPosTime;
QPointF lastPos;
qreal dragMargin;
qreal deceleration;
@@ -180,6 +180,7 @@ public:
int highlightMoveDuration;
int modelCount;
QPODVector<qreal,10> velocityBuffer;
+ QQuickPathView::SnapMode snapMode;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index e232746417..1549057ef8 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -88,6 +88,446 @@ const char *qtTexCoordAttributeName()
return qt_texcoord_attribute_name;
}
+namespace {
+
+ enum VariableQualifier {
+ AttributeQualifier,
+ UniformQualifier
+ };
+
+ inline bool qt_isalpha(char c)
+ {
+ char ch = c | 0x20;
+ return (ch >= 'a' && ch <= 'z') || c == '_';
+ }
+
+ inline bool qt_isalnum(char c)
+ {
+ return qt_isalpha(c) || (c >= '0' && c <= '9');
+ }
+
+ inline bool qt_isspace(char c)
+ {
+ return c == ' ' || (c >= 0x09 && c <= 0x0d);
+ }
+
+ // Returns -1 if not found, returns index to first character after the name if found.
+ int qt_search_for_variable(const char *s, int length, int index, VariableQualifier &decl,
+ int &typeIndex, int &typeLength,
+ int &nameIndex, int &nameLength)
+ {
+ enum Identifier {
+ QualifierIdentifier, // Base state
+ PrecisionIdentifier,
+ TypeIdentifier,
+ NameIdentifier
+ };
+ Identifier expected = QualifierIdentifier;
+ bool compilerDirectiveExpected = index == 0;
+
+ while (index < length) {
+ // Skip whitespace.
+ while (qt_isspace(s[index])) {
+ compilerDirectiveExpected |= s[index] == '\n';
+ ++index;
+ }
+
+ if (qt_isalpha(s[index])) {
+ // Read identifier.
+ int idIndex = index;
+ ++index;
+ while (qt_isalnum(s[index]))
+ ++index;
+ int idLength = index - idIndex;
+
+ const int attrLen = sizeof("attribute") - 1;
+ const int uniLen = sizeof("uniform") - 1;
+ const int loLen = sizeof("lowp") - 1;
+ const int medLen = sizeof("mediump") - 1;
+ const int hiLen = sizeof("highp") - 1;
+
+ switch (expected) {
+ case QualifierIdentifier:
+ if (idLength == attrLen && qstrncmp("attribute", s + idIndex, attrLen) == 0) {
+ decl = AttributeQualifier;
+ expected = PrecisionIdentifier;
+ } else if (idLength == uniLen && qstrncmp("uniform", s + idIndex, uniLen) == 0) {
+ decl = UniformQualifier;
+ expected = PrecisionIdentifier;
+ }
+ break;
+ case PrecisionIdentifier:
+ if ((idLength == loLen && qstrncmp("lowp", s + idIndex, loLen) == 0)
+ || (idLength == medLen && qstrncmp("mediump", s + idIndex, medLen) == 0)
+ || (idLength == hiLen && qstrncmp("highp", s + idIndex, hiLen) == 0))
+ {
+ expected = TypeIdentifier;
+ break;
+ }
+ // Fall through.
+ case TypeIdentifier:
+ typeIndex = idIndex;
+ typeLength = idLength;
+ expected = NameIdentifier;
+ break;
+ case NameIdentifier:
+ nameIndex = idIndex;
+ nameLength = idLength;
+ return index; // Attribute or uniform declaration found. Return result.
+ default:
+ break;
+ }
+ } else if (s[index] == '#' && compilerDirectiveExpected) {
+ // Skip compiler directives.
+ ++index;
+ while (index < length && (s[index] != '\n' || s[index - 1] == '\\'))
+ ++index;
+ } else if (s[index] == '/' && s[index + 1] == '/') {
+ // Skip comments.
+ index += 2;
+ while (index < length && s[index] != '\n')
+ ++index;
+ } else if (s[index] == '/' && s[index + 1] == '*') {
+ // Skip comments.
+ index += 2;
+ while (index < length && (s[index] != '*' || s[index + 1] != '/'))
+ ++index;
+ if (index < length)
+ index += 2; // Skip star-slash.
+ } else {
+ expected = QualifierIdentifier;
+ ++index;
+ }
+ compilerDirectiveExpected = false;
+ }
+ return -1;
+ }
+}
+
+
+
+QQuickShaderEffectCommon::~QQuickShaderEffectCommon()
+{
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType)
+ qDeleteAll(signalMappers[shaderType]);
+}
+
+void QQuickShaderEffectCommon::disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType)
+{
+ for (int i = 0; i < uniformData[shaderType].size(); ++i) {
+ if (signalMappers[shaderType].at(i) == 0)
+ continue;
+ const UniformData &d = uniformData[shaderType].at(i);
+ QSignalMapper *mapper = signalMappers[shaderType].at(i);
+ QObject::disconnect(item, 0, mapper, SLOT(map()));
+ QObject::disconnect(mapper, SIGNAL(mapped(int)), item, SLOT(propertyChanged(int)));
+ if (d.specialType == UniformData::Sampler) {
+ QQuickItem *source = qobject_cast<QQuickItem *>(qVariantValue<QObject *>(d.value));
+ if (source) {
+ if (item->canvas())
+ QQuickItemPrivate::get(source)->derefCanvas();
+ QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
+ }
+ }
+ }
+}
+
+void QQuickShaderEffectCommon::connectPropertySignals(QQuickItem *item, Key::ShaderType shaderType)
+{
+ for (int i = 0; i < uniformData[shaderType].size(); ++i) {
+ if (signalMappers[shaderType].at(i) == 0)
+ continue;
+ const UniformData &d = uniformData[shaderType].at(i);
+ int pi = item->metaObject()->indexOfProperty(d.name.constData());
+ if (pi >= 0) {
+ QMetaProperty mp = item->metaObject()->property(pi);
+ if (!mp.hasNotifySignal())
+ qWarning("QQuickShaderEffect: property '%s' does not have notification method!", d.name.constData());
+ QByteArray signalName("2");
+ signalName.append(mp.notifySignal().methodSignature());
+ QSignalMapper *mapper = signalMappers[shaderType].at(i);
+ QObject::connect(item, signalName, mapper, SLOT(map()));
+ QObject::connect(mapper, SIGNAL(mapped(int)), item, SLOT(propertyChanged(int)));
+ } else {
+ // If the source is set via a dynamic property, like the layer is, then we need this
+ // check to disable the warning.
+ if (!item->property(d.name.constData()).isValid())
+ qWarning("QQuickShaderEffect: '%s' does not have a matching property!", d.name.constData());
+ }
+
+ if (d.specialType == UniformData::Sampler) {
+ QQuickItem *source = qobject_cast<QQuickItem *>(qVariantValue<QObject *>(d.value));
+ if (source) {
+ if (item->canvas())
+ QQuickItemPrivate::get(source)->refCanvas(item->canvas());
+ QObject::connect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
+ }
+ }
+ }
+}
+
+void QQuickShaderEffectCommon::updateParseLog(bool ignoreAttributes)
+{
+ parseLog.clear();
+ if (!ignoreAttributes) {
+ if (!attributes.contains(qt_position_attribute_name)) {
+ parseLog += QLatin1String("Warning: Missing reference to \'");
+ parseLog += QLatin1String(qt_position_attribute_name);
+ parseLog += QLatin1String("\'.\n");
+ }
+ if (!attributes.contains(qt_texcoord_attribute_name)) {
+ parseLog += QLatin1String("Warning: Missing reference to \'");
+ parseLog += QLatin1String(qt_texcoord_attribute_name);
+ parseLog += QLatin1String("\'.\n");
+ }
+ }
+ bool respectsMatrix = false;
+ bool respectsOpacity = false;
+ for (int i = 0; i < uniformData[Key::VertexShader].size(); ++i)
+ respectsMatrix |= uniformData[Key::VertexShader].at(i).specialType == UniformData::Matrix;
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < uniformData[shaderType].size(); ++i)
+ respectsOpacity |= uniformData[shaderType].at(i).specialType == UniformData::Opacity;
+ }
+ if (!respectsMatrix)
+ parseLog += QLatin1String("Warning: Vertex shader is missing reference to \'qt_Matrix\'.\n");
+ if (!respectsOpacity)
+ parseLog += QLatin1String("Warning: Shaders are missing reference to \'qt_Opacity\'.\n");
+}
+
+void QQuickShaderEffectCommon::lookThroughShaderCode(QQuickItem *item, Key::ShaderType shaderType, const QByteArray &code)
+{
+ int index = 0;
+ int typeIndex, typeLength, nameIndex, nameLength;
+ const char *s = code.constData();
+ VariableQualifier decl;
+ while ((index = qt_search_for_variable(s, code.size(), index, decl, typeIndex, typeLength,
+ nameIndex, nameLength)) != -1)
+ {
+ if (decl == AttributeQualifier) {
+ if (shaderType == Key::VertexShader)
+ attributes.append(QByteArray(s + nameIndex, nameLength));
+ } else {
+ Q_ASSERT(decl == UniformQualifier);
+
+ const int sampLen = sizeof("sampler2D") - 1;
+ const int opLen = sizeof("qt_Opacity") - 1;
+ const int matLen = sizeof("qt_Matrix") - 1;
+
+ UniformData d;
+ QSignalMapper *mapper = 0;
+ d.name = QByteArray(s + nameIndex, nameLength);
+ if (nameLength == opLen && qstrncmp("qt_Opacity", s + nameIndex, opLen) == 0) {
+ d.specialType = UniformData::Opacity;
+ } else if (nameLength == matLen && qstrncmp("qt_Matrix", s + nameIndex, matLen) == 0) {
+ d.specialType = UniformData::Matrix;
+ } else {
+ mapper = new QSignalMapper;
+ mapper->setMapping(item, uniformData[shaderType].size() | (shaderType << 16));
+ d.value = item->property(d.name.constData());
+ bool sampler = typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0;
+ d.specialType = sampler ? UniformData::Sampler : UniformData::None;
+ }
+ uniformData[shaderType].append(d);
+ signalMappers[shaderType].append(mapper);
+ }
+ }
+}
+
+void QQuickShaderEffectCommon::updateShader(QQuickItem *item, Key::ShaderType shaderType)
+{
+ disconnectPropertySignals(item, shaderType);
+ qDeleteAll(signalMappers[shaderType]);
+ uniformData[shaderType].clear();
+ signalMappers[shaderType].clear();
+ if (shaderType == Key::VertexShader)
+ attributes.clear();
+
+ const QByteArray &code = source.sourceCode[shaderType];
+ if (code.isEmpty()) {
+ // Optimize for default code.
+ if (shaderType == Key::VertexShader) {
+ attributes.append(QByteArray(qt_position_attribute_name));
+ attributes.append(QByteArray(qt_texcoord_attribute_name));
+ UniformData d;
+ d.name = "qt_Matrix";
+ d.specialType = UniformData::Matrix;
+ uniformData[Key::VertexShader].append(d);
+ signalMappers[Key::VertexShader].append(0);
+ } else if (shaderType == Key::FragmentShader) {
+ UniformData d;
+ d.name = "qt_Opacity";
+ d.specialType = UniformData::Opacity;
+ uniformData[Key::FragmentShader].append(d);
+ signalMappers[Key::FragmentShader].append(0);
+ QSignalMapper *mapper = new QSignalMapper;
+ mapper->setMapping(item, 1 | (Key::FragmentShader << 16));
+ const char *sourceName = "source";
+ d.name = sourceName;
+ d.value = item->property(sourceName);
+ d.specialType = UniformData::Sampler;
+ uniformData[Key::FragmentShader].append(d);
+ signalMappers[Key::FragmentShader].append(mapper);
+ }
+ } else {
+ lookThroughShaderCode(item, shaderType, code);
+ }
+
+ connectPropertySignals(item, shaderType);
+}
+
+void QQuickShaderEffectCommon::updateMaterial(QQuickShaderEffectNode *node,
+ QQuickShaderEffectMaterial *material,
+ bool updateUniforms, bool updateUniformValues,
+ bool updateTextureProviders)
+{
+ if (updateUniforms) {
+ for (int i = 0; i < material->textureProviders.size(); ++i) {
+ QSGTextureProvider *t = material->textureProviders.at(i).second;
+ if (t) {
+ QObject::disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
+ QObject::disconnect(t, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
+ }
+ }
+ material->textureProviders.clear();
+
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < uniformData[shaderType].size(); ++i) {
+ const UniformData &d = uniformData[shaderType].at(i);
+ // First make room in the textureProviders array. Set to proper value further down.
+ if (d.specialType == UniformData::Sampler)
+ material->textureProviders.append(qMakePair(d.name, (QSGTextureProvider *)0));
+ }
+ material->uniforms[shaderType] = uniformData[shaderType];
+ }
+ updateUniformValues = false;
+ updateTextureProviders = true;
+ }
+
+ if (updateUniformValues) {
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ Q_ASSERT(uniformData[shaderType].size() == material->uniforms[shaderType].size());
+ for (int i = 0; i < uniformData[shaderType].size(); ++i)
+ material->uniforms[shaderType][i].value = uniformData[shaderType].at(i).value;
+ }
+ }
+
+ if (updateTextureProviders) {
+ int index = 0;
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < uniformData[shaderType].size(); ++i) {
+ const UniformData &d = uniformData[shaderType].at(i);
+ if (d.specialType != UniformData::Sampler)
+ continue;
+ Q_ASSERT(material->textureProviders.at(index).first == d.name);
+ QSGTextureProvider *oldProvider = material->textureProviders.at(index).second;
+ QSGTextureProvider *newProvider = 0;
+ QQuickItem *source = qobject_cast<QQuickItem *>(qVariantValue<QObject *>(d.value));
+ if (source && source->isTextureProvider())
+ newProvider = source->textureProvider();
+ if (newProvider != oldProvider) {
+ if (oldProvider) {
+ QObject::disconnect(oldProvider, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
+ QObject::disconnect(oldProvider, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
+ }
+ if (newProvider) {
+ Q_ASSERT_X(newProvider->thread() == QThread::currentThread(),
+ "QQuickShaderEffect::updatePaintNode",
+ "Texture provider must belong to the rendering thread");
+ QObject::connect(newProvider, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
+ QObject::connect(newProvider, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
+ } else {
+ const char *typeName = source ? source->metaObject()->className() : d.value.typeName();
+ qWarning("ShaderEffect: Property '%s' is not assigned a valid texture provider (%s).",
+ d.name.constData(), typeName);
+ }
+ material->textureProviders[index].second = newProvider;
+ }
+ ++index;
+ }
+ }
+ Q_ASSERT(index == material->textureProviders.size());
+ }
+}
+
+void QQuickShaderEffectCommon::updateCanvas(QQuickCanvas *canvas)
+{
+ // See comment in QQuickShaderEffectCommon::propertyChanged().
+ if (canvas) {
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < uniformData[shaderType].size(); ++i) {
+ const UniformData &d = uniformData[shaderType].at(i);
+ if (d.specialType == UniformData::Sampler) {
+ QQuickItem *source = qobject_cast<QQuickItem *>(qVariantValue<QObject *>(d.value));
+ if (source)
+ QQuickItemPrivate::get(source)->refCanvas(canvas);
+ }
+ }
+ }
+ } else {
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < uniformData[shaderType].size(); ++i) {
+ const UniformData &d = uniformData[shaderType].at(i);
+ if (d.specialType == UniformData::Sampler) {
+ QQuickItem *source = qobject_cast<QQuickItem *>(qVariantValue<QObject *>(d.value));
+ if (source)
+ QQuickItemPrivate::get(source)->derefCanvas();
+ }
+ }
+ }
+ }
+}
+
+void QQuickShaderEffectCommon::sourceDestroyed(QObject *object)
+{
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < uniformData[shaderType].size(); ++i) {
+ UniformData &d = uniformData[shaderType][i];
+ if (d.specialType == UniformData::Sampler && qVariantCanConvert<QObject *>(d.value)) {
+ if (qVariantValue<QObject *>(d.value) == object)
+ d.value = QVariant();
+ }
+ }
+ }
+}
+
+
+void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId,
+ bool *textureProviderChanged)
+{
+ Key::ShaderType shaderType = Key::ShaderType(mappedId >> 16);
+ int index = mappedId & 0xffff;
+ UniformData &d = uniformData[shaderType][index];
+ if (d.specialType == UniformData::Sampler) {
+ QQuickItem *source = qobject_cast<QQuickItem *>(qVariantValue<QObject *>(d.value));
+ if (source) {
+ if (item->canvas())
+ QQuickItemPrivate::get(source)->derefCanvas();
+ QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
+ }
+
+ d.value = item->property(d.name.constData());
+
+ source = qobject_cast<QQuickItem *>(qVariantValue<QObject *>(d.value));
+ if (source) {
+ // 'source' needs a canvas to get a scene graph node. It usually gets one through its
+ // parent, but if the source item is "inline" rather than a reference -- i.e.
+ // "property variant source: Image { }" instead of "property variant source: foo" -- it
+ // will not get a parent. In those cases, 'source' should get the canvas from 'item'.
+ if (item->canvas())
+ QQuickItemPrivate::get(source)->refCanvas(item->canvas());
+ QObject::connect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*)));
+ }
+ if (textureProviderChanged)
+ *textureProviderChanged = true;
+ } else {
+ d.value = item->property(d.name.constData());
+ if (textureProviderChanged)
+ *textureProviderChanged = false;
+ }
+}
+
+
/*!
\qmlclass ShaderEffect QQuickShaderEffect
\inqmlmodule QtQuick 2
@@ -187,18 +627,21 @@ QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
, m_cullMode(NoCulling)
, m_status(Uncompiled)
, m_blending(true)
- , m_dirtyData(true)
- , m_programDirty(true)
+ , m_dirtyUniforms(true)
+ , m_dirtyUniformValues(true)
+ , m_dirtyTextureProviders(true)
+ , m_dirtyProgram(true)
+ , m_dirtyParseLog(true)
, m_dirtyMesh(true)
, m_dirtyGeometry(true)
- , m_complete(false)
{
setFlag(QQuickItem::ItemHasContents);
}
QQuickShaderEffect::~QQuickShaderEffect()
{
- reset();
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType)
+ m_common.disconnectPropertySignals(this, Key::ShaderType(shaderType));
}
/*!
@@ -211,11 +654,16 @@ QQuickShaderEffect::~QQuickShaderEffect()
void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
{
- if (m_source.fragmentCode.constData() == code.constData())
+ if (m_common.source.sourceCode[Key::FragmentShader].constData() == code.constData())
return;
- m_source.fragmentCode = code;
+ m_common.source.sourceCode[Key::FragmentShader] = code;
+ m_dirtyProgram = true;
+ m_dirtyParseLog = true;
+
+ if (isComponentComplete())
+ m_common.updateShader(this, Key::FragmentShader);
+
update();
- m_complete = false;
if (m_status != Uncompiled) {
m_status = Uncompiled;
emit statusChanged();
@@ -234,11 +682,16 @@ void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
void QQuickShaderEffect::setVertexShader(const QByteArray &code)
{
- if (m_source.vertexCode.constData() == code.constData())
+ if (m_common.source.sourceCode[Key::VertexShader].constData() == code.constData())
return;
- m_source.vertexCode = code;
+ m_common.source.sourceCode[Key::VertexShader] = code;
+ m_dirtyProgram = true;
+ m_dirtyParseLog = true;
+
+ if (isComponentComplete())
+ m_common.updateShader(this, Key::VertexShader);
+
update();
- m_complete = false;
if (m_status != Uncompiled) {
m_status = Uncompiled;
emit statusChanged();
@@ -316,6 +769,7 @@ void QQuickShaderEffect::setMesh(const QVariant &mesh)
}
m_dirtyMesh = true;
+ m_dirtyParseLog = true;
update();
emit meshChanged();
}
@@ -343,6 +797,34 @@ void QQuickShaderEffect::setCullMode(CullMode face)
emit cullModeChanged();
}
+QString QQuickShaderEffect::parseLog()
+{
+ if (m_dirtyParseLog) {
+ m_common.updateParseLog(m_mesh != 0);
+ m_dirtyParseLog = false;
+ }
+ return m_common.parseLog;
+}
+
+bool QQuickShaderEffect::event(QEvent *event)
+{
+ if (event->type() == QEvent::DynamicPropertyChange) {
+ QDynamicPropertyChangeEvent *e = static_cast<QDynamicPropertyChangeEvent *>(event);
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < m_common.uniformData[shaderType].size(); ++i) {
+ if (m_common.uniformData[shaderType].at(i).name == e->propertyName()) {
+ bool textureProviderChanged;
+ m_common.propertyChanged(this, (shaderType << 16) | i, &textureProviderChanged);
+ m_dirtyTextureProviders |= textureProviderChanged;
+ m_dirtyUniformValues = true;
+ update();
+ }
+ }
+ }
+ }
+ return QQuickItem::event(event);
+}
+
/*!
\qmlproperty enumeration QtQuick2::ShaderEffect::status
@@ -371,19 +853,6 @@ void QQuickShaderEffect::setCullMode(CullMode face)
\sa status
*/
-void QQuickShaderEffect::changeSource(int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
- QVariant v = property(m_sources.at(index).name.constData());
- setSource(v, index);
-}
-
-void QQuickShaderEffect::updateData()
-{
- m_dirtyData = true;
- update();
-}
-
void QQuickShaderEffect::updateGeometry()
{
m_dirtyGeometry = true;
@@ -392,7 +861,7 @@ void QQuickShaderEffect::updateGeometry()
void QQuickShaderEffect::updateLogAndStatus(const QString &log, int status)
{
- m_log = m_parseLog + log;
+ m_log = parseLog() + log;
m_status = Status(status);
emit logChanged();
emit statusChanged();
@@ -400,341 +869,17 @@ void QQuickShaderEffect::updateLogAndStatus(const QString &log, int status)
void QQuickShaderEffect::sourceDestroyed(QObject *object)
{
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- if (object == source.sourceObject)
- source.sourceObject = 0;
- }
-}
-
-void QQuickShaderEffect::setSource(const QVariant &var, int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
-
- SourceData &source = m_sources[index];
-
- if (source.sourceObject) {
- if (canvas())
- QQuickItemPrivate::get(source.sourceObject)->derefCanvas();
- disconnect(source.sourceObject, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
- }
-
- source.sourceObject = 0;
- if (var.isNull()) {
- return;
- } else if (!qVariantCanConvert<QObject *>(var)) {
- qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData());
- return;
- }
-
- QObject *obj = qVariantValue<QObject *>(var);
- if (!obj)
- return;
- QQuickItem *item = qobject_cast<QQuickItem *>(obj);
- if (!item || !item->isTextureProvider()) {
- qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
- source.name.constData(), qPrintable(obj->objectName()), obj->metaObject()->className());
- return;
- }
-
- source.sourceObject = item;
-
- if (item) {
- // 'item' needs a canvas to get a scene graph node. It usually gets one through its
- // parent, but if the source item is "inline" rather than a reference -- i.e.
- // "property variant source: Image { }" instead of "property variant source: foo" -- it
- // will not get a parent. In those cases, 'item' should get the canvas from 'this'.
- if (canvas())
- QQuickItemPrivate::get(item)->refCanvas(canvas());
- connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
- }
-}
-
-void QQuickShaderEffect::disconnectPropertySignals()
-{
- disconnect(this, 0, this, SLOT(updateData()));
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- disconnect(this, 0, source.mapper, 0);
- disconnect(source.mapper, 0, this, 0);
- }
-}
-
-void QQuickShaderEffect::connectPropertySignals()
-{
- QSet<QByteArray>::const_iterator it;
- for (it = m_source.uniformNames.begin(); it != m_source.uniformNames.end(); ++it) {
- int pi = metaObject()->indexOfProperty(it->constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- if (!mp.hasNotifySignal())
- qWarning("QQuickShaderEffect: property '%s' does not have notification method!", it->constData());
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().methodSignature());
- connect(this, signalName, this, SLOT(updateData()));
- } else {
- // If the source is set via a dynamic property, like the layer is, then we need this check
- // to disable the warning.
- if (property(it->constData()).isValid())
- continue;
- qWarning("QQuickShaderEffect: '%s' does not have a matching property!", it->constData());
- }
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- int pi = metaObject()->indexOfProperty(source.name.constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().methodSignature());
- connect(this, signalName, source.mapper, SLOT(map()));
- source.mapper->setMapping(this, i);
- connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int)));
- } else {
- // If the source is set via a dynamic property, like the layer is, then we need this check
- // to disable the warning.
- if (property(source.name.constData()).isValid())
- continue;
- qWarning("QQuickShaderEffect: '%s' does not have a matching source!", source.name.constData());
- }
- }
-}
-
-
-void QQuickShaderEffect::ensureCompleted()
-{
- if (!m_complete) {
- reset();
- updateProperties();
- m_complete = true;
- }
-}
-
-
-void QQuickShaderEffect::reset()
-{
- disconnectPropertySignals();
-
- m_source.attributeNames.clear();
- m_source.uniformNames.clear();
- m_source.respectsOpacity = false;
- m_source.respectsMatrix = false;
- m_source.className = metaObject()->className();
-
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- delete source.mapper;
- if (source.sourceObject) {
- if (canvas())
- QQuickItemPrivate::get(source.sourceObject)->derefCanvas();
- disconnect(source.sourceObject, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
- }
- }
- m_sources.clear();
- m_log.clear();
- m_parseLog.clear();
- m_programDirty = true;
- m_dirtyMesh = true;
-}
-
-void QQuickShaderEffect::updateProperties()
-{
- if (m_source.vertexCode.isEmpty()) {
- m_source.attributeNames.append(QByteArray(qt_position_attribute_name));
- m_source.attributeNames.append(QByteArray(qt_texcoord_attribute_name));
- m_source.respectsMatrix = true;
- } else {
- lookThroughShaderCode(m_source.vertexCode);
- }
- if (m_source.fragmentCode.isEmpty()) {
- m_source.respectsOpacity = true;
- QByteArray name("source");
- m_source.uniformNames.insert(name);
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.sourceObject = 0;
- m_sources.append(d);
- } else {
- lookThroughShaderCode(m_source.fragmentCode);
- }
-
- if (!m_mesh && !m_source.attributeNames.contains(qt_position_attribute_name)) {
- m_parseLog += QLatin1String("Warning: Missing reference to \'");
- m_parseLog += QLatin1String(qt_position_attribute_name);
- m_parseLog += QLatin1String("\'.\n");
- }
- if (!m_mesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name)) {
- m_parseLog += QLatin1String("Warning: Missing reference to \'");
- m_parseLog += QLatin1String(qt_texcoord_attribute_name);
- m_parseLog += QLatin1String("\'.\n");
- }
- if (!m_source.respectsMatrix) {
- m_parseLog += QLatin1String("Warning: Missing reference to \'qt_Matrix\'.\n");
- }
- if (!m_source.respectsOpacity) {
- m_parseLog += QLatin1String("Warning: Missing reference to \'qt_Opacity\'.\n");
- }
-
- for (int i = 0; i < m_sources.size(); ++i) {
- QVariant v = property(m_sources.at(i).name);
- setSource(v, i);
- }
-
- connectPropertySignals();
+ m_common.sourceDestroyed(object);
}
-namespace {
-
- enum VariableQualifier {
- AttributeQualifier,
- UniformQualifier
- };
-
- inline bool qt_isalpha(char c)
- {
- char ch = c | 0x20;
- return (ch >= 'a' && ch <= 'z') || c == '_';
- }
-
- inline bool qt_isalnum(char c)
- {
- return qt_isalpha(c) || (c >= '0' && c <= '9');
- }
-
- inline bool qt_isspace(char c)
- {
- return c == ' ' || (c >= 0x09 && c <= 0x0d);
- }
-
- // Returns -1 if not found, returns index to first character after the name if found.
- int qt_search_for_variable(const char *s, int length, int index, VariableQualifier &decl,
- int &typeIndex, int &typeLength,
- int &nameIndex, int &nameLength)
- {
- enum Identifier {
- QualifierIdentifier, // Base state
- PrecisionIdentifier,
- TypeIdentifier,
- NameIdentifier
- };
- Identifier expected = QualifierIdentifier;
- bool compilerDirectiveExpected = index == 0;
-
- while (index < length) {
- // Skip whitespace.
- while (qt_isspace(s[index])) {
- compilerDirectiveExpected |= s[index] == '\n';
- ++index;
- }
-
- if (qt_isalpha(s[index])) {
- // Read identifier.
- int idIndex = index;
- ++index;
- while (qt_isalnum(s[index]))
- ++index;
- int idLength = index - idIndex;
-
- const int attrLen = sizeof("attribute") - 1;
- const int uniLen = sizeof("uniform") - 1;
- const int loLen = sizeof("lowp") - 1;
- const int medLen = sizeof("mediump") - 1;
- const int hiLen = sizeof("highp") - 1;
-
- switch (expected) {
- case QualifierIdentifier:
- if (idLength == attrLen && qstrncmp("attribute", s + idIndex, attrLen) == 0) {
- decl = AttributeQualifier;
- expected = PrecisionIdentifier;
- } else if (idLength == uniLen && qstrncmp("uniform", s + idIndex, uniLen) == 0) {
- decl = UniformQualifier;
- expected = PrecisionIdentifier;
- }
- break;
- case PrecisionIdentifier:
- if ((idLength == loLen && qstrncmp("lowp", s + idIndex, loLen) == 0)
- || (idLength == medLen && qstrncmp("mediump", s + idIndex, medLen) == 0)
- || (idLength == hiLen && qstrncmp("highp", s + idIndex, hiLen) == 0))
- {
- expected = TypeIdentifier;
- break;
- }
- // Fall through.
- case TypeIdentifier:
- typeIndex = idIndex;
- typeLength = idLength;
- expected = NameIdentifier;
- break;
- case NameIdentifier:
- nameIndex = idIndex;
- nameLength = idLength;
- return index; // Attribute or uniform declaration found. Return result.
- default:
- break;
- }
- } else if (s[index] == '#' && compilerDirectiveExpected) {
- // Skip compiler directives.
- ++index;
- while (index < length && (s[index] != '\n' || s[index - 1] == '\\'))
- ++index;
- } else if (s[index] == '/' && s[index + 1] == '/') {
- // Skip comments.
- index += 2;
- while (index < length && s[index] != '\n')
- ++index;
- } else if (s[index] == '/' && s[index + 1] == '*') {
- // Skip comments.
- index += 2;
- while (index < length && (s[index] != '*' || s[index + 1] != '/'))
- ++index;
- if (index < length)
- index += 2; // Skip star-slash.
- } else {
- expected = QualifierIdentifier;
- ++index;
- }
- compilerDirectiveExpected = false;
- }
- return -1;
- }
-}
-void QQuickShaderEffect::lookThroughShaderCode(const QByteArray &code)
+void QQuickShaderEffect::propertyChanged(int mappedId)
{
- int index = 0;
- int typeIndex, typeLength, nameIndex, nameLength;
- const char *s = code.constData();
- VariableQualifier decl;
- while ((index = qt_search_for_variable(s, code.size(), index, decl, typeIndex, typeLength,
- nameIndex, nameLength)) != -1)
- {
- if (decl == AttributeQualifier) {
- m_source.attributeNames.append(QByteArray(s + nameIndex, nameLength));
- } else {
- Q_ASSERT(decl == UniformQualifier);
-
- const int matLen = sizeof("qt_Matrix") - 1;
- const int opLen = sizeof("qt_Opacity") - 1;
- const int sampLen = sizeof("sampler2D") - 1;
-
- if (nameLength == matLen && qstrncmp("qt_Matrix", s + nameIndex, matLen) == 0) {
- m_source.respectsMatrix = true;
- } else if (nameLength == opLen && qstrncmp("qt_Opacity", s + nameIndex, opLen) == 0) {
- m_source.respectsOpacity = true;
- } else {
- QByteArray name(s + nameIndex, nameLength);
- m_source.uniformNames.insert(name);
- if (typeLength == sampLen && qstrncmp("sampler2D", s + typeIndex, sampLen) == 0) {
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.sourceObject = 0;
- m_sources.append(d);
- }
- }
- }
- }
+ bool textureProviderChanged;
+ m_common.propertyChanged(this, mappedId, &textureProviderChanged);
+ m_dirtyTextureProviders |= textureProviderChanged;
+ m_dirtyUniformValues = true;
+ update();
}
void QQuickShaderEffect::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
@@ -747,10 +892,8 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
{
QQuickShaderEffectNode *node = static_cast<QQuickShaderEffectNode *>(oldNode);
- ensureCompleted();
-
// In the case of a bad vertex shader, don't try to create a node...
- if (m_source.attributeNames.isEmpty()) {
+ if (m_common.attributes.isEmpty()) {
if (node)
delete node;
return 0;
@@ -758,14 +901,14 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
if (!node) {
node = new QQuickShaderEffectNode;
- m_programDirty = true;
- m_dirtyData = true;
+ node->setMaterial(new QQuickShaderEffectMaterial(node));
+ node->setFlag(QSGNode::OwnsMaterial, true);
+ m_dirtyProgram = true;
+ m_dirtyUniforms = true;
m_dirtyGeometry = true;
connect(node, SIGNAL(logAndStatusChanged(QString,int)), this, SLOT(updateLogAndStatus(QString,int)));
}
- QQuickShaderEffectMaterial *material = node->shaderMaterial();
-
if (m_dirtyMesh) {
node->setGeometry(0);
m_dirtyMesh = false;
@@ -778,11 +921,11 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
QRectF rect(0, 0, width(), height());
QQuickShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
- geometry = mesh->updateGeometry(geometry, m_source.attributeNames, rect);
+ geometry = mesh->updateGeometry(geometry, m_common.attributes, rect);
if (!geometry) {
QString log = mesh->log();
if (!log.isNull()) {
- m_log = m_parseLog;
+ m_log = parseLog();
m_log += QLatin1String("*** Mesh ***\n");
m_log += log;
m_status = Error;
@@ -799,18 +942,7 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
m_dirtyGeometry = false;
}
- if (m_programDirty) {
- QQuickShaderEffectProgram s = m_source;
- if (s.fragmentCode.isEmpty())
- s.fragmentCode = qt_default_fragment_code;
- if (s.vertexCode.isEmpty())
- s.vertexCode = qt_default_vertex_code;
- s.className = metaObject()->className();
-
- material->setProgramSource(s);
- node->markDirty(QSGNode::DirtyMaterial);
- m_programDirty = false;
- }
+ QQuickShaderEffectMaterial *material = static_cast<QQuickShaderEffectMaterial *>(node->material());
// Update blending
if (bool(material->flags() & QSGMaterial::Blending) != m_blending) {
@@ -818,66 +950,48 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
node->markDirty(QSGNode::DirtyMaterial);
}
- if (int(material->cullMode()) != int(m_cullMode)) {
- material->setCullMode(QQuickShaderEffectMaterial::CullMode(m_cullMode));
+ if (int(material->cullMode) != int(m_cullMode)) {
+ material->cullMode = QQuickShaderEffectMaterial::CullMode(m_cullMode);
node->markDirty(QSGNode::DirtyMaterial);
}
- if (m_dirtyData) {
- QVector<QPair<QByteArray, QVariant> > values;
- QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = material->textureProviders();
+ if (m_dirtyProgram) {
+ Key s = m_common.source;
+ if (s.sourceCode[Key::FragmentShader].isEmpty())
+ s.sourceCode[Key::FragmentShader] = qt_default_fragment_code;
+ if (s.sourceCode[Key::VertexShader].isEmpty())
+ s.sourceCode[Key::VertexShader] = qt_default_vertex_code;
+ s.className = metaObject()->className();
- for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin();
- it != m_source.uniformNames.end(); ++it) {
- values.append(qMakePair(*it, property(*it)));
- }
- for (int i = 0; i < oldTextures.size(); ++i) {
- QSGTextureProvider *t = oldTextures.at(i).second;
- if (t) {
- disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
- disconnect(t, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
- }
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- QSGTextureProvider *t = source.sourceObject ? source.sourceObject->textureProvider() : 0;
- textures.append(qMakePair(source.name, t));
- if (t) {
- Q_ASSERT_X(t->thread() == QThread::currentThread(),
- "QQuickShaderEffect::updatePaintNode",
- "Texture provider must belong to the rendering thread");
- connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
- connect(t, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
- }
- }
- material->setUniforms(values);
- material->setTextureProviders(textures);
+ material->setProgramSource(s);
+ material->attributes = m_common.attributes;
node->markDirty(QSGNode::DirtyMaterial);
- m_dirtyData = false;
+ m_dirtyProgram = false;
+ m_dirtyUniforms = true;
+ }
+
+ if (m_dirtyUniforms || m_dirtyUniformValues || m_dirtyTextureProviders) {
+ m_common.updateMaterial(node, material, m_dirtyUniforms, m_dirtyUniformValues,
+ m_dirtyTextureProviders);
+ node->markDirty(QSGNode::DirtyMaterial);
+ m_dirtyUniforms = m_dirtyUniformValues = m_dirtyTextureProviders = false;
}
return node;
}
+void QQuickShaderEffect::componentComplete()
+{
+ m_common.updateShader(this, Key::VertexShader);
+ m_common.updateShader(this, Key::FragmentShader);
+ QQuickItem::componentComplete();
+}
+
void QQuickShaderEffect::itemChange(ItemChange change, const ItemChangeData &value)
{
- if (change == QQuickItem::ItemSceneChange) {
- // See comment in QQuickShaderEffect::setSource().
- if (value.canvas) {
- for (int i = 0; i < m_sources.size(); ++i) {
- if (m_sources.at(i).sourceObject)
- QQuickItemPrivate::get(m_sources.at(i).sourceObject)->refCanvas(value.canvas);
- }
- } else {
- for (int i = 0; i < m_sources.size(); ++i) {
- if (m_sources.at(i).sourceObject)
- QQuickItemPrivate::get(m_sources.at(i).sourceObject)->derefCanvas();
- }
- }
- }
+ if (change == QQuickItem::ItemSceneChange)
+ m_common.updateCanvas(value.canvas);
QQuickItem::itemChange(change, value);
}
-
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index db1e4e78c1..32f12fad30 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -62,6 +62,34 @@ class QSGContext;
class QSignalMapper;
class QQuickCustomMaterialShader;
+// Common class for QQuickShaderEffect and QQuickCustomParticle.
+struct QQuickShaderEffectCommon
+{
+ typedef QQuickShaderEffectMaterialKey Key;
+ typedef QQuickShaderEffectMaterial::UniformData UniformData;
+
+ ~QQuickShaderEffectCommon();
+ void disconnectPropertySignals(QQuickItem *item, Key::ShaderType shaderType);
+ void connectPropertySignals(QQuickItem *item, Key::ShaderType shaderType);
+ void updateParseLog(bool ignoreAttributes);
+ void lookThroughShaderCode(QQuickItem *item, Key::ShaderType shaderType, const QByteArray &code);
+ void updateShader(QQuickItem *item, Key::ShaderType shaderType);
+ void updateMaterial(QQuickShaderEffectNode *node, QQuickShaderEffectMaterial *material,
+ bool updateUniforms, bool updateUniformValues, bool updateTextureProviders);
+ void updateCanvas(QQuickCanvas *canvas);
+
+ // Called by slots in QQuickShaderEffect:
+ void sourceDestroyed(QObject *object);
+ void propertyChanged(QQuickItem *item, int mappedId, bool *textureProviderChanged);
+
+ Key source;
+ QVector<QByteArray> attributes;
+ QVector<UniformData> uniformData[Key::ShaderTypeCount];
+ QVector<QSignalMapper *> signalMappers[Key::ShaderTypeCount];
+ QString parseLog;
+};
+
+
class Q_AUTOTEST_EXPORT QQuickShaderEffect : public QQuickItem
{
Q_OBJECT
@@ -93,10 +121,10 @@ public:
QQuickShaderEffect(QQuickItem *parent = 0);
~QQuickShaderEffect();
- QByteArray fragmentShader() const { return m_source.fragmentCode; }
+ QByteArray fragmentShader() const { return m_common.source.sourceCode[Key::FragmentShader]; }
void setFragmentShader(const QByteArray &code);
- QByteArray vertexShader() const { return m_source.vertexCode; }
+ QByteArray vertexShader() const { return m_common.source.sourceCode[Key::VertexShader]; }
void setVertexShader(const QByteArray &code);
bool blending() const { return m_blending; }
@@ -111,8 +139,9 @@ public:
QString log() const { return m_log; }
Status status() const { return m_status; }
- void ensureCompleted();
- QString parseLog() { return m_parseLog; }
+ QString parseLog();
+
+ virtual bool event(QEvent *);
Q_SIGNALS:
void fragmentShaderChanged();
@@ -126,27 +155,22 @@ Q_SIGNALS:
protected:
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ virtual void componentComplete();
virtual void itemChange(ItemChange change, const ItemChangeData &value);
private Q_SLOTS:
- void changeSource(int index);
- void updateData();
void updateGeometry();
void updateLogAndStatus(const QString &log, int status);
void sourceDestroyed(QObject *object);
+ void propertyChanged(int mappedId);
private:
friend class QQuickCustomMaterialShader;
friend class QQuickShaderEffectNode;
- void setSource(const QVariant &var, int index);
- void disconnectPropertySignals();
- void connectPropertySignals();
- void reset();
- void updateProperties();
- void lookThroughShaderCode(const QByteArray &code);
+ typedef QQuickShaderEffectMaterialKey Key;
+ typedef QQuickShaderEffectMaterial::UniformData UniformData;
- QQuickShaderEffectProgram m_source;
QSize m_meshResolution;
QQuickShaderEffectMesh *m_mesh;
QQuickGridMesh m_defaultMesh;
@@ -154,23 +178,16 @@ private:
QString m_log;
Status m_status;
- struct SourceData
- {
- QSignalMapper *mapper;
- QQuickItem *sourceObject;
- QByteArray name;
- };
- QVector<SourceData> m_sources;
- QString m_parseLog;
+ QQuickShaderEffectCommon m_common;
uint m_blending : 1;
- uint m_dirtyData : 1;
-
- uint m_programDirty : 1;
+ uint m_dirtyUniforms : 1;
+ uint m_dirtyUniformValues : 1;
+ uint m_dirtyTextureProviders : 1;
+ uint m_dirtyProgram : 1;
+ uint m_dirtyParseLog : 1;
uint m_dirtyMesh : 1;
uint m_dirtyGeometry : 1;
-
- uint m_complete : 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index c4b91844e0..a3cadb97a2 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -60,7 +60,6 @@ protected:
friend class QQuickShaderEffectNode;
virtual void compile();
- virtual void initialize();
virtual const char *vertexShader() const;
virtual const char *fragmentShader() const;
@@ -70,17 +69,15 @@ protected:
QString m_log;
bool m_compiled;
- QVector<int> m_uniformLocs;
- int m_opacityLoc;
- int m_matrixLoc;
- uint m_textureIndicesSet;
+ QVector<int> m_uniformLocs[QQuickShaderEffectMaterialKey::ShaderTypeCount];
+ uint m_initialized : 1;
};
QQuickCustomMaterialShader::QQuickCustomMaterialShader(const QQuickShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes)
: m_key(key)
, m_attributes(attributes)
, m_compiled(false)
- , m_textureIndicesSet(false)
+ , m_initialized(false)
{
for (int i = 0; i < attributes.count(); ++i)
m_attributeNames.append(attributes.at(i).constData());
@@ -104,24 +101,25 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
: QQuickShaderEffect::Error);
}
- if (!m_textureIndicesSet) {
- for (int i = 0; i < material->m_textures.size(); ++i)
- program()->setUniformValue(material->m_textures.at(i).first.constData(), i);
- m_textureIndicesSet = true;
- }
+ if (!m_initialized) {
+ for (int i = 0; i < material->textureProviders.size(); ++i)
+ program()->setUniformValue(material->textureProviders.at(i).first.constData(), i);
- if (m_uniformLocs.size() != material->m_uniformValues.size()) {
- m_uniformLocs.reserve(material->m_uniformValues.size());
- for (int i = 0; i < material->m_uniformValues.size(); ++i) {
- const QByteArray &name = material->m_uniformValues.at(i).first;
- m_uniformLocs.append(program()->uniformLocation(name.constData()));
+ for (int shaderType = 0; shaderType < QQuickShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
+ Q_ASSERT(m_uniformLocs[shaderType].isEmpty());
+ m_uniformLocs[shaderType].reserve(material->uniforms[shaderType].size());
+ for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
+ const QByteArray &name = material->uniforms[shaderType].at(i).name;
+ m_uniformLocs[shaderType].append(program()->uniformLocation(name.constData()));
+ }
}
+ m_initialized = true;
}
QOpenGLFunctions *functions = state.context()->functions();
- for (int i = material->m_textures.size() - 1; i >= 0; --i) {
+ for (int i = material->textureProviders.size() - 1; i >= 0; --i) {
functions->glActiveTexture(GL_TEXTURE0 + i);
- if (QSGTextureProvider *provider = material->m_textures.at(i).second) {
+ if (QSGTextureProvider *provider = material->textureProviders.at(i).second) {
if (QSGTexture *texture = provider->texture()) {
texture->bind();
continue;
@@ -131,57 +129,67 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
glBindTexture(GL_TEXTURE_2D, 0);
}
- if (material->m_source.respectsOpacity)
- program()->setUniformValue(m_opacityLoc, state.opacity());
-
- for (int i = 0; i < material->m_uniformValues.count(); ++i) {
- const QVariant &v = material->m_uniformValues.at(i).second;
-
- switch (v.type()) {
- case QMetaType::QColor:
- program()->setUniformValue(m_uniformLocs.at(i), qt_premultiply_color(qvariant_cast<QColor>(v)));
- break;
- case QMetaType::Float:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<float>(v));
- break;
- case QMetaType::Double:
- program()->setUniformValue(m_uniformLocs.at(i), (float) qvariant_cast<double>(v));
- break;
- case QMetaType::QTransform:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QTransform>(v));
- break;
- case QMetaType::Int:
- program()->setUniformValue(m_uniformLocs.at(i), v.toInt());
- break;
- case QMetaType::Bool:
- program()->setUniformValue(m_uniformLocs.at(i), GLint(v.toBool()));
- break;
- case QMetaType::QSize:
- case QMetaType::QSizeF:
- program()->setUniformValue(m_uniformLocs.at(i), v.toSizeF());
- break;
- case QMetaType::QPoint:
- case QMetaType::QPointF:
- program()->setUniformValue(m_uniformLocs.at(i), v.toPointF());
- break;
- case QMetaType::QRect:
- case QMetaType::QRectF:
- {
- QRectF r = v.toRectF();
- program()->setUniformValue(m_uniformLocs.at(i), r.x(), r.y(), r.width(), r.height());
+ for (int shaderType = 0; shaderType < QQuickShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < material->uniforms[shaderType].size(); ++i) {
+ const QQuickShaderEffectMaterial::UniformData &d = material->uniforms[shaderType].at(i);
+ int loc = m_uniformLocs[shaderType].at(i);
+
+ if (d.specialType == QQuickShaderEffectMaterial::UniformData::Opacity) {
+ program()->setUniformValue(loc, state.opacity());
+ } if (d.specialType == QQuickShaderEffectMaterial::UniformData::Matrix) {
+ if (state.isMatrixDirty())
+ program()->setUniformValue(loc, state.combinedMatrix());
+ } else {
+ switch (d.value.type()) {
+ case QMetaType::QColor:
+ program()->setUniformValue(loc, qt_premultiply_color(qvariant_cast<QColor>(d.value)));
+ break;
+ case QMetaType::Float:
+ program()->setUniformValue(loc, qvariant_cast<float>(d.value));
+ break;
+ case QMetaType::Double:
+ program()->setUniformValue(loc, (float) qvariant_cast<double>(d.value));
+ break;
+ case QMetaType::QTransform:
+ program()->setUniformValue(loc, qvariant_cast<QTransform>(d.value));
+ break;
+ case QMetaType::Int:
+ program()->setUniformValue(loc, d.value.toInt());
+ break;
+ case QMetaType::Bool:
+ program()->setUniformValue(loc, GLint(d.value.toBool()));
+ break;
+ case QMetaType::QSize:
+ case QMetaType::QSizeF:
+ program()->setUniformValue(loc, d.value.toSizeF());
+ break;
+ case QMetaType::QPoint:
+ case QMetaType::QPointF:
+ program()->setUniformValue(loc, d.value.toPointF());
+ break;
+ case QMetaType::QRect:
+ case QMetaType::QRectF:
+ {
+ QRectF r = d.value.toRectF();
+ program()->setUniformValue(loc, r.x(), r.y(), r.width(), r.height());
+ }
+ break;
+ case QMetaType::QVector3D:
+ program()->setUniformValue(loc, qvariant_cast<QVector3D>(d.value));
+ break;
+ case QMetaType::QVector4D:
+ program()->setUniformValue(loc, qvariant_cast<QVector4D>(d.value));
+ break;
+ default:
+ break;
+ }
}
- break;
- case QMetaType::QVector3D:
- program()->setUniformValue(m_uniformLocs.at(i), qvariant_cast<QVector3D>(v));
- break;
- default:
- break;
}
}
const QQuickShaderEffectMaterial *oldMaterial = static_cast<const QQuickShaderEffectMaterial *>(oldEffect);
- if (oldEffect == 0 || material->cullMode() != oldMaterial->cullMode()) {
- switch (material->cullMode()) {
+ if (oldEffect == 0 || material->cullMode != oldMaterial->cullMode) {
+ switch (material->cullMode) {
case QQuickShaderEffectMaterial::FrontFaceCulling:
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
@@ -195,9 +203,6 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
break;
}
}
-
- if ((state.isMatrixDirty()) && material->m_source.respectsMatrix)
- program()->setUniformValue(m_matrixLoc, state.combinedMatrix());
}
char const *const *QQuickCustomMaterialShader::attributeNames() const
@@ -277,38 +282,42 @@ void QQuickCustomMaterialShader::compile()
}
}
-void QQuickCustomMaterialShader::initialize()
-{
- m_opacityLoc = program()->uniformLocation("qt_Opacity");
- m_matrixLoc = program()->uniformLocation("qt_Matrix");
-}
-
const char *QQuickCustomMaterialShader::vertexShader() const
{
- return m_key.vertexCode.constData();
+ return m_key.sourceCode[QQuickShaderEffectMaterialKey::VertexShader].constData();
}
const char *QQuickCustomMaterialShader::fragmentShader() const
{
- return m_key.fragmentCode.constData();
+ return m_key.sourceCode[QQuickShaderEffectMaterialKey::FragmentShader].constData();
}
bool QQuickShaderEffectMaterialKey::operator == (const QQuickShaderEffectMaterialKey &other) const
{
- return vertexCode == other.vertexCode && fragmentCode == other.fragmentCode && className == other.className;
+ if (className != other.className)
+ return false;
+ for (int shaderType = 0; shaderType < ShaderTypeCount; ++shaderType) {
+ if (sourceCode[shaderType] != other.sourceCode[shaderType])
+ return false;
+ }
+ return true;
}
uint qHash(const QQuickShaderEffectMaterialKey &key)
{
- return qHash(qMakePair(qMakePair(key.vertexCode, key.fragmentCode), key.className));
+ uint hash = qHash((void *)key.className);
+ typedef QQuickShaderEffectMaterialKey Key;
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType)
+ hash = hash * 31337 + qHash(key.sourceCode[shaderType]);
+ return hash;
}
QHash<QQuickShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > QQuickShaderEffectMaterial::materialMap;
QQuickShaderEffectMaterial::QQuickShaderEffectMaterial(QQuickShaderEffectNode *node)
- : m_cullMode(NoCulling)
+ : cullMode(NoCulling)
, m_node(node)
, m_emittedLogChanged(false)
{
@@ -322,7 +331,7 @@ QSGMaterialType *QQuickShaderEffectMaterial::type() const
QSGMaterialShader *QQuickShaderEffectMaterial::createShader() const
{
- return new QQuickCustomMaterialShader(m_source, m_source.attributeNames);
+ return new QQuickCustomMaterialShader(m_source, attributes);
}
int QQuickShaderEffectMaterial::compare(const QSGMaterial *other) const
@@ -330,17 +339,7 @@ int QQuickShaderEffectMaterial::compare(const QSGMaterial *other) const
return this - static_cast<const QQuickShaderEffectMaterial *>(other);
}
-void QQuickShaderEffectMaterial::setCullMode(QQuickShaderEffectMaterial::CullMode face)
-{
- m_cullMode = face;
-}
-
-QQuickShaderEffectMaterial::CullMode QQuickShaderEffectMaterial::cullMode() const
-{
- return m_cullMode;
-}
-
-void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectProgram &source)
+void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectMaterialKey &source)
{
m_source = source;
m_emittedLogChanged = false;
@@ -351,25 +350,10 @@ void QQuickShaderEffectMaterial::setProgramSource(const QQuickShaderEffectProgra
}
}
-void QQuickShaderEffectMaterial::setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues)
-{
- m_uniformValues = uniformValues;
-}
-
-void QQuickShaderEffectMaterial::setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures)
-{
- m_textures = textures;
-}
-
-const QVector<QPair<QByteArray, QSGTextureProvider *> > &QQuickShaderEffectMaterial::textureProviders() const
-{
- return m_textures;
-}
-
void QQuickShaderEffectMaterial::updateTextures() const
{
- for (int i = 0; i < m_textures.size(); ++i) {
- if (QSGTextureProvider *provider = m_textures.at(i).second) {
+ for (int i = 0; i < textureProviders.size(); ++i) {
+ if (QSGTextureProvider *provider = textureProviders.at(i).second) {
if (QSGDynamicTexture *texture = qobject_cast<QSGDynamicTexture *>(provider->texture()))
texture->updateTexture();
}
@@ -378,18 +362,16 @@ void QQuickShaderEffectMaterial::updateTextures() const
void QQuickShaderEffectMaterial::invalidateTextureProvider(QSGTextureProvider *provider)
{
- for (int i = 0; i < m_textures.size(); ++i) {
- if (provider == m_textures.at(i).second)
- m_textures[i].second = 0;
+ for (int i = 0; i < textureProviders.size(); ++i) {
+ if (provider == textureProviders.at(i).second)
+ textureProviders[i].second = 0;
}
}
QQuickShaderEffectNode::QQuickShaderEffectNode()
- : m_material(this)
{
QSGNode::setFlag(UsePreprocess, true);
- setMaterial(&m_material);
#ifdef QML_RUNTIME_TESTING
description = QLatin1String("shadereffect");
@@ -407,8 +389,8 @@ void QQuickShaderEffectNode::markDirtyTexture()
void QQuickShaderEffectNode::textureProviderDestroyed(QObject *object)
{
- Q_ASSERT(qobject_cast<QSGTextureProvider *>(object));
- m_material.invalidateTextureProvider(static_cast<QSGTextureProvider *>(object));
+ Q_ASSERT(material());
+ static_cast<QQuickShaderEffectMaterial *>(material())->invalidateTextureProvider(static_cast<QSGTextureProvider *>(object));
}
void QQuickShaderEffectNode::preprocess()
diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h
index e22d2de9e2..1bbce86426 100644
--- a/src/quick/items/qquickshadereffectnode_p.h
+++ b/src/quick/items/qquickshadereffectnode_p.h
@@ -55,8 +55,14 @@ QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
struct QQuickShaderEffectMaterialKey {
- QByteArray vertexCode;
- QByteArray fragmentCode;
+ enum ShaderType
+ {
+ VertexShader,
+ FragmentShader,
+ ShaderTypeCount
+ };
+
+ QByteArray sourceCode[ShaderTypeCount];
const char *className;
bool operator == (const QQuickShaderEffectMaterialKey &other) const;
@@ -64,24 +70,21 @@ struct QQuickShaderEffectMaterialKey {
uint qHash(const QQuickShaderEffectMaterialKey &key);
-// TODO: Implement support for multisampling.
-struct QQuickShaderEffectProgram : public QQuickShaderEffectMaterialKey
-{
- QQuickShaderEffectProgram() : respectsOpacity(false), respectsMatrix(false) {}
-
- QVector<QByteArray> attributeNames;
- QSet<QByteArray> uniformNames;
-
- uint respectsOpacity : 1;
- uint respectsMatrix : 1;
-};
-
class QQuickCustomMaterialShader;
class QQuickShaderEffectNode;
class QQuickShaderEffectMaterial : public QSGMaterial
{
public:
+ struct UniformData
+ {
+ enum SpecialType { None, Sampler, Opacity, Matrix };
+
+ QByteArray name;
+ QVariant value;
+ SpecialType specialType;
+ };
+
enum CullMode
{
NoCulling,
@@ -94,13 +97,12 @@ public:
virtual QSGMaterialShader *createShader() const;
virtual int compare(const QSGMaterial *other) const;
- void setCullMode(CullMode face);
- CullMode cullMode() const;
+ QVector<QByteArray> attributes;
+ QVector<UniformData> uniforms[QQuickShaderEffectMaterialKey::ShaderTypeCount];
+ QVector<QPair<QByteArray, QSGTextureProvider *> > textureProviders;
+ CullMode cullMode;
- void setProgramSource(const QQuickShaderEffectProgram &);
- void setUniforms(const QVector<QPair<QByteArray, QVariant> > &uniformValues);
- void setTextureProviders(const QVector<QPair<QByteArray, QSGTextureProvider *> > &textures);
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &textureProviders() const;
+ void setProgramSource(const QQuickShaderEffectMaterialKey &source);
void updateTextures() const;
void invalidateTextureProvider(QSGTextureProvider *provider);
@@ -114,11 +116,8 @@ protected:
// one. To guarantee that the type pointer is unique, the type object must live as long as
// there are any CustomMaterialShaders of that type.
QSharedPointer<QSGMaterialType> m_type;
+ QQuickShaderEffectMaterialKey m_source;
- QQuickShaderEffectProgram m_source;
- QVector<QPair<QByteArray, QVariant> > m_uniformValues;
- QVector<QPair<QByteArray, QSGTextureProvider *> > m_textures;
- CullMode m_cullMode;
QQuickShaderEffectNode *m_node;
bool m_emittedLogChanged;
@@ -137,17 +136,12 @@ public:
virtual void preprocess();
- QQuickShaderEffectMaterial *shaderMaterial() { return &m_material; }
-
Q_SIGNALS:
void logAndStatusChanged(const QString &, int status);
private Q_SLOTS:
void markDirtyTexture();
void textureProviderDestroyed(QObject *object);
-
-private:
- QQuickShaderEffectMaterial m_material;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index d4ddbc400d..900cb84de8 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -389,6 +389,7 @@ QImage QQuickSpriteEngine::assembledImage()
else
qmlInfo(state) << "SpriteEngine: Animations too large to fit in one texture, pushed over the edge by:" << state->source().toLocalFile();
qmlInfo(state) << "SpriteEngine: Your texture max size today is " << maxSize;
+ return QImage();
}
state->m_generatedCount = rowsNeeded;
h += state->frameHeight() * rowsNeeded;
@@ -407,7 +408,7 @@ QImage QQuickSpriteEngine::assembledImage()
QPainter p(&image);
int y = 0;
foreach (QQuickSprite* state, m_sprites){
- QImage img(state->source().toLocalFile());
+ QImage img(state->m_pix.image());
int frameWidth = state->m_frameWidth;
int frameHeight = state->m_frameHeight;
if (img.height() == frameHeight && img.width() < maxSize){//Simple case
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index e1a28a466a..24dd10ac9f 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -748,7 +748,6 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
QTextLine line;
int visibleCount = 0;
bool elide;
- bool widthChanged;
qreal height = 0;
QString elideText;
bool once = true;
@@ -776,7 +775,6 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
bool truncateHeight = false;
truncated = false;
elide = false;
- widthChanged = false;
int characterCount = 0;
int unwrappedLineCount = 1;
int maxLineCount = maximumLineCount();
@@ -911,10 +909,8 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const naturalWidth)
const qreal oldWidth = lineWidth;
lineWidth = q->widthValid() && q->width() > 0 ? q->width() : FLT_MAX;
- if (lineWidth != oldWidth && (singlelineElide || multilineElide || canWrap || horizontalFit)) {
- widthChanged = true;
+ if (lineWidth != oldWidth && (singlelineElide || multilineElide || canWrap || horizontalFit))
continue;
- }
}
// If the next needs to be elided and there's an abbreviated string available
@@ -2363,9 +2359,6 @@ void QQuickText::componentComplete()
QQuickItem::componentComplete();
if (d->updateOnComponentComplete)
d->updateLayout();
-
- // Enable accessibility for text items.
- d->setAccessibleFlagAndListener();
}
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index eefe938467..739b5f859b 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_TEXTCONTROL
+#include <qcoreapplication.h>
#include <qfont.h>
#include <qpainter.h>
#include <qevent.h>
@@ -107,11 +108,12 @@ QQuickTextControlPrivate::QQuickTextControlPrivate()
ignoreAutomaticScrollbarAdjustement(false),
overwriteMode(false),
acceptRichText(true),
- hideCursor(false),
+ cursorVisible(false),
hasFocus(false),
isEnabled(true),
hadSelectionOnMousePress(false),
- wordSelectionEnabled(false)
+ wordSelectionEnabled(false),
+ hasImState(false)
{}
bool QQuickTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e)
@@ -292,6 +294,8 @@ void QQuickTextControlPrivate::setContent(Qt::TextFormat format, const QString &
{
Q_Q(QQuickTextControl);
+ cancelPreedit();
+
// for use when called from setPlainText. we may want to re-use the currently
// set char format then.
const QTextCharFormat charFormatForInsertion = cursor.charFormat();
@@ -1441,13 +1445,16 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
QList<QTextLayout::FormatRange> overrides;
const int oldPreeditCursor = preeditCursor;
preeditCursor = e->preeditString().length();
- hideCursor = false;
+ hasImState = !e->preeditString().isEmpty();
+ cursorVisible = true;
for (int i = 0; i < e->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = e->attributes().at(i);
if (a.type == QInputMethodEvent::Cursor) {
+ hasImState = true;
preeditCursor = a.start;
- hideCursor = !a.length;
+ cursorVisible = a.length != 0;
} else if (a.type == QInputMethodEvent::TextFormat) {
+ hasImState = true;
QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
if (f.isValid()) {
QTextLayout::FormatRange o;
@@ -1514,6 +1521,37 @@ void QQuickTextControlPrivate::focusEvent(QFocusEvent *e)
}
}
+bool QQuickTextControl::hasImState() const
+{
+ Q_D(const QQuickTextControl);
+ return d->hasImState;
+}
+
+bool QQuickTextControl::cursorVisible() const
+{
+ Q_D(const QQuickTextControl);
+ return d->cursorVisible;
+}
+
+void QQuickTextControl::setCursorVisible(bool visible)
+{
+ Q_D(QQuickTextControl);
+ d->cursorVisible = visible;
+ d->setBlinkingCursorEnabled(d->cursorVisible
+ && (d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard)));
+}
+
+QTextCursor QQuickTextControl::cursorForPosition(const QPointF &pos) const
+{
+ Q_D(const QQuickTextControl);
+ int cursorPos = hitTest(pos, Qt::FuzzyHit);
+ if (cursorPos == -1)
+ cursorPos = 0;
+ QTextCursor c(d->doc);
+ c.setPosition(cursorPos);
+ return c;
+}
+
QRectF QQuickTextControl::cursorRect(const QTextCursor &cursor) const
{
Q_D(const QQuickTextControl);
@@ -1727,21 +1765,31 @@ bool QQuickTextControlPrivate::isPreediting() const
void QQuickTextControlPrivate::commitPreedit()
{
- if (!isPreediting())
+ Q_Q(QQuickTextControl);
+
+ if (!hasImState)
return;
qApp->inputMethod()->commit();
- if (!isPreediting())
+ if (!hasImState)
return;
- cursor.beginEditBlock();
- preeditCursor = 0;
- QTextBlock block = cursor.block();
- QTextLayout *layout = block.layout();
- layout->setPreeditArea(-1, QString());
- layout->clearAdditionalFormats();
- cursor.endEditBlock();
+ QInputMethodEvent event;
+ QCoreApplication::sendEvent(q->parent(), &event);
+}
+
+void QQuickTextControlPrivate::cancelPreedit()
+{
+ Q_Q(QQuickTextControl);
+
+ if (!hasImState)
+ return;
+
+ qApp->inputMethod()->reset();
+
+ QInputMethodEvent event;
+ QCoreApplication::sendEvent(q->parent(), &event);
}
void QQuickTextControl::setTextInteractionFlags(Qt::TextInteractionFlags flags)
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index 9e3fc90eb1..be3f7f7ccf 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -98,6 +98,10 @@ public:
QString toHtml() const;
#endif
+ bool hasImState() const;
+ bool cursorVisible() const;
+ void setCursorVisible(bool visible);
+ QTextCursor cursorForPosition(const QPointF &pos) const;
QRectF cursorRect(const QTextCursor &cursor) const;
QRectF cursorRect() const;
QRectF selectionRect(const QTextCursor &cursor) const;
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index c5a39cc759..3a10f007be 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -127,6 +127,7 @@ public:
bool isPreediting() const;
void commitPreedit();
+ void cancelPreedit();
QPointF trippleClickPoint;
QPointF mousePressPos;
@@ -155,11 +156,12 @@ public:
bool ignoreAutomaticScrollbarAdjustement : 1;
bool overwriteMode : 1;
bool acceptRichText : 1;
- bool hideCursor : 1; // used to hide the cursor in the preedit area
+ bool cursorVisible : 1; // used to hide the cursor in the preedit area
bool hasFocus : 1;
bool isEnabled : 1;
bool hadSelectionOnMousePress : 1;
bool wordSelectionEnabled : 1;
+ bool hasImState : 1;
void _q_copyLink();
void _q_updateBlock(const QTextBlock &);
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 4fa5233b9a..f727c54322 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -871,10 +871,9 @@ void QQuickTextEdit::setCursorVisible(bool on)
if (d->cursorVisible == on)
return;
d->cursorVisible = on;
- QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
if (!on && !d->persistentSelection)
d->control->setCursorIsFocusIndicator(true);
- d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
+ d->control->setCursorVisible(on);
emit cursorVisibleChanged(d->cursorVisible);
}
@@ -1536,15 +1535,18 @@ void QQuickTextEdit::inputMethodEvent(QInputMethodEvent *event)
Q_D(QQuickTextEdit);
const bool wasComposing = isInputMethodComposing();
d->control->processEvent(event, QPointF(0, -d->yoff));
+ setCursorVisible(d->control->cursorVisible());
if (wasComposing != isInputMethodComposing())
emit inputMethodComposingChanged();
}
void QQuickTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
{
+ Q_D(QQuickTextEdit);
if (change == ItemActiveFocusHasChanged) {
setCursorVisible(value.boolValue); // ### refactor: focus handling && d->canvas && d->canvas->hasFocus());
-
+ QFocusEvent focusEvent(value.boolValue ? QEvent::FocusIn : QEvent::FocusOut);
+ d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
if (value.boolValue) {
q_updateAlignment();
connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
@@ -1729,9 +1731,7 @@ bool QQuickTextEdit::canRedo() const
bool QQuickTextEdit::isInputMethodComposing() const
{
Q_D(const QQuickTextEdit);
- if (QTextLayout *layout = d->control->textCursor().block().layout())
- return layout->preeditAreaText().length() > 0;
- return false;
+ return d->control->hasImState();
}
void QQuickTextEditPrivate::init()
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index f2da67bae7..5aa01d27f3 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -45,6 +45,7 @@
#include <private/qqmlglobal_p.h>
+#include <QtCore/qcoreapplication.h>
#include <QtQml/qqmlinfo.h>
#include <QtGui/qevent.h>
#include <QTextBoundaryFinder>
@@ -62,10 +63,6 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
-static const int qt_passwordEchoDelay = QT_GUI_PASSWORD_ECHO_DELAY;
-#endif
-
/*!
\qmlclass TextInput QQuickTextInput
\inqmlmodule QtQuick 2
@@ -128,8 +125,8 @@ void QQuickTextInput::setText(const QString &s)
Q_D(QQuickTextInput);
if (s == text())
return;
- if (d->composeMode())
- qApp->inputMethod()->reset();
+
+ d->cancelPreedit();
d->internalSetText(s, -1, false);
}
@@ -678,9 +675,7 @@ QRectF QQuickTextInput::cursorRectangle() const
{
Q_D(const QQuickTextInput);
- int c = d->m_cursor;
- if (d->m_preeditCursor != -1)
- c += d->m_preeditCursor;
+ int c = d->m_cursor + d->m_preeditCursor;
if (d->m_echoMode == NoEcho)
c = 0;
QTextLine l = d->m_textLayout.lineForTextPosition(c);
@@ -1402,7 +1397,7 @@ void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
{
Q_D(QQuickTextInput);
- const bool wasComposing = d->preeditAreaText().length() > 0;
+ const bool wasComposing = d->hasImState;
if (d->m_readOnly) {
ev->ignore();
} else {
@@ -1411,7 +1406,7 @@ void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
if (!ev->isAccepted())
QQuickImplicitSizeItem::inputMethodEvent(ev);
- if (wasComposing != (d->m_textLayout.preeditAreaText().length() > 0))
+ if (wasComposing != d->hasImState)
emit inputMethodComposingChanged();
}
@@ -1929,11 +1924,11 @@ void QQuickTextInput::redo()
void QQuickTextInput::insert(int position, const QString &text)
{
Q_D(QQuickTextInput);
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
- if (d->m_echoMode == QQuickTextInput::Password)
- d->m_passwordEchoTimer.start(qt_passwordEchoDelay, this);
-#endif
-
+ if (d->m_echoMode == QQuickTextInput::Password) {
+ int delay = qGuiApp->styleHints()->passwordMaskDelay();
+ if (delay > 0)
+ d->m_passwordEchoTimer.start(delay, this);
+ }
if (position < 0 || position > d->m_text.length())
return;
@@ -2484,11 +2479,7 @@ void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
if (change == ItemActiveFocusHasChanged) {
bool hasFocus = value.boolValue;
setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
if (!hasFocus && (d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive())) {
-#else
- if (!hasFocus && d->m_passwordEchoEditing) {
-#endif
d->updatePasswordEchoEditing(false);//QQuickTextInputPrivate sets it on key events, but doesn't deal with focus events
}
@@ -2521,7 +2512,7 @@ void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
bool QQuickTextInput::isInputMethodComposing() const
{
Q_D(const QQuickTextInput);
- return d->preeditAreaText().length() > 0;
+ return d->hasImState;
}
void QQuickTextInputPrivate::init()
@@ -2660,7 +2651,6 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate)
if (m_echoMode == QQuickTextInput::Password) {
str.fill(m_passwordCharacter);
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
if (m_passwordEchoTimer.isActive() && m_cursor > 0 && m_cursor <= m_text.length()) {
int cursor = m_cursor - 1;
QChar uc = m_text.at(cursor);
@@ -2673,7 +2663,6 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate)
str[cursor - 1] = uc;
}
}
-#endif
} else if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing) {
str.fill(m_passwordCharacter);
}
@@ -2830,18 +2819,31 @@ void QQuickTextInputPrivate::paste(QClipboard::Mode clipboardMode)
*/
void QQuickTextInputPrivate::commitPreedit()
{
- if (!composeMode())
+ Q_Q(QQuickTextInput);
+
+ if (!hasImState)
return;
qApp->inputMethod()->commit();
- if (!composeMode())
+ if (!hasImState)
+ return;
+
+ QInputMethodEvent ev;
+ QCoreApplication::sendEvent(q, &ev);
+}
+
+void QQuickTextInputPrivate::cancelPreedit()
+{
+ Q_Q(QQuickTextInput);
+
+ if (!hasImState)
return;
- m_preeditCursor = 0;
- m_textLayout.setPreeditArea(-1, QString());
- m_textLayout.clearAdditionalFormats();
- updateLayout();
+ qApp->inputMethod()->reset();
+
+ QInputMethodEvent ev;
+ QCoreApplication::sendEvent(q, &ev);
}
/*!
@@ -3123,15 +3125,19 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
m_textLayout.setPreeditArea(m_cursor, event->preeditString());
#endif //QT_NO_IM
const int oldPreeditCursor = m_preeditCursor;
+ const bool oldCursorVisible = cursorVisible;
m_preeditCursor = event->preeditString().length();
- m_hideCursor = false;
+ hasImState = !event->preeditString().isEmpty();
+ cursorVisible = true;
QList<QTextLayout::FormatRange> formats;
for (int i = 0; i < event->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
if (a.type == QInputMethodEvent::Cursor) {
+ hasImState = true;
m_preeditCursor = a.start;
- m_hideCursor = !a.length;
+ cursorVisible = a.length != 0;
} else if (a.type == QInputMethodEvent::TextFormat) {
+ hasImState = true;
QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
if (f.isValid()) {
QTextLayout::FormatRange o;
@@ -3154,6 +3160,9 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
if (isGettingInput)
finishChange(priorState);
+ if (cursorVisible != oldCursorVisible)
+ emit q->cursorVisibleChanged(cursorVisible);
+
if (selectionChange) {
emit q->selectionChanged();
q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
@@ -3333,11 +3342,12 @@ void QQuickTextInputPrivate::addCommand(const Command &cmd)
*/
void QQuickTextInputPrivate::internalInsert(const QString &s)
{
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
Q_Q(QQuickTextInput);
- if (m_echoMode == QQuickTextInput::Password)
- m_passwordEchoTimer.start(qt_passwordEchoDelay, q);
-#endif
+ if (m_echoMode == QQuickTextInput::Password) {
+ int delay = qGuiApp->styleHints()->passwordMaskDelay();
+ if (delay > 0)
+ m_passwordEchoTimer.start(delay, q);
+ }
if (hasSelectedText())
addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
if (m_maskData) {
@@ -3962,11 +3972,9 @@ void QQuickTextInput::timerEvent(QTimerEvent *event)
d->m_blinkStatus = !d->m_blinkStatus;
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
update();
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
} else if (event->timerId() == d->m_passwordEchoTimer.timerId()) {
d->m_passwordEchoTimer.stop();
d->updateDisplayText();
-#endif
}
}
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 3bd34b2661..1bc2cf548b 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -115,7 +115,7 @@ public:
, selectPressed(false)
, textLayoutDirty(true)
, persistentSelection(false)
- , m_hideCursor(false)
+ , hasImState(false)
, m_separator(0)
, m_readOnly(0)
, m_textDirty(0)
@@ -202,9 +202,7 @@ public:
QColor selectionColor;
QColor selectedTextColor;
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
QBasicTimer m_passwordEchoTimer;
-#endif
int lastSelectionStart;
int lastSelectionEnd;
int m_cursor;
@@ -247,7 +245,7 @@ public:
bool selectPressed:1;
bool textLayoutDirty:1;
bool persistentSelection:1;
- bool m_hideCursor : 1; // used to hide the m_cursor inside preedit areas
+ bool hasImState : 1;
bool m_separator : 1;
bool m_readOnly : 1;
bool m_textDirty : 1;
@@ -321,6 +319,7 @@ public:
#endif
void commitPreedit();
+ void cancelPreedit();
Qt::CursorMoveStyle cursorMoveStyle() const { return m_textLayout.cursorMoveStyle(); }
void setCursorMoveStyle(Qt::CursorMoveStyle style) { m_textLayout.setCursorMoveStyle(style); }
@@ -378,9 +377,7 @@ public:
void updatePasswordEchoEditing(bool editing);
void cancelPasswordEchoTimer() {
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
m_passwordEchoTimer.stop();
-#endif
}
Qt::LayoutDirection layoutDirection() const {
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 5be4963809..81340d6e66 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -254,9 +254,6 @@ namespace {
decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration);
qreal ascent = glyphRun.rawFont().ascent();
- // ### QTBUG-22919 The bounding rect returned by QGlyphRun appears to start on the
- // baseline, move it by the ascent so all bounding rects are at baseline - ascent.
- searchRect.translate(0, -ascent);
insert(binaryTree, BinaryTreeNode(glyphRun, selectionState, searchRect, decorations,
textColor, backgroundColor, position, ascent));
}
@@ -1219,12 +1216,6 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
int textPos = block.position();
QTextBlock::iterator blockIterator = block.begin();
- if (blockIterator.atEnd() && preeditLength) {
- engine.setPosition(blockPosition);
- textPos = engine.addText(block, block.charFormat(), textColor, colorChanges,
- textPos, textPos + preeditLength,
- selectionStart, selectionEnd);
- }
while (!blockIterator.atEnd()) {
QTextFragment fragment = blockIterator.fragment();
@@ -1275,6 +1266,19 @@ void QQuickTextNode::addTextDocument(const QPointF &position, QTextDocument *tex
++blockIterator;
}
+ if (preeditLength >= 0 && textPos <= block.position() + preeditPosition) {
+ engine.setPosition(blockPosition);
+ textPos = block.position() + preeditPosition;
+ QTextLine line = block.layout()->lineForTextPosition(preeditPosition);
+ if (!engine.currentLine().isValid()
+ || line.lineNumber() != engine.currentLine().lineNumber()) {
+ engine.setCurrentLine(line);
+ }
+ textPos = engine.addText(block, block.charFormat(), textColor, colorChanges,
+ textPos, textPos + preeditLength,
+ selectionStart, selectionEnd);
+ }
+
engine.setCurrentLine(QTextLine()); // Reset current line because the text layout changed
++it;
}
diff --git a/src/quick/items/qquickvisualdatamodel.cpp b/src/quick/items/qquickvisualdatamodel.cpp
index 88d46c60ee..cea83969f3 100644
--- a/src/quick/items/qquickvisualdatamodel.cpp
+++ b/src/quick/items/qquickvisualdatamodel.cpp
@@ -803,7 +803,7 @@ QObject *QQuickVisualDataModelPrivate::object(Compositor::Group group, int index
}
if (cacheItem->incubationTask) {
- if (!asynchronous) {
+ if (!asynchronous && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
// previously requested async - now needed immediately
cacheItem->incubationTask->forceCompletion();
}
diff --git a/src/quick/items/qquickwindowmanager.cpp b/src/quick/items/qquickwindowmanager.cpp
index bac5cc7582..d075d3b64b 100644
--- a/src/quick/items/qquickwindowmanager.cpp
+++ b/src/quick/items/qquickwindowmanager.cpp
@@ -1221,7 +1221,7 @@ void QQuickTrivialWindowManager::renderCanvas(QQuickCanvas *canvas)
maybeUpdate(canvas);
}
-void QQuickTrivialWindowManager::exposureChanged(QQuickCanvas *canvas)
+void QQuickTrivialWindowManager::exposureChanged(QQuickCanvas *)
{
}
diff --git a/src/quick/items/qquickwindowmodule_p.h b/src/quick/items/qquickwindowmodule_p.h
index 72fd2b32bd..156ccec127 100644
--- a/src/quick/items/qquickwindowmodule_p.h
+++ b/src/quick/items/qquickwindowmodule_p.h
@@ -42,14 +42,14 @@
#ifndef QQUICKWINDOWMODULE_H
#define QQUICKWINDOWMODULE_H
-#include <qqml.h>
+#include <private/qtquickglobal_p.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-class QQuickWindowModule
+class Q_QUICK_PRIVATE_EXPORT QQuickWindowModule
{
public:
static void defineModule();
diff --git a/src/quick/particles/qquickcustomparticle.cpp b/src/quick/particles/qquickcustomparticle.cpp
index 8f75672e32..7d27e48c6b 100644
--- a/src/quick/particles/qquickcustomparticle.cpp
+++ b/src/quick/particles/qquickcustomparticle.cpp
@@ -130,29 +130,27 @@ struct PlainVertices {
QQuickCustomParticle::QQuickCustomParticle(QQuickItem* parent)
: QQuickParticlePainter(parent)
- , m_dirtyData(true)
- , m_material(0)
- , m_rootNode(0)
+ , m_dirtyUniforms(true)
+ , m_dirtyUniformValues(true)
+ , m_dirtyTextureProviders(true)
+ , m_dirtyProgram(true)
{
setFlag(QQuickItem::ItemHasContents);
}
-class QQuickShaderEffectMaterialObject : public QObject, public QQuickShaderEffectMaterial { };
-
void QQuickCustomParticle::sceneGraphInvalidated()
{
m_nodes.clear();
- m_rootNode = 0;
}
QQuickCustomParticle::~QQuickCustomParticle()
{
- if (m_material)
- m_material->deleteLater();
}
void QQuickCustomParticle::componentComplete()
{
+ m_common.updateShader(this, Key::FragmentShader);
+ updateVertexShader();
reset();
QQuickParticlePainter::componentComplete();
}
@@ -170,10 +168,12 @@ void QQuickCustomParticle::componentComplete()
void QQuickCustomParticle::setFragmentShader(const QByteArray &code)
{
- if (m_source.fragmentCode.constData() == code.constData())
+ if (m_common.source.sourceCode[Key::FragmentShader].constData() == code.constData())
return;
- m_source.fragmentCode = code;
+ m_common.source.sourceCode[Key::FragmentShader] = code;
+ m_dirtyProgram = true;
if (isComponentComplete()) {
+ m_common.updateShader(this, Key::FragmentShader);
reset();
}
emit fragmentShaderChanged();
@@ -222,236 +222,108 @@ void QQuickCustomParticle::setFragmentShader(const QByteArray &code)
void QQuickCustomParticle::setVertexShader(const QByteArray &code)
{
- if (m_source.vertexCode.constData() == code.constData())
+ if (m_common.source.sourceCode[Key::VertexShader].constData() == code.constData())
return;
- m_source.vertexCode = code;
+ m_common.source.sourceCode[Key::VertexShader] = code;
+
+ m_dirtyProgram = true;
if (isComponentComplete()) {
+ updateVertexShader();
reset();
}
emit vertexShaderChanged();
}
-void QQuickCustomParticle::reset()
+void QQuickCustomParticle::updateVertexShader()
{
- disconnectPropertySignals();
-
- m_source.attributeNames.clear();
- m_source.uniformNames.clear();
- m_source.respectsOpacity = false;
- m_source.respectsMatrix = false;
- m_source.className = metaObject()->className();
-
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- delete source.mapper;
- if (source.item && source.item->parentItem() == this)
- source.item->setParentItem(0);
- }
- m_sources.clear();
-
- QQuickParticlePainter::reset();
- m_pleaseReset = true;
- update();
+ m_common.disconnectPropertySignals(this, Key::VertexShader);
+ qDeleteAll(m_common.signalMappers[Key::VertexShader]);
+ m_common.uniformData[Key::VertexShader].clear();
+ m_common.signalMappers[Key::VertexShader].clear();
+ m_common.attributes.clear();
+ m_common.attributes.append("qt_ParticlePos");
+ m_common.attributes.append("qt_ParticleTex");
+ m_common.attributes.append("qt_ParticleData");
+ m_common.attributes.append("qt_ParticleVec");
+ m_common.attributes.append("qt_ParticleR");
+
+ UniformData d;
+ d.name = "qt_Matrix";
+ d.specialType = UniformData::Matrix;
+ m_common.uniformData[Key::VertexShader].append(d);
+ m_common.signalMappers[Key::VertexShader].append(0);
+
+ d.name = "qt_Timestamp";
+ d.specialType = UniformData::None;
+ m_common.uniformData[Key::VertexShader].append(d);
+ m_common.signalMappers[Key::VertexShader].append(0);
+
+ const QByteArray &code = m_common.source.sourceCode[Key::VertexShader];
+ if (!code.isEmpty())
+ m_common.lookThroughShaderCode(this, Key::VertexShader, code);
+
+ m_common.connectPropertySignals(this, Key::VertexShader);
}
-
-void QQuickCustomParticle::changeSource(int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
- QVariant v = property(m_sources.at(index).name.constData());
- setSource(v, index);
-}
-
-void QQuickCustomParticle::updateData()
+void QQuickCustomParticle::reset()
{
- m_dirtyData = true;
+ QQuickParticlePainter::reset();
update();
}
-void QQuickCustomParticle::setSource(const QVariant &var, int index)
-{
- Q_ASSERT(index >= 0 && index < m_sources.size());
-
- SourceData &source = m_sources[index];
-
- source.item = 0;
- if (var.isNull()) {
- return;
- } else if (!qVariantCanConvert<QObject *>(var)) {
- qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData());
- return;
- }
-
- QObject *obj = qVariantValue<QObject *>(var);
- source.item = qobject_cast<QQuickItem *>(obj);
- if (!source.item || !source.item->isTextureProvider()) {
- qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
- source.name.constData(), qPrintable(obj->objectName()), obj->metaObject()->className());
- return;
- }
-
- // TODO: Copy better solution in QQuickShaderEffect when they find it.
- // 'source.item' needs a canvas to get a scenegraph node.
- // The easiest way to make sure it gets a canvas is to
- // make it a part of the same item tree as 'this'.
- if (source.item && source.item->parentItem() == 0) {
- source.item->setParentItem(this);
- source.item->setVisible(false);
- }
-}
-
-void QQuickCustomParticle::disconnectPropertySignals()
-{
- disconnect(this, 0, this, SLOT(updateData()));
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- disconnect(this, 0, source.mapper, 0);
- disconnect(source.mapper, 0, this, 0);
- }
-}
-
-void QQuickCustomParticle::connectPropertySignals()
-{
- QSet<QByteArray>::const_iterator it;
- for (it = m_source.uniformNames.begin(); it != m_source.uniformNames.end(); ++it) {
- int pi = metaObject()->indexOfProperty(it->constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- if (!mp.hasNotifySignal())
- qWarning("QQuickCustomParticle: property '%s' does not have notification method!", it->constData());
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().methodSignature());
- connect(this, signalName, this, SLOT(updateData()));
- } else {
- qWarning("QQuickCustomParticle: '%s' does not have a matching property!", it->constData());
- }
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- SourceData &source = m_sources[i];
- int pi = metaObject()->indexOfProperty(source.name.constData());
- if (pi >= 0) {
- QMetaProperty mp = metaObject()->property(pi);
- QByteArray signalName("2");
- signalName.append(mp.notifySignal().methodSignature());
- connect(this, signalName, source.mapper, SLOT(map()));
- source.mapper->setMapping(this, i);
- connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int)));
- } else {
- qWarning("QQuickCustomParticle: '%s' does not have a matching source!", source.name.constData());
- }
- }
-}
-
-void QQuickCustomParticle::updateProperties()
-{
- QByteArray vertexCode = m_source.vertexCode;
- QByteArray fragmentCode = m_source.fragmentCode;
- if (vertexCode.isEmpty())
- vertexCode = qt_particles_default_vertex_code;
- if (fragmentCode.isEmpty())
- fragmentCode = qt_particles_default_fragment_code;
- vertexCode = qt_particles_template_vertex_code + vertexCode;
-
- m_source.attributeNames.clear();
- m_source.attributeNames << "qt_ParticlePos"
- << "qt_ParticleTex"
- << "qt_ParticleData"
- << "qt_ParticleVec"
- << "qt_ParticleR";
-
- lookThroughShaderCode(vertexCode);
- lookThroughShaderCode(fragmentCode);
-
- if (!m_source.respectsMatrix)
- qWarning("QQuickCustomParticle: Missing reference to \'qt_Matrix\'.");
- if (!m_source.respectsOpacity)
- qWarning("QQuickCustomParticle: Missing reference to \'qt_Opacity\'.");
-
- for (int i = 0; i < m_sources.size(); ++i) {
- QVariant v = property(m_sources.at(i).name);
- setSource(v, i);
- }
-
- connectPropertySignals();
-}
-
-void QQuickCustomParticle::lookThroughShaderCode(const QByteArray &code)
-{
- // Regexp for matching attributes and uniforms.
- // In human readable form: attribute|uniform [lowp|mediump|highp] <type> <name>
- static QRegExp re(QLatin1String("\\b(attribute|uniform)\\b\\s*\\b(?:lowp|mediump|highp)?\\b\\s*\\b(\\w+)\\b\\s*\\b(\\w+)"));
- Q_ASSERT(re.isValid());
-
- int pos = -1;
-
- QString wideCode = QString::fromLatin1(code.constData(), code.size());
-
- while ((pos = re.indexIn(wideCode, pos + 1)) != -1) {
- QByteArray decl = re.cap(1).toLatin1(); // uniform or attribute
- QByteArray type = re.cap(2).toLatin1(); // type
- QByteArray name = re.cap(3).toLatin1(); // variable name
-
- if (decl == "attribute") {
- if (!m_source.attributeNames.contains(name))
- qWarning() << "Custom Particle: Unknown attribute " << name;
- } else {
- Q_ASSERT(decl == "uniform");//TODO: Shouldn't assert
-
- if (name == "qt_Matrix") {
- m_source.respectsMatrix = true;
- } else if (name == "qt_Opacity") {
- m_source.respectsOpacity = true;
- } else if (name == "qt_Timestamp") {
- //Not strictly necessary
- } else {
- m_source.uniformNames.insert(name);
- if (type == "sampler2D") {
- SourceData d;
- d.mapper = new QSignalMapper;
- d.name = name;
- d.item = 0;
- m_sources.append(d);
- }
- }
- }
- }
-}
-
QSGNode *QQuickCustomParticle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
- Q_UNUSED(oldNode);
+ QQuickShaderEffectNode *rootNode = static_cast<QQuickShaderEffectNode *>(oldNode);
if (m_pleaseReset){
-
- //delete m_material;//Shader effect item doesn't regen material?
-
- delete m_rootNode;//Automatically deletes children
- m_rootNode = 0;
+ delete rootNode;//Automatically deletes children
+ rootNode = 0;
m_nodes.clear();
m_pleaseReset = false;
- m_dirtyData = false;
+ m_dirtyProgram = true;
}
if (m_system && m_system->isRunning() && !m_system->isPaused()){
- prepareNextFrame();
- if (m_rootNode) {
+ rootNode = prepareNextFrame(rootNode);
+ if (rootNode)
update();
- foreach (QSGGeometryNode* node, m_nodes)
- node->markDirty(QSGNode::DirtyGeometry);//done in buildData?
- }
}
- return m_rootNode;
+ return rootNode;
}
-void QQuickCustomParticle::prepareNextFrame(){
- if (!m_rootNode)
- m_rootNode = buildCustomNodes();
- if (!m_rootNode)
- return;
+QQuickShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickShaderEffectNode *rootNode)
+{
+ if (!rootNode)
+ rootNode = buildCustomNodes();
+
+ if (!rootNode)
+ return 0;
+
+ if (m_dirtyProgram) {
+ QQuickShaderEffectMaterial *material = static_cast<QQuickShaderEffectMaterial *>(rootNode->material());
+ Q_ASSERT(material);
+
+ Key s = m_common.source;
+ if (s.sourceCode[Key::FragmentShader].isEmpty())
+ s.sourceCode[Key::FragmentShader] = qt_particles_default_fragment_code;
+ if (s.sourceCode[Key::VertexShader].isEmpty())
+ s.sourceCode[Key::VertexShader] = qt_particles_default_vertex_code;
+ s.sourceCode[Key::VertexShader] = qt_particles_template_vertex_code + s.sourceCode[Key::VertexShader];
+ s.className = metaObject()->className();
+
+ material->setProgramSource(s);
+ material->attributes = m_common.attributes;
+ foreach (QQuickShaderEffectNode* node, m_nodes)
+ node->markDirty(QSGNode::DirtyMaterial);
+
+ m_dirtyProgram = false;
+ m_dirtyUniforms = true;
+ }
m_lastTime = m_system->systemSync(this) / 1000.;
- if (m_dirtyData || true)//Currently this is how we update timestamp... potentially over expensive.
- buildData();
+ if (true) //Currently this is how we update timestamp... potentially over expensive.
+ buildData(rootNode);
+ return rootNode;
}
QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
@@ -468,20 +340,13 @@ QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
return 0;
}
- updateProperties();
-
- QQuickShaderEffectProgram s = m_source;
- if (s.fragmentCode.isEmpty())
- s.fragmentCode = qt_particles_default_fragment_code;
- if (s.vertexCode.isEmpty())
- s.vertexCode = qt_particles_default_vertex_code;
+ if (m_groups.isEmpty())
+ return 0;
- if (!m_material) {
- m_material = new QQuickShaderEffectMaterialObject;
- }
+ QQuickShaderEffectNode *rootNode = 0;
+ QQuickShaderEffectMaterial *material = new QQuickShaderEffectMaterial;
+ m_dirtyProgram = true;
- s.vertexCode = qt_particles_template_vertex_code + s.vertexCode;
- m_material->setProgramSource(s);
foreach (const QString &str, m_groups){
int gIdx = m_system->groupIds[str];
int count = m_system->groupData[gIdx]->size();
@@ -489,8 +354,7 @@ QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
QQuickShaderEffectNode* node = new QQuickShaderEffectNode();
m_nodes.insert(gIdx, node);
- node->setMaterial(m_material);
- node->markDirty(QSGNode::DirtyMaterial);
+ node->setMaterial(material);
//Create Particle Geometry
int vCount = count * 4;
@@ -498,6 +362,7 @@ QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
QSGGeometry *g = new QSGGeometry(PlainParticle_AttributeSet, vCount, iCount);
g->setDrawingMode(GL_TRIANGLES);
node->setGeometry(g);
+ node->setFlag(QSGNode::OwnsGeometry, true);
PlainVertex *vertices = (PlainVertex *) g->vertexData();
for (int p=0; p < count; ++p) {
commit(gIdx, p);
@@ -526,48 +391,46 @@ QQuickShaderEffectNode* QQuickCustomParticle::buildCustomNodes()
indices += 6;
}
}
- foreach (QQuickShaderEffectNode* node, m_nodes){
- if (node == *(m_nodes.begin()))
- continue;
- (*(m_nodes.begin()))->appendChildNode(node);
- }
- return *(m_nodes.begin());
+ QHash<int, QQuickShaderEffectNode*>::const_iterator it = m_nodes.begin();
+ rootNode = it.value();
+ rootNode->setFlag(QSGNode::OwnsMaterial, true);
+ for (++it; it != m_nodes.end(); ++it)
+ rootNode->appendChildNode(it.value());
+
+ return rootNode;
}
+void QQuickCustomParticle::sourceDestroyed(QObject *object)
+{
+ m_common.sourceDestroyed(object);
+}
-void QQuickCustomParticle::buildData()
+void QQuickCustomParticle::propertyChanged(int mappedId)
{
- if (!m_rootNode)
+ bool textureProviderChanged;
+ m_common.propertyChanged(this, mappedId, &textureProviderChanged);
+ m_dirtyTextureProviders |= textureProviderChanged;
+ m_dirtyUniformValues = true;
+ update();
+}
+
+
+void QQuickCustomParticle::buildData(QQuickShaderEffectNode *rootNode)
+{
+ if (!rootNode)
return;
- const QByteArray timestampName("qt_Timestamp");
- QVector<QPair<QByteArray, QVariant> > values;
- QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = m_material->textureProviders();
- for (int i = 0; i < oldTextures.size(); ++i) {
- QSGTextureProvider *t = oldTextures.at(i).second;
- if (t)
- foreach (QQuickShaderEffectNode* node, m_nodes)
- disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
- }
- for (int i = 0; i < m_sources.size(); ++i) {
- const SourceData &source = m_sources.at(i);
- QSGTextureProvider *t = source.item->textureProvider();
- textures.append(qMakePair(source.name, t));
- if (t)
- foreach (QQuickShaderEffectNode* node, m_nodes)
- connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
- }
- for (QSet<QByteArray>::const_iterator it = m_source.uniformNames.begin();
- it != m_source.uniformNames.end(); ++it) {
- values.append(qMakePair(*it, property(*it)));
+ for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
+ for (int i = 0; i < m_common.uniformData[shaderType].size(); ++i) {
+ if (m_common.uniformData[shaderType].at(i).name == "qt_Timestamp")
+ m_common.uniformData[shaderType][i].value = qVariantFromValue(m_lastTime);
+ }
}
- values.append(qMakePair(timestampName, QVariant(m_lastTime)));
- m_material->setUniforms(values);
- m_material->setTextureProviders(textures);
- m_dirtyData = false;
+ m_common.updateMaterial(rootNode, static_cast<QQuickShaderEffectMaterial *>(rootNode->material()),
+ m_dirtyUniforms, true, m_dirtyTextureProviders);
foreach (QQuickShaderEffectNode* node, m_nodes)
node->markDirty(QSGNode::DirtyMaterial);
+ m_dirtyUniforms = m_dirtyUniformValues = m_dirtyTextureProviders = false;
}
void QQuickCustomParticle::initialize(int gIdx, int pIdx)
@@ -599,4 +462,12 @@ void QQuickCustomParticle::commit(int gIdx, int pIdx)
}
}
+void QQuickCustomParticle::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ if (change == QQuickItem::ItemSceneChange)
+ m_common.updateCanvas(value.canvas);
+ QQuickParticlePainter::itemChange(change, value);
+}
+
+
QT_END_NAMESPACE
diff --git a/src/quick/particles/qquickcustomparticle_p.h b/src/quick/particles/qquickcustomparticle_p.h
index e04ac704d0..f689091268 100644
--- a/src/quick/particles/qquickcustomparticle_p.h
+++ b/src/quick/particles/qquickcustomparticle_p.h
@@ -43,6 +43,7 @@
#define CUSTOM_PARTICLE_H
#include "qquickparticlepainter_p.h"
#include <private/qquickshadereffectnode_p.h>
+#include <private/qquickshadereffect_p.h>
#include <QSignalMapper>
QT_BEGIN_HEADER
@@ -65,53 +66,50 @@ public:
explicit QQuickCustomParticle(QQuickItem* parent=0);
~QQuickCustomParticle();
- QByteArray fragmentShader() const { return m_source.fragmentCode; }
+ QByteArray fragmentShader() const { return m_common.source.sourceCode[Key::FragmentShader]; }
void setFragmentShader(const QByteArray &code);
- QByteArray vertexShader() const { return m_source.vertexCode; }
+ QByteArray vertexShader() const { return m_common.source.sourceCode[Key::VertexShader]; }
void setVertexShader(const QByteArray &code);
-public Q_SLOTS:
- void updateData();
- void changeSource(int);
+
Q_SIGNALS:
void fragmentShaderChanged();
void vertexShaderChanged();
+
protected:
virtual void initialize(int gIdx, int pIdx);
virtual void commit(int gIdx, int pIdx);
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- void prepareNextFrame();
- void setSource(const QVariant &var, int index);
- void disconnectPropertySignals();
- void connectPropertySignals();
+ QQuickShaderEffectNode *prepareNextFrame(QQuickShaderEffectNode *rootNode);
void reset();
void resize(int oldCount, int newCount);
- void updateProperties();
- void lookThroughShaderCode(const QByteArray &code);
virtual void componentComplete();
QQuickShaderEffectNode *buildCustomNodes();
- void performPendingResize();
void sceneGraphInvalidated();
+ void itemChange(ItemChange change, const ItemChangeData &value);
+
+private Q_SLOTS:
+ void sourceDestroyed(QObject *object);
+ void propertyChanged(int mappedId);
private:
- void buildData();
-
- bool m_dirtyData;
- QQuickShaderEffectProgram m_source;
- struct SourceData
- {
- QSignalMapper *mapper;
- QPointer<QQuickItem> item;
- QByteArray name;
- };
- QVector<SourceData> m_sources;
- QQuickShaderEffectMaterialObject *m_material;
- QQuickShaderEffectNode* m_rootNode;
+ typedef QQuickShaderEffectMaterialKey Key;
+ typedef QQuickShaderEffectMaterial::UniformData UniformData;
+
+ void buildData(QQuickShaderEffectNode *rootNode);
+ void updateVertexShader();
+
+ QQuickShaderEffectCommon m_common;
+
QHash<int, QQuickShaderEffectNode*> m_nodes;
qreal m_lastTime;
+ uint m_dirtyUniforms : 1;
+ uint m_dirtyUniformValues : 1;
+ uint m_dirtyTextureProviders : 1;
+ uint m_dirtyProgram : 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/particles/qquickparticleemitter_p.h b/src/quick/particles/qquickparticleemitter_p.h
index 70adcff34c..eb9e1fd591 100644
--- a/src/quick/particles/qquickparticleemitter_p.h
+++ b/src/quick/particles/qquickparticleemitter_p.h
@@ -178,7 +178,8 @@ public slots:
{
if (m_system != arg) {
m_system = arg;
- m_system->registerParticleEmitter(this);
+ if (m_system)
+ m_system->registerParticleEmitter(this);
emit systemChanged(arg);
}
}
diff --git a/src/quick/particles/qquickparticlesmodule_p.h b/src/quick/particles/qquickparticlesmodule_p.h
index b7cf09919e..23a40488cf 100644
--- a/src/quick/particles/qquickparticlesmodule_p.h
+++ b/src/quick/particles/qquickparticlesmodule_p.h
@@ -39,16 +39,16 @@
**
****************************************************************************/
-#ifndef QQuickPARTICLESMODULE_H
-#define QQuickPARTICLESMODULE_H
+#ifndef QQUICKPARTICLESMODULE_H
+#define QQUICKPARTICLESMODULE_H
-#include <qqml.h>
+#include <private/qtquickglobal_p.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-class QQuickParticlesModule
+class Q_QUICK_PRIVATE_EXPORT QQuickParticlesModule
{
public:
static void defineModule();
@@ -58,4 +58,4 @@ QT_END_NAMESPACE
QT_END_HEADER
-#endif // QQuickPARTICLESMODULE_H
+#endif // QQUICKPARTICLESMODULE_H
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 16cf2198a2..8a0c05618a 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -44,14 +44,12 @@
#include <private/qquickutilmodule_p.h>
#include <private/qquickvaluetypes_p.h>
#include <private/qquickitemsmodule_p.h>
-#include <private/qquickparticlesmodule_p.h>
-#include <private/qquickwindowmodule_p.h>
-#include <private/qquickapplication_p.h>
#include <private/qqmlenginedebugservice_p.h>
#include <private/qqmldebugstatesdelegate_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlcontext_p.h>
+#include <private/qquickapplication_p.h>
#include <QtQuick/private/qquickpropertychanges_p.h>
#include <QtQuick/private/qquickstate_p.h>
#include <qqmlproperty.h>
@@ -176,8 +174,6 @@ void QQmlQtQuick2Module::defineModule()
QQuickUtilModule::defineModule();
QQmlEnginePrivate::defineModule();
QQuickItemsModule::defineModule();
- QQuickParticlesModule::defineModule();
- QQuickWindowModule::defineModule();
qmlRegisterUncreatableType<QQuickApplication>("QtQuick",2,0,"Application", QQuickApplication::tr("Application is an abstract class"));
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
index cd5aaaedd7..dd9db4e904 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
@@ -86,11 +86,11 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
connect(sharedGraphicsCache, SIGNAL(itemsMissing(QByteArray,QVector<quint32>)),
this, SLOT(reportItemsMissing(QByteArray,QVector<quint32>)),
Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsAvailable(QByteArray,void*,QSize,QVector<quint32>,QVector<QPoint>)),
- this, SLOT(reportItemsAvailable(QByteArray,void*,QSize,QVector<quint32>,QVector<QPoint>)),
+ connect(sharedGraphicsCache, SIGNAL(itemsAvailable(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
+ this, SLOT(reportItemsAvailable(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
Qt::DirectConnection);
- connect(sharedGraphicsCache, SIGNAL(itemsUpdated(QByteArray,void*,QSize,QVector<quint32>,QVector<QPoint>)),
- this, SLOT(reportItemsUpdated(QByteArray,void*,QSize,QVector<quint32>,QVector<QPoint>)),
+ connect(sharedGraphicsCache, SIGNAL(itemsUpdated(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
+ this, SLOT(reportItemsUpdated(QByteArray,void*,QVector<quint32>,QVector<QPoint>)),
Qt::DirectConnection);
connect(sharedGraphicsCache, SIGNAL(itemsInvalidated(QByteArray,QVector<quint32>)),
this, SLOT(reportItemsInvalidated(QByteArray,QVector<quint32>)),
@@ -537,7 +537,7 @@ void QSGSharedDistanceFieldGlyphCache::processPendingGlyphs()
while (it != textureContentForBuffer.constEnd()) {
Texture texture;
texture.textureId = m_sharedGraphicsCache->textureIdForBuffer(it.key());
- texture.size = it.value().size;
+ texture.size = m_sharedGraphicsCache->sizeOfBuffer(it.key());
#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG_)
saveTexture(texture.textureId, texture.size.width(), texture.size.height());
@@ -557,7 +557,6 @@ void QSGSharedDistanceFieldGlyphCache::processPendingGlyphs()
void QSGSharedDistanceFieldGlyphCache::reportItemsAvailable(const QByteArray &cacheId,
void *bufferId,
- const QSize &bufferSize,
const QVector<quint32> &itemIds,
const QVector<QPoint> &positions)
{
@@ -568,8 +567,8 @@ void QSGSharedDistanceFieldGlyphCache::reportItemsAvailable(const QByteArray &ca
return;
#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsAvailable() called for %s (%d glyphs, bufferSize: %dx%d)",
- cacheId.constData(), itemIds.size(), bufferSize.width(), bufferSize.height());
+ qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsAvailable() called for %s (%d glyphs)",
+ cacheId.constData(), itemIds.size());
#endif
for (int i=0; i<itemIds.size(); ++i) {
@@ -581,11 +580,11 @@ void QSGSharedDistanceFieldGlyphCache::reportItemsAvailable(const QByteArray &ca
}
if (requestedItemsInList)
- reportItemsUpdated(cacheId, bufferId, bufferSize, itemIds, positions);
+ reportItemsUpdated(cacheId, bufferId,itemIds, positions);
}
void QSGSharedDistanceFieldGlyphCache::reportItemsUpdated(const QByteArray &cacheId,
- void *bufferId, const QSize &bufferSize,
+ void *bufferId,
const QVector<quint32> &itemIds,
const QVector<QPoint> &positions)
{
@@ -597,19 +596,17 @@ void QSGSharedDistanceFieldGlyphCache::reportItemsUpdated(const QByteArray &cach
Q_ASSERT(itemIds.size() == positions.size());
#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
- qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsUpdated() called for %s (%d glyphs, bufferSize: %dx%d)",
- cacheId.constData(), itemIds.size(), bufferSize.width(), bufferSize.height());
+ qDebug("QSGSharedDistanceFieldGlyphCache::reportItemsUpdated() called for %s (%d glyphs)",
+ cacheId.constData(), itemIds.size());
#endif
for (int i=0; i<itemIds.size(); ++i) {
if (m_requestedGlyphs.contains(itemIds.at(i))) {
PendingGlyph &pendingGlyph = m_pendingReadyGlyphs[itemIds.at(i)];
void *oldBuffer = pendingGlyph.buffer;
- Q_ASSERT(bufferSize.height() >= pendingGlyph.bufferSize.height());
pendingGlyph.buffer = bufferId;
pendingGlyph.position = positions.at(i);
- pendingGlyph.bufferSize = bufferSize;
m_sharedGraphicsCache->referenceBuffer(bufferId);
if (oldBuffer != 0)
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
index 19844bbda4..2d43246bb0 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
@@ -77,10 +77,13 @@ Q_SIGNALS:
private Q_SLOTS:
void reportItemsMissing(const QByteArray &cacheId, const QVector<quint32> &itemIds);
void reportItemsAvailable(const QByteArray &cacheId,
- void *bufferId, const QSize &bufferSize,
- const QVector<quint32> &itemIds, const QVector<QPoint> &positions);
- void reportItemsUpdated(const QByteArray &cacheId, void *bufferId, const QSize &bufferSize,
- const QVector<quint32> &itemIds, const QVector<QPoint> &positions);
+ void *bufferId,
+ const QVector<quint32> &itemIds,
+ const QVector<QPoint> &positions);
+ void reportItemsUpdated(const QByteArray &cacheId,
+ void *bufferId,
+ const QVector<quint32> &itemIds,
+ const QVector<QPoint> &positions);
void reportItemsInvalidated(const QByteArray &cacheId, const QVector<quint32> &itemIds);
private:
diff --git a/src/quick/scenegraph/util/qsgpainternode.cpp b/src/quick/scenegraph/util/qsgpainternode.cpp
index 1ea64f6205..87a54d3124 100644
--- a/src/quick/scenegraph/util/qsgpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgpainternode.cpp
@@ -73,6 +73,10 @@ QSGPainterTexture::QSGPainterTexture()
}
+#ifdef QT_OPENGL_ES
+extern void qsg_swizzleBGRAToRGBA(QImage *image);
+#endif
+
void QSGPainterTexture::bind()
{
if (m_dirty_rect.isNull()) {
@@ -91,6 +95,7 @@ void QSGPainterTexture::bind()
int h = m_dirty_rect.height();
#ifdef QT_OPENGL_ES
+ qsg_swizzleBGRAToRGBA(&subImage);
glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h,
GL_RGBA, GL_UNSIGNED_BYTE, subImage.constBits());
#else
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 24b92fa98f..7be38ff109 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -402,7 +402,7 @@ QSGPlainTexture::~QSGPlainTexture()
}
#ifdef QT_OPENGL_ES
-static void swizzleBGRAToRGBA(QImage *image)
+void qsg_swizzleBGRAToRGBA(QImage *image)
{
const int width = image->width();
const int height = image->height();
@@ -500,7 +500,7 @@ void QSGPlainTexture::bind()
updateBindOptions(m_dirty_bind_options);
#ifdef QT_OPENGL_ES
- swizzleBGRAToRGBA(&tmp);
+ qsg_swizzleBGRAToRGBA(&tmp);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp.constBits());
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, tmp.constBits());
diff --git a/src/quick/util/qquickconnections.cpp b/src/quick/util/qquickconnections.cpp
index acc9738f2c..27b66ba38f 100644
--- a/src/quick/util/qquickconnections.cpp
+++ b/src/quick/util/qquickconnections.cpp
@@ -280,10 +280,9 @@ void QQuickConnections::connectSignals()
location = ddata->outerContext->urlString;
}
- QQmlExpression *expression = ctxtdata ?
- QQmlExpressionPrivate::create(ctxtdata, 0, script, true, location, line, column) : 0;
+ QQmlBoundSignalExpression *expression = ctxtdata ?
+ new QQmlBoundSignalExpression(ctxtdata, 0, script, true, location, line, column) : 0;
signal->setExpression(expression);
- signal->addToObject();
d->boundsignals += signal;
} else {
if (!d->ignoreUnknownSignals)
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 8b0818c96c..4bff006d9b 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -55,6 +55,7 @@
#include <private/qqmlproperty_p.h>
#include <private/qqmlcontext_p.h>
#include <private/qquickstate_p_p.h>
+#include <private/qqmlboundsignal_p.h>
#include <QtCore/qdebug.h>
@@ -139,7 +140,7 @@ class QQuickReplaceSignalHandler : public QQuickActionEvent
{
public:
QQuickReplaceSignalHandler() : expression(0), reverseExpression(0),
- rewindExpression(0), ownedExpression(0) {}
+ rewindExpression(0), ownedExpression(0), ownedExpressionWatcher(0) {}
~QQuickReplaceSignalHandler() {
delete ownedExpression;
}
@@ -147,22 +148,35 @@ public:
virtual EventType type() const { return SignalHandler; }
QQmlProperty property;
- QQmlExpression *expression;
- QQmlExpression *reverseExpression;
- QQmlExpression *rewindExpression;
- QQmlGuard<QQmlExpression> ownedExpression;
+ QQmlBoundSignalExpression *expression;
+ QQmlBoundSignalExpression *reverseExpression;
+ QQmlBoundSignalExpression *rewindExpression;
+ QQmlBoundSignalExpression *ownedExpression;
+ QQmlAbstractExpression::DeleteWatcher *ownedExpressionWatcher; // TODO: refactor the ownership impl.
virtual void execute(Reason) {
ownedExpression = QQmlPropertyPrivate::setSignalExpression(property, expression);
- if (ownedExpression == expression)
+ if (ownedExpression == expression) {
+ delete ownedExpressionWatcher;
+ ownedExpressionWatcher = 0;
ownedExpression = 0;
+ } else if (ownedExpression) {
+ delete ownedExpressionWatcher;
+ ownedExpressionWatcher = new QQmlAbstractExpression::DeleteWatcher(ownedExpression);
+ }
}
virtual bool isReversable() { return true; }
virtual void reverse(Reason) {
ownedExpression = QQmlPropertyPrivate::setSignalExpression(property, reverseExpression);
- if (ownedExpression == reverseExpression)
+ if (ownedExpression == reverseExpression) {
+ delete ownedExpressionWatcher;
+ ownedExpressionWatcher = 0;
ownedExpression = 0;
+ } else if (ownedExpression) {
+ delete ownedExpressionWatcher;
+ ownedExpressionWatcher = new QQmlAbstractExpression::DeleteWatcher(ownedExpression);
+ }
}
virtual void saveOriginals() {
@@ -181,6 +195,8 @@ public:
if (rsh->ownedExpression == reverseExpression) {
ownedExpression = rsh->ownedExpression;
rsh->ownedExpression = 0;
+ delete ownedExpressionWatcher;
+ ownedExpressionWatcher = new QQmlAbstractExpression::DeleteWatcher(ownedExpression);
}
}
@@ -225,11 +241,17 @@ public:
public:
ExpressionChange(const QString &_name,
QQmlBinding::Identifier _id,
- QQmlExpression *_expr)
- : name(_name), id(_id), expression(_expr) {}
+ const QString& _expr,
+ const QUrl &_url,
+ int _line,
+ int _column)
+ : name(_name), id(_id), expression(_expr), url(_url), line(_line), column(_column) {}
QString name;
QQmlBinding::Identifier id;
- QQmlExpression *expression;
+ QString expression;
+ QUrl url;
+ int line;
+ int column;
};
QList<QPair<QString, QVariant> > properties;
@@ -334,20 +356,36 @@ void QQuickPropertyChangesPrivate::decode()
QQmlProperty prop = property(name); //### better way to check for signal property?
if (prop.type() & QQmlProperty::SignalProperty) {
- QQmlExpression *expression = new QQmlExpression(qmlContext(q), object, data.toString());
+ QString expression = data.toString();
+ QUrl url = QUrl();
+ int line = -1;
+ int column = -1;
+
QQmlData *ddata = QQmlData::get(q);
- if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
- expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber, ddata->columnNumber);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) {
+ url = ddata->outerContext->url;
+ line = ddata->lineNumber;
+ column = ddata->columnNumber;
+ }
+
QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler;
handler->property = prop;
- handler->expression = expression;
+ handler->expression = new QQmlBoundSignalExpression(QQmlContextData::get(qmlContext(q)), object, expression, false, url.toString(), line, column);
signalReplacements << handler;
- } else if (isScript) {
- QQmlExpression *expression = new QQmlExpression(qmlContext(q), object, data.toString());
+ } else if (isScript) { // binding
+ QString expression = data.toString();
+ QUrl url = QUrl();
+ int line = -1;
+ int column = -1;
+
QQmlData *ddata = QQmlData::get(q);
- if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty())
- expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber, ddata->columnNumber);
- expressions << ExpressionChange(name, id, expression);
+ if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) {
+ url = ddata->outerContext->url;
+ line = ddata->lineNumber;
+ column = ddata->columnNumber;
+ }
+
+ expressions << ExpressionChange(name, id, expression, url, line, column);
} else {
properties << qMakePair(name, data);
}
@@ -374,8 +412,6 @@ QQuickPropertyChanges::QQuickPropertyChanges()
QQuickPropertyChanges::~QQuickPropertyChanges()
{
Q_D(QQuickPropertyChanges);
- for(int ii = 0; ii < d->expressions.count(); ++ii)
- delete d->expressions.at(ii).expression;
for(int ii = 0; ii < d->signalReplacements.count(); ++ii)
delete d->signalReplacements.at(ii);
}
@@ -460,7 +496,8 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
for (int ii = 0; ii < d->expressions.count(); ++ii) {
- const QString &property = d->expressions.at(ii).name;
+ QQuickPropertyChangesPrivate::ExpressionChange e = d->expressions.at(ii);
+ const QString &property = e.name;
QQmlProperty prop = d->property(property);
if (prop.isValid()) {
@@ -471,16 +508,18 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
a.specifiedObject = d->object;
a.specifiedProperty = property;
+ QQmlBinding *newBinding = e.id != QQmlBinding::Invalid ? QQmlBinding::createBinding(e.id, object(), qmlContext(this), e.url.toString(), e.column) : 0;
+ if (!newBinding)
+ newBinding = new QQmlBinding(e.expression, false, object(), QQmlContextData::get(qmlContext(this)), e.url.toString(), e.line, e.column);
+
if (d->isExplicit) {
- a.toValue = d->expressions.at(ii).expression->evaluate();
+ // in this case, we don't want to assign a binding, per se,
+ // so we evaluate the expression and assign the result.
+ // XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
+ // so that we can avoid creating then destroying the binding in this case.
+ a.toValue = newBinding->evaluate();
+ newBinding->destroy();
} else {
- QQmlExpression *e = d->expressions.at(ii).expression;
-
- QQmlBinding::Identifier id = d->expressions.at(ii).id;
- QQmlBinding *newBinding = id != QQmlBinding::Invalid ? QQmlBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber()) : 0;
- if (!newBinding)
- newBinding = new QQmlBinding(e->expression(), false, object(), QQmlContextData::get(qmlContext(this)),
- e->sourceFile(), e->lineNumber(), e->columnNumber());
newBinding->setTarget(prop);
a.toBinding = QQmlAbstractBinding::getPointer(newBinding);
a.deletableToBinding = true;
@@ -635,14 +674,14 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions);
while (expressionIterator.hasNext()) {
- const ExpressionEntry &entry = expressionIterator.next();
+ ExpressionEntry &entry = expressionIterator.next();
if (entry.name == name) {
- entry.expression->setExpression(expression);
+ entry.expression = expression;
if (state() && state()->isStateActive()) {
QQmlAbstractBinding *oldBinding = QQmlPropertyPrivate::binding(d->property(name));
if (oldBinding) {
- QQmlPropertyPrivate::setBinding(d->property(name), 0);
- oldBinding->destroy();
+ QQmlPropertyPrivate::setBinding(d->property(name), 0);
+ oldBinding->destroy();
}
QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this));
@@ -653,8 +692,8 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
}
}
- QQmlExpression *newExpression = new QQmlExpression(qmlContext(this), d->object, expression);
- expressionIterator.insert(ExpressionEntry(name, QQmlBinding::Invalid, newExpression));
+ // adding a new expression.
+ expressionIterator.insert(ExpressionEntry(name, QQmlBinding::Invalid, expression, QUrl(), -1, -1));
if (state() && state()->isStateActive()) {
if (hadValue) {
@@ -675,11 +714,14 @@ void QQuickPropertyChanges::changeExpression(const QString &name, const QString
action.specifiedObject = object();
action.specifiedProperty = name;
-
+ QQmlBinding *newBinding = new QQmlBinding(expression, object(), qmlContext(this));
if (d->isExplicit) {
- action.toValue = newExpression->evaluate();
+ // don't assign the binding, merely evaluate the expression.
+ // XXX TODO: add a static QQmlJavaScriptExpression::evaluate(QString)
+ // so that we can avoid creating then destroying the binding in this case.
+ action.toValue = newBinding->evaluate();
+ newBinding->destroy();
} else {
- QQmlBinding *newBinding = new QQmlBinding(newExpression->expression(), object(), qmlContext(this));
newBinding->setTarget(d->property(name));
action.toBinding = QQmlAbstractBinding::getPointer(newBinding);
action.deletableToBinding = true;
@@ -714,7 +756,7 @@ QVariant QQuickPropertyChanges::property(const QString &name) const
while (expressionIterator.hasNext()) {
const ExpressionEntry &entry = expressionIterator.next();
if (entry.name == name) {
- return QVariant(entry.expression->expression());
+ return QVariant(entry.expression);
}
}
@@ -773,7 +815,7 @@ QString QQuickPropertyChanges::expression(const QString &name) const
while (expressionIterator.hasNext()) {
const ExpressionEntry &entry = expressionIterator.next();
if (entry.name == name) {
- return entry.expression->expression();
+ return entry.expression;
}
}
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index 2d52ea9f50..036641cdfc 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -81,7 +81,6 @@ void tst_QQmlDebugClient::initTestCase()
QQmlDebugTestClient client("tst_QQmlDebugClient::handshake()", m_conn);
QQmlDebugTestService service("tst_QQmlDebugClient::handshake()");
- QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established.");
for (int i = 0; i < 50; ++i) {
// try for 5 seconds ...
m_conn->connectToHost("127.0.0.1", PORT);
@@ -173,7 +172,6 @@ void tst_QQmlDebugClient::sequentialConnect()
QTest::qWait(100);
connection2.connectToHost("127.0.0.1", PORT);
- QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established.");
QVERIFY(connection2.waitForConnected());
QVERIFY(connection2.isConnected());
QTRY_VERIFY(client2.state() == QQmlDebugClient::Enabled);
diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
index 8eb1523af9..12acb9feae 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -81,8 +81,6 @@ void tst_QQmlDebugService::initTestCase()
m_conn = new QQmlDebugConnection(this);
-
- QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established.");
for (int i = 0; i < 50; ++i) {
// try for 5 seconds ...
m_conn->connectToHost("127.0.0.1", PORT);
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp
index 9639a36065..0c5dfddffa 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/qqmlenginedebugclient.cpp
@@ -50,12 +50,14 @@ struct QmlObjectData {
QString objectType;
int objectId;
int contextId;
+ int parentId;
};
QDataStream &operator>>(QDataStream &ds, QmlObjectData &data)
{
ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
- >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId
+ >> data.parentId;
return ds;
}
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index b66ba289ce..cc1193b0f1 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -205,7 +205,7 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(
// signal properties are fake - they are generated from QQmlAbstractBoundSignal children
if (p.name.startsWith("on") && p.name.length() > 2 && p.name[2].isUpper()) {
QString signal = p.value.toString();
- QQmlExpression *expr = QQmlPropertyPrivate::signalExpression(QQmlProperty(o, p.name));
+ QQmlBoundSignalExpression *expr = QQmlPropertyPrivate::signalExpression(QQmlProperty(o, p.name));
QVERIFY(expr && expr->expression() == signal);
QVERIFY(p.valueTypeName.isEmpty());
QVERIFY(p.binding.isEmpty());
@@ -328,7 +328,6 @@ void tst_QQmlEngineDebugService::initTestCase()
m_conn = new QQmlDebugConnection(this);
m_conn->connectToHost("127.0.0.1", 3768);
- QTest::ignoreMessage(QtDebugMsg, "QML Debugger: Connection established.");
bool ok = m_conn->waitForConnected();
QVERIFY(ok);
QTRY_VERIFY(QQmlDebugService::hasDebuggingClient());
diff --git a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
index 497d544390..2961cedd51 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
+++ b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
@@ -77,8 +77,11 @@ public:
V8MaximumMessage
};
+ enum ServiceState { NotRunning, Running } serviceState;
+
QV8ProfilerClient(QQmlDebugConnection *connection)
: QQmlDebugClient(QLatin1String("V8Profiler"), connection)
+ , serviceState(NotRunning)
{
}
@@ -165,12 +168,15 @@ void QV8ProfilerClient::messageReceived(const QByteArray &message)
switch (messageType) {
case QV8ProfilerClient::V8Entry: {
+ QCOMPARE(serviceState, Running);
QV8ProfilerData entry;
stream >> entry.filename >> entry.functionname >> entry.lineNumber >> entry.totalTime >> entry.selfTime >> entry.treeLevel;
traceMessages.append(entry);
break;
}
case QV8ProfilerClient::V8Complete:
+ QCOMPARE(serviceState, Running);
+ serviceState = NotRunning;
emit complete();
break;
case QV8ProfilerClient::V8SnapshotChunk: {
@@ -183,6 +189,8 @@ void QV8ProfilerClient::messageReceived(const QByteArray &message)
emit snapshot();
break;
case QV8ProfilerClient::V8Started:
+ QCOMPARE(serviceState, NotRunning);
+ serviceState = Running;
emit started();
break;
default:
@@ -208,15 +216,16 @@ void tst_QV8ProfilerService::connect(bool block, const QString &testFile)
m_process = new QQmlDebugProcess(executable);
m_process->start(QStringList() << arguments);
if (!m_process->waitForSessionStart()) {
- QString failMsg = QString("Could not launch app '%1'.\nApplication output:\n%2").arg(
- executable, m_process->output());
+ QString failMsg = QString("Could not launch app '%1'.").arg(executable);
QFAIL(qPrintable(failMsg));
}
- QQmlDebugConnection *m_connection = new QQmlDebugConnection();
+ m_connection = new QQmlDebugConnection();
m_client = new QV8ProfilerClient(m_connection);
m_connection->connectToHost(QLatin1String("127.0.0.1"), PORT);
+ if (!m_connection->waitForConnected())
+ QFAIL("Could not connect to debugger port.");
}
void tst_QV8ProfilerService::cleanup()
@@ -226,7 +235,6 @@ void tst_QV8ProfilerService::cleanup()
delete m_process;
delete m_connection;
- delete m_client;
}
void tst_QV8ProfilerService::blockingConnectWithTraceEnabled()
@@ -235,8 +243,6 @@ void tst_QV8ProfilerService::blockingConnectWithTraceEnabled()
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->startProfiling("");
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
- "No start signal received in time.");
m_client->stopProfiling("");
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
"No trace received in time.");
@@ -254,8 +260,6 @@ void tst_QV8ProfilerService::blockingConnectWithTraceDisabled()
QFAIL(qPrintable(failMsg));
}
m_client->startProfiling("");
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
- "No start signal received in time.");
m_client->stopProfiling("");
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
"No trace received in time.");
@@ -267,8 +271,6 @@ void tst_QV8ProfilerService::nonBlockingConnect()
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->startProfiling("");
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
- "No start signal received in time.");
m_client->stopProfiling("");
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
"No trace received in time.");
@@ -290,9 +292,6 @@ void tst_QV8ProfilerService::profileOnExit()
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->startProfiling("");
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
- "No start signal received in time.");
-
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
"No trace received in time.");
//QVERIFY(!m_client->traceMessages.isEmpty());
@@ -305,8 +304,6 @@ void tst_QV8ProfilerService::console()
m_client->stopProfiling("");
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(started())),
- "No start signal received in time.");
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())),
"No trace received in time.");
QVERIFY(!m_client->traceMessages.isEmpty());
diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp
index ac9fa5fae2..925f5372cd 100644
--- a/tests/auto/qml/debugger/shared/debugutil.cpp
+++ b/tests/auto/qml/debugger/shared/debugutil.cpp
@@ -123,7 +123,7 @@ bool QQmlDebugProcess::waitForSessionStart()
qWarning() << "Could not start up " << m_executable;
return false;
}
- m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
+ m_eventLoop.exec();
return m_started;
}
@@ -161,9 +161,6 @@ void QQmlDebugProcess::processAppOutput()
m_eventLoop.quit();
continue;
}
- if (line.contains("Connection established.")) {
- continue;
- }
}
}
m_mutex.unlock();
diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
index 3be7919404..6f0b2e45a2 100644
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
@@ -158,6 +158,10 @@ with a lower case letter.
void tst_qmlmin::qmlMinify_data()
{
+#if defined(QTEST_CROSS_COMPILED)
+ return;
+#endif
+
QTest::addColumn<QString>("file");
QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
@@ -173,11 +177,10 @@ void tst_qmlmin::qmlMinify_data()
void tst_qmlmin::qmlMinify()
{
- QFETCH(QString, file);
-
#if defined(QTEST_CROSS_COMPILED)
QSKIP("sources not available when cross compiled");
#endif
+ QFETCH(QString, file);
QProcess qmlminify;
qmlminify.start(qmlminPath, QStringList() << QLatin1String("--verify-only") << file);
diff --git a/tests/auto/qml/qqmlecmascript/data/InnerObject.qml b/tests/auto/qml/qqmlecmascript/data/InnerObject.qml
new file mode 100644
index 0000000000..a8ed9593d1
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/InnerObject.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+QtObject {
+ property int foo1: 100
+ property int foo2: 100
+ property int foo3: { return 100; }
+ property int foo4: { return 100; }
+
+ property string bar1: 'Hello'
+ property string bar2: 'Hello'
+ property string bar3: { return 'Hello'; }
+ property string bar4: { return 'Hello'; }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/OuterObject.qml b/tests/auto/qml/qqmlecmascript/data/OuterObject.qml
new file mode 100644
index 0000000000..da571a9732
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/OuterObject.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+ property InnerObject inner: InnerObject {}
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/deleteLaterObjectMethodCall.qml b/tests/auto/qml/qqmlecmascript/data/deleteLaterObjectMethodCall.qml
new file mode 100644
index 0000000000..d1418e57a1
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/deleteLaterObjectMethodCall.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+QtObject {
+ property var fn
+
+ property var c: Component {
+ MyQmlObject {
+ function go() {
+ try { methodNoArgs(); } catch(e) { }
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ var f = c.createObject().go;
+
+ gc();
+
+ f();
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/ownershipQmlIncubated.qml b/tests/auto/qml/qqmlecmascript/data/ownershipQmlIncubated.qml
new file mode 100644
index 0000000000..6f536b27ca
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/ownershipQmlIncubated.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ property QtObject incubatedItem
+
+ Component.onCompleted: {
+ var component = Qt.createComponent("PropertyVarBaseItem.qml");
+
+ var incubator = component.incubateObject(root);
+ if (incubator.status != Component.Ready) {
+ incubator.onStatusChanged = function(status) {
+ if (status == Component.Ready) {
+ incubatedItem = incubator.object;
+ }
+ }
+ } else {
+ incubatedItem = incubator.object;
+ }
+ }
+
+ function deleteIncubatedItem() {
+ incubatedItem.destroy();
+ gc();
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/replaceBinding.qml b/tests/auto/qml/qqmlecmascript/data/replaceBinding.qml
new file mode 100644
index 0000000000..670231a144
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/replaceBinding.qml
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+
+OuterObject {
+ property bool success: false
+
+ inner.foo1: 200
+ inner.foo2: { return 200; }
+ inner.foo3: 200
+ inner.foo4: { return 200; }
+
+ inner.bar1: 'Goodbye'
+ inner.bar2: { return 'Goodbye' }
+ inner.bar3: 'Goodbye'
+ inner.bar4: { return 'Goodbye' }
+
+ Component.onCompleted: {
+ success = (inner.foo1 == 200 &&
+ inner.foo2 == 200 &&
+ inner.foo3 == 200 &&
+ inner.foo4 == 200 &&
+ inner.bar1 == 'Goodbye' &&
+ inner.bar2 == 'Goodbye' &&
+ inner.bar3 == 'Goodbye' &&
+ inner.bar4 == 'Goodbye');
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/singleV8BindingDestroyedDuringEvaluation.qml b/tests/auto/qml/qqmlecmascript/data/singleV8BindingDestroyedDuringEvaluation.qml
new file mode 100644
index 0000000000..ae84f028a5
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/singleV8BindingDestroyedDuringEvaluation.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ MyQmlObject {
+ value: if (1) 3
+ }
+
+ MyQmlObject {
+ value: { deleteMe(), 2 }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index b3bf92fe81..c2d490e3c5 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -135,6 +135,7 @@ private slots:
void ownershipCustomReturnValue();
void ownershipRootObject();
void ownershipConsistency();
+ void ownershipQmlIncubated();
void qlistqobjectMethods();
void strictlyEquals();
void compiled();
@@ -183,7 +184,7 @@ private slots:
void assignSequenceTypes();
void qtbug_22464();
void qtbug_21580();
-
+ void singleV8BindingDestroyedDuringEvaluation();
void bug1();
void bug2();
void dynamicCreationCrash();
@@ -246,12 +247,13 @@ private slots:
void invokableWithQObjectDerived();
void realTypePrecision();
void registeredFlagMethod();
-
+ void deleteLaterObjectMethodCall();
void automaticSemicolon();
void unaryExpression();
void switchStatement();
void withStatement();
void tryStatement();
+ void replaceBinding();
private:
static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -1902,6 +1904,16 @@ void tst_qqmlecmascript::qtbug_21580()
delete object;
}
+// Causes a v8 binding, but not all v8 bindings to be destroyed during evaluation
+void tst_qqmlecmascript::singleV8BindingDestroyedDuringEvaluation()
+{
+ QQmlComponent component(&engine, testFileUrl("singleV8BindingDestroyedDuringEvaluation.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ delete object;
+}
+
// QTBUG-6781
void tst_qqmlecmascript::bug1()
{
@@ -3009,6 +3021,24 @@ void tst_qqmlecmascript::ownershipConsistency()
delete object;
}
+void tst_qqmlecmascript::ownershipQmlIncubated()
+{
+ QQmlComponent component(&engine, testFileUrl("ownershipQmlIncubated.qml"));
+ QObject *object = component.create();
+ QVERIFY(object);
+
+ QTRY_VERIFY(object->property("incubatedItem").value<QObject*>() != 0);
+
+ QMetaObject::invokeMethod(object, "deleteIncubatedItem");
+
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ QVERIFY(object->property("incubatedItem").value<QObject*>() == 0);
+
+ delete object;
+}
+
class QListQObjectMethodsObject : public QObject
{
Q_OBJECT
@@ -6000,6 +6030,13 @@ void tst_qqmlecmascript::dynamicString()
QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
}
+void tst_qqmlecmascript::deleteLaterObjectMethodCall()
+{
+ QQmlComponent component(&engine, testFileUrl("deleteLaterObjectMethodCall.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
void tst_qqmlecmascript::automaticSemicolon()
{
QQmlComponent component(&engine, testFileUrl("automaticSemicolon.qml"));
@@ -6408,6 +6445,18 @@ void tst_qqmlecmascript::registeredFlagMethod()
delete object;
}
+// QTBUG-23138
+void tst_qqmlecmascript::replaceBinding()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("replaceBinding.qml"));
+ QObject *obj = c.create();
+ QVERIFY(obj != 0);
+
+ QVERIFY(obj->property("success").toBool());
+ delete obj;
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 837a9d2604..4720269313 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -181,7 +181,7 @@ private slots:
private:
QQmlEngine engine;
- void testType(const QString& qml, const QString& type, const QString& error);
+ void testType(const QString& qml, const QString& type, const QString& error, bool partialMatch = false);
};
#define DETERMINE_ERRORS(errorfile,expected,actual)\
@@ -1480,7 +1480,7 @@ void tst_qqmllanguage::reservedWords()
}
// Check that first child of qml is of given type. Empty type insists on error.
-void tst_qqmllanguage::testType(const QString& qml, const QString& type, const QString& expectederror)
+void tst_qqmllanguage::testType(const QString& qml, const QString& type, const QString& expectederror, bool partialMatch)
{
QQmlComponent component(&engine);
component.setData(qml.toUtf8(), TEST_FILE("empty.qml")); // just a file for relative local imports
@@ -1495,7 +1495,7 @@ void tst_qqmllanguage::testType(const QString& qml, const QString& type, const Q
actualerror.append("; ");
actualerror.append(e.description());
}
- QCOMPARE(actualerror,expectederror);
+ QCOMPARE(actualerror.left(partialMatch ? expectederror.length(): -1),expectederror);
} else {
VERIFY_ERRORS(0);
QObject *object = component.create();
@@ -1616,13 +1616,13 @@ void tst_qqmllanguage::importsBuiltin_data()
"import com.nokia.Test 1.12\n"
"Test {}"
<< (!qmlCheckTypes()?"TestType2":"")
- << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
+ << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test/ in version 1.12 and 1.11");
QTest::newRow("multiversion 2")
<< "import com.nokia.Test 1.11\n"
"import com.nokia.Test 1.12\n"
"OldTest {}"
<< (!qmlCheckTypes()?"TestType":"")
- << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test in version 1.12 and 1.11");
+ << (!qmlCheckTypes()?"":"OldTest is ambiguous. Found in com/nokia/Test/ in version 1.12 and 1.11");
QTest::newRow("qualified multiversion 3")
<< "import com.nokia.Test 1.0 as T0\n"
"import com.nokia.Test 1.8 as T8\n"
@@ -1691,7 +1691,7 @@ void tst_qqmllanguage::importsLocal_data()
"import com.nokia.Test 1.0\n"
"Test {}"
<< (!qmlCheckTypes()?"TestType":"")
- << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test and in subdir");
+ << (!qmlCheckTypes()?"":"Test is ambiguous. Found in com/nokia/Test/ and in subdir/");
}
void tst_qqmllanguage::importsLocal()
@@ -1841,32 +1841,37 @@ void tst_qqmllanguage::importsOrder_data()
QTest::addColumn<QString>("qml");
QTest::addColumn<QString>("type");
QTest::addColumn<QString>("error");
+ QTest::addColumn<bool>("partialMatch");
QTest::newRow("double import") <<
"import com.nokia.installedtest 1.4\n"
"import com.nokia.installedtest 1.4\n"
"InstalledTest {}"
<< (!qmlCheckTypes()?"QQuickText":"")
- << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.4");
+ << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.4")
+ << false;
QTest::newRow("installed import overrides 1") <<
"import com.nokia.installedtest 1.0\n"
"import com.nokia.installedtest 1.4\n"
"InstalledTest {}"
<< (!qmlCheckTypes()?"QQuickText":"")
- << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
+ << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.0")
+ << false;
QTest::newRow("installed import overrides 2") <<
"import com.nokia.installedtest 1.4\n"
"import com.nokia.installedtest 1.0\n"
"InstalledTest {}"
<< (!qmlCheckTypes()?"QQuickRectangle":"")
- << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
+ << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.0 and 1.4")
+ << false;
QTest::newRow("installed import re-overrides 1") <<
"import com.nokia.installedtest 1.4\n"
"import com.nokia.installedtest 1.0\n"
"import com.nokia.installedtest 1.4\n"
"InstalledTest {}"
<< (!qmlCheckTypes()?"QQuickText":"")
- << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.4 and 1.0");
+ << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.4 and 1.0")
+ << false;
QTest::newRow("installed import re-overrides 2") <<
"import com.nokia.installedtest 1.4\n"
"import com.nokia.installedtest 1.0\n"
@@ -1874,41 +1879,47 @@ void tst_qqmllanguage::importsOrder_data()
"import com.nokia.installedtest 1.0\n"
"InstalledTest {}"
<< (!qmlCheckTypes()?"QQuickRectangle":"")
- << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest in version 1.0 and 1.4");
-
+ << (!qmlCheckTypes()?"":"InstalledTest is ambiguous. Found in lib/com/nokia/installedtest/ in version 1.0 and 1.4")
+ << false;
QTest::newRow("installed import versus builtin 1") <<
"import com.nokia.installedtest 1.5\n"
"import QtQuick 2.0\n"
"Rectangle {}"
<< (!qmlCheckTypes()?"QQuickRectangle":"")
- << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in Qt and in lib/com/nokia/installedtest");
+ << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in file://")
+ << true;
QTest::newRow("installed import versus builtin 2") <<
"import QtQuick 2.0\n"
"import com.nokia.installedtest 1.5\n"
"Rectangle {}"
<< (!qmlCheckTypes()?"QQuickText":"")
- << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest and in Qt");
+ << (!qmlCheckTypes()?"":"Rectangle is ambiguous. Found in lib/com/nokia/installedtest/ and in file://")
+ << true;
QTest::newRow("namespaces cannot be overridden by types 1") <<
"import QtQuick 2.0 as Rectangle\n"
"import com.nokia.installedtest 1.5\n"
"Rectangle {}"
- << ""
- << "Namespace Rectangle cannot be used as a type";
+ << ""
+ << "Namespace Rectangle cannot be used as a type"
+ << false;
QTest::newRow("namespaces cannot be overridden by types 2") <<
"import QtQuick 2.0 as Rectangle\n"
"import com.nokia.installedtest 1.5\n"
"Rectangle.Image {}"
- << "QQuickImage"
- << "";
+ << "QQuickImage"
+ << ""
+ << false;
QTest::newRow("local last 1") <<
"LocalLast {}"
- << "QQuickText"
- << "";
+ << "QQuickText"
+ << ""
+ << false;
QTest::newRow("local last 2") <<
"import com.nokia.installedtest 1.0\n"
"LocalLast {}"
<< (!qmlCheckTypes()?"QQuickRectangle":"")// i.e. from com.nokia.installedtest, not data/LocalLast.qml
- << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest and in local directory");
+ << (!qmlCheckTypes()?"":"LocalLast is ambiguous. Found in lib/com/nokia/installedtest/ and in ")
+ << false;
}
void tst_qqmllanguage::importsOrder()
@@ -1916,7 +1927,8 @@ void tst_qqmllanguage::importsOrder()
QFETCH(QString, qml);
QFETCH(QString, type);
QFETCH(QString, error);
- testType(qml,type,error);
+ QFETCH(bool, partialMatch);
+ testType(qml,type,error,partialMatch);
}
void tst_qqmllanguage::importIncorrectCase()
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt
new file mode 100644
index 0000000000..262193788b
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.errors.txt
@@ -0,0 +1 @@
+1:1:module "com.nokia.AutoTestQmlNestedPluginType.Nested" is not installed
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml
new file mode 100644
index 0000000000..b3f9ac6c3f
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.1.qml
@@ -0,0 +1,5 @@
+import com.nokia.AutoTestQmlNestedPluginType.Nested 1.0
+import com.nokia.AutoTestQmlNestedPluginType 1.0
+
+MyNestedPluginType {
+}
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.2.qml b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.2.qml
new file mode 100644
index 0000000000..cb8e0e33d1
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.2.qml
@@ -0,0 +1,5 @@
+import com.nokia.AutoTestQmlNestedPluginType 1.0
+import com.nokia.AutoTestQmlNestedPluginType.Nested 1.0
+
+MyNestedPluginType {
+}
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.errors.txt
new file mode 100644
index 0000000000..f0c73e336f
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.errors.txt
@@ -0,0 +1 @@
+3:1:MyNestedPluginType is not a type
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.qml b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.qml
new file mode 100644
index 0000000000..69c6a34f46
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.3.qml
@@ -0,0 +1,4 @@
+import com.nokia.AutoTestQmlNestedPluginType 1.0
+
+MyNestedPluginType {
+}
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.errors.txt
new file mode 100644
index 0000000000..9743ae4f68
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.errors.txt
@@ -0,0 +1 @@
+2:1:module "com.nokia.AutoTestQmlNestedPluginType.Nested" version 6.66 is not installed
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.qml b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.qml
new file mode 100644
index 0000000000..dce8b7564a
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/importsNested.4.qml
@@ -0,0 +1,5 @@
+import com.nokia.AutoTestQmlNestedPluginType 1.0
+import com.nokia.AutoTestQmlNestedPluginType.Nested 6.66
+
+MyNestedPluginType {
+}
diff --git a/tests/auto/qml/qqmlmoduleplugin/imports/com/nokia/AutoTestQmlNestedPluginType/qmldir b/tests/auto/qml/qqmlmoduleplugin/imports/com/nokia/AutoTestQmlNestedPluginType/qmldir
new file mode 100644
index 0000000000..f6ed20dda4
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/imports/com/nokia/AutoTestQmlNestedPluginType/qmldir
@@ -0,0 +1 @@
+plugin nestedPlugin
diff --git a/src/plugins/qmltooling/qmldbg_qtquick2/selectiontool.cpp b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
index 5ad102a92d..2d0af471c2 100644
--- a/src/plugins/qmltooling/qmldbg_qtquick2/selectiontool.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
-** This file is part of the QtQml module of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -38,55 +38,52 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+#include <QStringList>
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqml.h>
+#include <QDebug>
-#include "selectiontool.h"
-
-#include "highlight.h"
-#include "qquickviewinspector.h"
+class MyPluginType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString value READ value)
-#include <QtGui/QMouseEvent>
-#include <QtQuick/QQuickView>
-#include <QtQuick/QQuickItem>
+public:
+ MyPluginType(QObject *parent=0) : QObject(parent) {}
-namespace QmlJSDebugger {
-namespace QtQuick2 {
+ QString value() const { return "Hello"; }
+};
-SelectionTool::SelectionTool(QQuickViewInspector *inspector) :
- AbstractTool(inspector),
- m_hoverHighlight(new HoverHighlight(inspector->overlay()))
+class MyNestedPluginType : public QObject
{
-}
+ Q_OBJECT
+ Q_PROPERTY(QString value READ value)
-void SelectionTool::leaveEvent(QEvent *)
-{
- m_hoverHighlight->setVisible(false);
-}
+public:
+ MyNestedPluginType(QObject *parent=0) : QObject(parent) {}
-void SelectionTool::mousePressEvent(QMouseEvent *event)
-{
- if (event->button() == Qt::LeftButton) {
- if (QQuickItem *item = inspector()->topVisibleItemAt(event->pos()))
- inspector()->setSelectedItems(QList<QQuickItem*>() << item);
- } else if (event->button() == Qt::RightButton) {
- // todo: Show context menu
- }
-}
+ QString value() const { return "Goodbye"; }
+};
-void SelectionTool::hoverMoveEvent(QMouseEvent *event)
-{
- QQuickItem *item = inspector()->topVisibleItemAt(event->pos());
- if (!item) {
- m_hoverHighlight->setVisible(false);
- } else {
- m_hoverHighlight->setItem(item);
- m_hoverHighlight->setVisible(true);
- }
-}
-QQuickViewInspector *SelectionTool::inspector() const
+class MyPlugin : public QQmlExtensionPlugin
{
- return static_cast<QQuickViewInspector*>(AbstractTool::inspector());
-}
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface" FILE "../empty.json")
+
+public:
+ MyPlugin() {}
+
+ void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == "com.nokia.AutoTestQmlNestedPluginType");
+ qmlRegisterType<MyPluginType>(uri, 1, 0, "MyPluginType");
+
+ QString nestedUri(uri);
+ nestedUri += QLatin1String(".Nested");
+
+ qmlRegisterType<MyNestedPluginType>(nestedUri.toLatin1().constData(), 1, 0, "MyNestedPluginType");
+ }
+};
-} // namespace QtQuick2
-} // namespace QmlJSDebugger
+#include "nestedPlugin.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.pro b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.pro
new file mode 100644
index 0000000000..94dc236a4c
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.pro
@@ -0,0 +1,7 @@
+TEMPLATE = lib
+CONFIG += nestedPlugin
+SOURCES = nestedPlugin.cpp
+QT = core qml
+DESTDIR = ../imports/com/nokia/AutoTestQmlNestedPluginType
+
+QT += core-private gui-private qml-private
diff --git a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
index 42eedc20f2..6da88320cd 100644
--- a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
+++ b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
@@ -1,6 +1,6 @@
QT = core
TEMPLATE = subdirs
-SUBDIRS = plugin plugin.2 plugin.2.1 pluginWrongCase pluginWithQmlFile pluginMixed pluginVersion
+SUBDIRS = plugin plugin.2 plugin.2.1 pluginWrongCase pluginWithQmlFile pluginMixed pluginVersion nestedPlugin
tst_qqmlmoduleplugin_pro.depends += plugin
SUBDIRS += tst_qqmlmoduleplugin.pro
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index b574bad595..f6c165840d 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -70,6 +70,8 @@ private slots:
void versionNotInstalled_data();
void implicitQmldir();
void implicitQmldir_data();
+ void importsNested();
+ void importsNested_data();
private:
QString m_importsDirectory;
@@ -347,6 +349,47 @@ void tst_qqmlmoduleplugin::implicitQmldir()
delete obj;
}
+void tst_qqmlmoduleplugin::importsNested_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("errorFile");
+
+ // Note: no other test case should import the plugin used for this test, or the
+ // wrong order test will pass spuriously
+ QTest::newRow("wrongOrder") << "importsNested.1.qml" << "importsNested.1.errors.txt";
+ QTest::newRow("missingImport") << "importsNested.3.qml" << "importsNested.3.errors.txt";
+ QTest::newRow("invalidVersion") << "importsNested.4.qml" << "importsNested.4.errors.txt";
+ QTest::newRow("correctOrder") << "importsNested.2.qml" << QString();
+}
+void tst_qqmlmoduleplugin::importsNested()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, errorFile);
+
+ // Note: because imports are cached between test case data rows (and the plugins remain loaded),
+ // these tests should really be run in new instances of the app...
+
+ QQmlEngine engine;
+ engine.addImportPath(m_importsDirectory);
+
+ if (!errorFile.isEmpty()) {
+ QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
+ }
+
+ QQmlComponent component(&engine, testFile(file));
+ QObject *obj = component.create();
+
+ if (errorFile.isEmpty()) {
+ if (qgetenv("DEBUG") != "" && !component.errors().isEmpty())
+ qWarning() << "Unexpected Errors:" << component.errors();
+ QVERIFY(obj);
+ delete obj;
+ } else {
+ QList<QQmlError> errors = component.errors();
+ VERIFY_ERRORS(errorFile.toLatin1().constData());
+ QVERIFY(!obj);
+ }
+}
QTEST_MAIN(tst_qqmlmoduleplugin)
diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
index 00b64e04a1..cb42be91d7 100644
--- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
+++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
@@ -165,6 +165,10 @@ and ensures that the subnode's source locations are inside parent node's source
void tst_qqmlparser::qmlParser_data()
{
+#if defined(QTEST_CROSS_COMPILED)
+ return;
+#endif
+
QTest::addColumn<QString>("file");
QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
@@ -180,11 +184,10 @@ void tst_qqmlparser::qmlParser_data()
void tst_qqmlparser::qmlParser()
{
- QFETCH(QString, file);
-
#if defined(QTEST_CROSS_COMPILED)
QSKIP("sources not available when cross compiled");
#endif
+ QFETCH(QString, file);
using namespace QQmlJS;
diff --git a/tests/auto/qml/qqmlproperty/data/invalidBinding.qml b/tests/auto/qml/qqmlproperty/data/invalidBinding.qml
new file mode 100644
index 0000000000..e2bb1d172d
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/invalidBinding.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+ property Text text: myText
+
+ property Rectangle rectangle1: myText
+ property Rectangle rectangle2: eval('getMyText()') // eval to force non-shared (v8) binding
+
+ function getMyText() { return myText; }
+
+ Text {
+ id: myText
+
+ anchors.verticalCenter: parent // invalid binding
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index aa22450bd3..f2521e93ef 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -45,6 +45,7 @@
#include <QtQml/qqmlproperty.h>
#include <QtQml/private/qqmlproperty_p.h>
#include <private/qqmlbinding_p.h>
+#include <private/qqmlboundsignal_p.h>
#include <QtWidgets/QLineEdit>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
@@ -133,6 +134,7 @@ private slots:
void aliasPropertyBindings();
void noContext();
void assignEmptyVariantMap();
+ void warnOnInvalidBinding();
void copy();
private:
@@ -145,8 +147,9 @@ void tst_qqmlproperty::qmlmetaproperty()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -178,8 +181,8 @@ void tst_qqmlproperty::qmlmetaproperty()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -248,8 +251,9 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -281,8 +285,8 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -295,8 +299,9 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -330,8 +335,8 @@ void tst_qqmlproperty::qmlmetaproperty_object()
QVERIFY(binding != 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -349,8 +354,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -382,8 +388,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -396,8 +402,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -431,8 +438,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QVERIFY(binding != 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -445,8 +452,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -478,9 +486,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression != 0);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == expression.data());
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!sigExprWatcher.wasDeleted());
+ QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -493,8 +501,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -526,9 +535,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression != 0);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == expression.data());
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!sigExprWatcher.wasDeleted());
+ QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -546,8 +555,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -579,8 +589,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -593,8 +603,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -628,8 +639,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_context()
QVERIFY(binding != 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -647,8 +658,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -680,8 +692,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), -1);
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -694,8 +706,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -729,8 +742,8 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QVERIFY(binding != 0);
QVERIFY(QQmlPropertyPrivate::binding(prop) == binding.data());
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression == 0);
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(sigExprWatcher.wasDeleted());
QCOMPARE(prop.index(), dobject.metaObject()->indexOfProperty("defaultProperty"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -743,8 +756,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -776,9 +790,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression != 0);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == expression.data());
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!sigExprWatcher.wasDeleted());
+ QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("clicked()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -791,8 +805,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QWeakPointer<QQmlAbstractBinding> binding(QQmlAbstractBinding::getPointer(new QQmlBinding(QLatin1String("null"), 0, engine.rootContext())));
static_cast<QQmlBinding *>(binding.data())->setTarget(prop);
QVERIFY(binding != 0);
- QWeakPointer<QQmlExpression> expression(new QQmlExpression());
- QVERIFY(expression != 0);
+ QQmlBoundSignalExpression *sigExpr = new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1);
+ QQmlAbstractExpression::DeleteWatcher sigExprWatcher(sigExpr);
+ QVERIFY(sigExpr != 0 && !sigExprWatcher.wasDeleted());
QObject *obj = new QObject;
@@ -824,9 +839,9 @@ void tst_qqmlproperty::qmlmetaproperty_object_string_context()
QVERIFY(QQmlPropertyPrivate::setBinding(prop, binding.data()) == 0);
QVERIFY(binding == 0);
QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == 0);
- QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, expression.data()) == 0);
- QVERIFY(expression != 0);
- QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == expression.data());
+ QVERIFY(QQmlPropertyPrivate::setSignalExpression(prop, sigExpr) == 0);
+ QVERIFY(!sigExprWatcher.wasDeleted());
+ QVERIFY(QQmlPropertyPrivate::signalExpression(prop) == sigExpr);
QCOMPARE(prop.index(), dobject.metaObject()->indexOfMethod("oddlyNamedNotifySignal()"));
QCOMPARE(QQmlPropertyPrivate::valueTypeCoreIndex(prop), -1);
@@ -972,7 +987,7 @@ void tst_qqmlproperty::read()
QQmlProperty p(&o, "onClicked");
QCOMPARE(p.read(), QVariant());
- QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlExpression()));
+ QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.read(), QVariant());
@@ -984,7 +999,7 @@ void tst_qqmlproperty::read()
QQmlProperty p(&o, "onPropertyWithNotifyChanged");
QCOMPARE(p.read(), QVariant());
- QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlExpression()));
+ QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.read(), QVariant());
@@ -1140,7 +1155,7 @@ void tst_qqmlproperty::write()
QQmlProperty p(&o, "onClicked");
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
- QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlExpression()));
+ QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
@@ -1154,7 +1169,7 @@ void tst_qqmlproperty::write()
QQmlProperty p(&o, "onPropertyWithNotifyChanged");
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
- QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlExpression()));
+ QVERIFY(0 == QQmlPropertyPrivate::setSignalExpression(p, new QQmlBoundSignalExpression(QQmlContextData::get(engine.rootContext()), 0, QLatin1String("null"), false, QString(), -1, -1)));
QVERIFY(0 != QQmlPropertyPrivate::signalExpression(p));
QCOMPARE(p.write(QVariant("console.log(1921)")), false);
@@ -1708,6 +1723,29 @@ void tst_qqmlproperty::assignEmptyVariantMap()
delete obj;
}
+void tst_qqmlproperty::warnOnInvalidBinding()
+{
+ QUrl testUrl(testFileUrl("invalidBinding.qml"));
+ QString expectedWarning;
+
+ // V4 error message for property-to-property binding
+ expectedWarning = testUrl.toString() + QString::fromLatin1(":6:36: Unable to assign QQuickText to QQuickRectangle");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
+
+ // V8 error message for function-to-property binding
+ expectedWarning = testUrl.toString() + QString::fromLatin1(":7:36: Unable to assign QQuickText to QQuickRectangle");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
+
+ // V8 error message for invalid binding to anchor
+ expectedWarning = testUrl.toString() + QString::fromLatin1(":14: Unable to assign QQuickItem_QML_7 to QQuickAnchorLine");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toLatin1().constData());
+
+ QQmlComponent component(&engine, testUrl);
+ QObject *obj = component.create();
+ QVERIFY(obj);
+ delete obj;
+}
+
void tst_qqmlproperty::initTestCase()
{
QQmlDataTest::initTestCase();
diff --git a/tests/auto/qml/qqmlqt/data/dateTimeConversion.qml b/tests/auto/qml/qqmlqt/data/dateTimeConversion.qml
index 641ba6e1ca..300074dec1 100644
--- a/tests/auto/qml/qqmlqt/data/dateTimeConversion.qml
+++ b/tests/auto/qml/qqmlqt/data/dateTimeConversion.qml
@@ -11,4 +11,10 @@ QtObject {
property variant qdatetime4: new Date(2001,1,2) // 2001/02/02 hh:mm:ss.zzz
property variant qdatetime5: new Date(1999,0,1,2,3,4) // 1999/01/01 02:03:04.zzz
property variant qdatetime6: new Date(2008,1,24,14,15,38,200) // 2008/02/24 14:15:38.200
+
+ // Use UTC for historical dates to avoid DST issues
+ property variant qdatetime7: new Date(Date.UTC(1970,0,1,0,0,0,0)) // 1970/01/01 00:00:00.000
+ property variant qdatetime8: new Date(Date.UTC(1586,1,2)) // 1586/02/02 hh:mm:ss.zzz
+ property variant qdatetime9: new Date(Date.UTC(955,0,1,0,0,0,0)) // 955/01/01 00:00:00.000
+ property variant qdatetime10: new Date(Date.UTC(113,1,24,14,15,38,200)) // 113/02/24 14:15:38.200
}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index a1d7291565..c81e6771b8 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -480,6 +480,10 @@ void tst_qqmlqt::dateTimeConversion()
QDateTime dateTime4(QDate(2001,2,2), QTime(0,0,0,0));
QDateTime dateTime5(QDate(1999,1,1), QTime(2,3,4,0));
QDateTime dateTime6(QDate(2008,2,24), QTime(14,15,38,200));
+ QDateTime dateTime7(QDate(1970,1,1), QTime(0,0,0,0), Qt::UTC);
+ QDateTime dateTime8(QDate(1586,2,2), QTime(0,0,0,0), Qt::UTC);
+ QDateTime dateTime9(QDate(955,1,1), QTime(0,0,0,0), Qt::UTC);
+ QDateTime dateTime10(QDate(113,2,24), QTime(14,15,38,200), Qt::UTC);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("dateTimeConversion.qml"));
@@ -493,6 +497,10 @@ void tst_qqmlqt::dateTimeConversion()
QCOMPARE(obj->property("qdatetime4").toDateTime(), dateTime4);
QCOMPARE(obj->property("qdatetime5").toDateTime(), dateTime5);
QCOMPARE(obj->property("qdatetime6").toDateTime(), dateTime6);
+ QCOMPARE(obj->property("qdatetime7").toDateTime(), dateTime7);
+ QCOMPARE(obj->property("qdatetime8").toDateTime(), dateTime8);
+ QCOMPARE(obj->property("qdatetime9").toDateTime(), dateTime9);
+ QCOMPARE(obj->property("qdatetime10").toDateTime(), dateTime10);
}
void tst_qqmlqt::dateTimeFormatting()
diff --git a/tests/auto/qml/v4/data/conversions.1.qml b/tests/auto/qml/v4/data/conversions.1.qml
new file mode 100644
index 0000000000..b3abde770a
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.1.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning bool prop to other proptypes.
+ boolProp: true
+ intProp: boolProp
+ floatProp: boolProp
+ doubleProp: boolProp
+ qrealProp: boolProp
+ qstringProp: boolProp
+ qurlProp: boolProp
+ vec3Prop: Qt.vector3d(boolProp, boolProp, boolProp)
+}
diff --git a/tests/auto/qml/v4/data/conversions.2.qml b/tests/auto/qml/v4/data/conversions.2.qml
new file mode 100644
index 0000000000..2fd0453ac2
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.2.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning int prop to other proptypes.
+ boolProp: intProp
+ intProp: 4
+ floatProp: intProp
+ doubleProp: intProp
+ qrealProp: intProp
+ qstringProp: intProp
+ qurlProp: intProp
+ vec3Prop: Qt.vector3d(intProp, intProp, intProp)
+}
diff --git a/tests/auto/qml/v4/data/conversions.3.qml b/tests/auto/qml/v4/data/conversions.3.qml
new file mode 100644
index 0000000000..66f0761a25
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.3.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning float prop to other proptypes.
+ boolProp: floatProp
+ intProp: floatProp
+ floatProp: 4.4
+ doubleProp: floatProp
+ qrealProp: floatProp
+ qstringProp: floatProp
+ qurlProp: floatProp
+ vec3Prop: Qt.vector3d(floatProp, floatProp, floatProp)
+}
diff --git a/tests/auto/qml/v4/data/conversions.4.qml b/tests/auto/qml/v4/data/conversions.4.qml
new file mode 100644
index 0000000000..ccf0035313
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.4.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning double prop to other prop types
+ boolProp: doubleProp
+ intProp: doubleProp
+ floatProp: doubleProp
+ doubleProp: 4.444444444
+ qrealProp: doubleProp
+ qstringProp: doubleProp
+ qurlProp: doubleProp
+ vec3Prop: Qt.vector3d(doubleProp, doubleProp, doubleProp)
+}
diff --git a/tests/auto/qml/v4/data/conversions.5.qml b/tests/auto/qml/v4/data/conversions.5.qml
new file mode 100644
index 0000000000..26dc3b7195
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.5.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning qreal prop to other prop types
+ boolProp: qrealProp
+ intProp: qrealProp
+ floatProp: qrealProp
+ doubleProp: qrealProp
+ qrealProp: 4.44
+ qstringProp: qrealProp
+ qurlProp: qrealProp
+ vec3Prop: Qt.vector3d(qrealProp, qrealProp, qrealProp)
+}
diff --git a/tests/auto/qml/v4/data/conversions.6.qml b/tests/auto/qml/v4/data/conversions.6.qml
new file mode 100644
index 0000000000..573b227ada
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.6.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning string prop to other proptypes.
+ boolProp: qstringProp
+ intProp: qstringProp
+ floatProp: qstringProp
+ doubleProp: qstringProp
+ qrealProp: qstringProp
+ qstringProp: "4"
+ qurlProp: qstringProp
+ vec3Prop: Qt.vector3d(qstringProp, qstringProp, qstringProp)
+}
diff --git a/tests/auto/qml/v4/data/conversions.7.qml b/tests/auto/qml/v4/data/conversions.7.qml
new file mode 100644
index 0000000000..5112b06b1e
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.7.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning url prop to other proptypes.
+ boolProp: qurlProp
+ intProp: qurlProp
+ floatProp: qurlProp
+ doubleProp: qurlProp
+ qrealProp: qurlProp
+ qstringProp: qurlProp
+ qurlProp: "4"
+ vec3Prop: Qt.vector3d(qurlProp, qurlProp, qurlProp)
+}
diff --git a/tests/auto/qml/v4/data/conversions.8.qml b/tests/auto/qml/v4/data/conversions.8.qml
new file mode 100644
index 0000000000..18bf160e7e
--- /dev/null
+++ b/tests/auto/qml/v4/data/conversions.8.qml
@@ -0,0 +1,13 @@
+import Qt.v4 1.0
+
+Conversion {
+ // test assigning vector prop to other proptypes.
+ boolProp: vec3Prop
+ intProp: vec3Prop
+ floatProp: vec3Prop
+ doubleProp: vec3Prop
+ qrealProp: vec3Prop
+ qstringProp: vec3Prop
+ qurlProp: vec3Prop
+ vec3Prop: Qt.vector3d(4, 4, 4)
+}
diff --git a/tests/auto/qml/v4/data/subscriptions.1.qml b/tests/auto/qml/v4/data/subscriptions.1.qml
new file mode 100644
index 0000000000..607233819e
--- /dev/null
+++ b/tests/auto/qml/v4/data/subscriptions.1.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ width: 400
+ height: 400
+
+ property real targetHeight: menuItems.height + 1
+ property real heightValue: if (1) menuItems.height //this must be v8?
+ property bool boolProp: menuItems.height > heightValue //this must be v4?
+
+ Column {
+ id: menuItems
+ Item { height: 200; width: 10 }
+ }
+}
diff --git a/tests/auto/qml/v4/testtypes.cpp b/tests/auto/qml/v4/testtypes.cpp
index c879cf2226..80ccf007a5 100644
--- a/tests/auto/qml/v4/testtypes.cpp
+++ b/tests/auto/qml/v4/testtypes.cpp
@@ -46,4 +46,5 @@ void registerTypes()
{
qmlRegisterType<ResultObject>("Qt.v4", 1,0, "Result");
qmlRegisterType<NestedObject>();
+ qmlRegisterType<ConversionObject>("Qt.v4", 1, 0, "Conversion");
}
diff --git a/tests/auto/qml/v4/testtypes.h b/tests/auto/qml/v4/testtypes.h
index 18b5b27b36..04dd82e8fe 100644
--- a/tests/auto/qml/v4/testtypes.h
+++ b/tests/auto/qml/v4/testtypes.h
@@ -42,6 +42,8 @@
#define TESTTYPES_H
#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+#include <QVector3D>
class NestedObject : public QObject
{
@@ -80,6 +82,61 @@ private:
NestedObject m_nested2;
};
+class ConversionObject : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool boolProp READ boolProp WRITE setBoolProp NOTIFY boolPropChanged)
+ Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged)
+ Q_PROPERTY(float floatProp READ floatProp WRITE setFloatProp NOTIFY floatPropChanged)
+ Q_PROPERTY(double doubleProp READ doubleProp WRITE setDoubleProp NOTIFY doublePropChanged)
+ Q_PROPERTY(qreal qrealProp READ qrealProp WRITE setQrealProp NOTIFY qrealPropChanged)
+ Q_PROPERTY(QString qstringProp READ qstringProp WRITE setQstringProp NOTIFY qstringPropChanged)
+ Q_PROPERTY(QUrl qurlProp READ qurlProp WRITE setQurlProp NOTIFY qurlPropChanged)
+ Q_PROPERTY(QVector3D vec3Prop READ vec3Prop WRITE setVec3Prop NOTIFY vec3PropChanged)
+
+public:
+ ConversionObject() : m_boolProp(false), m_intProp(0), m_floatProp(0.0), m_doubleProp(0.0), m_qrealProp(0.0) {}
+ ~ConversionObject() {}
+
+ bool boolProp() const { return m_boolProp; }
+ void setBoolProp(bool v) { m_boolProp = v; emit boolPropChanged(); }
+ int intProp() const { return m_intProp; }
+ void setIntProp(int v) { m_intProp = v; emit intPropChanged(); }
+ float floatProp() const { return m_floatProp; }
+ void setFloatProp(float v) { m_floatProp = v; emit floatPropChanged(); }
+ double doubleProp() const { return m_doubleProp; }
+ void setDoubleProp(double v) { m_doubleProp = v; emit doublePropChanged(); }
+ qreal qrealProp() const { return m_qrealProp; }
+ void setQrealProp(qreal v) { m_qrealProp = v; emit qrealPropChanged(); }
+ QString qstringProp() const { return m_qstringProp; }
+ void setQstringProp(const QString& v) { m_qstringProp = v; emit qstringPropChanged(); }
+ QUrl qurlProp() const { return m_qurlProp; }
+ void setQurlProp(const QUrl& v) { m_qurlProp = v; emit qurlPropChanged(); }
+ QVector3D vec3Prop() const { return m_vec3Prop; }
+ void setVec3Prop(const QVector3D& v) { m_vec3Prop = v; emit vec3PropChanged(); }
+
+signals:
+ void boolPropChanged();
+ void intPropChanged();
+ void floatPropChanged();
+ void doublePropChanged();
+ void qrealPropChanged();
+ void qstringPropChanged();
+ void qurlPropChanged();
+ void vec3PropChanged();
+
+private:
+ bool m_boolProp;
+ int m_intProp;
+ float m_floatProp;
+ double m_doubleProp;
+ qreal m_qrealProp;
+ QString m_qstringProp;
+ QUrl m_qurlProp;
+ QVector3D m_vec3Prop;
+};
+
void registerTypes();
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/v4/tst_v4.cpp b/tests/auto/qml/v4/tst_v4.cpp
index 47fa10b595..dfb7cc48c7 100644
--- a/tests/auto/qml/v4/tst_v4.cpp
+++ b/tests/auto/qml/v4/tst_v4.cpp
@@ -46,6 +46,7 @@
#include <QtQml/qqmlcomponent.h>
#include <QtCore/qdebug.h>
#include <QtGui/qcolor.h>
+#include <QtCore/qnumeric.h>
#include <private/qv4compiler_p.h>
@@ -83,6 +84,12 @@ private slots:
void mathMin();
void moduleApi();
+ void conversions_data();
+ void conversions();
+ void subscriptions();
+
+ void debuggingDumpInstructions(); // this test should be last.
+
private:
QQmlEngine engine;
};
@@ -135,6 +142,14 @@ void tst_v4::qtscript_data()
QTest::newRow("unary minus") << "unaryMinus.qml";
QTest::newRow("null qobject") << "nullQObject.qml";
QTest::newRow("qobject -> bool") << "objectToBool.qml";
+ QTest::newRow("conversion from bool") << "conversions.1.qml"; // QTBUG-24706
+ QTest::newRow("conversion from int") << "conversions.2.qml"; // QTBUG-24706
+ QTest::newRow("conversion from float") << "conversions.3.qml";
+ QTest::newRow("conversion from double") << "conversions.4.qml"; // QTBUG-24706
+ QTest::newRow("conversion from real") << "conversions.5.qml"; // QTBUG-24706
+ QTest::newRow("conversion from string") << "conversions.6.qml"; // QTBUG-24706
+ QTest::newRow("conversion from url") << "conversions.7.qml"; // QTBUG-24706
+ QTest::newRow("conversion from vec3") << "conversions.8.qml";
}
void tst_v4::unnecessaryReeval()
@@ -630,6 +645,334 @@ void tst_v4::moduleApi()
delete o;
}
+void tst_v4::conversions_data()
+{
+ QTest::addColumn<QUrl>("file");
+ QTest::addColumn<QStringList>("warnings");
+ QTest::addColumn<bool>("boolProp");
+ QTest::addColumn<int>("intProp");
+ QTest::addColumn<float>("floatProp");
+ QTest::addColumn<double>("doubleProp");
+ QTest::addColumn<qreal>("qrealProp");
+ QTest::addColumn<QString>("qstringProp");
+ QTest::addColumn<QUrl>("qurlProp");
+ QTest::addColumn<QVector3D>("vec3Prop");
+
+ QTest::newRow("from bool") << testFileUrl("conversions.1.qml")
+ << (QStringList() << (testFileUrl("conversions.1.qml").toString() + QLatin1String(":11:15: Unable to assign bool to QUrl")))
+ << true
+ << (int)true
+ << (float)1.0
+ << (double)1.0
+ << (qreal)1.0
+ << QString(QLatin1String("true"))
+ << QUrl() // cannot assign bool to url.
+ << QVector3D(1, 1, 1);
+
+ QTest::newRow("from integer") << testFileUrl("conversions.2.qml")
+ << (QStringList() << (testFileUrl("conversions.2.qml").toString() + QLatin1String(":11:15: Unable to assign int to QUrl")))
+ << (bool)4
+ << 4
+ << (float)4.0
+ << (double)4.0
+ << (qreal)4.0
+ << QString(QLatin1String("4"))
+ << QUrl() // cannot assign int to url.
+ << QVector3D(4, 4, 4);
+
+ QTest::newRow("from float") << testFileUrl("conversions.3.qml")
+ << (QStringList() << (testFileUrl("conversions.3.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
+ << (bool)4.4
+ << (int)4.4
+ << (float)4.4
+ << (double)((float)4.4)
+ << (qreal)((float)4.4)
+ << QString::number((double)((float)4.4), 'g', 16)
+ << QUrl() // cannot assign number to url.
+ << QVector3D(4.4, 4.4, 4.4);
+
+ QTest::newRow("from double") << testFileUrl("conversions.4.qml")
+ << (QStringList() << (testFileUrl("conversions.4.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
+ << (bool)4.444444444
+ << (int)4.444444444
+ << (float)4.444444444
+ << (double)4.444444444
+ << (qreal)4.444444444
+ << QString::number((double)4.444444444, 'g', 16)
+ << QUrl() // cannot assign number to url.
+ << QVector3D(4.444444444, 4.444444444, 4.444444444);
+
+ QTest::newRow("from qreal") << testFileUrl("conversions.5.qml")
+ << (QStringList() << (testFileUrl("conversions.5.qml").toString() + QLatin1String(":11:15: Unable to assign number to QUrl")))
+ << (bool)4.44
+ << (int)4.44
+ << (float)4.44
+ << (double)4.44
+ << (qreal)4.44
+ << QString(QLatin1String("4.44"))
+ << QUrl() // cannot assign number to url.
+ << QVector3D(4.44, 4.44, 4.44);
+
+ QTest::newRow("from string") << testFileUrl("conversions.6.qml")
+ << (QStringList())
+ << true
+ << 4
+ << (float)4.0
+ << (double)4.0
+ << (qreal)4.0
+ << QString(QLatin1String("4"))
+ << QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
+ << QVector3D(4, 4, 4);
+
+ // QTBUG-24706
+ QTest::newRow("from url") << testFileUrl("conversions.7.qml")
+ << (QStringList() << (testFileUrl("conversions.7.qml").toString() + QLatin1String(":6:14: Unable to assign QUrl to int"))
+ << (testFileUrl("conversions.7.qml").toString() + QLatin1String(":7:16: Unable to assign QUrl to number"))
+ << (testFileUrl("conversions.7.qml").toString() + QLatin1String(":8:17: Unable to assign QUrl to number"))
+ << (testFileUrl("conversions.7.qml").toString() + QLatin1String(":9:16: Unable to assign QUrl to number")))
+ << true
+ << 0
+ << (float) 0
+ << (double) 0
+ << (qreal) 0
+ << QString(testFileUrl("").toString() + QString(QLatin1String("4")))
+ << QUrl(testFileUrl("").toString() + QString(QLatin1String("4")))
+ << QVector3D(qQNaN(), qQNaN(), qQNaN());
+
+ QTest::newRow("from vector") << testFileUrl("conversions.8.qml")
+ << (QStringList() << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":11: Unable to assign QVector3D to QUrl"))
+ << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":10: Unable to assign QVector3D to QString"))
+ << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":9: Unable to assign QVector3D to double"))
+ << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":8: Unable to assign QVector3D to double"))
+ << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":7: Unable to assign QVector3D to float"))
+ << (testFileUrl("conversions.8.qml").toString() + QLatin1String(":6: Unable to assign QVector3D to int")))
+ << true // non-null therefore true
+ << (int)0 // the other values should be the default-ctor values.
+ << (float)0
+ << (double)0
+ << (qreal)0
+ << QString()
+ << QUrl()
+ << QVector3D(4, 4, 4); // except this one.
+}
+
+#define COMPARE_NUMBER(type, prop, expected) \
+ if (qIsNaN(expected)) \
+ QVERIFY(qIsNaN(qvariant_cast<type>(prop))); \
+ else \
+ QCOMPARE((prop), QVariant::fromValue<type>(expected));
+
+void tst_v4::conversions()
+{
+ QFETCH(QUrl, file);
+ QFETCH(QStringList, warnings);
+ QFETCH(bool, boolProp);
+ QFETCH(int, intProp);
+ QFETCH(float, floatProp);
+ QFETCH(double, doubleProp);
+ QFETCH(qreal, qrealProp);
+ QFETCH(QString, qstringProp);
+ QFETCH(QUrl, qurlProp);
+ QFETCH(QVector3D, vec3Prop);
+
+ foreach (const QString &w, warnings)
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
+
+ QQmlComponent component(&engine, file);
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+ QCOMPARE(o->property("boolProp"), QVariant::fromValue<bool>(boolProp));
+ QCOMPARE(o->property("intProp"), QVariant::fromValue<int>(intProp));
+ COMPARE_NUMBER(float, o->property("floatProp"), floatProp);
+ COMPARE_NUMBER(double, o->property("doubleProp"), doubleProp);
+ COMPARE_NUMBER(qreal, o->property("qrealProp"), qrealProp);
+ QCOMPARE(o->property("qstringProp"), QVariant::fromValue<QString>(qstringProp));
+ QCOMPARE(o->property("qurlProp"), QVariant::fromValue<QUrl>(qurlProp));
+
+ QVector3D vec3 = qvariant_cast<QVector3D>(o->property("vec3Prop"));
+ COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.x()), vec3Prop.x());
+ COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.y()), vec3Prop.y());
+ COMPARE_NUMBER(qreal, QVariant::fromValue<qreal>(vec3.z()), vec3Prop.z());
+ delete o;
+}
+
+void tst_v4::subscriptions()
+{
+ {
+ QQmlComponent component(&engine, testFileUrl("subscriptions.1.qml"));
+
+ QObject *o = component.create();
+ QVERIFY(o != 0);
+
+ QObject *ro = qobject_cast<QObject *>(o);
+ QVERIFY(ro != 0);
+
+ QCOMPARE(ro->property("targetHeight"), QVariant::fromValue<qreal>(201));
+
+ delete o;
+ }
+}
+
+static QStringList messages;
+static void msgHandler(QtMsgType, const char *msg)
+{
+ messages << QLatin1String(msg);
+}
+
+static QByteArray getAddress(int address)
+{
+ return QByteArray::number(address);
+}
+
+static QByteArray getLeading(int address)
+{
+ QByteArray leading;
+ if (address != -1) {
+ leading = getAddress(address);
+ leading.prepend(QByteArray(8 - leading.count(), ' '));
+ }
+ return leading;
+}
+
+#include <private/qv4instruction_p.h>
+void tst_v4::debuggingDumpInstructions()
+{
+ QStringList expectedPreAddress;
+ expectedPreAddress << "\t\tNoop";
+ expectedPreAddress << "\t0:0:";
+ expectedPreAddress << "\t\tSubscribe\t\tObject_Reg(0) Notify_Signal(0) -> Subscribe_Slot(0)";
+ expectedPreAddress << "\t\tSubscribeId\t\tId_Offset(0) -> Subscribe_Slot(0)";
+ expectedPreAddress << "\t\tFetchAndSubscribe\tObject_Reg(0) Fast_Accessor(0x0) -> Output_Reg(0) Subscription_Slot(0)";
+ expectedPreAddress << "\t\tLoadId\t\t\tId_Offset(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadScope\t\t-> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadRoot\t\t-> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadModuleObject\t\t) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadAttached\t\tObject_Reg(0) Attached_Index(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tUnaryNot\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tUnaryMinusNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tUnaryMinusInt\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tUnaryPlusNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tUnaryPlusInt\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertBoolToInt\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertBoolToNumber\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertBoolToString\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertIntToBool\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertIntToNumber\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertIntToString\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertNumberToBool\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertNumberToInt\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertNumberToString\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertStringToBool\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertStringToInt\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertStringToNumber\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertStringToUrl\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertStringToColor\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertUrlToBool\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertUrlToString\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertColorToBool\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertColorToString\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertObjectToBool\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tConvertNullToObject\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tResolveUrl\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathSinNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathCosNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathAbsNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathRoundNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathFloorNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathCeilNumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathPINumber\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadNull\t\tConstant(null) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadNumber\t\tConstant(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadInt\t\t\tConstant(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadBool\t\tConstant(false) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLoadString\t\tString_DataIndex(0) String_Length(0) -> Output_Register(0)";
+ expectedPreAddress << "\t\tEnableV4Test\t\tString_DataIndex(0) String_Length(0)";
+ expectedPreAddress << "\t\tTestV4Store\t\tInput_Reg(0) Reg_Type(0)";
+ expectedPreAddress << "\t\tBitAndInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tBitOrInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tBitXorInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tAddNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tAddString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tSubNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMulNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tDivNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tModNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tRShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tURShiftInt\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tGtNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLtNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tGeNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLeNumber\t\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tNotEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tStrictEqualNumber\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tStrictNotEqualNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tGtString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLtString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tGeString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tLeString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tEqualString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tNotEqualString\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tStrictEqualString\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tStrictNotEqualString\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tEqualObject\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tNotEqualObject\t\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tStrictEqualObject\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tStrictNotEqualObject\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathMaxNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tMathMinNumber\tInput_Reg(0) Input_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tNewString\t\tRegister(0)";
+ expectedPreAddress << "\t\tNewUrl\t\t\tRegister(0)";
+ expectedPreAddress << "\t\tCleanupRegister\t\tRegister(0)";
+ expectedPreAddress << "\t\tCopy\t\t\tInput_Reg(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tFetch\t\t\tObject_Reg(0) Property_Index(0) -> Output_Reg(0)";
+ expectedPreAddress << "\t\tStore\t\t\tInput_Reg(0) -> Object_Reg(0) Property_Index(0)";
+ expectedPreAddress << "\t\tJump\t\t\tAddress(UNIT_TEST_JUMP_ADDRESS) [if false == Input_Reg(0)]"; //(address + size() + i->jump.count)
+ expectedPreAddress << "\t\tBranchTrue\t\tAddress(UNIT_TEST_BRANCH_ADDRESS) [if true == Input_Reg(0)]"; //(address + size() + i->branchop.offset)
+ expectedPreAddress << "\t\tBranchFalse\t\tAddress(UNIT_TEST_BRANCH_ADDRESS) [if false == Input_Reg(0)]"; //(address + size() + i->branchop.offset)
+ expectedPreAddress << "\t\tBranch\t\t\tAddress(UNIT_TEST_BRANCH_ADDRESS)"; //(address + size() + i->branchop.offset)
+ expectedPreAddress << "\t\tBlock\t\t\tMask(0)";
+ expectedPreAddress << "\t\tThrow\t\t\tInputReg(0)";
+ expectedPreAddress << "\t\tInitString\t\tString_DataIndex(0) -> String_Slot(0)";
+ QStringList expected;
+
+ messages = QStringList();
+ QtMsgHandler old = qInstallMsgHandler(msgHandler);
+
+ QQmlJS::Bytecode bc;
+#define DUMP_INSTR_IN_UNIT_TEST(I, FMT) { QQmlJS::V4InstrData<QQmlJS::V4Instr::I> i; memset(&i, 0, sizeof(i)); bc.append(i); }
+ FOR_EACH_V4_INSTR(DUMP_INSTR_IN_UNIT_TEST);
+#undef DUMP_INSTR_IN_UNIT_TEST // NOTE: we memset in order to ensure stable output.
+ const char *start = bc.constData();
+ const char *end = start + bc.size();
+ const char *codeAddr = start;
+ int whichExpected = 0;
+#define DUMP_INSTR_SIZE_IN_UNIT_TEST(I, FMT) { \
+ QString currExpected = whichExpected < expectedPreAddress.size() ? expectedPreAddress.at(whichExpected++) : QString(); \
+ currExpected.prepend(getLeading(codeAddr - start)); \
+ expected.append(currExpected); \
+ codeAddr += QQmlJS::V4Instr::size(static_cast<QQmlJS::V4Instr::Type>(QQmlJS::V4Instr::I)); \
+ }
+ FOR_EACH_V4_INSTR(DUMP_INSTR_SIZE_IN_UNIT_TEST);
+#undef DUMP_INSTR_SIZE_IN_UNIT_TEST // so that we generate the correct address for each instruction comparison
+ bc.dump(start, end);
+
+ // ensure that the output was expected.
+ qInstallMsgHandler(old);
+ QCOMPARE(messages.count(), expected.count());
+ for (int ii = 0; ii < messages.count(); ++ii) {
+ // Calculating the destination address of a null jump/branch instruction is tricky
+ // so instead we simply don't compare that part of those instructions.
+ QRegExp ignoreAddress("\\bAddress\\((\\w*)\\)");
+ ignoreAddress.setMinimal(true);
+ QString expectOut = expected.at(ii); expectOut.replace(ignoreAddress, "");
+ QString actualOut = messages.at(ii); actualOut.replace(ignoreAddress, "");
+ QCOMPARE(actualOut, expectOut);
+ }
+}
+
+
QTEST_MAIN(tst_v4)
#include "tst_v4.moc"
diff --git a/tests/auto/qmltest/selftests/tst_datadriven.qml b/tests/auto/qmltest/selftests/tst_datadriven.qml
new file mode 100644
index 0000000000..0686c12c00
--- /dev/null
+++ b/tests/auto/qmltest/selftests/tst_datadriven.qml
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+
+Item {
+ TestCase {
+ name:"data-driven-empty-init-data"
+ property int tests:0;
+ property int init_data_called_times:0;
+ function init_data() {init_data_called_times++;}
+ function initTestCase() {tests = 0; init_data_called_times = 0;}
+ function cleanupTestCase() {compare(tests, 2); compare(init_data_called_times, 2);}
+
+ function test_test1() {tests++;}
+ function test_test2() {tests++;}
+ }
+ TestCase {
+ name:"data-driven-no-init-data"
+ property int tests:0;
+ function initTestCase() {tests = 0;}
+ function cleanupTestCase() {compare(tests, 2);}
+
+ function test_test1() {tests++;}
+ function test_test2() {tests++;}
+ }
+ TestCase {
+ name:"data-driven-init-data"
+ property int tests:0;
+ property int init_data_called_times:0;
+ function initTestCase() {tests = 0; init_data_called_times = 0;}
+ function cleanupTestCase() {compare(tests, 2); compare(init_data_called_times, 1);}
+ function init_data() {init_data_called_times++; return [{tag:"data1", data:"test data 1"}];}
+
+ function test_test1(row) {tests++; compare(row.data, "test data 1");}
+ function test_test2_data() {return [{tag:"data2", data:"test data 2"}]; }
+ function test_test2(row) {tests++; compare(row.data, "test data 2");}
+ }
+}
diff --git a/tests/auto/quick/examples/examples.pro b/tests/auto/quick/examples/examples.pro
index c320fdad9e..d24fe80498 100644
--- a/tests/auto/quick/examples/examples.pro
+++ b/tests/auto/quick/examples/examples.pro
@@ -8,5 +8,3 @@ DEFINES += SRCDIR=\\\"$$PWD\\\"
CONFIG += parallel_test
#temporary
QT += core-private gui-private qml-private quick-private v8-private testlib
-
-cross_compile: DEFINES += QTEST_CROSS_COMPILED
diff --git a/tests/auto/quick/examples/tst_examples.cpp b/tests/auto/quick/examples/tst_examples.cpp
index 9a2a800cfd..b019c716b0 100644
--- a/tests/auto/quick/examples/tst_examples.cpp
+++ b/tests/auto/quick/examples/tst_examples.cpp
@@ -249,10 +249,6 @@ void tst_examples::sgexamples()
{
QFETCH(QString, file);
-#if defined(QTEST_CROSS_COMPILED)
- QSKIP("sources not available when cross compiled");
-#endif
-
QQmlComponent component(&engine, QUrl::fromLocalFile(file));
if (component.status() == QQmlComponent::Error)
qWarning() << component.errors();
@@ -293,10 +289,6 @@ void tst_examples::sgsnippets()
{
QFETCH(QString, file);
-#if defined(QTEST_CROSS_COMPILED)
- QSKIP("sources not available when cross compiled");
-#endif
-
QQmlComponent component(&engine, QUrl::fromLocalFile(file));
if (component.status() == QQmlComponent::Error)
qWarning() << component.errors();
diff --git a/tests/auto/quick/qquickaccessible/data/statictext.qml b/tests/auto/quick/qquickaccessible/data/statictext.qml
index a0821cfc4d..7cf1b707a0 100644
--- a/tests/auto/quick/qquickaccessible/data/statictext.qml
+++ b/tests/auto/quick/qquickaccessible/data/statictext.qml
@@ -10,6 +10,10 @@ Item {
width: 200
height: 50
text : "Hello Accessibility"
+
+ // Setting any value of the attached property
+ // makes an item accessible.
+ Accessible.name: text
}
Text {
diff --git a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
index 48c07c6e2c..45a9d11c69 100644
--- a/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
+++ b/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp
@@ -340,23 +340,25 @@ void tst_QQuickAccessible::hitTest()
canvas->setSource(testFileUrl("hittest.qml"));
canvas->show();
- QAI iface = QAI(QAccessible::queryAccessibleInterface(canvas));
- QVERIFY(iface.data());
- QAI rootItem = QAI(iface->child(0));
+ QAI canvasIface = QAI(QAccessible::queryAccessibleInterface(canvas));
+ QVERIFY(canvasIface.data());
+ QAI rootItem = QAI(canvasIface->child(0));
QRect rootRect = rootItem->rect();
- // hit the root item
- QAI itemHit(iface->childAt(rootRect.x() + 200, rootRect.y() + 50));
+ // check the root item from app
+ QAI appIface = QAI(QAccessible::queryAccessibleInterface(qApp));
+ QVERIFY(appIface);
+ QAI itemHit(appIface->childAt(rootRect.x() + 200, rootRect.y() + 50));
QVERIFY(itemHit);
QCOMPARE(rootRect, itemHit->rect());
// hit rect1
- QAI rect1(rootItem->child(1));
+ QAI rect1(rootItem->child(0));
QRect rect1Rect = rect1->rect();
- itemHit = QAI(rootItem->childAt(rect1Rect.x() + 10, rect1Rect.y() + 10));
- QVERIFY(itemHit);
- QCOMPARE(rect1Rect, itemHit->rect());
- QCOMPARE(itemHit->text(QAccessible::Name), QLatin1String("rect1"));
+ QAI rootItemIface = QAI(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)
QAI app(QAccessible::queryAccessibleInterface(qApp));
@@ -366,16 +368,20 @@ void tst_QQuickAccessible::hitTest()
QCOMPARE(itemHit2->text(QAccessible::Name), QLatin1String("rect1"));
// hit rect201
- QAI rect2(rootItem->child(2));
- QAI rect20(rect2->child(1));
- QAI rect201(rect20->child(2));
+ QAI 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));
+ QAI rect20(rect2->child(0));
+ QVERIFY(rect20);
+ QAI rect201(rect20->child(1));
QVERIFY(rect201);
QRect rect201Rect = rect201->rect();
- itemHit = QAI(iface->childAt(rect201Rect.x() + 20, rect201Rect.y() + 20));
- QVERIFY(itemHit);
- QCOMPARE(itemHit->rect(), rect201Rect);
- QCOMPARE(itemHit->text(QAccessible::Name), QLatin1String("rect201"));
+ rootItemIface = QAI(canvasIface->childAt(rect201Rect.x() + 20, rect201Rect.y() + 20));
+ QVERIFY(rootItemIface);
+ QCOMPARE(rootItemIface->rect(), rect201Rect);
+ QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect201"));
delete canvas;
}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
index c33901d294..10bc37e82d 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml
@@ -43,7 +43,10 @@ Canvas {
ctx.moveTo(100, 0);
ctx.arc(100, 0, 150, (512+1/2)*Math.PI, (1024-1)*Math.PI, true);
ctx.fill();
+ /*FIXME: from: http://www.w3.org/TR/2dcontext/#dom-context-2d-arc
+ If the anticlockwise argument is omitted or false and endAngle-startAngle is equal to or greater than 2Ï€, or, if the anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2Ï€, then the arc is the whole circumference of this circle.
//verify(Helper.comparePixel(ctx,50,25, 0,255,0,255));
+ */
}
function test_angle_4() {
var ctx = canvas.getContext('2d');
@@ -72,11 +75,10 @@ Canvas {
ctx.moveTo(100, 0);
ctx.arc(100, 0, 150, (1024-1)*Math.PI, (512+1/2)*Math.PI, false);
ctx.fill();
- /*FIXME:
- actual :[255,0,0,255]
- expected:[0,255,0,255] +/- 0
- */
+ /*FIXME: from: http://www.w3.org/TR/2dcontext/#dom-context-2d-arc
+ If the anticlockwise argument is omitted or false and endAngle-startAngle is equal to or greater than 2Ï€, or, if the anticlockwise argument is true and startAngle-endAngle is equal to or greater than 2Ï€, then the arc is the whole circumference of this circle.
//verify(Helper.comparePixel(ctx,50,25, 0,255,0,255));
+ */
}
function test_angle_6() {
@@ -108,11 +110,7 @@ Canvas {
ctx.beginPath();
ctx.arc(200, 25, 5, 0, 2*Math.PI, true);
ctx.stroke();
- /*FIXME:
- actual :[255,0,0,255]
- expected:[0,255,0,255] +/- 0
- */
- //verify(Helper.comparePixel(ctx,50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx,50,25, 0,255,0,255));
}
function test_nonempty() {
var ctx = canvas.getContext('2d');
@@ -129,7 +127,6 @@ Canvas {
verify(Helper.comparePixel(ctx,50,25, 0,255,0,255));
}
function test_nonfinite() {
- skip("FIXME");
var ctx = canvas.getContext('2d');
ctx.reset();
@@ -241,13 +238,13 @@ Canvas {
verify(Helper.comparePixel(ctx, 0,0, 0,255,0,255));
verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
verify(Helper.comparePixel(ctx, 0,25, 0,255,0,255));
verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 0,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 0,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
}
function test_scale_2() {
@@ -271,7 +268,7 @@ Canvas {
verify(Helper.comparePixel(ctx, 98,25, 0,255,0,255));
verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
verify(Helper.comparePixel(ctx, 50,48, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
}
function test_selfintersect_1() {
@@ -288,8 +285,8 @@ Canvas {
ctx.beginPath();
ctx.arc(0, 0, 25, 0, -Math.PI/2, true);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
}
function test_selfintersect_2() {
@@ -307,10 +304,10 @@ Canvas {
ctx.arc(100, 0, 25, 0, -Math.PI/2, true);
ctx.stroke();
verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 90,10, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 97,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 97,2, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 97,3, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 90,10, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 97,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 97,2, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 97,3, 0,255,0,255));
verify(Helper.comparePixel(ctx, 2,48, 0,255,0,255));
}
@@ -325,12 +322,12 @@ Canvas {
ctx.beginPath();
ctx.arc(50, 50, 50, 0, Math.PI, false);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
verify(Helper.comparePixel(ctx, 20,48, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
}
function test_shape_2() {
@@ -362,11 +359,11 @@ Canvas {
ctx.beginPath();
ctx.arc(0, 50, 50, 0, -Math.PI/2, false);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
}
function test_shape_4() {
@@ -398,11 +395,11 @@ Canvas {
ctx.beginPath();
ctx.arc(300, 0, 100, 0, 5*Math.PI, false);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
}
function test_twopie() {
@@ -416,7 +413,7 @@ Canvas {
ctx.beginPath();
ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, true);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -436,7 +433,8 @@ Canvas {
ctx.beginPath();
ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, true);
ctx.stroke();
- verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
+ //FIXME:still different behavior from browsers, > 2pi span issue
+ //verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -460,7 +458,7 @@ Canvas {
ctx.beginPath();
ctx.arc(50, 25, 50, 0, 0, true);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -470,7 +468,7 @@ Canvas {
ctx.beginPath();
ctx.arc(50, 25, 50, 0, 0, false);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,20, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00'
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
index 84bfc1a8db..188d538d29 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml
@@ -118,7 +118,7 @@ Canvas {
ctx.beginPath();
ctx.arcTo(100, 50, 200, 50, 0.1);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -152,8 +152,6 @@ Canvas {
var ctx = canvas.getContext('2d');
ctx.reset();
- skip("FIXME");
-
ctx.moveTo(0, 0);
ctx.lineTo(100, 0);
ctx.arcTo(Infinity, 50, 0, 50, 0);
@@ -221,7 +219,7 @@ Canvas {
ctx.lineTo(-1000, 0);
ctx.fill();
- skip("FIXME");
+ //FIXME
//verify(Helper.comparePixel(ctx, 0,0, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
@@ -332,7 +330,8 @@ Canvas {
ctx.arcTo(200, 25, 200, 50, 10);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
+ //FIXME
+ //verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
@@ -354,16 +353,15 @@ Canvas {
ctx.lineTo(-100, 0);
ctx.fill();
- skip("FIXME");
- //verify(Helper.comparePixel(ctx, 0,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 0,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 0,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 0,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 0,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 0,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
}
function test_zero() {
var ctx = canvas.getContext('2d');
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
index 23d7b719ff..a70c798594 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
@@ -271,6 +271,7 @@ Rectangle {
ctx = c.getContext('2D');
verify(ctx);
compare(ctx.canvas, c);
+ ignoreWarning(Qt.resolvedUrl("tst_canvas.qml") + ":10:9: QML Canvas: Canvas already initialized with a different context type");
ctx = c.getContext('invalid');
verify(!ctx);
c.destroy();
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml b/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml
index bdc9d37663..60c63ae04b 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml
@@ -133,7 +133,6 @@ Canvas {
}
function test_solid() {
- skip("FIXME");
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = Qt.rgba(0, 1, 1, 1.0);
@@ -230,7 +229,6 @@ Canvas {
}
function test_transparent() {
- skip("FIXME");
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
@@ -279,7 +277,8 @@ Canvas {
ctx.globalCompositeOperation = 'lighter';
ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
ctx.fillRect(0, 0, 100, 50);
- verify(Helper.comparePixel(ctx, 50,25, 0,127,191,255, 5));
+ //FIXME
+ //verify(Helper.comparePixel(ctx, 50,25, 0,127,191,255, 5));
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
@@ -325,7 +324,6 @@ Canvas {
}
function test_uncovered() {
- skip("FIXME");
var ctx = canvas.getContext('2d');
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
@@ -334,7 +332,8 @@ Canvas {
ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
ctx.translate(0, 25);
ctx.fillRect(0, 50, 100, 50);
- verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
+ //FIXME
+ //verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
@@ -343,7 +342,8 @@ Canvas {
ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
ctx.translate(0, 25);
ctx.fillRect(0, 50, 100, 50);
- verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
+ //FIXME
+ //verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
@@ -354,7 +354,8 @@ Canvas {
ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
ctx.translate(0, 25);
ctx.fillRect(0, 50, 100, 50);
- verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
+ //FIXME
+ //verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
@@ -363,7 +364,8 @@ Canvas {
ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
ctx.translate(0, 25);
ctx.fillRect(0, 50, 100, 50);
- verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
+ //FIXME
+ //verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
ctx.reset();
ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
@@ -372,7 +374,8 @@ Canvas {
ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
ctx.translate(0, 25);
ctx.fillRect(0, 50, 100, 50);
- verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
+ //FIXME
+ //verify(Helper.comparePixel(ctx, 50,25, 0,0,0,0, 5));
}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
index f72e5b9eaa..7c88106e5f 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml
@@ -4,7 +4,6 @@ import "testhelper.js" as Helper
Canvas {
id:canvas; width:100;height:50; renderTarget: Canvas.Image; renderStrategy:Canvas.Threaded
- smooth: false
TestCase {
name: "path"; when: windowShown
@@ -102,7 +101,7 @@ Canvas {
ctx.reset();
ctx.rect(20, 0, 20, 20);
- //verify(ctx.isPointInPath(10, 10));
+ verify(!ctx.isPointInPath(10, 10));
verify(ctx.isPointInPath(30, 10));
ctx.reset();
@@ -111,19 +110,19 @@ Canvas {
verify(!ctx.isPointInPath(25, 30));
//verify(ctx.isPointInPath(30, 20));
verify(!ctx.isPointInPath(30, 30));
- //verify(!ctx.isPointInPath(40, 2));
+ verify(!ctx.isPointInPath(40, 2));
//verify(ctx.isPointInPath(40, 20));
verify(!ctx.isPointInPath(40, 30));
verify(!ctx.isPointInPath(40, 47));
//verify(ctx.isPointInPath(45, 20));
- //verify(!ctx.isPointInPath(45, 30));
+ verify(!ctx.isPointInPath(45, 30));
//verify(!ctx.isPointInPath(55, 20));
//verify(ctx.isPointInPath(55, 30));
- verify(!ctx.isPointInPath(60, 2));
+ //verify(!ctx.isPointInPath(60, 2));
//verify(!ctx.isPointInPath(60, 20));
verify(ctx.isPointInPath(60, 30));
verify(!ctx.isPointInPath(60, 47));
- verify(!ctx.isPointInPath(70, 20));
+ //verify(!ctx.isPointInPath(70, 20));
verify(ctx.isPointInPath(70, 30));
verify(!ctx.isPointInPath(75, 20));
verify(!ctx.isPointInPath(75, 30));
@@ -131,8 +130,8 @@ Canvas {
ctx.reset();
ctx.arc(50, 25, 10, 0, 7, false);
verify(!ctx.isPointInPath(50, 10));
- //verify(ctx.isPointInPath(50, 20));
- //verify(ctx.isPointInPath(50, 30));
+ verify(ctx.isPointInPath(50, 20));
+ verify(ctx.isPointInPath(50, 30));
verify(!ctx.isPointInPath(50, 40));
verify(!ctx.isPointInPath(30, 20));
verify(!ctx.isPointInPath(70, 20));
@@ -143,16 +142,16 @@ Canvas {
ctx.rect(0, 0, 20, 20);
verify(ctx.isPointInPath(0, 0));
verify(ctx.isPointInPath(10, 0));
- //verify(ctx.isPointInPath(20, 0));
- //verify(ctx.isPointInPath(20, 10));
- //verify(ctx.isPointInPath(20, 20));
- //verify(ctx.isPointInPath(10, 20));
- //verify(ctx.isPointInPath(0, 20));
+ verify(ctx.isPointInPath(20, 0));
+ verify(ctx.isPointInPath(20, 10));
+ verify(ctx.isPointInPath(20, 20));
+ verify(ctx.isPointInPath(10, 20));
+ verify(ctx.isPointInPath(0, 20));
verify(ctx.isPointInPath(0, 10));
verify(!ctx.isPointInPath(10, -0.01));
verify(!ctx.isPointInPath(10, 20.01));
verify(!ctx.isPointInPath(-0.01, 10));
- //verify(!ctx.isPointInPath(20.01, 10));
+ verify(!ctx.isPointInPath(20.01, 10));
ctx.reset();
verify(!ctx.isPointInPath(0, 0));
@@ -160,13 +159,13 @@ Canvas {
ctx.reset();
ctx.rect(-100, -50, 200, 100);
- //verify(ctx.isPointInPath(Infinity, 0));
- //verify(ctx.isPointInPath(-Infinity, 0));
- //verify(ctx.isPointInPath(NaN, 0));
- //verify(ctx.isPointInPath(0, Infinity));
- //verify(ctx.isPointInPath(0, -Infinity));
- //verify(ctx.isPointInPath(0, NaN));
- //verify(ctx.isPointInPath(NaN, NaN));
+ verify(!ctx.isPointInPath(Infinity, 0));
+ verify(!ctx.isPointInPath(-Infinity, 0));
+ verify(!ctx.isPointInPath(NaN, 0));
+ verify(!ctx.isPointInPath(0, Infinity));
+ verify(!ctx.isPointInPath(0, -Infinity));
+ verify(!ctx.isPointInPath(0, NaN));
+ verify(!ctx.isPointInPath(NaN, NaN));
ctx.reset();
ctx.rect(0, -100, 20, 20);
@@ -174,9 +173,9 @@ Canvas {
verify(!ctx.isPointInPath(10, -110));
verify(ctx.isPointInPath(10, -90));
verify(!ctx.isPointInPath(10, -70));
- //verify(!ctx.isPointInPath(30, -20));
- //verify(ctx.isPointInPath(30, 0));
- //verify(!ctx.isPointInPath(30, 20));
+ verify(!ctx.isPointInPath(30, -20));
+ verify(ctx.isPointInPath(30, 0));
+ verify(!ctx.isPointInPath(30, 20));
ctx.reset();
ctx.rect(0, 0, 20, 20);
@@ -193,7 +192,7 @@ Canvas {
ctx.rect(0, 0, 20, 20);
verify(!ctx.isPointInPath(-40, 10));
verify(!ctx.isPointInPath(10, 10));
- //verify(!ctx.isPointInPath(49, 10));
+ verify(!ctx.isPointInPath(49, 10));
verify(ctx.isPointInPath(51, 10));
verify(ctx.isPointInPath(69, 10));
verify(!ctx.isPointInPath(71, 10));
@@ -203,7 +202,7 @@ Canvas {
ctx.translate(50, 0);
verify(!ctx.isPointInPath(-40, 10));
verify(!ctx.isPointInPath(10, 10));
- //verify(!ctx.isPointInPath(49, 10));
+ verify(!ctx.isPointInPath(49, 10));
verify(ctx.isPointInPath(51, 10));
verify(ctx.isPointInPath(69, 10));
verify(!ctx.isPointInPath(71, 10));
@@ -213,7 +212,7 @@ Canvas {
ctx.rect(-70, 0, 20, 20);
verify(!ctx.isPointInPath(-40, 10));
verify(!ctx.isPointInPath(10, 10));
- //verify(!ctx.isPointInPath(49, 10));
+ verify(!ctx.isPointInPath(49, 10));
verify(ctx.isPointInPath(51, 10));
verify(ctx.isPointInPath(69, 10));
verify(!ctx.isPointInPath(71, 10));
@@ -224,7 +223,7 @@ Canvas {
ctx.lineTo(20, 20);
ctx.lineTo(0, 20);
verify(ctx.isPointInPath(10, 10));
- //verify(!ctx.isPointInPath(30, 10));
+ verify(!ctx.isPointInPath(30, 10));
ctx.reset();
ctx.moveTo(0, 0);
@@ -279,8 +278,8 @@ Canvas {
ctx.fillStyle = '#0f0';
ctx.fill();
- //verify(Helper.comparePixel(ctx, 90,10, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 10,40, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 90,10, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 10,40, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#000';
@@ -292,7 +291,7 @@ Canvas {
ctx.rect(10, 10, 80, 30);
ctx.fill();
- //verify(Helper.comparePixel(ctx, 50,25, 0,127,0,255, 1));
+ verify(Helper.comparePixel(ctx, 50,25, 0,127,0,255, 1));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -310,7 +309,7 @@ Canvas {
ctx.lineTo(0, 50);
ctx.fill();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -422,7 +421,7 @@ Canvas {
ctx.arc(50, 25, 10, 0, 0, false);
ctx.stroke();
- // verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
@@ -457,7 +456,8 @@ Canvas {
ctx.lineTo(-100, 1000);
ctx.stroke();
- verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ //FIXME:lineJoin with miterLimit test fail!
+ //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#0f0';
@@ -564,15 +564,15 @@ Canvas {
ctx.stroke();
ctx.restore();
- //verify(Helper.comparePixel(ctx, 0,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 0,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 0,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 0,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 0,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 0,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -611,14 +611,14 @@ Canvas {
ctx.restore();
//verify(Helper.comparePixel(ctx, 0,0, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,0, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 99,0, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 0,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,25, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 0,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,49, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 99,49, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -847,7 +847,7 @@ Canvas {
ctx.beginPath();
ctx.lineTo(100, 50);
ctx.stroke();
- // verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -911,8 +911,8 @@ Canvas {
ctx.beginPath();
ctx.bezierCurveTo(100, 50, 200, 50, 200, 50);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 95,45, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 95,45, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -923,7 +923,7 @@ Canvas {
ctx.bezierCurveTo(0, 25, 100, 25, 100, 25);
ctx.stroke();
verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 5,45, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 5,45, 0,255,0,255));
ctx.reset();
ctx.moveTo(0, 0);
@@ -1035,11 +1035,11 @@ Canvas {
ctx.moveTo(-2, 3.1);
ctx.bezierCurveTo(-2, -1, 2.1, -1, 2.1, 3.1);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -1078,8 +1078,8 @@ Canvas {
ctx.beginPath();
ctx.quadraticCurveTo(100, 50, 200, 50);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 95,45, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 95,45, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -1090,7 +1090,7 @@ Canvas {
ctx.quadraticCurveTo(0, 25, 100, 25);
ctx.stroke();
verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 5,45, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 5,45, 0,255,0,255));
ctx.reset();
ctx.moveTo(0, 0);
@@ -1135,11 +1135,11 @@ Canvas {
ctx.moveTo(-1, 1.05);
ctx.quadraticCurveTo(0, -1, 1.2, 1.05);
ctx.stroke();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 1,1, 0,255,0,255));
//verify(Helper.comparePixel(ctx, 98,1, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 1,48, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 98,48, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -1260,8 +1260,8 @@ Canvas {
ctx.lineTo(0, 50);
ctx.fillStyle = '#0f0';
ctx.fill();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
- //verify(Helper.comparePixel(ctx, 90,45, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 90,45, 0,255,0,255));
ctx.reset();
@@ -1399,7 +1399,7 @@ Canvas {
ctx.fillStyle = '#0f0';
ctx.fill();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#f00';
@@ -1416,7 +1416,7 @@ Canvas {
ctx.rotate(Math.PI/2);
ctx.scale(0.1, 0.1);
ctx.fill();
- //verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
+ verify(Helper.comparePixel(ctx, 50,25, 0,255,0,255));
ctx.reset();
ctx.fillStyle = '#0f0';
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 2ed42e7f0f..f926dbe8f0 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -443,11 +443,14 @@ void tst_qquickflickable::movingAndDragging()
// Vertical with a quick press-move-release: should cause a flick in release.
QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged()));
-
- QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 90));
- QTest::qWait(10);
- QTest::mouseMove(canvas, QPoint(50, 40));
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 40));
+ // Use something that generates a huge velocity just to make it testable.
+ // In practice this feature matters on touchscreen devices where the
+ // underlying drivers will hopefully provide a pre-calculated velocity
+ // (based on more data than what the UI gets), thus making this use case
+ // working even with small movements.
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50, 10));
+ QTest::mouseMove(canvas, QPoint(50, 300), 10);
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 100), 10);
QCOMPARE(vFlickSpy.count(), 1);
diff --git a/tests/auto/quick/qquickflipable/data/flip-flipable.qml b/tests/auto/quick/qquickflipable/data/flip-flipable.qml
new file mode 100644
index 0000000000..4f22a0df6d
--- /dev/null
+++ b/tests/auto/quick/qquickflipable/data/flip-flipable.qml
@@ -0,0 +1,28 @@
+import QtQuick 2.0
+
+Flipable {
+ id: flipable
+ width: 640; height: 480
+ property bool flipped: false
+
+ front: Rectangle { color: "red"; anchors.fill: flipable }
+ back: Rectangle { color: "blue"; anchors.fill: flipable }
+
+ transform: Rotation {
+ id: rotation
+ origin.x: flipable.width/2
+ origin.y: flipable.height/2
+ axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis
+ angle: 0 // the default angle
+ }
+
+ states: State {
+ name: "back"
+ PropertyChanges { target: rotation; angle: 540 }
+ when: flipable.flipped
+ }
+
+ transitions: Transition {
+ NumberAnimation { target: rotation; property: "angle"; duration: 500 }
+ }
+}
diff --git a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
index 4fe155168a..8c1c248925 100644
--- a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
+++ b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp
@@ -58,6 +58,7 @@ private slots:
void create();
void checkFrontAndBack();
void setFrontAndBack();
+ void flipFlipable();
// below here task issues
void QTBUG_9161_crash();
@@ -109,6 +110,20 @@ void tst_qquickflipable::setFrontAndBack()
delete obj;
}
+void tst_qquickflipable::flipFlipable()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("flip-flipable.qml"));
+ QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->side() == QQuickFlipable::Front);
+ obj->setProperty("flipped", QVariant(true));
+ QTRY_VERIFY(obj->side() == QQuickFlipable::Back);
+ QTRY_VERIFY(obj->side() == QQuickFlipable::Front);
+ QTRY_VERIFY(obj->side() == QQuickFlipable::Back);
+ delete obj;
+}
+
void tst_qquickflipable::QTBUG_9161_crash()
{
QQuickView *canvas = new QQuickView;
diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
index c7b5ca6b40..22c9004ccc 100644
--- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
+++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp
@@ -2094,15 +2094,17 @@ void tst_QQuickGridView::componentChanges()
QTRY_VERIFY(gridView);
QQmlComponent component(canvas->engine());
- component.setData("import QtQuick 1.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
+ component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
QQmlComponent delegateComponent(canvas->engine());
- delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
+ delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
+ QSignalSpy headerItemSpy(gridView, SIGNAL(headerItemChanged()));
+ QSignalSpy footerItemSpy(gridView, SIGNAL(footerItemChanged()));
gridView->setHighlight(&component);
gridView->setDelegate(&delegateComponent);
@@ -2114,10 +2116,15 @@ void tst_QQuickGridView::componentChanges()
QTRY_COMPARE(gridView->header(), &component);
QTRY_COMPARE(gridView->footer(), &component);
+ QVERIFY(gridView->headerItem());
+ QVERIFY(gridView->footerItem());
+
QTRY_COMPARE(highlightSpy.count(),1);
QTRY_COMPARE(delegateSpy.count(),1);
QTRY_COMPARE(headerSpy.count(),1);
QTRY_COMPARE(footerSpy.count(),1);
+ QTRY_COMPARE(headerItemSpy.count(),1);
+ QTRY_COMPARE(footerItemSpy.count(),1);
gridView->setHighlight(&component);
gridView->setDelegate(&delegateComponent);
@@ -2128,6 +2135,8 @@ void tst_QQuickGridView::componentChanges()
QTRY_COMPARE(delegateSpy.count(),1);
QTRY_COMPARE(headerSpy.count(),1);
QTRY_COMPARE(footerSpy.count(),1);
+ QTRY_COMPARE(headerItemSpy.count(),1);
+ QTRY_COMPARE(footerItemSpy.count(),1);
delete canvas;
}
diff --git a/tests/auto/quick/qquickitem/data/focusSubItemInNonFocusScope.qml b/tests/auto/quick/qquickitem/data/focusSubItemInNonFocusScope.qml
new file mode 100644
index 0000000000..0e50710717
--- /dev/null
+++ b/tests/auto/quick/qquickitem/data/focusSubItemInNonFocusScope.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 400; height: 400
+
+ FocusScope {
+ width: 400; height: 400
+ focus: true
+ Item {
+ width: 400; height: 400
+ Item {
+ id: dummy
+ objectName: "dummyItem"
+ focus: true
+ }
+ TextInput {
+ id: ti
+ objectName: "textInput"
+ focus: true
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
index abd0da8ac1..a1377694e4 100644
--- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp
@@ -139,6 +139,9 @@ private slots:
void addedToCanvas();
void changeParent();
void multipleFocusClears();
+ void focusSubItemInNonFocusScope();
+ void parentItemWithFocus();
+ void reparentFocusedItem();
void constructor();
void setParentItem();
@@ -707,6 +710,7 @@ void tst_qquickitem::changeParent()
focusState[item].set(true, true);
focusState.active(item);
FVERIFY();
+ delete child2;
}
}
@@ -720,6 +724,133 @@ void tst_qquickitem::multipleFocusClears()
QTRY_VERIFY(QGuiApplication::focusWindow() == view);
}
+void tst_qquickitem::focusSubItemInNonFocusScope()
+{
+ QQuickView *view = new QQuickView;
+ view->setSource(testFileUrl("focusSubItemInNonFocusScope.qml"));
+ view->show();
+ qApp->processEvents();
+
+ QQuickItem *dummyItem = view->rootObject()->findChild<QQuickItem *>("dummyItem");
+ QVERIFY(dummyItem);
+
+ QQuickItem *textInput = view->rootObject()->findChild<QQuickItem *>("textInput");
+ QVERIFY(textInput);
+
+ QVERIFY(dummyItem->hasFocus());
+ QVERIFY(!textInput->hasFocus());
+ QVERIFY(dummyItem->hasActiveFocus());
+
+ QVERIFY(QMetaObject::invokeMethod(textInput, "forceActiveFocus"));
+
+ QVERIFY(!dummyItem->hasFocus());
+ QVERIFY(textInput->hasFocus());
+ QVERIFY(textInput->hasActiveFocus());
+
+ delete view;
+}
+
+void tst_qquickitem::parentItemWithFocus()
+{
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+ {
+ QQuickItem parent;
+ QQuickItem child;
+
+ FocusState focusState;
+ focusState << &parent << &child;
+ FVERIFY();
+
+ parent.setFocus(true);
+ child.setFocus(true);
+ focusState[&parent].set(true, false);
+ focusState[&child].set(true, false);
+ FVERIFY();
+
+ child.setParentItem(&parent);
+ focusState[&parent].set(true, false);
+ focusState[&child].set(false, false);
+ FVERIFY();
+
+ parent.setParentItem(canvas.rootItem());
+ focusState[&parent].set(true, true);
+ focusState[&child].set(false, false);
+ focusState.active(&parent);
+ FVERIFY();
+
+ child.forceActiveFocus();
+ focusState[&parent].set(false, false);
+ focusState[&child].set(true, true);
+ focusState.active(&child);
+ FVERIFY();
+ } {
+ QQuickItem parent;
+ QQuickItem child;
+ QQuickItem grandchild(&child);
+
+ FocusState focusState;
+ focusState << &parent << &child << &grandchild;
+ FVERIFY();
+
+ parent.setFocus(true);
+ grandchild.setFocus(true);
+ focusState[&parent].set(true, false);
+ focusState[&child].set(false, false);
+ focusState[&grandchild].set(true, false);
+ FVERIFY();
+
+ child.setParentItem(&parent);
+ focusState[&parent].set(true, false);
+ focusState[&child].set(false, false);
+ focusState[&grandchild].set(false, false);
+ FVERIFY();
+
+ parent.setParentItem(canvas.rootItem());
+ focusState[&parent].set(true, true);
+ focusState[&child].set(false, false);
+ focusState[&grandchild].set(false, false);
+ focusState.active(&parent);
+ FVERIFY();
+
+ grandchild.forceActiveFocus();
+ focusState[&parent].set(false, false);
+ focusState[&child].set(false, false);
+ focusState[&grandchild].set(true, true);
+ focusState.active(&grandchild);
+ FVERIFY();
+ }
+}
+
+void tst_qquickitem::reparentFocusedItem()
+{
+ QQuickCanvas canvas;
+ ensureFocus(&canvas);
+ QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
+
+ QQuickItem parent(canvas.rootItem());
+ QQuickItem child(&parent);
+ QQuickItem sibling(&parent);
+ QQuickItem grandchild(&child);
+
+ FocusState focusState;
+ focusState << &parent << &child << &sibling << &grandchild;
+ FVERIFY();
+
+ grandchild.setFocus(true);
+ focusState[&parent].set(false, false);
+ focusState[&child].set(false, false);
+ focusState[&sibling].set(false, false);
+ focusState[&grandchild].set(true, true);
+ focusState.active(&grandchild);
+ FVERIFY();
+
+ // Parenting the item to another item within the same focus scope shouldn't change it's focus.
+ child.setParentItem(&sibling);
+ FVERIFY();
+}
+
void tst_qquickitem::constructor()
{
QQuickItem *root = new QQuickItem;
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index 1218d3cfcb..1ef895d111 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -2120,13 +2120,13 @@ void tst_QQuickListView::sectionsPositioning()
QVERIFY(bottomItem);
QCOMPARE(bottomItem->y(), 380.);
- // Change current section
+ // Change current section, and verify case insensitive comparison
listview->setContentY(10);
model.modifyItem(0, "One", "aaa");
- model.modifyItem(1, "Two", "aaa");
- model.modifyItem(2, "Three", "aaa");
- model.modifyItem(3, "Four", "aaa");
- model.modifyItem(4, "Five", "aaa");
+ model.modifyItem(1, "Two", "AAA");
+ model.modifyItem(2, "Three", "aAa");
+ model.modifyItem(3, "Four", "aaA");
+ model.modifyItem(4, "Five", "Aaa");
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
QTRY_COMPARE(listview->currentSection(), QString("aaa"));
diff --git a/tests/auto/quick/qquickloader/data/RedRect.qml b/tests/auto/quick/qquickloader/data/RedRect.qml
new file mode 100644
index 0000000000..0eec9b56b7
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/RedRect.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Rectangle {
+ objectName: "red"
+ width: 100
+ height: 100
+ color: "red"
+}
diff --git a/tests/auto/quick/qquickloader/data/implicitSize.qml b/tests/auto/quick/qquickloader/data/implicitSize.qml
index 5c8c8348ed..ae8c0b8b30 100644
--- a/tests/auto/quick/qquickloader/data/implicitSize.qml
+++ b/tests/auto/quick/qquickloader/data/implicitSize.qml
@@ -3,12 +3,17 @@ import QtQuick 2.0
Rectangle {
property real implWidth: 0
property real implHeight: 0
+ function changeImplicitSize () {
+ loader.item.implicitWidth = 200
+ loader.item.implicitHeight = 300
+ }
color: "green"
width: loader.implicitWidth+50
height: loader.implicitHeight+50
Loader {
id: loader
+ objectName: "loader"
sourceComponent: Item {
anchors.centerIn: parent
diff --git a/tests/auto/quick/qquickloader/data/loadedSignal.2.qml b/tests/auto/quick/qquickloader/data/loadedSignal.2.qml
new file mode 100644
index 0000000000..a4a663c71f
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/loadedSignal.2.qml
@@ -0,0 +1,31 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ width: 200
+ height: 200
+
+ property bool success: true
+ property int loadCount: 0
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ asynchronous: true
+ active: false
+ source: "TestComponent.qml"
+ onLoaded: {
+ if (status !== Loader.Ready) {
+ root.success = false;
+ }
+ root.loadCount++;
+ }
+ }
+
+ function triggerLoading() {
+ // we set source to a valid path (but which is an invalid / erroneous component)
+ // we should not get onLoaded, since the status should not be Ready.
+ loader.source = "GreenRect.qml" // causes reference error.
+ }
+}
diff --git a/tests/auto/quick/qquickloader/data/loadedSignal.qml b/tests/auto/quick/qquickloader/data/loadedSignal.qml
new file mode 100644
index 0000000000..7cc0fed001
--- /dev/null
+++ b/tests/auto/quick/qquickloader/data/loadedSignal.qml
@@ -0,0 +1,48 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+
+ width: 200
+ height: 200
+
+ property bool success: true
+ property int loadCount: 0
+
+ Loader {
+ id: loader
+ anchors.fill: parent
+ asynchronous: true
+ active: false
+ source: "TestComponent.qml"
+ onLoaded: {
+ if (status !== Loader.Ready) {
+ root.success = false;
+ }
+ root.loadCount++;
+ }
+ }
+
+ function triggerLoading() {
+ // we set active to true, which triggers loading.
+ // we then immediately set active to false.
+ // this should clear the incubator and stop loading.
+ loader.active = true;
+ loader.active = false;
+ }
+
+ function activate() {
+ loader.active = true;
+ }
+
+ function deactivate() {
+ loader.active = false;
+ }
+
+ function triggerMultipleLoad() {
+ loader.active = false; // deactivate as a precondition.
+ loader.source = "BlueRect.qml"
+ loader.active = true; // should trigger loading to begin
+ loader.source = "RedRect.qml"; // should clear the incubator and restart loading
+ }
+}
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 01781f7b54..3bb06f737b 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -92,7 +92,7 @@ private slots:
void noResize();
void networkRequestUrl();
void failNetworkRequest();
-// void networkComponent();
+ void networkComponent();
void active();
void initialPropertyValues_data();
void initialPropertyValues();
@@ -111,6 +111,7 @@ private slots:
void asynchronous();
void asynchronous_clear();
void simultaneousSyncAsync();
+ void loadedSignal();
void parented();
void sizeBound();
@@ -442,21 +443,21 @@ void tst_QQuickLoader::networkRequestUrl()
delete loader;
}
-/* XXX Component waits until all dependencies are loaded. Is this actually possible?
+/* XXX Component waits until all dependencies are loaded. Is this actually possible? */
void tst_QQuickLoader::networkComponent()
{
TestHTTPServer server(SERVER_PORT);
QVERIFY(server.isValid());
- server.serveDirectory("slowdata", TestHTTPServer::Delay);
+ server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
QQmlComponent component(&engine);
component.setData(QByteArray(
"import QtQuick 2.0\n"
"import \"http://127.0.0.1:14450/\" as NW\n"
"Item {\n"
- " Component { id: comp; NW.SlowRect {} }\n"
+ " Component { id: comp; NW.Rect120x60 {} }\n"
" Loader { sourceComponent: comp } }")
- , dataDirectoryUrl());
+ , dataDirectory());
QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
QVERIFY(item);
@@ -472,7 +473,6 @@ void tst_QQuickLoader::networkComponent()
delete loader;
}
-*/
void tst_QQuickLoader::failNetworkRequest()
{
@@ -842,6 +842,18 @@ void tst_QQuickLoader::implicitSize()
QCOMPARE(item->property("implHeight").toReal(), 100.);
QCOMPARE(item->property("implWidth").toReal(), 100.);
+ QQuickLoader *loader = item->findChild<QQuickLoader*>("loader");
+ QSignalSpy implWidthSpy(loader, SIGNAL(implicitWidthChanged()));
+ QSignalSpy implHeightSpy(loader, SIGNAL(implicitHeightChanged()));
+
+ QMetaObject::invokeMethod(item, "changeImplicitSize");
+
+ QCOMPARE(loader->property("implicitWidth").toReal(), 200.);
+ QCOMPARE(loader->property("implicitHeight").toReal(), 300.);
+
+ QCOMPARE(implWidthSpy.count(), 1);
+ QCOMPARE(implHeightSpy.count(), 1);
+
delete item;
}
@@ -988,6 +1000,47 @@ void tst_QQuickLoader::simultaneousSyncAsync()
delete root;
}
+void tst_QQuickLoader::loadedSignal()
+{
+ {
+ // ensure that triggering loading (by setting active = true)
+ // and then immediately setting active to false, causes the
+ // loader to be deactivated, including disabling the incubator.
+ QQmlComponent component(&engine, testFileUrl("loadedSignal.qml"));
+ QObject *obj = component.create();
+
+ QMetaObject::invokeMethod(obj, "triggerLoading");
+ QTest::qWait(100); // ensure that loading would have finished if it wasn't deactivated
+ QCOMPARE(obj->property("loadCount").toInt(), 0);
+ QVERIFY(obj->property("success").toBool());
+
+ QMetaObject::invokeMethod(obj, "triggerLoading");
+ QTest::qWait(100);
+ QCOMPARE(obj->property("loadCount").toInt(), 0);
+ QVERIFY(obj->property("success").toBool());
+
+ QMetaObject::invokeMethod(obj, "triggerMultipleLoad");
+ QTest::qWait(100);
+ QCOMPARE(obj->property("loadCount").toInt(), 1); // only one loaded signal should be emitted.
+ QVERIFY(obj->property("success").toBool());
+
+ delete obj;
+ }
+
+ {
+ // ensure that an error doesn't result in the onLoaded signal being emitted.
+ QQmlComponent component(&engine, testFileUrl("loadedSignal.2.qml"));
+ QObject *obj = component.create();
+
+ QMetaObject::invokeMethod(obj, "triggerLoading");
+ QTest::qWait(100);
+ QCOMPARE(obj->property("loadCount").toInt(), 0);
+ QVERIFY(obj->property("success").toBool());
+
+ delete obj;
+ }
+}
+
void tst_QQuickLoader::parented()
{
QQmlComponent component(&engine, testFileUrl("parented.qml"));
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index a4b04bb88a..f072b005bc 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -796,13 +796,11 @@ void tst_QQuickMouseArea::hoverVisible()
mouseTracker->setVisible(true);
- QTest::mouseMove(canvas,QPoint(10,31));
-
QCOMPARE(mouseTracker->hovered(), true);
QCOMPARE(enteredSpy.count(), 1);
QEXPECT_FAIL("", "QTBUG-24282", Continue);
- QCOMPARE(QPointF(mouseTracker->mouseX(), mouseTracker->mouseY()), QPointF(10,32));
+ QCOMPARE(QPointF(mouseTracker->mouseX(), mouseTracker->mouseY()), QPointF(11,33));
delete canvas;
}
diff --git a/tests/auto/quick/qquickpathview/data/panels.qml b/tests/auto/quick/qquickpathview/data/panels.qml
new file mode 100644
index 0000000000..a111e45736
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/panels.qml
@@ -0,0 +1,44 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+ property bool snapOne: false
+ property bool enforceRange: false
+ width: 320; height: 480
+
+ VisualItemModel {
+ id: itemModel
+
+ Rectangle {
+ width: root.width
+ height: root.height
+ color: "blue"
+ }
+ Rectangle {
+ width: root.width
+ height: root.height
+ color: "yellow"
+ }
+ Rectangle {
+ width: root.width
+ height: root.height
+ color: "green"
+ }
+ }
+
+ PathView {
+ id: view
+ objectName: "view"
+ anchors.fill: parent
+ model: itemModel
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+ flickDeceleration: 30
+ highlightRangeMode: enforceRange ? PathView.StrictlyEnforceRange : PathView.NoHighlightRange
+ snapMode: root.snapOne ? PathView.SnapOneItem : PathView.SnapToItem
+ path: Path {
+ startX: -root.width; startY: root.height/2
+ PathLine { x: root.width*2; y: root.height/2 }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 85d2c3b6ea..fbe96bf672 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -125,6 +125,10 @@ private slots:
void asynchronous();
void cancelDrag();
void maximumFlickVelocity();
+ void snapToItem();
+ void snapToItem_data();
+ void snapOneItem();
+ void snapOneItem_data();
};
class TestObject : public QObject
@@ -1541,6 +1545,89 @@ void tst_QQuickPathView::maximumFlickVelocity()
delete canvas;
}
+void tst_QQuickPathView::snapToItem()
+{
+ QFETCH(bool, enforceRange);
+
+ QQuickView *canvas = createView();
+ canvas->setSource(testFileUrl("panels.qml"));
+ QQuickPathView *pathview = canvas->rootObject()->findChild<QQuickPathView*>("view");
+ QVERIFY(pathview != 0);
+
+ canvas->rootObject()->setProperty("enforceRange", enforceRange);
+ QTRY_VERIFY(!pathview->isMoving()); // ensure stable
+
+ int currentIndex = pathview->currentIndex();
+
+ QSignalSpy snapModeSpy(pathview, SIGNAL(snapModeChanged()));
+
+ flick(canvas, QPoint(200,10), QPoint(10,10), 180);
+
+ QVERIFY(pathview->isMoving());
+ QTRY_VERIFY(!pathview->isMoving());
+
+ QVERIFY(pathview->offset() == qFloor(pathview->offset()));
+
+ if (enforceRange)
+ QVERIFY(pathview->currentIndex() != currentIndex);
+ else
+ QVERIFY(pathview->currentIndex() == currentIndex);
+}
+
+void tst_QQuickPathView::snapToItem_data()
+{
+ QTest::addColumn<bool>("enforceRange");
+
+ QTest::newRow("no enforce range") << false;
+ QTest::newRow("enforce range") << true;
+}
+
+void tst_QQuickPathView::snapOneItem()
+{
+ QFETCH(bool, enforceRange);
+
+ QQuickView *canvas = createView();
+ canvas->setSource(testFileUrl("panels.qml"));
+ canvas->show();
+ canvas->requestActivateWindow();
+ QTest::qWaitForWindowShown(canvas);
+ QTRY_COMPARE(canvas, qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = canvas->rootObject()->findChild<QQuickPathView*>("view");
+ QVERIFY(pathview != 0);
+
+ canvas->rootObject()->setProperty("enforceRange", enforceRange);
+
+ QSignalSpy snapModeSpy(pathview, SIGNAL(snapModeChanged()));
+
+ canvas->rootObject()->setProperty("snapOne", true);
+ QVERIFY(snapModeSpy.count() == 1);
+ QTRY_VERIFY(!pathview->isMoving()); // ensure stable
+
+ int currentIndex = pathview->currentIndex();
+
+ double startOffset = pathview->offset();
+ flick(canvas, QPoint(200,10), QPoint(10,10), 180);
+
+ QVERIFY(pathview->isMoving());
+ QTRY_VERIFY(!pathview->isMoving());
+
+ // must have moved only one item
+ QCOMPARE(pathview->offset(), fmodf(3.0 + startOffset - 1.0, 3.0));
+
+ if (enforceRange)
+ QVERIFY(pathview->currentIndex() == currentIndex+1);
+ else
+ QVERIFY(pathview->currentIndex() == currentIndex);
+}
+
+void tst_QQuickPathView::snapOneItem_data()
+{
+ QTest::addColumn<bool>("enforceRange");
+
+ QTest::newRow("no enforce range") << false;
+ QTest::newRow("enforce range") << true;
+}
QTEST_MAIN(tst_QQuickPathView)
diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
index ab24fbe995..ae2bdc7fae 100644
--- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
+++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp
@@ -636,7 +636,7 @@ void tst_qquickpositioners::moveTransitions(const QString &positionerObjectName)
QQuickView *canvas = QQuickViewTestUtil::createView();
QQmlContext *ctxt = canvas->rootContext();
- ctxt->setContextProperty("enableAddTransition", false);
+ ctxt->setContextProperty("enableAddTransition", QVariant(false));
ctxt->setContextProperty("model_targetItems_transitionFrom", &model_targetItems_transitionFrom);
ctxt->setContextProperty("model_displacedItems_transitionVia", &model_displacedItems_transitionVia);
ctxt->setContextProperty("targetItems_transitionFrom", targetItems_transitionFrom);
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index 00ae8fc76d..1edf511ebf 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -257,13 +257,12 @@ void tst_qquickshadereffect::lookThroughShaderCode()
if ((presenceFlags & TexCoordPresent) == 0)
expected += "Warning: Missing reference to \'qt_MultiTexCoord0\'.\n";
if ((presenceFlags & MatrixPresent) == 0)
- expected += "Warning: Missing reference to \'qt_Matrix\'.\n";
+ expected += "Warning: Vertex shader is missing reference to \'qt_Matrix\'.\n";
if ((presenceFlags & OpacityPresent) == 0)
- expected += "Warning: Missing reference to \'qt_Opacity\'.\n";
+ expected += "Warning: Shaders are missing reference to \'qt_Opacity\'.\n";
item.setVertexShader(vertexShader);
item.setFragmentShader(fragmentShader);
- item.ensureCompleted();
QCOMPARE(item.parseLog(), expected);
// If the uniform was successfully parsed, the notify signal has been connected to an update slot.
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index f4ba0864e5..724b24280a 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -1654,7 +1654,7 @@ void tst_qquicktext::implicitSizeBinding()
QFETCH(QString, format);
QString componentStr = "import QtQuick 2.0\nText { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }";
- QDeclarativeComponent textComponent(&engine);
+ QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickText *textObject = qobject_cast<QQuickText *>(object.data());
diff --git a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
index ab21f3bc54..dd9aa0acad 100644
--- a/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
+++ b/tests/auto/quick/qquicktextedit/tst_qquicktextedit.cpp
@@ -1999,15 +1999,16 @@ void tst_qquicktextedit::cursorDelegate()
void tst_qquicktextedit::cursorVisible()
{
+ QQuickTextEdit edit;
+ edit.componentComplete();
+ QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
+
QQuickView view(testFileUrl("cursorVisible.qml"));
view.show();
view.requestActivateWindow();
QTest::qWaitForWindowShown(&view);
QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextEdit edit;
- QSignalSpy spy(&edit, SIGNAL(cursorVisibleChanged(bool)));
-
QCOMPARE(edit.isCursorVisible(), false);
edit.setCursorVisible(true);
@@ -2034,7 +2035,7 @@ void tst_qquicktextedit::cursorVisible()
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.count(), 5);
- QQuickView alternateView;
+ QWindow alternateView;
alternateView.show();
alternateView.requestActivateWindow();
QTest::qWaitForWindowShown(&alternateView);
@@ -2046,6 +2047,47 @@ void tst_qquicktextedit::cursorVisible()
QTest::qWaitForWindowShown(&view);
QCOMPARE(edit.isCursorVisible(), true);
QCOMPARE(spy.count(), 7);
+
+ { // Cursor attribute with 0 length hides cursor.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 8);
+
+ { // Cursor attribute with non zero length shows cursor.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 9);
+
+
+ { // If the cursor is hidden by the input method and the text is changed it should be visible again.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 10);
+
+ edit.setText("something");
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 11);
+
+ { // If the cursor is hidden by the input method and the cursor position is changed it should be visible again.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&edit, &ev);
+ }
+ QCOMPARE(edit.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 12);
+
+ edit.setCursorPosition(5);
+ QCOMPARE(edit.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 13);
}
void tst_qquicktextedit::delegateLoading_data()
@@ -2568,7 +2610,7 @@ void tst_qquicktextedit::implicitSizeBinding()
QFETCH(QString, wrap);
QFETCH(QString, format);
QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + "; textFormat: " + format + " }";
- QDeclarativeComponent textComponent(&engine);
+ QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickTextEdit *textObject = qobject_cast<QQuickTextEdit *>(object.data());
@@ -2682,6 +2724,74 @@ void tst_qquicktextedit::inputMethodComposing()
}
QCOMPARE(edit->isInputMethodComposing(), false);
QCOMPARE(spy.count(), 2);
+
+ // Changing the text while not composing doesn't alter the composing state.
+ edit->setText(text.mid(0, 16));
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 2);
+
+ {
+ QInputMethodEvent event(text.mid(16), QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 3);
+
+ // Changing the text while composing cancels composition.
+ edit->setText(text.mid(0, 12));
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 4);
+
+ { // Preedit cursor positioned outside (empty) preedit; composing.
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, -2, 1, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Cursor hidden; composing
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Default cursor attributes; composing.
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Selections are persisted: not composing
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 2, 4, QVariant()));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 6);
+
+ edit->setCursorPosition(0);
+
+ { // Formatting applied; composing.
+ QTextCharFormat format;
+ format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 2, 4, format));
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 7);
+
+ {
+ QInputMethodEvent event;
+ QGuiApplication::sendEvent(edit, &event);
+ }
+ QCOMPARE(edit->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 8);
}
void tst_qquicktextedit::cursorRectangleSize()
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 1c8bff9d69..4f2f3cbb62 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -158,9 +158,7 @@ private slots:
void focusOutClearSelection();
void echoMode();
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void passwordEchoDelay();
-#endif
void geometrySignals();
void contentSize();
@@ -2368,16 +2366,16 @@ void tst_qquicktextinput::cursorDelegate()
void tst_qquicktextinput::cursorVisible()
{
+ QQuickTextInput input;
+ input.componentComplete();
+ QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
+
QQuickView view(testFileUrl("cursorVisible.qml"));
view.show();
view.requestActivateWindow();
QTest::qWaitForWindowShown(&view);
QTRY_COMPARE(&view, qGuiApp->focusWindow());
- QQuickTextInput input;
- input.componentComplete();
- QSignalSpy spy(&input, SIGNAL(cursorVisibleChanged(bool)));
-
QCOMPARE(input.isCursorVisible(), false);
input.setCursorVisible(true);
@@ -2404,7 +2402,7 @@ void tst_qquicktextinput::cursorVisible()
QCOMPARE(input.isCursorVisible(), true);
QCOMPARE(spy.count(), 5);
- QQuickView alternateView;
+ QWindow alternateView;
alternateView.show();
alternateView.requestActivateWindow();
QTest::qWaitForWindowShown(&alternateView);
@@ -2416,6 +2414,46 @@ void tst_qquicktextinput::cursorVisible()
QTest::qWaitForWindowShown(&view);
QCOMPARE(input.isCursorVisible(), true);
QCOMPARE(spy.count(), 7);
+
+ { // Cursor attribute with 0 length hides cursor.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&input, &ev);
+ }
+ QCOMPARE(input.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 8);
+
+ { // Cursor attribute with non zero length shows cursor.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant()));
+ QCoreApplication::sendEvent(&input, &ev);
+ }
+ QCOMPARE(input.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 9);
+
+ { // If the cursor is hidden by the input method and the text is changed it should be visible again.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&input, &ev);
+ }
+ QCOMPARE(input.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 10);
+
+ input.setText("something");
+ QCOMPARE(input.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 11);
+
+ { // If the cursor is hidden by the input method and the cursor position is changed it should be visible again.
+ QInputMethodEvent ev(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QCoreApplication::sendEvent(&input, &ev);
+ }
+ QCOMPARE(input.isCursorVisible(), false);
+ QCOMPARE(spy.count(), 12);
+
+ input.setCursorPosition(5);
+ QCOMPARE(input.isCursorVisible(), true);
+ QCOMPARE(spy.count(), 13);
}
void tst_qquicktextinput::cursorRectangle_data()
@@ -2716,9 +2754,11 @@ void tst_qquicktextinput::echoMode()
QCOMPARE(input->inputMethodQuery(Qt::ImSurroundingText).toString(), initial);
}
-#ifdef QT_GUI_PASSWORD_ECHO_DELAY
void tst_qquicktextinput::passwordEchoDelay()
{
+ int maskDelay = qGuiApp->styleHints()->passwordMaskDelay();
+ if (maskDelay <= 0)
+ QSKIP("No mask delay in use");
QQuickView canvas(testFileUrl("echoMode.qml"));
canvas.show();
canvas.requestActivateWindow();
@@ -2747,7 +2787,7 @@ void tst_qquicktextinput::passwordEchoDelay()
QCOMPARE(input->displayText(), QString(4, fillChar));
QTest::keyPress(&canvas, '4');
QCOMPARE(input->displayText(), QString(4, fillChar) + QLatin1Char('4'));
- QTest::qWait(QT_GUI_PASSWORD_ECHO_DELAY);
+ QTest::qWait(maskDelay);
QTRY_COMPARE(input->displayText(), QString(5, fillChar));
QTest::keyPress(&canvas, '5');
QCOMPARE(input->displayText(), QString(5, fillChar) + QLatin1Char('5'));
@@ -2772,7 +2812,6 @@ void tst_qquicktextinput::passwordEchoDelay()
QTest::keyPress(&canvas, Qt::Key_Backspace);
QCOMPARE(input->displayText(), QString(8, fillChar));
}
-#endif
void tst_qquicktextinput::simulateKey(QWindow *view, int key)
@@ -3281,6 +3320,75 @@ void tst_qquicktextinput::inputMethodComposing()
}
QCOMPARE(input->isInputMethodComposing(), false);
QCOMPARE(spy.count(), 2);
+
+ // Changing the text while not composing doesn't alter the composing state.
+ input->setText(text.mid(0, 16));
+ QCOMPARE(input->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 2);
+
+ {
+ QInputMethodEvent event(text.mid(16), QList<QInputMethodEvent::Attribute>());
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 3);
+
+ // Changing the text while composing cancels composition.
+ input->setText(text.mid(0, 12));
+ QCOMPARE(input->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 4);
+
+ { // Preedit cursor positioned outside (empty) preedit; composing.
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, -2, 1, QVariant()));
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+
+ { // Cursor hidden; composing
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 0, QVariant()));
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Default cursor attributes; composing.
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, 1, QVariant()));
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 5);
+
+ { // Selections are persisted: not composing
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, -5, 4, QVariant()));
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 6);
+
+ input->setCursorPosition(12);
+
+ { // Formatting applied; composing.
+ QTextCharFormat format;
+ format.setUnderlineStyle(QTextCharFormat::SingleUnderline);
+ QInputMethodEvent event(QString(), QList<QInputMethodEvent::Attribute>()
+ << QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, -5, 4, format));
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), true);
+ QCOMPARE(spy.count(), 7);
+
+ {
+ QInputMethodEvent event;
+ QGuiApplication::sendEvent(input, &event);
+ }
+ QCOMPARE(input->isInputMethodComposing(), false);
+ QCOMPARE(spy.count(), 8);
}
void tst_qquicktextinput::inputMethodUpdate()
@@ -4949,7 +5057,7 @@ void tst_qquicktextinput::implicitSize()
QFETCH(QString, text);
QFETCH(QString, wrap);
QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: 50; wrapMode: " + wrap + " }";
- QDeclarativeComponent textComponent(&engine);
+ QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickTextInput *textObject = qobject_cast<QQuickTextInput*>(textComponent.create());
@@ -4971,7 +5079,7 @@ void tst_qquicktextinput::implicitSizeBinding()
QFETCH(QString, text);
QFETCH(QString, wrap);
QString componentStr = "import QtQuick 2.0\nTextInput { text: \"" + text + "\"; width: implicitWidth; height: implicitHeight; wrapMode: " + wrap + " }";
- QDeclarativeComponent textComponent(&engine);
+ QQmlComponent textComponent(&engine);
textComponent.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QScopedPointer<QObject> object(textComponent.create());
QQuickTextInput *textObject = qobject_cast<QQuickTextInput *>(object.data());
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index 73a35c1c78..78e9060acb 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -2707,9 +2707,6 @@ void tst_qquickvisualdatamodel::resolve_data()
const QUrl stringListSource[] = {
testFileUrl("stringlistproperties.qml"),
testFileUrl("stringlistproperties-package.qml") };
- const QUrl objectListSource[] = {
- testFileUrl("objectlistproperties.qml"),
- testFileUrl("objectlistproperties-package.qml") };
for (int i = 0; i < 2; ++i) {
// List Model.
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 654b1c86f0..b018fbf14a 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -1,12 +1,13 @@
TEMPLATE = subdirs
PUBLICTESTS += \
- examples \
geometry \
nodes \
rendernode \
qquickpixmapcache
+!cross_compile: PUBLICTESTS += examples
+
# This test requires the qtconcurrent module
!contains(QT_CONFIG, concurrent):PUBLICTESTS -= qquickpixmapcache
diff --git a/tests/auto/quick/shared/viewtestutil.cpp b/tests/auto/quick/shared/viewtestutil.cpp
index d00a0e2a96..1c4319f82f 100644
--- a/tests/auto/quick/shared/viewtestutil.cpp
+++ b/tests/auto/quick/shared/viewtestutil.cpp
@@ -88,12 +88,8 @@ void QQuickViewTestUtil::flick(QQuickView *canvas, const QPoint &from, const QPo
// send press, five equally spaced moves, and release.
QTest::mousePress(canvas, Qt::LeftButton, 0, from);
- for (int i = 0; i < pointCount; ++i) {
- QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QGuiApplication::sendEvent(canvas, &mv);
- QTest::qWait(duration/pointCount);
- QCoreApplication::processEvents();
- }
+ for (int i = 0; i < pointCount; ++i)
+ QTest::mouseMove(canvas, from + (i+1)*diff/pointCount, duration / pointCount);
QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
QTest::qWait(50);
diff --git a/tools/qmlprofiler/qmlprofiler.pro b/tools/qmlprofiler/qmlprofiler.pro
index b90554455f..7ab61e7a96 100644
--- a/tools/qmlprofiler/qmlprofiler.pro
+++ b/tools/qmlprofiler/qmlprofiler.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
TARGET = qmlprofiler
DESTDIR = $$QT.qml.bins
-QT += qml qml-private network core-private
+QT += qml qml-private v8-private network core-private
target.path = $$[QT_INSTALL_BINS]
INSTALLS += target
diff --git a/tools/qmlscene/qmlscene.pro b/tools/qmlscene/qmlscene.pro
index 3e63bd7659..464f9b3758 100644
--- a/tools/qmlscene/qmlscene.pro
+++ b/tools/qmlscene/qmlscene.pro
@@ -14,4 +14,4 @@ SOURCES += main.cpp
CONFIG += console
-DEFINES += QML_RUNTIME_TESTING QT_DECLARATIVE_DEBUG_NO_WARNING
+DEFINES += QML_RUNTIME_TESTING QT_QML_DEBUG_NO_WARNING