aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2014-10-09 18:13:54 +0200
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-10-09 18:14:56 +0200
commite1dfb78667bd7e8dc418e12a9669404adea7e2cb (patch)
tree16f40a9852281a63c1f98af21c680bddedaa5258
parent28949c9699014b4f7abba396c28dea207b29821e (diff)
parent26bbd784d67d151eee531e5ff57977a5353549f5 (diff)
Merge remote-tracking branch 'origin/5.4' into dev
Conflicts: src/quick/items/context2d/qquickcanvasitem.cpp src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp src/quick/scenegraph/coreapi/qsgrenderer.cpp src/quick/scenegraph/qsgadaptationlayer.cpp src/quick/scenegraph/qsgrenderloop.cpp src/quick/scenegraph/qsgthreadedrenderloop.cpp src/quick/scenegraph/qsgwindowsrenderloop.cpp src/quick/scenegraph/util/qsgatlastexture.cpp src/quick/scenegraph/util/qsgtexture.cpp src/quick/util/qquickprofiler_p.h Change-Id: Ie274c3baf72a8a0711c87d67238d68e2b2887429
-rw-r--r--.gitignore2
-rw-r--r--examples/qml/doc/src/qml-extending.qdoc14
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/app.qml (renamed from examples/qml/tutorials/extending/chapter1-basics/app.qml)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pro (renamed from examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.pro)2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.qrc (renamed from examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.qrc)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp (renamed from examples/qml/tutorials/extending/chapter1-basics/main.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/piechart.cpp (renamed from examples/qml/tutorials/extending/chapter1-basics/piechart.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h (renamed from examples/qml/tutorials/extending/chapter1-basics/piechart.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/app.qml (renamed from examples/qml/tutorials/extending/chapter2-methods/app.qml)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pro (renamed from examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.pro)2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.qrc (renamed from examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.qrc)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp (renamed from examples/qml/tutorials/extending/chapter2-methods/main.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/piechart.cpp (renamed from examples/qml/tutorials/extending/chapter2-methods/piechart.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h (renamed from examples/qml/tutorials/extending/chapter2-methods/piechart.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml (renamed from examples/qml/tutorials/extending/chapter3-bindings/app.qml)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-binding.qrc (renamed from examples/qml/tutorials/extending/chapter3-bindings/chapter3-binding.qrc)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pro (renamed from examples/qml/tutorials/extending/chapter3-bindings/chapter3-bindings.pro)2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp (renamed from examples/qml/tutorials/extending/chapter3-bindings/main.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.cpp (renamed from examples/qml/tutorials/extending/chapter3-bindings/piechart.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h (renamed from examples/qml/tutorials/extending/chapter3-bindings/piechart.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro)2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.qrc (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.qrc)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/main.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/piechart.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/piechart.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.cpp (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/pieslice.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h (renamed from examples/qml/tutorials/extending/chapter4-customPropertyTypes/pieslice.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml (renamed from examples/qml/tutorials/extending/chapter5-listproperties/app.qml)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pro (renamed from examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro)2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.qrc (renamed from examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.qrc)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp (renamed from examples/qml/tutorials/extending/chapter5-listproperties/main.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.cpp (renamed from examples/qml/tutorials/extending/chapter5-listproperties/piechart.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h (renamed from examples/qml/tutorials/extending/chapter5-listproperties/piechart.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp (renamed from examples/qml/tutorials/extending/chapter5-listproperties/pieslice.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h (renamed from examples/qml/tutorials/extending/chapter5-listproperties/pieslice.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro (renamed from examples/qml/tutorials/extending/chapter6-plugins/app.pro)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml (renamed from examples/qml/tutorials/extending/chapter6-plugins/app.qml)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/app.qrc (renamed from examples/qml/tutorials/extending/chapter6-plugins/app.qrc)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/chapter6-plugins.pro (renamed from examples/qml/tutorials/extending/chapter6-plugins/chapter6-plugins.pro)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/chartsplugin.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/chartsplugin.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/import.pro (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/import.pro)2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.cpp (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/piechart.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/piechart.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.cpp (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/pieslice.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/pieslice.h)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/qmldir (renamed from examples/qml/tutorials/extending/chapter6-plugins/import/qmldir)0
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp (renamed from examples/qml/tutorials/extending/chapter6-plugins/main.cpp)0
-rw-r--r--examples/qml/tutorials/extending-qml/extending-qml.pro (renamed from examples/qml/tutorials/extending/extending.pro)0
-rw-r--r--examples/qml/xmlhttprequest/doc/src/xmlhttprequest.qdoc2
-rw-r--r--examples/quick/animation/basics/animators.qml8
-rw-r--r--examples/quick/animation/basics/color-animation.qml14
-rw-r--r--examples/quick/animation/basics/property-animation.qml8
-rw-r--r--examples/quick/animation/behaviors/tvtennis.qml18
-rw-r--r--examples/quick/canvas/doc/src/canvas.qdoc8
-rw-r--r--examples/quick/customitems/dialcontrol/dialcontrol.pro11
-rw-r--r--examples/quick/customitems/dialcontrol/dialcontrol.qml19
-rw-r--r--examples/quick/customitems/dialcontrol/dialcontrol.qrc12
-rw-r--r--examples/quick/customitems/dialcontrol/main.cpp41
-rw-r--r--examples/quick/demos/calqlatr/calqlatr.qml52
-rw-r--r--examples/quick/demos/calqlatr/content/Button.qml36
-rw-r--r--examples/quick/demos/calqlatr/content/Display.qml63
-rw-r--r--examples/quick/demos/calqlatr/content/NumberPad.qml18
-rw-r--r--examples/quick/demos/calqlatr/content/calculator.js46
-rw-r--r--examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc67
-rw-r--r--examples/quick/demos/clocks/doc/src/clocks.qdoc92
-rw-r--r--examples/quick/demos/photosurface/doc/src/photosurface.qdoc18
-rw-r--r--examples/quick/demos/photosurface/photosurface.qml17
-rw-r--r--examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc291
-rw-r--r--examples/quick/demos/photoviewer/main.cpp3
-rw-r--r--examples/quick/demos/stocqt/content/StockChart.qml24
-rw-r--r--examples/quick/demos/stocqt/doc/src/stocqt.qdoc49
-rw-r--r--examples/quick/demos/tweetsearch/content/SearchDelegate.qml6
-rw-r--r--examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc2
-rw-r--r--examples/quick/rendercontrol/window.cpp7
-rw-r--r--examples/quick/text/doc/src/text.qdoc2
-rw-r--r--examples/quick/window/main.cpp4
-rw-r--r--src/imports/statemachine/childrenprivate.h6
-rw-r--r--src/imports/testlib/TestCase.qml32
-rw-r--r--src/particles/qquickimageparticle.cpp3
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp19
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4compiler.cpp25
-rw-r--r--src/qml/compiler/qv4compiler_p.h9
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter.cpp10
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter_p.h13
-rw-r--r--src/qml/debugger/qqmlenginedebugservice.cpp8
-rw-r--r--src/qml/debugger/qqmlenginedebugservice_p.h2
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp14
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h41
-rw-r--r--src/qml/debugger/qqmlprofilerdefinitions_p.h16
-rw-r--r--src/qml/debugger/qqmlprofilerservice.cpp25
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h4
-rw-r--r--src/qml/debugger/qv4profileradapter.cpp7
-rw-r--r--src/qml/doc/snippets/code/src_script_qjsengine.cpp6
-rw-r--r--src/qml/doc/src/cppintegration/definetypes.qdoc2
-rw-r--r--src/qml/doc/src/cppintegration/exposecppattributes.qdoc2
-rw-r--r--src/qml/doc/src/cppintegration/extending-tutorial.qdoc188
-rw-r--r--src/qml/doc/src/qmllanguageref/documents/scope.qdoc4
-rw-r--r--src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc19
-rw-r--r--src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc2
-rw-r--r--src/qml/jit/qv4isel_masm.cpp2
-rw-r--r--src/qml/jsapi/qjsengine.cpp27
-rw-r--r--src/qml/jsapi/qjsvalue.cpp69
-rw-r--r--src/qml/jsapi/qjsvalue_p.h7
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp56
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp27
-rw-r--r--src/qml/jsruntime/qv4engine.cpp6
-rw-r--r--src/qml/jsruntime/qv4managed_p.h1
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp38
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h18
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp6
-rw-r--r--src/qml/jsruntime/qv4script.cpp2
-rw-r--r--src/qml/jsruntime/qv4string.cpp2
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp2
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp26
-rw-r--r--src/qml/qml/ftw/qqmlthread_p.h2
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp12
-rw-r--r--src/qml/qml/qqmldirparser.cpp27
-rw-r--r--src/qml/qml/qqmldirparser_p.h3
-rw-r--r--src/qml/qml/qqmlengine.cpp64
-rw-r--r--src/qml/qml/qqmlextensionplugin.cpp2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp12
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp2
-rw-r--r--src/qml/qml/qqmlproperty.cpp7
-rw-r--r--src/qml/qml/qqmltypeloader.cpp2
-rw-r--r--src/qml/qml/v8/qv8engine.cpp305
-rw-r--r--src/qml/qml/v8/qv8engine_p.h20
-rw-r--r--src/qml/types/qqmlbind.cpp2
-rw-r--r--src/qml/types/qqmllistmodel.cpp11
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp1
-rw-r--r--src/qml/util/qqmllistaccessor.cpp7
-rw-r--r--src/quick/doc/images/qml-blending-layered.pngbin0 -> 7582 bytes
-rw-r--r--src/quick/doc/images/qml-blending-nonlayered.pngbin0 -> 7707 bytes
-rw-r--r--src/quick/doc/images/qml-shadereffect-layereffect.pngbin0 -> 22264 bytes
-rw-r--r--src/quick/doc/images/qml-shadereffect-nolayereffect.pngbin0 -> 26718 bytes
-rw-r--r--src/quick/doc/images/qml-shadereffect-opacitymask.pngbin0 -> 15661 bytes
-rw-r--r--src/quick/doc/qtquick.qdocconf6
-rw-r--r--src/quick/doc/snippets/qml/layerblending.qml111
-rw-r--r--src/quick/doc/snippets/qml/layerwitheffect.qml111
-rw-r--r--src/quick/doc/snippets/qml/opacitymask.qml114
-rw-r--r--src/quick/doc/src/concepts/input/focus.qdoc2
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc8
-rw-r--r--src/quick/doc/src/concepts/positioning/righttoleft.qdoc8
-rw-r--r--src/quick/doc/src/dynamicview-tutorial.qdoc34
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp9
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp6
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp7
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h3
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture.cpp19
-rw-r--r--src/quick/items/context2d/qquickcontext2dtexture_p.h6
-rw-r--r--src/quick/items/qquickborderimage.cpp213
-rw-r--r--src/quick/items/qquickdrag.cpp13
-rw-r--r--src/quick/items/qquickframebufferobject.cpp1
-rw-r--r--src/quick/items/qquickgridview.cpp2
-rw-r--r--src/quick/items/qquickimagebase_p_p.h2
-rw-r--r--src/quick/items/qquickitem.cpp111
-rw-r--r--src/quick/items/qquicklistview.cpp2
-rw-r--r--src/quick/items/qquickscreen.cpp34
-rw-r--r--src/quick/items/qquickscreen_p.h10
-rw-r--r--src/quick/items/qquickshadereffect.cpp24
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp60
-rw-r--r--src/quick/items/qquicktextcontrol.cpp6
-rw-r--r--src/quick/items/qquicktextcontrol_p.h2
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h2
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp73
-rw-r--r--src/quick/items/qquicktextnodeengine_p.h14
-rw-r--r--src/quick/items/qquickview.cpp10
-rw-r--r--src/quick/items/qquickwindow.cpp13
-rw-r--r--src/quick/items/qquickwindow.h3
-rw-r--r--src/quick/items/qquickwindowmodule.cpp11
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp83
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp21
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h9
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp135
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp24
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer.cpp13
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer_p.h3
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp43
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h2
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp21
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h1
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp48
-rw-r--r--src/quick/scenegraph/shaders/styledtext.vert4
-rw-r--r--src/quick/scenegraph/shaders/styledtext_core.vert4
-rw-r--r--src/quick/scenegraph/shaders/textmask.vert2
-rw-r--r--src/quick/scenegraph/shaders/textmask_core.vert2
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp11
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp2
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp9
-rw-r--r--src/quick/util/qquickanimatorjob.cpp28
-rw-r--r--src/quick/util/qquickanimatorjob_p.h7
-rw-r--r--src/quick/util/qquickpixmapcache.cpp53
-rw-r--r--src/quick/util/qquickprofiler.cpp18
-rw-r--r--src/quick/util/qquickprofiler_p.h42
-rw-r--r--src/quickwidgets/qquickwidget.cpp81
-rw-r--r--src/quickwidgets/qquickwidget_p.h1
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp19
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp50
-rw-r--r--tests/auto/qml/qqmldirparser/data/dependency/qmldir3
-rw-r--r--tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp32
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/sequenceSort.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/utcdate.qml34
-rw-r--r--tests/auto/qml/qqmlecmascript/data/variants.qml55
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp71
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp4
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp18
-rw-r--r--tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp5
-rw-r--r--tests/auto/qmltest/animators/tst_targetdestroyed.qml77
-rw-r--r--tests/auto/qmltest/selftests/tst_findChild.qml37
-rw-r--r--tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml4
-rw-r--r--tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml82
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml5
-rw-r--r--tests/auto/qmltest/shadersource/tst_SourceItem.qml57
-rw-r--r--tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml3
-rw-r--r--tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml71
-rw-r--r--tests/auto/quick/dialogs/data/RectWithFileDialog.qml33
-rw-r--r--tests/auto/quick/dialogs/dialogs.pro20
-rw-r--r--tests/auto/quick/dialogs/tst_dialogs.cpp152
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp67
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml7
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_image.qml2
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_state.qml2
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp4
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp3
-rw-r--r--tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp33
-rw-r--r--tests/auto/quick/qquickscreen/data/screen.qml3
-rw-r--r--tests/auto/quick/qquickscreen/tst_qquickscreen.cpp1
-rw-r--r--tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp3
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp11
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp2
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp33
-rw-r--r--tests/auto/quick/quick.pro3
-rw-r--r--tests/auto/shared/platformquirks.h4
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_height.qml32
-rw-r--r--tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_width.qml32
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/textinput_selected_fallback_font.qml17
-rw-r--r--tools/qml/main.cpp6
-rw-r--r--tools/qmlimportscanner/main.cpp67
-rw-r--r--tools/qmlplugindump/main.cpp4
-rw-r--r--tools/qmlscene/main.cpp14
247 files changed, 3584 insertions, 1533 deletions
diff --git a/.gitignore b/.gitignore
index c14d237ee3..b0854aab2a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,7 +55,6 @@ bin/pixeltool*
bin/qmake*
bin/qdoc3*
bin/qt3to4*
-bin/qtdemo*
bin/qttracereplay*
bin/rcc*
bin/uic*
@@ -106,7 +105,6 @@ tools/activeqt/testcon/testcon.tlb
translations/*.qm
translations/*_untranslated.ts
qrc_*.cpp
-src/imports/dialogs/dialogs.qrc
# Test generated files
QObject.log
diff --git a/examples/qml/doc/src/qml-extending.qdoc b/examples/qml/doc/src/qml-extending.qdoc
index 7dbd147cc1..8f44e4f506 100644
--- a/examples/qml/doc/src/qml-extending.qdoc
+++ b/examples/qml/doc/src/qml-extending.qdoc
@@ -36,7 +36,7 @@ The \c Person type can be used from QML like this:
\snippet referenceexamples/adding/example.qml 0
-\section1 Declare the Person class
+\section1 Declare the Person Class
All QML types map to C++ types. Here we declare a basic C++ Person class
with the two properties we want accessible on the QML type - name and shoeSize.
@@ -45,7 +45,7 @@ type, the C++ class can be named differently, or appear in a namespace.
\snippet referenceexamples/adding/person.h 0
-\section1 Define the Person class
+\section1 Define the Person Class
\snippet referenceexamples/adding/person.cpp 0
@@ -56,7 +56,7 @@ The \c main.cpp file also calls the \c qmlRegisterType() function to
register the \c Person type with QML as a type in the People library version 1.0,
and defines the mapping between the C++ and QML class names.
-\section1 Running the example
+\section1 Running the Example
The main.cpp file in the example includes a simple shell application that
loads and runs the QML snippet shown at the beginning of this page.
@@ -106,7 +106,7 @@ The implementation of BirthdayParty property accessors is straight forward.
\snippet referenceexamples/properties/birthdayparty.cpp 0
-\section1 Running the example
+\section1 Running the Example
The main.cpp file in the example includes a simple shell application that
loads and runs the QML snippet shown at the beginning of this page.
@@ -162,7 +162,7 @@ The implementation of Boy and Girl are trivial.
All that is necessary is to implement the constructor, and to register the types
and their QML name with the QML engine.
-\section1 Running the example
+\section1 Running the Example
The BirthdayParty type has not changed since the previous example. The
celebrant and guests property still use the People type.
@@ -196,7 +196,7 @@ specification of a BirthdayParty through the use of a default property.
\snippet referenceexamples/default/example.qml 0
-\section1 Declaring the BirthdayParty class
+\section1 Declaring the BirthdayParty Class
The only difference between this example and the last, is the addition of the
\c DefaultProperty class info annotation.
@@ -209,7 +209,7 @@ property. It is purely a syntactic simplification, the behavior is identical
to specifying the property by name, but it can add a more natural feel in many
situations. The default property must be either an object or list property.
-\section1 Running the example
+\section1 Running the Example
The main.cpp file in the example includes a simple shell application that
loads and runs the QML snippet shown at the beginning of this page.
diff --git a/examples/qml/tutorials/extending/chapter1-basics/app.qml b/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml
index d2f03daf83..d2f03daf83 100644
--- a/examples/qml/tutorials/extending/chapter1-basics/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/app.qml
diff --git a/examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.pro b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pro
index c28664ea51..9911e02484 100644
--- a/examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.pro
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.pro
@@ -6,7 +6,7 @@ SOURCES += piechart.cpp \
RESOURCES += chapter1-basics.qrc
-DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending/chapter1-basics
+DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter1-basics
target.path = $$DESTPATH
qml.files = *.qml
diff --git a/examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.qrc b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.qrc
index f1168aef3b..f1168aef3b 100644
--- a/examples/qml/tutorials/extending/chapter1-basics/chapter1-basics.qrc
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/chapter1-basics.qrc
diff --git a/examples/qml/tutorials/extending/chapter1-basics/main.cpp b/examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp
index 4e719d2722..4e719d2722 100644
--- a/examples/qml/tutorials/extending/chapter1-basics/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/main.cpp
diff --git a/examples/qml/tutorials/extending/chapter1-basics/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.cpp
index fa005781d8..fa005781d8 100644
--- a/examples/qml/tutorials/extending/chapter1-basics/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.cpp
diff --git a/examples/qml/tutorials/extending/chapter1-basics/piechart.h b/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h
index a6272453ce..a6272453ce 100644
--- a/examples/qml/tutorials/extending/chapter1-basics/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter1-basics/piechart.h
diff --git a/examples/qml/tutorials/extending/chapter2-methods/app.qml b/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml
index 06ecb3a09d..06ecb3a09d 100644
--- a/examples/qml/tutorials/extending/chapter2-methods/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/app.qml
diff --git a/examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.pro b/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pro
index a451c775cf..7fd850ce36 100644
--- a/examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.pro
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.pro
@@ -6,7 +6,7 @@ SOURCES += piechart.cpp \
RESOURCES += chapter2-methods.qrc
-DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending/chapter2-methods
+DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter2-methods
target.path = $$DESTPATH
qml.files = *.qml
diff --git a/examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.qrc b/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.qrc
index f1168aef3b..f1168aef3b 100644
--- a/examples/qml/tutorials/extending/chapter2-methods/chapter2-methods.qrc
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/chapter2-methods.qrc
diff --git a/examples/qml/tutorials/extending/chapter2-methods/main.cpp b/examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp
index 4e719d2722..4e719d2722 100644
--- a/examples/qml/tutorials/extending/chapter2-methods/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/main.cpp
diff --git a/examples/qml/tutorials/extending/chapter2-methods/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.cpp
index ddcb1b3efd..ddcb1b3efd 100644
--- a/examples/qml/tutorials/extending/chapter2-methods/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.cpp
diff --git a/examples/qml/tutorials/extending/chapter2-methods/piechart.h b/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h
index 86750197d2..86750197d2 100644
--- a/examples/qml/tutorials/extending/chapter2-methods/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter2-methods/piechart.h
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/app.qml b/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
index afb9e25c51..afb9e25c51 100644
--- a/examples/qml/tutorials/extending/chapter3-bindings/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/app.qml
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/chapter3-binding.qrc b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-binding.qrc
index f1168aef3b..f1168aef3b 100644
--- a/examples/qml/tutorials/extending/chapter3-bindings/chapter3-binding.qrc
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-binding.qrc
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/chapter3-bindings.pro b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pro
index 6193f466c1..0c31592eeb 100644
--- a/examples/qml/tutorials/extending/chapter3-bindings/chapter3-bindings.pro
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/chapter3-bindings.pro
@@ -6,7 +6,7 @@ SOURCES += piechart.cpp \
RESOURCES += chapter3-binding.qrc
-DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending/chapter3-binding
+DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter3-binding
target.path = $$DESTPATH
qml.files = *.qml
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/main.cpp b/examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp
index 4e719d2722..4e719d2722 100644
--- a/examples/qml/tutorials/extending/chapter3-bindings/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/main.cpp
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.cpp
index a63035033f..a63035033f 100644
--- a/examples/qml/tutorials/extending/chapter3-bindings/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.cpp
diff --git a/examples/qml/tutorials/extending/chapter3-bindings/piechart.h b/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h
index 25e82d66cc..25e82d66cc 100644
--- a/examples/qml/tutorials/extending/chapter3-bindings/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter3-bindings/piechart.h
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml
index c757fdaedd..c757fdaedd 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/app.qml
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
index 1742334107..12dfbd6280 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.pro
@@ -8,7 +8,7 @@ SOURCES += piechart.cpp \
RESOURCES += chapter4-customPropertyTypes.qrc
-DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending/chapter4-customPropertyTypes
+DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter4-customPropertyTypes
target.path = $$DESTPATH
qml.files = *.qml
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.qrc b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.qrc
index f1168aef3b..f1168aef3b 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/chapter4-customPropertyTypes.qrc
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/chapter4-customPropertyTypes.qrc
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/main.cpp b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp
index fc59a11987..fc59a11987 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
index c1e2996e83..c1e2996e83 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/piechart.h b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h
index 9f0ea47eb9..9f0ea47eb9 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/pieslice.cpp b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.cpp
index 2afe82048f..2afe82048f 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/pieslice.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.cpp
diff --git a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/pieslice.h b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h
index 4eef9bb6d1..4eef9bb6d1 100644
--- a/examples/qml/tutorials/extending/chapter4-customPropertyTypes/pieslice.h
+++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/app.qml b/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml
index 68aa6e0c1d..68aa6e0c1d 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/app.qml
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro b/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pro
index ba51dd9093..67d1cd35c3 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.pro
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.pro
@@ -8,7 +8,7 @@ SOURCES += piechart.cpp \
RESOURCES += chapter5-listproperties.qrc
-DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending/chapter5-listproperties
+DESTPATH = $$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter5-listproperties
target.path = $$DESTPATH
qml.files = *.qml
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.qrc b/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.qrc
index f1168aef3b..f1168aef3b 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/chapter5-listproperties.qrc
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/chapter5-listproperties.qrc
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/main.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp
index 8a4afcf96d..8a4afcf96d 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/main.cpp
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.cpp
index 9fb61d9cd8..9fb61d9cd8 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.cpp
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/piechart.h b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h
index 55488f4900..55488f4900 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/piechart.h
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/pieslice.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
index 52b409aa22..52b409aa22 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/pieslice.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp
diff --git a/examples/qml/tutorials/extending/chapter5-listproperties/pieslice.h b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h
index f324179481..f324179481 100644
--- a/examples/qml/tutorials/extending/chapter5-listproperties/pieslice.h
+++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.h
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/app.pro b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro
index c55db00d27..c55db00d27 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/app.pro
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/app.qml b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml
index d5a474b8d3..d5a474b8d3 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/app.qml
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/app.qrc b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.qrc
index f1168aef3b..f1168aef3b 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/app.qrc
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.qrc
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/chapter6-plugins.pro b/examples/qml/tutorials/extending-qml/chapter6-plugins/chapter6-plugins.pro
index f858c80876..f858c80876 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/chapter6-plugins.pro
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/chapter6-plugins.pro
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/chartsplugin.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp
index fea4c1aa85..fea4c1aa85 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/chartsplugin.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/chartsplugin.h b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h
index d768306967..d768306967 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/chartsplugin.h
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/import.pro b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/import.pro
index 83cfb96ab5..cefcf3b477 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/import.pro
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/import.pro
@@ -13,7 +13,7 @@ SOURCES += piechart.cpp \
pieslice.cpp \
chartsplugin.cpp
-DESTPATH=$$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending/chapter6-plugins/Charts
+DESTPATH=$$[QT_INSTALL_EXAMPLES]/qml/tutorials/extending-qml/chapter6-plugins/Charts
target.path=$$DESTPATH
qmldir.files=$$PWD/qmldir
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.cpp
index 295bb8961d..295bb8961d 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/piechart.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.cpp
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/piechart.h b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h
index b37bcdd411..b37bcdd411 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/piechart.h
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/piechart.h
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/pieslice.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.cpp
index 52b409aa22..52b409aa22 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/pieslice.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.cpp
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/pieslice.h b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h
index 0b488b4835..0b488b4835 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/pieslice.h
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/pieslice.h
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/import/qmldir b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/qmldir
index d9e8471b3c..d9e8471b3c 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/import/qmldir
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/qmldir
diff --git a/examples/qml/tutorials/extending/chapter6-plugins/main.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp
index 60d8c6cd7a..60d8c6cd7a 100644
--- a/examples/qml/tutorials/extending/chapter6-plugins/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp
diff --git a/examples/qml/tutorials/extending/extending.pro b/examples/qml/tutorials/extending-qml/extending-qml.pro
index a665975382..a665975382 100644
--- a/examples/qml/tutorials/extending/extending.pro
+++ b/examples/qml/tutorials/extending-qml/extending-qml.pro
diff --git a/examples/qml/xmlhttprequest/doc/src/xmlhttprequest.qdoc b/examples/qml/xmlhttprequest/doc/src/xmlhttprequest.qdoc
index 579cc5f80f..8619c528a9 100644
--- a/examples/qml/xmlhttprequest/doc/src/xmlhttprequest.qdoc
+++ b/examples/qml/xmlhttprequest/doc/src/xmlhttprequest.qdoc
@@ -36,7 +36,7 @@
\include examples-run.qdocinc
- \section1 Get data
+ \section1 Get Data
\e{Get data} uses the XMLHttpRequest API to fetch an XML document from a
server. It displays the header of the HTTP response and the body of the XML
diff --git a/examples/quick/animation/basics/animators.qml b/examples/quick/animation/basics/animators.qml
index 3454eca13c..df1bd55be7 100644
--- a/examples/quick/animation/basics/animators.qml
+++ b/examples/quick/animation/basics/animators.qml
@@ -48,10 +48,10 @@ Item {
Rectangle {
anchors.fill: parent
gradient: Gradient {
- GradientStop { position: 0.0; color: "DeepSkyBlue" }
- GradientStop { position: 0.499; color: "LightSkyBlue" }
- GradientStop { position: 0.5; color: "ForestGreen" }
- GradientStop { position: 1.0; color: "DarkGreen" }
+ GradientStop { position: 0.0; color: "#14148c" }
+ GradientStop { position: 0.499; color: "#14aaff" }
+ GradientStop { position: 0.5; color: "#80c342" }
+ GradientStop { position: 1.0; color: "#006325" }
}
}
diff --git a/examples/quick/animation/basics/color-animation.qml b/examples/quick/animation/basics/color-animation.qml
index 0de4177a9f..a4a149df5c 100644
--- a/examples/quick/animation/basics/color-animation.qml
+++ b/examples/quick/animation/basics/color-animation.qml
@@ -54,16 +54,16 @@ Item {
position: 0.0
SequentialAnimation on color {
loops: Animation.Infinite
- ColorAnimation { from: "DeepSkyBlue"; to: "#0E1533"; duration: 5000 }
- ColorAnimation { from: "#0E1533"; to: "DeepSkyBlue"; duration: 5000 }
+ ColorAnimation { from: "#14148c"; to: "#0E1533"; duration: 5000 }
+ ColorAnimation { from: "#0E1533"; to: "#14148c"; duration: 5000 }
}
}
GradientStop {
position: 1.0
SequentialAnimation on color {
loops: Animation.Infinite
- ColorAnimation { from: "SkyBlue"; to: "#437284"; duration: 5000 }
- ColorAnimation { from: "#437284"; to: "SkyBlue"; duration: 5000 }
+ ColorAnimation { from: "#14aaff"; to: "#437284"; duration: 5000 }
+ ColorAnimation { from: "#437284"; to: "#14aaff"; duration: 5000 }
}
}
}
@@ -113,11 +113,11 @@ Item {
position: 0.0
SequentialAnimation on color {
loops: Animation.Infinite
- ColorAnimation { from: "ForestGreen"; to: "#001600"; duration: 5000 }
- ColorAnimation { from: "#001600"; to: "ForestGreen"; duration: 5000 }
+ ColorAnimation { from: "#80c342"; to: "#001600"; duration: 5000 }
+ ColorAnimation { from: "#001600"; to: "#80c342"; duration: 5000 }
}
}
- GradientStop { position: 1.0; color: "DarkGreen" }
+ GradientStop { position: 1.0; color: "#006325" }
}
}
}
diff --git a/examples/quick/animation/basics/property-animation.qml b/examples/quick/animation/basics/property-animation.qml
index ae808ba2fe..d237bb1f87 100644
--- a/examples/quick/animation/basics/property-animation.qml
+++ b/examples/quick/animation/basics/property-animation.qml
@@ -48,8 +48,8 @@ Item {
Rectangle {
anchors { left: parent.left; top: parent.top; right: parent.right; bottom: parent.verticalCenter }
gradient: Gradient {
- GradientStop { position: 0.0; color: "DeepSkyBlue" }
- GradientStop { position: 1.0; color: "LightSkyBlue" }
+ GradientStop { position: 0.0; color: "#14148c" }
+ GradientStop { position: 1.0; color: "#14aaff" }
}
}
@@ -57,8 +57,8 @@ Item {
Rectangle {
anchors { left: parent.left; top: parent.verticalCenter; right: parent.right; bottom: parent.bottom }
gradient: Gradient {
- GradientStop { position: 0.0; color: "ForestGreen" }
- GradientStop { position: 1.0; color: "DarkGreen" }
+ GradientStop { position: 0.0; color: "#80c342" }
+ GradientStop { position: 1.0; color: "#006325" }
}
}
diff --git a/examples/quick/animation/behaviors/tvtennis.qml b/examples/quick/animation/behaviors/tvtennis.qml
index b5ad2e8667..46dd861fc8 100644
--- a/examples/quick/animation/behaviors/tvtennis.qml
+++ b/examples/quick/animation/behaviors/tvtennis.qml
@@ -43,7 +43,7 @@ import QtQuick 2.0
Rectangle {
id: page
width: 320; height: 480;
- color: "Black"
+ color: "#1e1b18"
// Make a ball to bounce
Rectangle {
@@ -53,7 +53,7 @@ Rectangle {
property variant direction : "right"
x: 20; width: 20; height: 20; z: 1
- color: "Lime"
+ color: "#80c342"
// Move the ball to the right and back to the left repeatedly
SequentialAnimation on x {
@@ -84,7 +84,7 @@ Rectangle {
// coordinates of the ball.
Rectangle {
id: leftBat
- color: "Lime"
+ color: "#328930"
x: 2; width: 20; height: 90
// ![0]
y: ball.direction == 'left' ? ball.y - 45 : page.height/2 -45;
@@ -93,19 +93,19 @@ Rectangle {
}
Rectangle {
id: rightBat
- color: "Lime"
+ color: "#328930"
x: page.width - 22; width: 20; height: 90
y: ball.direction == 'right' ? ball.y - 45 : page.height/2 -45;
Behavior on y { SpringAnimation{ velocity: 300 } }
}
// The rest, to make it look realistic, if neither ever scores...
- Rectangle { color: "Lime"; x: page.width/2-80; y: 0; width: 40; height: 60 }
- Rectangle { color: "Black"; x: page.width/2-70; y: 10; width: 20; height: 40 }
- Rectangle { color: "Lime"; x: page.width/2+40; y: 0; width: 40; height: 60 }
- Rectangle { color: "Black"; x: page.width/2+50; y: 10; width: 20; height: 40 }
+ Rectangle { color: "#328930"; x: page.width/2-80; y: 0; width: 40; height: 60 }
+ Rectangle { color: "#1e1b18"; x: page.width/2-70; y: 10; width: 20; height: 40 }
+ Rectangle { color: "#328930"; x: page.width/2+40; y: 0; width: 40; height: 60 }
+ Rectangle { color: "#1e1b18"; x: page.width/2+50; y: 10; width: 20; height: 40 }
Repeater {
model: page.height / 20
- Rectangle { color: "Lime"; x: page.width/2-5; y: index * 20; width: 10; height: 10 }
+ Rectangle { color: "#328930"; x: page.width/2-5; y: index * 20; width: 10; height: 10 }
}
}
diff --git a/examples/quick/canvas/doc/src/canvas.qdoc b/examples/quick/canvas/doc/src/canvas.qdoc
index 2c4bd1f752..e5138e3f35 100644
--- a/examples/quick/canvas/doc/src/canvas.qdoc
+++ b/examples/quick/canvas/doc/src/canvas.qdoc
@@ -38,12 +38,12 @@
\include examples-run.qdocinc
- \section1 Red heart
+ \section1 Red Heart
\e{Red heart} uses the bezier curve API to stroke and fill a red heart.
\snippet canvas/bezierCurve/bezierCurve.qml 0
- \section1 Talk bubble
+ \section1 Talk Bubble
\e{Talk bubble} uses the quadraticCurveTo() API to stroke and fill a
customized talk bubble:
@@ -57,12 +57,12 @@
\e Squircle uses a collection of simple moveTo() and lineTo() path APIs to
draw a smooth squircle.
- \section1 Rounded rectangle
+ \section1 Rounded Rectangle
\e{Rounded rectangle} uses a collection of lineTo() and arcTo() path APIs to
draw a rounded rectangle.
- \section1 Smile face
+ \section1 Smile Face
\e{Smile face} uses several paths to draw and fill a smiling face.
diff --git a/examples/quick/customitems/dialcontrol/dialcontrol.pro b/examples/quick/customitems/dialcontrol/dialcontrol.pro
new file mode 100644
index 0000000000..ceb8e239dc
--- /dev/null
+++ b/examples/quick/customitems/dialcontrol/dialcontrol.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = dialcontrol
+
+QT += quick qml
+
+SOURCES += main.cpp
+
+RESOURCES += dialcontrol.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/customitems/dialcontrol
+INSTALLS += target
diff --git a/examples/quick/customitems/dialcontrol/dialcontrol.qml b/examples/quick/customitems/dialcontrol/dialcontrol.qml
index f545877655..0bf6d7e68c 100644
--- a/examples/quick/customitems/dialcontrol/dialcontrol.qml
+++ b/examples/quick/customitems/dialcontrol/dialcontrol.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
@@ -39,7 +39,8 @@
****************************************************************************/
//! [imports]
-import QtQuick 2.0
+import QtQuick 2.2
+import QtQuick.Window 2.1
import "content"
//! [imports]
@@ -53,12 +54,13 @@ Rectangle {
Dial {
id: dial
anchors.centerIn: parent
- value: slider.x * 100 / (container.width - 34)
+ value: slider.x * 100 / (container.width - 32)
}
//! [the dial in use]
Rectangle {
id: container
+ property int oldWidth: 0
anchors { bottom: parent.bottom; left: parent.left
right: parent.right; leftMargin: 20; rightMargin: 20
bottomMargin: 10
@@ -73,6 +75,17 @@ Rectangle {
GradientStop { position: 1.0; color: "white" }
}
+ onWidthChanged: {
+ if (oldWidth === 0) {
+ oldWidth = width;
+ return
+ }
+
+ var desiredPercent = slider.x * 100 / (oldWidth - 32)
+ slider.x = desiredPercent * (width - 32) / 100
+ oldWidth = width
+ }
+
Rectangle {
id: slider
x: 1; y: 1; width: 30; height: 14
diff --git a/examples/quick/customitems/dialcontrol/dialcontrol.qrc b/examples/quick/customitems/dialcontrol/dialcontrol.qrc
new file mode 100644
index 0000000000..6433d68bb8
--- /dev/null
+++ b/examples/quick/customitems/dialcontrol/dialcontrol.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/">
+ <file>dialcontrol.qml</file>
+ <file>content/background.png</file>
+ <file>content/Dial.qml</file>
+ <file>content/needle_shadow.png</file>
+ <file>content/needle.png</file>
+ <file>content/overlay.png</file>
+ <file>content/quit.png</file>
+ <file>content/QuitButton.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/customitems/dialcontrol/main.cpp b/examples/quick/customitems/dialcontrol/main.cpp
new file mode 100644
index 0000000000..c72251cde7
--- /dev/null
+++ b/examples/quick/customitems/dialcontrol/main.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia Plc 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$
+**
+****************************************************************************/
+#include "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(dialcontrol)
diff --git a/examples/quick/demos/calqlatr/calqlatr.qml b/examples/quick/demos/calqlatr/calqlatr.qml
index 5f0ebe85a8..8bda2c521e 100644
--- a/examples/quick/demos/calqlatr/calqlatr.qml
+++ b/examples/quick/demos/calqlatr/calqlatr.qml
@@ -53,13 +53,22 @@ Rectangle {
onWidthChanged: controller.reload()
onHeightChanged: controller.reload()
- function operatorPressed(operator) { CalcEngine.operatorPressed(operator) }
- function digitPressed(digit) { CalcEngine.digitPressed(digit) }
+ function operatorPressed(operator) {
+ CalcEngine.operatorPressed(operator)
+ numPad.buttonPressed()
+ }
+ function digitPressed(digit) {
+ CalcEngine.digitPressed(digit)
+ numPad.buttonPressed()
+ }
+ function isButtonDisabled(op) {
+ return CalcEngine.disabled(op)
+ }
Item {
id: pad
width: 180
- NumberPad { y: 10; anchors.horizontalCenter: parent.horizontalCenter }
+ NumberPad { id: numPad; y: 10; anchors.horizontalCenter: parent.horizontalCenter }
}
AnimationController {
@@ -75,6 +84,43 @@ Rectangle {
}
}
+ Keys.onPressed: {
+ if (event.key == Qt.Key_0)
+ digitPressed("0")
+ else if (event.key == Qt.Key_1)
+ digitPressed("1")
+ else if (event.key == Qt.Key_2)
+ digitPressed("2")
+ else if (event.key == Qt.Key_3)
+ digitPressed("3")
+ else if (event.key == Qt.Key_4)
+ digitPressed("4")
+ else if (event.key == Qt.Key_5)
+ digitPressed("5")
+ else if (event.key == Qt.Key_6)
+ digitPressed("6")
+ else if (event.key == Qt.Key_7)
+ digitPressed("7")
+ else if (event.key == Qt.Key_8)
+ digitPressed("8")
+ else if (event.key == Qt.Key_9)
+ digitPressed("9")
+ else if (event.key == Qt.Key_Plus)
+ operatorPressed("+")
+ else if (event.key == Qt.Key_Minus)
+ operatorPressed("−")
+ else if (event.key == Qt.Key_Asterisk)
+ operatorPressed("×")
+ else if (event.key == Qt.Key_Slash)
+ operatorPressed("÷")
+ else if (event.key == Qt.Key_Enter || event.key == Qt.Key_Return)
+ operatorPressed("=")
+ else if (event.key == Qt.Key_Comma || event.key == Qt.Key_Period)
+ digitPressed(".")
+ else if (event.key == Qt.Key_Backspace)
+ operatorPressed("backspace")
+ }
+
Display {
id: display
x: -16
diff --git a/examples/quick/demos/calqlatr/content/Button.qml b/examples/quick/demos/calqlatr/content/Button.qml
index 3f28e6f3c0..0748645274 100644
--- a/examples/quick/demos/calqlatr/content/Button.qml
+++ b/examples/quick/demos/calqlatr/content/Button.qml
@@ -41,12 +41,13 @@
import QtQuick 2.0
Item {
+ id: button
property alias text: textItem.text
- property alias color: textItem.color
+ property color color: "#eceeea"
property bool operator: false
-
- signal clicked
+ property bool dimmable: false
+ property bool dimmed: false
width: 30
height: 50
@@ -56,25 +57,38 @@ Item {
font.pixelSize: 48
wrapMode: Text.WordWrap
lineHeight: 0.75
- color: "white"
+ color: (dimmable && dimmed) ? Qt.darker(button.color) : button.color
+ Behavior on color { ColorAnimation { duration: 120; easing.type: Easing.OutElastic} }
+ states: [
+ State {
+ name: "pressed"
+ when: mouse.pressed && !dimmed
+ PropertyChanges {
+ target: textItem
+ color: Qt.lighter(button.color)
+ }
+ }
+ ]
}
-// Rectangle {
-// color: "red"
-// opacity: 0.2
-// anchors.fill: mouse
-// }
-
MouseArea {
id: mouse
anchors.fill: parent
anchors.margins: -5
onClicked: {
- //parent.clicked()
if (operator)
window.operatorPressed(parent.text)
else
window.digitPressed(parent.text)
}
}
+
+ function updateDimmed() {
+ dimmed = window.isButtonDisabled(button.text)
+ }
+
+ Component.onCompleted: {
+ numPad.buttonPressed.connect(updateDimmed)
+ updateDimmed()
+ }
}
diff --git a/examples/quick/demos/calqlatr/content/Display.qml b/examples/quick/demos/calqlatr/content/Display.qml
index ec8edfea66..efa7a1ab66 100644
--- a/examples/quick/demos/calqlatr/content/Display.qml
+++ b/examples/quick/demos/calqlatr/content/Display.qml
@@ -39,20 +39,28 @@
****************************************************************************/
import QtQuick 2.0
+import QtQuick.Window 2.0
Item {
id: display
+ property real fontSize: Math.floor(Screen.pixelDensity * 5.0)
property bool enteringDigits: false
+ property int maxDigits: (width / fontSize) + 1
+ property string displayedOperand
+ property string errorString: qsTr("ERROR")
+ property bool isError: displayedOperand === errorString
function displayOperator(operator)
{
listView.model.append({ "operator": operator, "operand": "" })
enteringDigits = true
+ listView.positionViewAtEnd()
}
function newLine(operator, operand)
{
- listView.model.append({ "operator": operator, "operand": operand })
+ displayedOperand = displayNumber(operand)
+ listView.model.append({ "operator": operator, "operand": displayedOperand })
enteringDigits = false
listView.positionViewAtEnd()
}
@@ -64,10 +72,19 @@ Item {
var i = listView.model.count - 1;
listView.model.get(i).operand = listView.model.get(i).operand + digit;
enteringDigits = true
+ listView.positionViewAtEnd()
+ }
+
+ function setDigit(digit)
+ {
+ var i = listView.model.count - 1;
+ listView.model.get(i).operand = digit;
+ listView.positionViewAtEnd()
}
function clear()
{
+ displayedOperand = ""
if (enteringDigits) {
var i = listView.model.count - 1
if (i >= 0)
@@ -76,6 +93,42 @@ Item {
}
}
+ // Returns a string representation of a number that fits in
+ // display.maxDigits characters, trying to keep as much precision
+ // as possible. If the number cannot be displayed, returns an
+ // error string.
+ function displayNumber(num) {
+ if (typeof(num) != "number")
+ return errorString;
+
+ var intNum = parseInt(num);
+ var intLen = intNum.toString().length;
+
+ // Do not count the minus sign as a digit
+ var maxLen = num < 0 ? maxDigits + 1 : maxDigits;
+
+ if (num.toString().length <= maxLen) {
+ if (isFinite(num))
+ return num.toString();
+ return errorString;
+ }
+
+ // Integer part of the number is too long - try
+ // an exponential notation
+ if (intNum == num || intLen > maxLen - 3) {
+ var expVal = num.toExponential(maxDigits - 6).toString();
+ if (expVal.length <= maxLen)
+ return expVal;
+ }
+
+ // Try a float presentation with fixed number of digits
+ var floatStr = parseFloat(num).toFixed(maxDigits - intLen - 1).toString();
+ if (floatStr.length <= maxLen)
+ return floatStr;
+
+ return errorString;
+ }
+
Item {
id: theItem
width: parent.width + 32
@@ -119,16 +172,16 @@ Item {
width: parent.width
Text {
id: operator
- x: 8
- font.pixelSize: 18
+ x: 6
+ font.pixelSize: display.fontSize
color: "#6da43d"
text: model.operator
}
Text {
id: operand
- font.pixelSize: 18
+ font.pixelSize: display.fontSize
anchors.right: parent.right
- anchors.rightMargin: 26
+ anchors.rightMargin: 22
text: model.operand
}
}
diff --git a/examples/quick/demos/calqlatr/content/NumberPad.qml b/examples/quick/demos/calqlatr/content/NumberPad.qml
index c7f2680651..c4ae1bb582 100644
--- a/examples/quick/demos/calqlatr/content/NumberPad.qml
+++ b/examples/quick/demos/calqlatr/content/NumberPad.qml
@@ -45,6 +45,8 @@ Grid {
columnSpacing: 32
rowSpacing: 16
+ signal buttonPressed
+
Button { text: "7" }
Button { text: "8" }
Button { text: "9" }
@@ -55,15 +57,15 @@ Grid {
Button { text: "2" }
Button { text: "3" }
Button { text: "0" }
- Button { text: "." }
+ Button { text: "."; dimmable: true }
Button { text: " " }
- Button { text: "±"; color: "#6da43d"; operator: true }
- Button { text: "−"; color: "#6da43d"; operator: true }
- Button { text: "+"; color: "#6da43d"; operator: true }
- Button { text: "√"; color: "#6da43d"; operator: true }
- Button { text: "÷"; color: "#6da43d"; operator: true }
- Button { text: "×"; color: "#6da43d"; operator: true }
+ Button { text: "±"; color: "#6da43d"; operator: true; dimmable: true }
+ Button { text: "−"; color: "#6da43d"; operator: true; dimmable: true }
+ Button { text: "+"; color: "#6da43d"; operator: true; dimmable: true }
+ Button { text: "√"; color: "#6da43d"; operator: true; dimmable: true }
+ Button { text: "÷"; color: "#6da43d"; operator: true; dimmable: true }
+ Button { text: "×"; color: "#6da43d"; operator: true; dimmable: true }
Button { text: "C"; color: "#6da43d"; operator: true }
Button { text: " "; color: "#6da43d"; operator: true }
- Button { text: "="; color: "#6da43d"; operator: true }
+ Button { text: "="; color: "#6da43d"; operator: true; dimmable: true }
}
diff --git a/examples/quick/demos/calqlatr/content/calculator.js b/examples/quick/demos/calqlatr/content/calculator.js
index da8e940b16..841ba9414c 100644
--- a/examples/quick/demos/calqlatr/content/calculator.js
+++ b/examples/quick/demos/calqlatr/content/calculator.js
@@ -38,7 +38,6 @@
**
****************************************************************************/
-
var curVal = 0
var memory = 0
var lastOp = ""
@@ -46,9 +45,13 @@ var previousOperator = ""
var digits = ""
function disabled(op) {
- if (op == "." && digits.toString().search(/\./) != -1) {
+ if (digits == "" && !((op >= "0" && op <= "9") || op == "."))
+ return true
+ else if (op == '=' && previousOperator.length != 1)
+ return true
+ else if (op == "." && digits.toString().search(/\./) != -1) {
return true
- } else if (op == window.squareRoot && digits.toString().search(/-/) != -1) {
+ } else if (op == "√" && digits.toString().search(/-/) != -1) {
return true
} else {
return false
@@ -59,7 +62,7 @@ function digitPressed(op)
{
if (disabled(op))
return
- if (digits.toString().length >= 14)
+ if (digits.toString().length >= display.maxDigits)
return
if (lastOp.toString().length == 1 && ((lastOp >= "0" && lastOp <= "9") || lastOp == ".") ) {
digits = digits + op.toString()
@@ -77,26 +80,32 @@ function operatorPressed(op)
return
lastOp = op
+ if (op == "±") {
+ digits = Number(digits.valueOf() * -1)
+ display.setDigit(display.displayNumber(digits))
+ return
+ }
+
if (previousOperator == "+") {
digits = Number(digits.valueOf()) + Number(curVal.valueOf())
} else if (previousOperator == "−") {
- digits = Number(curVal) - Number(digits.valueOf())
+ digits = Number(curVal.valueOf()) - Number(digits.valueOf())
} else if (previousOperator == "×") {
digits = Number(curVal) * Number(digits.valueOf())
} else if (previousOperator == "÷") {
digits = Number(curVal) / Number(digits.valueOf())
- } else if (previousOperator == "=") {
}
if (op == "+" || op == "−" || op == "×" || op == "÷") {
previousOperator = op
curVal = digits.valueOf()
+ digits = ""
display.displayOperator(previousOperator)
return
}
if (op == "=") {
- display.newLine("=", digits.toString())
+ display.newLine("=", digits.valueOf())
}
curVal = 0
@@ -110,10 +119,9 @@ function operatorPressed(op)
digits = (Math.abs(digits.valueOf())).toString()
} else if (op == "Int") {
digits = (Math.floor(digits.valueOf())).toString()
- } else if (op == "±") {
- digits = (digits.valueOf() * -1).toString()
} else if (op == "√") {
- digits = (Math.sqrt(digits.valueOf())).toString()
+ digits = Number(Math.sqrt(digits.valueOf()))
+ display.newLine("√", digits.valueOf())
} else if (op == "mc") {
memory = 0;
} else if (op == "m+") {
@@ -122,22 +130,22 @@ function operatorPressed(op)
digits = memory.toString()
} else if (op == "m-") {
memory = digits.valueOf()
- } else if (op == window.leftArrow) {
+ } else if (op == "backspace") {
digits = digits.toString().slice(0, -1)
- if (digits.length == 0) {
- digits = "0"
- }
+ display.clear()
+ display.appendDigit(digits)
} else if (op == "Off") {
Qt.quit();
- } else if (op == "C") {
+ }
+
+ // Reset the state on 'C' operator or after
+ // an error occurred
+ if (op == "C" || display.isError) {
display.clear()
- } else if (op == "AC") {
curVal = 0
memory = 0
lastOp = ""
- digits ="0"
+ digits = ""
}
-
-
}
diff --git a/examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc b/examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc
index e72d048567..7316f27595 100644
--- a/examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc
+++ b/examples/quick/demos/calqlatr/doc/src/calqlatr.qdoc
@@ -49,7 +49,6 @@
\li Button.qml
\li Display.qml
\li NumberPad.qml
- \li StyleLabel.qml
\endlist
To use the custom types, we add an import statement to the main QML file,
@@ -70,7 +69,7 @@
\printuntil }
\printuntil }
- Further, we use the Button type in the NumberPad type to create the
+ Further, we use the Button type in the \c NumberPad type to create the
calculator buttons. Button.qml specifies the basic properties for a
button that we can modify for each button instance in NumberPad.qml. For the
digit and separator buttons, we additionally specify the text property using
@@ -86,6 +85,11 @@
\skipto Grid
\printuntil /^\}/
+ Some of the buttons also have a \c dimmable property set, meaning that they
+ can be visually disabled (dimmed) whenever the calculator engine does not
+ accept input from that button. As an example, the button for square root
+ operator is dimmed for negative values.
+
\section1 Animating Components
We use the Display type to display calculations. In Display.qml, we use
@@ -100,7 +104,11 @@
is the id of our AnimationController:
\quotefromfile demos/calqlatr/calqlatr.qml
- \skipto onPressed
+ \skipto MouseArea
+ \printuntil {
+ \dots 12
+ \skipto onReleased
+ \printuntil }
\printuntil }
Unlike other QML animation types, AnimationController is not driven by
@@ -123,26 +131,63 @@
We use the easing curve of the type \c Easing.InOutQuad to accelerate the
motion until halfway and then decelerate it.
+ In Button.qml, the text colors of the number pad buttons are also animated.
+
+ \quotefromfile demos/calqlatr/content/Button.qml
+ \skipto Text
+ \printuntil id:
+ \dots 8
+ \skipto color:
+ \printuntil ]
+ \printuntil }
+
+ We use \l {QtQml::Qt::darker()}{Qt.darker()} to darken the color when the
+ button is dimmed, and \l {QtQml::Qt::lighter()}{Qt.lighter()} to \e {light up}
+ the button when pressed. The latter is done in a separate \l [QML] {State}
+ {state} called \e "pressed", which activates when the \c pressed
+ property of the button's MouseArea is set.
+
+ The color changes are animated by defining a \l Behavior on the \c color
+ property.
+
+ In order to dynamically change the \c dimmed property of all the buttons
+ of the \c NumberPad, we connect its \c buttonPressed signal to the
+ \c Button's \c updateDimmed() function in Button.qml:
+
+ \quotefromfile demos/calqlatr/content/Button.qml
+ \skipto function updateDimmed() {
+ \printuntil buttonPressed.connect
+ \printuntil }
+
+ This way, when a button is pressed, all buttons on the \c NumPad
+ receive a \c buttonPressed signal and are activated or deactivated
+ according to the state of the calculator engine.
+
\section1 Performing Calculations
- The calculator.js file contains definitions for the functions to execute
- when users press the digit and operator buttons. To use the functions, we
+ The calculator.js file defines our calculator engine. It contains variables
+ to store the calculator state, and functions that are called when the
+ user presses the digit and operator buttons. To use the engine, we
import calculator.js in the calqlatr.qml file as \c CalcEngine:
\code
import "content/calculator.js" as CalcEngine
\endcode
- We can then declare the functions to execute depending on whether the
- operator property for a button is set to \c true in NumberPad.qml:
+ Importing the engine creates a new instance of it. Therefore, we only do it
+ in the main QML file, \c calqlatr.qml. The root item defined in this file
+ contains helper functions that allow other types to access the calculator
+ engine:
\quotefromfile demos/calqlatr/calqlatr.qml
\skipto operatorPressed
- \printuntil digitPressed
+ \printuntil CalcEngine.disabled
+ \printuntil }
- When users press a digit or operator, the text from the digit appears on the
- display. When they press the equals operator (=), the appropriate
- calculation is performed, and the results appear on the display.
+ When users press a digit, the text from the digit appears on the
+ display. When they press an operator, the appropriate calculation is
+ performed, and the result can be displayed using the equals (=) operator.
+ The clear (C) operator resets the calculator engine.
\section1 List of Files
diff --git a/examples/quick/demos/clocks/doc/src/clocks.qdoc b/examples/quick/demos/clocks/doc/src/clocks.qdoc
index b57894c5d3..1118984a7d 100644
--- a/examples/quick/demos/clocks/doc/src/clocks.qdoc
+++ b/examples/quick/demos/clocks/doc/src/clocks.qdoc
@@ -29,13 +29,99 @@
\title Qt Quick Demo - Clocks
\ingroup qtquickdemos
\example demos/clocks
- \brief A QML application that shows the current time in different cities.
+ \brief A QML clock application that demonstrates using a ListView type to
+ display data generated by a ListModel and a SpringAnimation type to animate
+ images.
\image qtquick-demo-clocks-small.png
- \e Clocks demonstrates various QML and \l{Qt Quick} features such as
- displaying custom components.
+ \e Clocks demonstrates using a ListView type to display data generated by a
+ ListModel. The delegate used by the model is specified as a custom QML type
+ that is specified in the Clock.qml file.
+
+ JavaScript methods are used to fetch the current time in several cities in
+ different time zones and QML types are used to display the time on a clock
+ face with animated clock hands.
\include examples-run.qdocinc
+ \section1 Displaying Data Generated by List Models
+
+ In the clocks.qml file, we use a \l Rectangle type to create the application
+ main window:
+
+ \quotefromfile demos/clocks/clocks.qml
+ \skipto Rectangle
+ \printuntil color
+
+ We use a ListView type to display a list of the items provided by a
+ ListModel type:
+
+ \printuntil Los Angeles
+ \printuntil }
+ \printuntil }
+
+ List elements are defined like other QML types except that they contain a
+ collection of \e role definitions instead of properties. Roles both define
+ how the data is accessed and include the data itself.
+
+ For each list element, we use the \c cityName role to specify the name of a
+ city and the \c timeShift role to specify a time zone as a positive or
+ negative offset from UTC (coordinated universal time).
+
+ The Clock custom type is used as the ListView's \c delegate, defining the
+ visual appearance of list items. To use the Clock type, we add an import
+ statement that imports the folder called \c content where the type is
+ located:
+
+ \quotefromfile demos/clocks/clocks.qml
+ \skipto content
+ \printuntil "
+
+ We use an \l Image type to display arrows that indicate whether users can
+ flick the view to see more clocks on the left or right:
+
+ \quotefromfile demos/clocks/clocks.qml
+ \skipto Image
+ \printuntil /^\}/
+
+ We use the \c opacity property to hide the arrows when the list view is
+ located at the beginning or end of the x axis.
+
+ In Clock.qml, we define a \c timeChanged() function in which we use
+ methods from the JavaScript \c Date object to fetch the current time in
+ UTC and to adjust it to the correct time zone:
+
+ \quotefromfile demos/clocks/content/Clock.qml
+ \skipto timeChanged
+ \printuntil }
+
+ We use a \l Timer type to update the time at intervals of 100 milliseconds:
+
+ \printuntil }
+
+ We use \l Image types within an \l Item type to display the time on an
+ analog clock face. Different images are used for daytime and nighttime
+ hours:
+
+ \printuntil clock-night.png
+
+ A \l Rotation transform applied to \l Image types provides a way to rotate
+ the clock hands. The \c origin property holds the point that stays fixed
+ relative to the parent as the rest of the item rotates. The \c angle
+ property determines the angle to rotate the hands in degrees clockwise.
+
+ \printuntil center.png
+ \printuntil }
+
+ We use a \l Behavior type on the \c angle property to apply a
+ SpringAnimation when the time changes. The \c spring and \c damping
+ properties enable the spring-like motion of the clock hands, and a
+ \c modulus of \c 360 makes the animation target values wrap around at a
+ full circle.
+
+ We use a \l Text type to display the city name below the clock:
+
+ \printuntil }
+
\sa {QML Applications}
*/
diff --git a/examples/quick/demos/photosurface/doc/src/photosurface.qdoc b/examples/quick/demos/photosurface/doc/src/photosurface.qdoc
index b66143368e..49f864b4d9 100644
--- a/examples/quick/demos/photosurface/doc/src/photosurface.qdoc
+++ b/examples/quick/demos/photosurface/doc/src/photosurface.qdoc
@@ -53,7 +53,7 @@
\quotefromfile demos/photosurface/photosurface.qml
\skipto Window {
- \printuntil defaultSize
+ \printuntil currentFrame
To use the \l{Window} type, we must import it:
@@ -123,9 +123,7 @@
We use a PinchArea that contains a MouseArea in the photo frames to handle
dragging, rotation and pinch zooming of the frame:
- \quotefromfile demos/photosurface/photosurface.qml
- \skipto PinchArea
- \printuntil onPinchFinished
+ \printuntil onPinchStarted
We use the \c pinch group property to control how the photo frames react to
pinch gestures. The \c pinch.target sets \c photoFrame as the item to
@@ -136,18 +134,14 @@
In the MouseArea's \c onPressed signal handler, we raise the selected photo
frame to the top by increasing the value of its \c z property. The root item
stores the z value of the top-most frame. The border color of the photo
- frame is controlled in the \c onEntered and \c onExited signal handlers to
- highlight the selected image.
+ frame is controlled in the \c onEntered signal handler to highlight the
+ selected image:
- \quotefromfile demos/photosurface/photosurface.qml
- \skipto MouseArea
- \printuntil onExited
+ \printuntil onEntered
To enable you to test the example on the desktop, we use the MouseArea's
\c onWheel signal handler to simulate pinch gestures by using a mouse:
- \quotefromfile demos/photosurface/photosurface.qml
- \skipto onWheel
\printuntil photoFrame.y
\printuntil }
\printuntil }
@@ -157,7 +151,5 @@
Use the vertical wheel to zoom and Ctrl and the vertical wheel to rotate
frames. If the mouse has a horizontal wheel, use it to rotate frames.
- \section1 List of Files
-
\sa {QML Applications}
*/
diff --git a/examples/quick/demos/photosurface/photosurface.qml b/examples/quick/demos/photosurface/photosurface.qml
index 9d081de1e3..c269018426 100644
--- a/examples/quick/demos/photosurface/photosurface.qml
+++ b/examples/quick/demos/photosurface/photosurface.qml
@@ -49,6 +49,7 @@ Window {
color: "black"
property int highestZ: 0
property real defaultSize: 200
+ property var currentFrame: undefined
FileDialog {
id: fileDialog
@@ -90,15 +91,17 @@ Window {
pinch.maximumRotation: 360
pinch.minimumScale: 0.1
pinch.maximumScale: 10
- onPinchFinished: photoFrame.border.color = "black";
+ onPinchStarted: setFrameColor();
MouseArea {
id: dragArea
hoverEnabled: true
anchors.fill: parent
drag.target: photoFrame
- onPressed: photoFrame.z = ++root.highestZ;
- onEntered: photoFrame.border.color = "red";
- onExited: photoFrame.border.color = "black";
+ onPressed: {
+ photoFrame.z = ++root.highestZ;
+ parent.setFrameColor();
+ }
+ onEntered: parent.setFrameColor();
onWheel: {
if (wheel.modifiers & Qt.ControlModifier) {
photoFrame.rotation += wheel.angleDelta.y / 120 * 5;
@@ -115,6 +118,12 @@ Window {
}
}
}
+ function setFrameColor() {
+ if (currentFrame)
+ currentFrame.border.color = "black";
+ currentFrame = photoFrame;
+ currentFrame.border.color = "red";
+ }
}
}
}
diff --git a/examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc b/examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc
index 29c432be3c..ac56cb2b7a 100644
--- a/examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc
+++ b/examples/quick/demos/photoviewer/doc/src/photoviewer.qdoc
@@ -29,13 +29,298 @@
\title Qt Quick Demo - Photo Viewer
\ingroup qtquickdemos
\example demos/photoviewer
- \brief A photo viewer that displays Flickr feeds.
+ \brief A QML photo viewer that that uses XmlListModel and XmlRole to
+ download Flickr feeds, and Package to display the photos in different views.
+
\image qtquick-demo-photoviewer-small.png
- \e{Photo Viewer} demonstrates various QML and \l{Qt Quick} features such as
- displaying custom components.
+ \e{Photo Viewer} demonstrates the following \l{Qt Quick} features:
+
+ \list
+ \li Using custom types to create screens and screen controls.
+ \li Using Qt Quick Controls to create an application window.
+ \li Using the \l Package type with a \l DelegateModel to provide
+ delegates with a shared context to multiple views.
+ \li Using XML list models to download Flickr feeds.
+ \li Using the \l Flipable type to create labels with different text on
+ the front and back.
+ \li Using the PathView, \l Path, PathAttribute, and PathLine types to
+ lay out photos on a path.
+ \li Providing feedback to users while data is loading.
+ \li Localizing applications.
+ \endlist
\include examples-run.qdocinc
+ \section1 Using Custom Types
+
+ In the Photo Viewer app, we use the following custom types that are each
+ defined in a separate .qml file:
+
+ \list
+ \li \c AlbumDelegate.qml
+ \li \c BusyIndicator.qml
+ \li \c Button.qml
+ \li \c EditableButton.qml
+ \li \c PhotoDelegate.qml
+ \li \c ProgressBar.qml
+ \li \c RssModel.qml
+ \li \c Tag.qml
+ \endlist
+
+ To use the custom types, we add an import statement to the main QML file,
+ main.qml, that imports the folder called \c PhotoViewerCore where the types
+ are located:
+
+ \quotefromfile demos/photoviewer/main.qml
+ \skipto PhotoViewerCore
+ \printuntil "
+
+ \section1 Creating the Main Window
+
+ In main.qml, we use the ApplicationWindow Qt Quick Control to create the app
+ main window:
+
+ \printuntil visible
+
+ We use a ListModel type with \l ListElement types to display photo albums:
+
+ \skipto ListModel
+ \printuntil Prague
+ \printuntil }
+
+ List elements are defined like other QML types except that they contain a
+ collection of \e role definitions instead of properties. Roles both define
+ how the data is accessed and include the data itself. For each list element,
+ we use the \c tag role to specify the photos to download.
+
+ A DelegateModel type is used together with the \l Package type to provide
+ delegates to multiple views. The \c model property holds the model providing
+ data for the delegate model and the \c delegate property specifies the
+ template defining each item instantiated by a view:
+
+ \printuntil DelegateModel
+
+ We use a GridView type to lay out the albums as a grid:
+
+ \printuntil }
+
+ The \c model property references the package name \c album that we specify
+ in AlbumDelegate.qml. We use the \l Package type to allow the photos to move
+ between different views. The \l Package contains the named items \c browser,
+ \c fullscreen, and \c album:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
+ \skipto Package
+ \printuntil albumWrapper
+
+ The named items are used as the delegates by the views that reference the
+ special DelegateModel::parts property to select the model that provides
+ the chosen delegate.
+
+ We use a ListView type to lay out albums in other views:
+
+ \quotefromfile demos/photoviewer/main.qml
+ \skipto ListView
+ \printuntil }
+ \skipto ListView
+ \printuntil }
+
+ \section1 Displaying Photos
+
+ We use the PhotoDelegate custom type that is specified in PhotoDelegate.qml
+ to display photos. We use a \l Package type to lay out the photos either in
+ a stack, list, or a grid:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml
+ \skipto Package
+ \printuntil gridItem
+
+ The photos are rotated at random angles by using the \c Math.random()
+ JavaScript method:
+
+ \printuntil stackItem
+
+ We use a BorderImage type to create borders for the images:
+
+ \printuntil border.left
+ \printuntil }
+
+ \section1 Downloading Flickr Feeds
+
+ In AlbumDelegate.qml, we use the DelegateModel to provide the
+ PhotoDelegate delegate to the RssModel model:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
+ \skipto DelegateModel
+ \printuntil RssModel
+ \printuntil }
+
+ In RssModel.qml, we use an XmlListModel type as a data source for
+ \l Package objects to download photos from the selected feeds:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/RssModel.qml
+ \skipto XmlListModel
+ \printuntil encodeTags
+
+ We use the \c tags custom property to specify which photos to download. The
+ \c encodeTags custom function uses the \c encodeURIComponent JavaScript
+ method to ensure that the requests to the server are correctly formatted.
+
+ We use the \c source property to fetch photos that have the specified tags
+ attached from public Flickr feeds:
+
+ \printuntil namespaceDeclarations
+
+ The \c query property specifies that the XmlListModel generates a model item
+ for each feed entry.
+
+ The \c namespaceDeclarations property specifies that the requested document
+ uses the namespace \c{http://www.w3.org/2005/Atom}, which is declared as the
+ default namespace.
+
+ We use the XmlRole type to specify the model item attributes. Each model
+ item has the \c title, \c content, and \c hq attributes that match the
+ values of the corresponding feed entry:
+
+ \printuntil hq
+
+ \section1 Creating Flipable Labels
+
+ When users select the \b Edit button, the album labels are flipped from
+ their front side to their back side and the text on them changes from album
+ name to \b Remove.
+
+ In AlbumDelegate.qml, we use the Tag custom type to specify the text to
+ display on the front and back sides of album labels:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
+ \skipto Tag
+ \printuntil onBackClicked
+ \printuntil }
+
+ The \c onTagChanged signal handler is used to change the tag based on
+ which the model is populated. The \c onBackClicked signal handler is used to
+ remove the album.
+
+ In Tag.qml, we use a \l Flipable type with custom properties and signals to
+ create the labels:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/Tag.qml
+ \skipto Flipable
+ \printuntil tagChanged
+
+ The \c front property holds the EditableButton custom type that enables
+ users to edit the label text:
+
+ \printuntil onLabelChanged
+ \printuntil }
+
+ The \c back property holds the \c Button custom type that is used to remove
+ the album:
+
+ \printuntil onClicked
+ \printuntil }
+
+ \section1 Laying out Photos on a Path
+
+ In AlbumDelegate.qml, we use a PathView type to lay out the photos provided
+ by the \c visualModel.parts.stack model on a path that has the form of a
+ stack:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
+ \skipto PathView
+ \printuntil 0.0
+ \printuntil }
+ \printuntil }
+
+ The \c path property holds the \l Path type that defines the path used by
+ the PathView. The PathAttribute types are used to set a range of
+ \c 0 to \c 9999 for the \c z attribute. This way, the path creates a stack
+ of album photos. Because each PhotoDelegate is slightly rotated at a random
+ angle, this results in a realistic-looking stack of photos.
+
+ \section1 Providing Feedback to Users
+
+ We use a busy indicator and a progress bar to indicate activity while
+ Flickr feeds and photos are being loaded.
+
+ In AlbumDelegate.qml, we use the \c BusyIndicator custom type and the
+ \c on custom property to display a rotating image while the Flickr feed is
+ being loaded:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/AlbumDelegate.qml
+ \skipto BusyIndicator
+ \printuntil rssModel
+ \printuntil }
+
+ In PhotoDelegate.qml, we use them to indicate activity while a photo is
+ being loaded:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/PhotoDelegate.qml
+ \skipto BusyIndicator
+ \printuntil }
+
+ We define the \c BusyIndicator type in \c BusyIndicator.qml. We use an
+ \l Image type to display an image and apply a NumberAnimation to its
+ \c rotation property to rotate the image in an infinite loop:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/BusyIndicator.qml
+ \skipto Image
+ \printuntil }
+ \printuntil }
+
+ In your apps, you can also use the BusyIndicator type from the
+ \l {Qt Quick Controls} module.
+
+ In main.qml, we use the \c ProgressBar custom type to indicate progress
+ while a high quality version of a photo is being opened on full screen:
+
+ \quotefromfile demos/photoviewer/main.qml
+ \skipto ProgressBar
+ \printuntil }
+
+ We define the \c ProgressBar type in \c ProgressBar.qml. We use a
+ \l Rectangle type to create the progress bar and apply a NumberAnimation to
+ its \c opacity property to change the color of the bar from black to white
+ as data loading proceeds:
+
+ \quotefromfile demos/photoviewer/PhotoViewerCore/ProgressBar.qml
+ \skipto Item
+ \printuntil /^\}/
+
+ In your apps, you can also use the ProgressBar type from the
+ \l {Qt Quick Controls} module.
+
+ \section1 Localizing Applications
+
+ The example application is translated into German and French. The translated
+ strings are loaded at runtime according to the current locale.
+
+ We use a \l Column type in main.qml to position buttons for adding and
+ editing albums and exiting the application:
+
+ \quotefromfile demos/photoviewer/main.qml
+ \skipto Column
+ \printuntil quit()
+ \printuntil }
+ \printuntil }
+
+ We use the \l qsTr() command to mark the button labels translatable.
+
+ We use the \l lupdate tool to generate the translation source files and
+ the \l lrelease tool to convert the translated strings to the QM files used
+ by the application at runtime. These files are stored in the \c i18n
+ directory.
+
+ To make the application aware of the translations, we add code to the
+ \c main() function in the main.cpp file. The code creates a \l QTranslator
+ object, loads a translation according to the current locale at runtime, and
+ installs the translator object into the application:
+
+ \quotefromfile demos/photoviewer/main.cpp
+ \skipto main
+ \printuntil app.installTranslator
+
\sa {QML Applications}
*/
diff --git a/examples/quick/demos/photoviewer/main.cpp b/examples/quick/demos/photoviewer/main.cpp
index ca495242a4..1351f043f3 100644
--- a/examples/quick/demos/photoviewer/main.cpp
+++ b/examples/quick/demos/photoviewer/main.cpp
@@ -40,8 +40,9 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+ QLocale locale;
QTranslator qtTranslator;
- qtTranslator.load("qml_" + QLocale::system().name(), ":/i18n/");
+ qtTranslator.load(locale, QLatin1String("qml"), QLatin1String("_"), QLatin1String(":/i18n"));
app.installTranslator(&qtTranslator);
QQmlApplicationEngine engine;
diff --git a/examples/quick/demos/stocqt/content/StockChart.qml b/examples/quick/demos/stocqt/content/StockChart.qml
index 2b97863f76..625a91e6f9 100644
--- a/examples/quick/demos/stocqt/content/StockChart.qml
+++ b/examples/quick/demos/stocqt/content/StockChart.qml
@@ -168,7 +168,7 @@ Rectangle {
property int pixelSkip: 1
property int numPoints: 1
- property int tickMargin: 32
+ property int tickMargin: 34
property real xGridStep: (width - tickMargin) / numPoints
property real yGridOffset: height / 26
@@ -214,6 +214,21 @@ Rectangle {
ctx.restore();
}
+ // Returns a shortened, readable version of the potentially
+ // large volume number.
+ function volumeToString(value) {
+ if (value < 1000)
+ return value;
+ var exponent = parseInt(Math.log(value) / Math.log(1000));
+ var shortVal = parseFloat(parseFloat(value) / Math.pow(1000, exponent)).toFixed(1);
+
+ // Drop the decimal point on 3-digit values to make it fit
+ if (shortVal >= 100.0) {
+ shortVal = parseFloat(shortVal).toFixed(0);
+ }
+ return shortVal + "KMBTG".charAt(exponent - 1);
+ }
+
function drawScales(ctx, high, low, vol)
{
ctx.save();
@@ -229,8 +244,11 @@ Rectangle {
ctx.text(price, x, canvas.yGridOffset + i * yGridStep - 2);
}
- // highest volume
- ctx.text(vol, 0, canvas.yGridOffset + 9 * yGridStep + 12);
+ // volume scale
+ for (i = 0; i < 3; i++) {
+ var volume = volumeToString(vol - (i * (vol/3)));
+ ctx.text(volume, x, canvas.yGridOffset + (i + 9) * yGridStep + 10);
+ }
ctx.closePath();
ctx.stroke();
diff --git a/examples/quick/demos/stocqt/doc/src/stocqt.qdoc b/examples/quick/demos/stocqt/doc/src/stocqt.qdoc
index 5f090e84f9..5e5ba3caf5 100644
--- a/examples/quick/demos/stocqt/doc/src/stocqt.qdoc
+++ b/examples/quick/demos/stocqt/doc/src/stocqt.qdoc
@@ -32,8 +32,53 @@
\brief A configurable stock chart for the NASDAQ-100.
\image qtquick-demo-stocqt.png
- \e{StocQt} demonstrates various QML and \l{Qt Quick} features such as
- displaying custom components and downloading data from the internet.
+ The \e{StocQt} application presents a trend chart for the first stock in
+ the list of NASDAQ-100 stocks maintained by it. It allows the user to
+ choose another stock from the list, and fetches the required data for
+ the selected stock by sending an \c XMLHttpRequest to
+ http://finance.yahoo.com.
+
+ The application uses several custom types such as Button, CheckBox,
+ StockChart, StockInfo, StockView, and so on. These types are used to
+ present the stock data in a readable form and also let the user customize
+ the trend chart. For example, the user can choose to view the yearly,
+ monthly, or daily trends in the stock price.
+
+ The application uses the ObjectModel type to access the two visual data
+ models that it depends on.
+
+ \quotefromfile demos/stocqt/stocqt.qml
+ \skipto ListView
+ \printuntil id
+ \dots 8
+ \skipto model
+ \printuntil StockView
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ The StockListView model is a static data model listing the
+ NASDAQ-100 stocks with basic information such as stockId, name, value,
+ change, and so on. This data model is used by the application if the
+ user wants to choose another stock from the list.
+
+ StockView is a complex data model that presents a trend chart for the
+ selected stock. It uses another custom type, StockChart, which presents
+ the graphical trend of the stock price using a Canvas. This data model
+ is used for most of the time during the lifetime of the application.
+
+ \quotefromfile demos/stocqt/content/StockChart.qml
+ \skipto Rectangle
+ \printuntil height
+ \dots
+ \skipto Canvas
+ \printuntil id
+ \dots 8
+ \skipto onPaint
+ \printuntil /^\}$/
+
+ To understand the application better, browse through its code using
+ Qt Creator.
\include examples-run.qdocinc
diff --git a/examples/quick/demos/tweetsearch/content/SearchDelegate.qml b/examples/quick/demos/tweetsearch/content/SearchDelegate.qml
index cb0e190fe8..669021a582 100644
--- a/examples/quick/demos/tweetsearch/content/SearchDelegate.qml
+++ b/examples/quick/demos/tweetsearch/content/SearchDelegate.qml
@@ -113,7 +113,11 @@ FlipBar {
hint: flipBar.placeHolder
focus: flipBar.opened
anchors { fill: parent; margins: 6 }
- onAccepted: flipBar.ok()
+ onAccepted: {
+ if (Qt.inputMethod.visible)
+ Qt.inputMethod.hide()
+ flipBar.ok()
+ }
}
}
}
diff --git a/examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc b/examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc
index cdf4cadf82..d823074b37 100644
--- a/examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc
+++ b/examples/quick/painteditem/textballoons/doc/src/textballoons.qdoc
@@ -83,7 +83,7 @@
returned by the \l {QQuickPaintedItem::}{contentsBoundingRect()} function is the size
of the item as defined in the QML file.
- \section1 textballoons.qml file
+ \section1 Textballoons.qml File
The Interface consists of two main parts. The scrollable area with the
textballoons and the controls button to add new balloons.
diff --git a/examples/quick/rendercontrol/window.cpp b/examples/quick/rendercontrol/window.cpp
index 396e9f8afa..4813936538 100644
--- a/examples/quick/rendercontrol/window.cpp
+++ b/examples/quick/rendercontrol/window.cpp
@@ -111,8 +111,11 @@ Window::Window()
Window::~Window()
{
- // Make sure the context is current while doing cleanup.
- m_context->makeCurrent(this);
+ // Make sure the context is current while doing cleanup. Note that we use the
+ // offscreen surface here because passing 'this' at this point is not safe: the
+ // underlying platform window may already be destroyed. To avoid all the trouble, use
+ // another surface that is valid for sure.
+ m_context->makeCurrent(m_offscreenSurface);
// Delete the render control first since it will free the scenegraph resources.
// Destroy the QQuickWindow only afterwards.
diff --git a/examples/quick/text/doc/src/text.qdoc b/examples/quick/text/doc/src/text.qdoc
index 8ef79ab9d9..e882ba3535 100644
--- a/examples/quick/text/doc/src/text.qdoc
+++ b/examples/quick/text/doc/src/text.qdoc
@@ -73,7 +73,7 @@
\e Banner is a simple example showing how to create a banner using a row of
text types and a \l NumberAnimation.
- \section1 Img tag
+ \section1 Img Tag
\e{Img tag} shows different ways of displaying images in text objects using
the \c{<img>} tag.
diff --git a/examples/quick/window/main.cpp b/examples/quick/window/main.cpp
index 7872c7183c..953b87e047 100644
--- a/examples/quick/window/main.cpp
+++ b/examples/quick/window/main.cpp
@@ -39,6 +39,7 @@
****************************************************************************/
#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtQuick/QQuickWindow>
@@ -48,6 +49,9 @@
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
+ foreach (QScreen * screen, QGuiApplication::screens())
+ screen->setOrientationUpdateMask(Qt::LandscapeOrientation | Qt::PortraitOrientation |
+ Qt::InvertedLandscapeOrientation | Qt::InvertedPortraitOrientation);
QQmlEngine engine;
QQmlComponent component(&engine);
QQuickWindow::setDefaultAlphaBuffer(true);
diff --git a/src/imports/statemachine/childrenprivate.h b/src/imports/statemachine/childrenprivate.h
index 5e2d60e299..d66454ca1c 100644
--- a/src/imports/statemachine/childrenprivate.h
+++ b/src/imports/statemachine/childrenprivate.h
@@ -51,9 +51,6 @@ public:
{
QAbstractState *state = qobject_cast<QAbstractState*>(item);
if (state) {
- if (qobject_cast<QStateMachine*>(item))
- qmlInfo(static_cast<T *>(prop->object)) << "StateMachines should not be nested.";
-
item->setParent(prop->object);
} else {
QAbstractTransition *trans = qobject_cast<QAbstractTransition*>(item);
@@ -68,9 +65,6 @@ public:
{
QAbstractState *state = qobject_cast<QAbstractState*>(item);
if (state) {
- if (qobject_cast<QStateMachine*>(item))
- qmlInfo(static_cast<T *>(prop->object)) << "StateMachines should not be nested.";
-
item->setParent(prop->object);
}
static_cast<ChildrenPrivate<T>*>(prop->data)->children.append(item);
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 8d9f6822f4..700c9112eb 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -633,17 +633,45 @@ Item {
\since 5.4
\qmlmethod QtObject TestCase::findChild(parent, objectName)
- Returns the first child of \a parent with \a objectName,
- or \c null if no such item exists. Children are searched recursively.
+ Returns the first child of \a parent with \a objectName, or \c null if
+ no such item exists. Both visual and non-visual children are searched
+ recursively, with visual children being searched first.
\code
compare(findChild(item, "childObject"), expectedChildObject);
\endcode
*/
function findChild(parent, objectName) {
+ // First, search the visual item hierarchy.
+ var child = qtest_findVisualChild(parent, objectName);
+ if (child)
+ return child;
+
+ // If it's not a visual child, it might be a QObject child.
return qtest_results.findChild(parent, objectName);
}
+ /*! \internal */
+ function qtest_findVisualChild(parent, objectName) {
+ if (!parent || parent.children === undefined)
+ return null;
+
+ for (var i = 0; i < parent.children.length; ++i) {
+ // Is this direct child of ours the child we're after?
+ var child = parent.children[i];
+ if (child.objectName === objectName)
+ return child;
+ }
+
+ for (i = 0; i < parent.children.length; ++i) {
+ // Try the direct child's children.
+ child = qtest_findVisualChild(parent.children[i], objectName);
+ if (child)
+ return child;
+ }
+ return null;
+ }
+
/*!
\qmlmethod TestCase::tryCompare(obj, property, expected, timeout = 5000, message = "")
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index 08d3142701..60a67d55a6 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -1223,6 +1223,9 @@ void QQuickImageParticle::buildParticleNodes(QSGNode** passThrough)
void QQuickImageParticle::finishBuildParticleNodes(QSGNode** node)
{
+ if (!QOpenGLContext::currentContext())
+ return;
+
if (QOpenGLContext::currentContext()->isOpenGLES() && m_count * 4 > 0xffff) {
printf("ImageParticle: Too many particles - maximum 16,000 per ImageParticle.\n");//ES 2 vertex count limit is ushort
return;
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 34db06ca4c..a96fafac9b 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1523,7 +1523,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
objectsSize += signalTableSize;
}
- const int totalSize = unitSize + importSize + objectOffsetTableSize + objectsSize;
+ const int totalSize = unitSize + importSize + objectOffsetTableSize + objectsSize + output.jsGenerator.stringTable.sizeOfTableAndData();
char *data = (char*)malloc(totalSize);
memcpy(data, jsUnit, unitSize);
if (jsUnit != compilationUnit->data)
@@ -1539,6 +1539,8 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
qmlUnit->offsetToObjects = unitSize + importSize;
qmlUnit->nObjects = output.objects.count();
qmlUnit->indexOfRootObject = output.indexOfRootObject;
+ qmlUnit->offsetToStringTable = totalSize - output.jsGenerator.stringTable.sizeOfTableAndData();
+ qmlUnit->stringTableSize = output.jsGenerator.stringTable.stringCount();
// write imports
char *importPtr = data + qmlUnit->offsetToImports;
@@ -1630,6 +1632,8 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
}
}
+ output.jsGenerator.stringTable.serialize(qmlUnit);
+
return qmlUnit;
}
@@ -1805,13 +1809,14 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
}
if (type->isCompositeSingleton()) {
- QQmlTypeData *tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url);
+ QQmlRefPointer<QQmlTypeData> tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url);
Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
- initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId));
- tdata->release();
- resolver->flags |= AllPropertiesAreFinal;
- return resolver->resolveMember(qmlEngine, resolver, member);
+ // When a singleton tries to reference itself, it may not be complete yet.
+ if (tdata->isComplete()) {
+ initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId));
+ resolver->flags |= AllPropertiesAreFinal;
+ return resolver->resolveMember(qmlEngine, resolver, member);
+ }
} else if (type->isSingleton()) {
const QMetaObject *singletonMeta = type->singletonInstanceInfo()->instanceMetaObject;
if (singletonMeta) { // QJSValue-based singletons cannot be accelerated
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 90f775f781..13367efc3d 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -571,7 +571,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
QV4::CompiledData::Property::Type dtype;
int metaType;
} builtinTypes[] = {
- { QV4::CompiledData::Property::Var, qMetaTypeId<QJSValue>() },
+ { QV4::CompiledData::Property::Var, QMetaType::QVariant },
{ QV4::CompiledData::Property::Variant, QMetaType::QVariant },
{ QV4::CompiledData::Property::Int, QMetaType::Int },
{ QV4::CompiledData::Property::Bool, QMetaType::Bool },
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index a5530e167d..d242fb7b3a 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -181,7 +181,7 @@ void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
{
- return irDocument->jsGenerator.generateUnit();
+ return irDocument->jsGenerator.generateUnit(QV4::Compiler::JSUnitGenerator::GenerateWithoutStringTable);
}
QString Binding::valueAsString(const Unit *unit) const
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index d6f0bc8335..22107c4bd1 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -66,8 +66,11 @@ void QV4::Compiler::StringTableGenerator::clear()
stringDataSize = 0;
}
-void QV4::Compiler::StringTableGenerator::serialize(uint *stringTable, char *dataStart, char *stringData)
+void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit)
{
+ char *dataStart = reinterpret_cast<char *>(unit);
+ uint *stringTable = reinterpret_cast<uint *>(dataStart + unit->offsetToStringTable);
+ char *stringData = dataStart + unit->offsetToStringTable + unit->stringTableSize * sizeof(uint);
for (int i = 0; i < strings.size(); ++i) {
stringTable[i] = stringData - dataStart;
const QString &qstr = strings.at(i);
@@ -190,7 +193,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *arg
return jsClasses.size() - 1;
}
-QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
+QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorOption option)
{
registerString(irModule->fileName);
foreach (QV4::IR::Function *f, irModule->functions) {
@@ -214,7 +217,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
functionDataSize += QV4::CompiledData::Function::calculateSize(f->formals.size(), f->locals.size(), f->nestedFunctions.size(), qmlIdDepsCount, qmlPropertyDepsCount);
}
- const int totalSize = unitSize + functionDataSize + jsClassDataSize + stringTable.sizeOfTableAndData();
+ const int totalSize = unitSize + functionDataSize + jsClassDataSize + (option == GenerateWithStringTable ? stringTable.sizeOfTableAndData() : 0);
char *data = (char *)malloc(totalSize);
memset(data, 0, totalSize);
QV4::CompiledData::Unit *unit = (QV4::CompiledData::Unit*)data;
@@ -234,8 +237,13 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
unit->offsetToConstantTable = unit->offsetToRegexpTable + unit->regexpTableSize * CompiledData::RegExp::calculateSize();
unit->jsClassTableSize = jsClasses.count();
unit->offsetToJSClassTable = unit->offsetToConstantTable + unit->constantTableSize * sizeof(ReturnedValue);
- unit->stringTableSize = stringTable.stringCount();
- unit->offsetToStringTable = unitSize + functionDataSize + jsClassDataSize;
+ if (option == GenerateWithStringTable) {
+ unit->stringTableSize = stringTable.stringCount();
+ unit->offsetToStringTable = unitSize + functionDataSize + jsClassDataSize;
+ } else {
+ unit->stringTableSize = 0;
+ unit->offsetToStringTable = 0;
+ }
unit->indexOfRootFunction = -1;
unit->sourceFileIndex = getStringId(irModule->fileName);
unit->nImports = 0;
@@ -287,11 +295,8 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
}
// write strings and string table
- {
- uint *stringTablePtr = (uint *)(data + unit->offsetToStringTable);
- char *string = data + unit->offsetToStringTable + unit->stringTableSize * sizeof(uint);
- stringTable.serialize(stringTablePtr, data, string);
- }
+ if (option == GenerateWithStringTable)
+ stringTable.serialize(unit);
return unit;
}
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 109998dc33..7b349caaf8 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -63,7 +63,7 @@ struct Q_QML_PRIVATE_EXPORT StringTableGenerator {
void clear();
- void serialize(uint *stringTable, char *dataStart, char *stringData);
+ void serialize(CompiledData::Unit *unit);
private:
QHash<QString, int> stringToId;
@@ -90,7 +90,12 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
int registerJSClass(int count, IR::ExprList *args);
- QV4::CompiledData::Unit *generateUnit();
+ enum GeneratorOption {
+ GenerateWithStringTable,
+ GenerateWithoutStringTable
+ };
+
+ QV4::CompiledData::Unit *generateUnit(GeneratorOption option = GenerateWithStringTable);
// Returns bytes written
int writeFunction(char *f, int index, IR::Function *irFunction);
diff --git a/src/qml/debugger/qqmlabstractprofileradapter.cpp b/src/qml/debugger/qqmlabstractprofileradapter.cpp
index 1267503226..165772335a 100644
--- a/src/qml/debugger/qqmlabstractprofileradapter.cpp
+++ b/src/qml/debugger/qqmlabstractprofileradapter.cpp
@@ -69,13 +69,13 @@ QT_BEGIN_NAMESPACE
* If the profiler's thread is waiting for an initial start signal we can emit the signal over a
* \c Qt::DirectConnection to avoid the delay of the event loop.
*/
-void QQmlAbstractProfilerAdapter::startProfiling()
+void QQmlAbstractProfilerAdapter::startProfiling(quint64 features)
{
if (waiting)
- emit profilingEnabledWhileWaiting();
+ emit profilingEnabledWhileWaiting(features);
else
- emit profilingEnabled();
- running = true;
+ emit profilingEnabled(features);
+ featuresEnabled = features;
}
/*!
@@ -90,7 +90,7 @@ void QQmlAbstractProfilerAdapter::stopProfiling() {
emit profilingDisabledWhileWaiting();
else
emit profilingDisabled();
- running = false;
+ featuresEnabled = 0;
}
/*!
diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h
index f06d51e8f7..03f6645178 100644
--- a/src/qml/debugger/qqmlabstractprofileradapter_p.h
+++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h
@@ -59,12 +59,12 @@ class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapter : public QObject, public
public:
QQmlAbstractProfilerAdapter(QQmlProfilerService *service) :
- service(service), waiting(true), running(false) {}
+ service(service), waiting(true), featuresEnabled(0) {}
virtual ~QQmlAbstractProfilerAdapter() {}
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0;
- void startProfiling();
+ void startProfiling(quint64 features);
void stopProfiling();
@@ -73,13 +73,14 @@ public:
void stopWaiting() { waiting = false; }
void startWaiting() { waiting = true; }
- bool isRunning() const { return running; }
+ bool isRunning() const { return featuresEnabled != 0; }
+ quint64 features() const { return featuresEnabled; }
void synchronize(const QElapsedTimer &t) { emit referenceTimeKnown(t); }
signals:
- void profilingEnabled();
- void profilingEnabledWhileWaiting();
+ void profilingEnabled(quint64 features);
+ void profilingEnabledWhileWaiting(quint64 features);
void profilingDisabled();
void profilingDisabledWhileWaiting();
@@ -92,7 +93,7 @@ protected:
private:
bool waiting;
- bool running;
+ quint64 featuresEnabled;
};
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp
index 399cc3e07d..cb533a0459 100644
--- a/src/qml/debugger/qqmlenginedebugservice.cpp
+++ b/src/qml/debugger/qqmlenginedebugservice.cpp
@@ -169,9 +169,13 @@ QQmlEngineDebugService::propertyData(QObject *obj, int propIdx)
return rv;
}
-QVariant QQmlEngineDebugService::valueContents(const QVariant &value) const
+QVariant QQmlEngineDebugService::valueContents(QVariant value) const
{
- int userType = value.userType();
+ // We can't send JS objects across the wire, so transform them to variant
+ // maps for serialization.
+ if (value.userType() == qMetaTypeId<QJSValue>())
+ value = value.value<QJSValue>().toVariant();
+ const int userType = value.userType();
//QObject * is not streamable.
//Convert all such instances to a String value
diff --git a/src/qml/debugger/qqmlenginedebugservice_p.h b/src/qml/debugger/qqmlenginedebugservice_p.h
index 1bab51d17b..940ca7d99c 100644
--- a/src/qml/debugger/qqmlenginedebugservice_p.h
+++ b/src/qml/debugger/qqmlenginedebugservice_p.h
@@ -111,7 +111,7 @@ private:
void buildStatesList(bool cleanList, const QList<QPointer<QObject> > &instances);
QQmlObjectData objectData(QObject *);
QQmlObjectProperty propertyData(QObject *, int);
- QVariant valueContents(const QVariant &defaultValue) const;
+ QVariant valueContents(QVariant defaultValue) const;
bool setBinding(int objectId, const QString &propertyName, const QVariant &expression, bool isLiteralValue, QString filename = QString(), int line = -1, int column = 0);
bool resetBinding(int objectId, const QString &propertyName);
bool setMethodBody(int objectId, const QString &method, const QString &body);
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index 3a647e704d..b102201ff1 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -82,9 +82,9 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
QQmlAbstractProfilerAdapter(service)
{
engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled()), engine->profiler, SLOT(startProfiling()));
- connect(this, SIGNAL(profilingEnabledWhileWaiting()),
- engine->profiler, SLOT(startProfiling()), Qt::DirectConnection);
+ connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
+ connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
+ engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
@@ -111,21 +111,21 @@ void QQmlProfilerAdapter::receiveData(const QList<QQmlProfilerData> &new_data)
}
-QQmlProfiler::QQmlProfiler() : enabled(false)
+QQmlProfiler::QQmlProfiler() : featuresEnabled(0)
{
static int metatype = qRegisterMetaType<QList<QQmlProfilerData> >();
Q_UNUSED(metatype);
m_timer.start();
}
-void QQmlProfiler::startProfiling()
+void QQmlProfiler::startProfiling(quint64 features)
{
- enabled = true;
+ featuresEnabled = features;
}
void QQmlProfiler::stopProfiling()
{
- enabled = false;
+ featuresEnabled = false;
reportData();
m_data.clear();
}
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 02cdbf0a4e..13e6b8ddae 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -56,14 +56,14 @@
QT_BEGIN_NAMESPACE
-#define Q_QML_PROFILE_IF_ENABLED(profiler, Code)\
- if (profiler && profiler->enabled) {\
+#define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code)\
+ if (profiler && (profiler->featuresEnabled & (1 << feature))) {\
Code;\
} else\
(void)0
-#define Q_QML_PROFILE(profiler, Method)\
- Q_QML_PROFILE_IF_ENABLED(profiler, profiler->Method)
+#define Q_QML_PROFILE(feature, profiler, Method)\
+ Q_QML_PROFILE_IF_ENABLED(feature, profiler, profiler->Method)
// This struct is somewhat dangerous to use:
// The messageType is a bit field. You can pack multiple messages into
@@ -162,10 +162,10 @@ public:
QQmlProfiler();
- bool enabled;
+ quint64 featuresEnabled;
public slots:
- void startProfiling();
+ void startProfiling(quint64 features);
void stopProfiling();
void reportData();
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
@@ -204,12 +204,14 @@ struct QQmlBindingProfiler : public QQmlProfilerHelper {
QQmlBindingProfiler(QQmlProfiler *profiler, const QString &url, int line, int column) :
QQmlProfilerHelper(profiler)
{
- Q_QML_PROFILE(profiler, startBinding(url, line, column));
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
+ startBinding(url, line, column));
}
~QQmlBindingProfiler()
{
- Q_QML_PROFILE(profiler, endRange<Binding>());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
+ endRange<Binding>());
}
};
@@ -217,12 +219,14 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
QQmlHandlingSignalProfiler(QQmlProfiler *profiler, QQmlBoundSignalExpression *expression) :
QQmlProfilerHelper(profiler)
{
- Q_QML_PROFILE(profiler, startHandlingSignal(expression->sourceLocation()));
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler,
+ startHandlingSignal(expression->sourceLocation()));
}
~QQmlHandlingSignalProfiler()
{
- Q_QML_PROFILE(profiler, endRange<QQmlProfiler::HandlingSignal>());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler,
+ endRange<QQmlProfiler::HandlingSignal>());
}
};
@@ -230,12 +234,12 @@ struct QQmlCompilingProfiler : public QQmlProfilerHelper {
QQmlCompilingProfiler(QQmlProfiler *profiler, const QString &name) :
QQmlProfilerHelper(profiler)
{
- Q_QML_PROFILE(profiler, startCompiling(name));
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(name));
}
~QQmlCompilingProfiler()
{
- Q_QML_PROFILE(profiler, endRange<Compiling>());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, endRange<Compiling>());
}
};
@@ -278,20 +282,20 @@ private:
QFiniteStack<Data> ranges;
};
-#define Q_QML_OC_PROFILE(profilerMember, Code)\
- Q_QML_PROFILE_IF_ENABLED(profilerMember.profiler, Code)
+#define Q_QML_OC_PROFILE(member, Code)\
+ Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
class QQmlObjectCreationProfiler : public QQmlVmeProfiler::Data {
public:
QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
{
- Q_QML_PROFILE(profiler, startCreating());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating());
}
~QQmlObjectCreationProfiler()
{
- Q_QML_PROFILE(profiler, endRange<QQmlProfilerDefinitions::Creating>());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>());
}
void update(const QString &typeName, const QUrl &url, int line, int column)
@@ -312,7 +316,7 @@ public:
QQmlObjectCompletionProfiler(QQmlVmeProfiler *parent) :
profiler(parent->profiler)
{
- Q_QML_PROFILE_IF_ENABLED(profiler, {
+ Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler, {
QQmlVmeProfiler::Data data = parent->pop();
profiler->startCreating(data.m_typeName, data.m_url, data.m_line, data.m_column);
});
@@ -320,7 +324,8 @@ public:
~QQmlObjectCompletionProfiler()
{
- Q_QML_PROFILE(profiler, endRange<QQmlProfilerDefinitions::Creating>());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler,
+ endRange<QQmlProfilerDefinitions::Creating>());
}
private:
QQmlProfiler *profiler;
diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h
index 7abff8857e..713134f394 100644
--- a/src/qml/debugger/qqmlprofilerdefinitions_p.h
+++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h
@@ -124,6 +124,22 @@ struct QQmlProfilerDefinitions {
};
typedef QV4::Profiling::MemoryType MemoryType;
+
+ enum ProfileFeature {
+ ProfileJavaScript = QV4::Profiling::FeatureFunctionCall,
+ ProfileMemory = QV4::Profiling::FeatureMemoryAllocation,
+ ProfilePixmapCache,
+ ProfileSceneGraph,
+ ProfileAnimations,
+ ProfilePainting,
+ ProfileCompiling,
+ ProfileCreating,
+ ProfileBinding,
+ ProfileHandlingSignal,
+ ProfileInputEvents,
+
+ MaximumProfileFeature
+ };
};
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
index 6157d2f191..5ec8178f32 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/qml/debugger/qqmlprofilerservice.cpp
@@ -171,12 +171,12 @@ void QQmlProfilerService::addGlobalProfiler(QQmlAbstractProfilerAdapter *profile
// Global profiler, not connected to a specific engine.
// Global profilers are started whenever any engine profiler is started and stopped when
// all engine profilers are stopped.
- foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers) {
- if (engineProfiler->isRunning()) {
- profiler->startProfiling();
- break;
- }
- }
+ quint64 features = 0;
+ foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers)
+ features |= engineProfiler->features();
+
+ if (features != 0)
+ profiler->startProfiling(features);
}
void QQmlProfilerService::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler)
@@ -206,7 +206,7 @@ void QQmlProfilerService::removeProfilerFromStartTimes(const QQmlAbstractProfile
*
* If any engine profiler is started like that also start all global profilers.
*/
-void QQmlProfilerService::startProfiling(QQmlEngine *engine)
+void QQmlProfilerService::startProfiling(QQmlEngine *engine, quint64 features)
{
QMutexLocker lock(configMutex());
@@ -218,7 +218,7 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine)
if (engine != 0) {
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) {
if (!profiler->isRunning()) {
- profiler->startProfiling();
+ profiler->startProfiling(features);
startedAny = true;
}
}
@@ -230,7 +230,7 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine)
i != m_engineProfilers.end(); ++i) {
if (!i.value()->isRunning()) {
engines << i.key();
- i.value()->startProfiling();
+ i.value()->startProfiling(features);
startedAny = true;
}
}
@@ -241,7 +241,7 @@ void QQmlProfilerService::startProfiling(QQmlEngine *engine)
if (startedAny) {
foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
if (!profiler->isRunning())
- profiler->startProfiling();
+ profiler->startProfiling(features);
}
}
@@ -359,14 +359,17 @@ void QQmlProfilerService::messageReceived(const QByteArray &message)
QQmlDebugStream stream(&rwData, QIODevice::ReadOnly);
int engineId = -1;
+ quint64 features = std::numeric_limits<quint64>::max();
bool enabled;
stream >> enabled;
if (!stream.atEnd())
stream >> engineId;
+ if (!stream.atEnd())
+ stream >> features;
// If engineId == -1 objectForId() and then the cast will return 0.
if (enabled)
- startProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)));
+ startProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)), features);
else
stopProfiling(qobject_cast<QQmlEngine *>(objectForId(engineId)));
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index 5405905861..c4c40adc4f 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -78,8 +78,8 @@ public:
void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler);
- void startProfiling(QQmlEngine *engine = 0);
- void stopProfiling(QQmlEngine *engine = 0);
+ void startProfiling(QQmlEngine *engine, quint64 features = std::numeric_limits<quint64>::max());
+ void stopProfiling(QQmlEngine *engine);
QQmlProfilerService();
~QQmlProfilerService();
diff --git a/src/qml/debugger/qv4profileradapter.cpp b/src/qml/debugger/qv4profileradapter.cpp
index 19a6ea3e74..a5492ce805 100644
--- a/src/qml/debugger/qv4profileradapter.cpp
+++ b/src/qml/debugger/qv4profileradapter.cpp
@@ -41,9 +41,10 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
QQmlAbstractProfilerAdapter(service)
{
engine->enableProfiler();
- connect(this, SIGNAL(profilingEnabled()), engine->profiler, SLOT(startProfiling()));
- connect(this, SIGNAL(profilingEnabledWhileWaiting()), engine->profiler, SLOT(startProfiling()),
- Qt::DirectConnection);
+ connect(this, SIGNAL(profilingEnabled(quint64)),
+ engine->profiler, SLOT(startProfiling(quint64)));
+ connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
+ engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
Qt::DirectConnection);
diff --git a/src/qml/doc/snippets/code/src_script_qjsengine.cpp b/src/qml/doc/snippets/code/src_script_qjsengine.cpp
index b836fabf3d..7428cedcaf 100644
--- a/src/qml/doc/snippets/code/src_script_qjsengine.cpp
+++ b/src/qml/doc/snippets/code/src_script_qjsengine.cpp
@@ -79,12 +79,12 @@ if (result.isError())
//! [5]
-QPushButton button;
-QJSValue scriptButton = myEngine.newQObject(&button);
+QPushButton *button = new QPushButton;
+QJSValue scriptButton = myEngine.newQObject(button);
myEngine.globalObject().setProperty("button", scriptButton);
myEngine.evaluate("button.checkable = true");
-qDebug() << scriptButton.property("checkable").toBoolean();
+qDebug() << scriptButton.property("checkable").toBool();
scriptButton.property("show").call(); // call the show() slot
//! [5]
diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc
index 6aed2f1339..03607df2e5 100644
--- a/src/qml/doc/src/cppintegration/definetypes.qdoc
+++ b/src/qml/doc/src/cppintegration/definetypes.qdoc
@@ -47,7 +47,7 @@ features such as \e{attached properties} and \e{default properties} in C++.
demonstrated in the \l{Writing QML Extensions with C++} tutorial.)
-\section1 Registering C++ types with the QML type system
+\section1 Registering C++ Types with the QML Type System
A QObject-derived class can be registered with the QML type system to enable the
type to be used as a data type from within QML code.
diff --git a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
index 8f6836558a..9527229204 100644
--- a/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
+++ b/src/qml/doc/src/cppintegration/exposecppattributes.qdoc
@@ -359,7 +359,7 @@ implementation, whereas an object-type property can be freely created and
destroyed through QML code.
-\section1 Exposing Methods (including Qt Slots)
+\section1 Exposing Methods (Including Qt Slots)
Any method of a QObject-derived type is accessible from QML code if it is:
diff --git a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
index aab729656b..b593753d33 100644
--- a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
+++ b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
@@ -26,9 +26,9 @@
****************************************************************************/
/*!
-\page qml-extending-tutorial-index.html tutorial
+\example tutorials/extending-qml
\title Writing QML Extensions with C++
-\brief tutorial about extending QML with Qt C++
+\brief Tutorial about extending QML with Qt C++.
The \l {Qt QML} module provides a set of APIs for extending QML through
C++ extensions. You can write extensions to add your own QML types, extend existing
@@ -38,33 +38,22 @@ This tutorial shows how to write a QML extension using C++ that includes
core QML features, including properties, signals and bindings. It also shows how
extensions can be deployed through plugins.
-You can find the source code for this tutorial in \c Qt's
-examples/qml/tutorials/extending directory.
-
-Tutorial chapters:
-
-\list 1
-\li \l{tutorials/extending/chapter1-basics}{Creating a New Type}
-\li \l{tutorials/extending/chapter2-methods}{Connecting to C++ Methods and Signals}
-\li \l{tutorials/extending/chapter3-bindings}{Property Binding}
-\li \l{tutorials/extending/chapter4-customPropertyTypes}{Using Custom Property Types}
-\li \l{tutorials/extending/chapter5-listproperties}{Using List Property Types}
-\li \l{tutorials/extending/chapter6-plugins}{Writing an Extension Plugin}
-\li \l{qml-extending-tutorial7.html}{In Summary}
-\endlist
-
Many of the topics covered in this tutorial are documented in further detail in
\l {qtqml-cppintegration-topic.html}{Integrating QML and C++} and its documentation
sub-topics. In particular, you may be interested in the sub-topics
\l{qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++ Classes to QML}
and \l {qtqml-cppintegration-definetypes.html}{Defining QML Types from C++}.
-*/
+\section1 Running the Tutorial Examples
-/*!
-\title Chapter 1: Creating a New Type
+The code in this tutorial is available as an example project with subprojects
+associated with each tutorial chapter. In \l{Qt Creator Manual}{Qt Creator}, open
+the \uicontrol Welcome mode and select the tutorial from \uicontrol Examples. In
+\uicontrol Edit mode, expand the \e extending-qml project, right-click on the
+subproject (chapter) you want to run and select \uicontrol Run.
-\example tutorials/extending/chapter1-basics
+\section1 Chapter 1: Creating a New Type
+\c extending-qml/chapter1-basics
A common task when extending QML is to provide a new QML type that supports some
custom functionality beyond what is provided by the built-in \l {Qt Quick QML Types}{Qt Quick types}.
@@ -83,7 +72,7 @@ a version of 1.0.
We want this \c PieChart type to be usable from QML like this:
-\code
+\badcode
import Charts 1.0
PieChart {
@@ -104,7 +93,7 @@ this new class must:
Here is our \c PieChart class, defined in \c piechart.h:
-\snippet tutorials/extending/chapter1-basics/piechart.h 0
+\snippet tutorials/extending-qml/chapter1-basics/piechart.h 0
The class inherits from QQuickPaintedItem because we want to override
QQuickPaintedItem::paint() in perform drawing operations with the QPainter API.
@@ -120,15 +109,15 @@ simply sets and returns the \c m_name and \c m_color values as appropriate, and
implements \c paint() to draw a simple pie chart. It also turns off the
QGraphicsItem::ItemHasNoContents flag to enable painting:
-\snippet tutorials/extending/chapter1-basics/piechart.cpp 0
+\snippet tutorials/extending-qml/chapter1-basics/piechart.cpp 0
\dots 0
-\snippet tutorials/extending/chapter1-basics/piechart.cpp 1
+\snippet tutorials/extending-qml/chapter1-basics/piechart.cpp 1
Now that we have defined the \c PieChart type, we will use it from QML. The \c app.qml
file creates a \c PieChart item and display the pie chart's details
using a standard QML \l Text item:
-\snippet tutorials/extending/chapter1-basics/app.qml 0
+\snippet tutorials/extending-qml/chapter1-basics/app.qml 0
Notice that although the color is specified as a string in QML, it is automatically
converted to a QColor object for the PieChart \c color property. Automatic conversions are
@@ -142,46 +131,46 @@ you don't register the type, \c app.qml won't be able to create a \c PieChart.
Here is the application \c main.cpp:
-\snippet tutorials/extending/chapter1-basics/main.cpp 0
+\snippet tutorials/extending-qml/chapter1-basics/main.cpp 0
This call to qmlRegisterType() registers the \c PieChart type as a type called "PieChart",
in a type namespace called "Charts", with a version of 1.0.
Lastly, we write a \c .pro project file that includes the files and the \c declarative library:
-\quotefile tutorials/extending/chapter1-basics/chapter1-basics.pro
+\quotefile tutorials/extending-qml/chapter1-basics/chapter1-basics.pro
Now we can build and run the application:
\image extending-tutorial-chapter1.png
-Try it yourself with the code in Qt's \c examples/qml/tutorials/extending/chapter1-basics directory.
-*/
-
-
-/*!
-\title Chapter 2: Connecting to C++ Methods and Signals
+\note You may see a warning \e {Expression ... depends on non-NOTIFYable properties:
+ PieChart::name}. This happens because we add a binding to the writable \c name
+ property, but haven't yet defined a notify signal for it. The QML engine therefore
+ cannot update the binding if the \c name value changes. This is addressed in
+ the following chapters.
-\example tutorials/extending/chapter2-methods
+\section1 Chapter 2: Connecting to C++ Methods and Signals
+\c extending-qml/chapter2-methods
Suppose we want \c PieChart to have a "clearChart()" method that erases the
chart and then emits a "chartCleared" signal. Our \c app.qml would be able
to call \c clearChart() and receive \c chartCleared() signals like this:
-\snippet tutorials/extending/chapter2-methods/app.qml 0
+\snippet tutorials/extending-qml/chapter2-methods/app.qml 0
\image extending-tutorial-chapter2.png
To do this, we add a \c clearChart() method and a \c chartCleared() signal
to our C++ class:
-\snippet tutorials/extending/chapter2-methods/piechart.h 0
+\snippet tutorials/extending-qml/chapter2-methods/piechart.h 0
\dots
-\snippet tutorials/extending/chapter2-methods/piechart.h 1
+\snippet tutorials/extending-qml/chapter2-methods/piechart.h 1
\dots
-\snippet tutorials/extending/chapter2-methods/piechart.h 2
+\snippet tutorials/extending-qml/chapter2-methods/piechart.h 2
\dots
-\snippet tutorials/extending/chapter2-methods/piechart.h 3
+\snippet tutorials/extending-qml/chapter2-methods/piechart.h 3
The use of Q_INVOKABLE makes the \c clearChart() method available to the
Qt Meta-Object system, and in turn, to QML. Note that it could have
@@ -191,23 +180,17 @@ slots are also callable from QML. Both of these approaches are valid.
The \c clearChart() method simply changes the color to Qt::transparent,
repaints the chart, then emits the \c chartCleared() signal:
-\snippet tutorials/extending/chapter2-methods/piechart.cpp 0
+\snippet tutorials/extending-qml/chapter2-methods/piechart.cpp 0
Now when we run the application and click the window, the pie chart
disappears, and the application outputs:
-\code
- The chart has been cleared
+\badcode
+ qml: The chart has been cleared
\endcode
-Try out the example yourself with the updated code in Qt's \c examples/qml/tutorials/extending/chapter2-methods directory.
-
-*/
-
-/*!
-\title Chapter 3: Adding Property Bindings
-
-\example tutorials/extending/chapter3-bindings
+\section1 Chapter 3: Adding Property Bindings
+\c extending-qml/chapter3-bindings
Property binding is a powerful feature of QML that allows values of different
types to be synchronized automatically. It uses signals to notify and update
@@ -216,7 +199,7 @@ other types' values when property values are changed.
Let's enable property bindings for the \c color property. That means
if we have code like this:
-\snippet tutorials/extending/chapter3-bindings/app.qml 0
+\snippet tutorials/extending-qml/chapter3-bindings/app.qml 0
\image extending-tutorial-chapter3.png
@@ -231,17 +214,17 @@ It's easy to enable property binding for the \c color property.
We add a \l{Qt's Property System}{NOTIFY} feature to its Q_PROPERTY() declaration to indicate that a "colorChanged" signal
is emitted whenever the value changes.
-\snippet tutorials/extending/chapter3-bindings/piechart.h 0
+\snippet tutorials/extending-qml/chapter3-bindings/piechart.h 0
\dots
-\snippet tutorials/extending/chapter3-bindings/piechart.h 1
+\snippet tutorials/extending-qml/chapter3-bindings/piechart.h 1
\dots
-\snippet tutorials/extending/chapter3-bindings/piechart.h 2
+\snippet tutorials/extending-qml/chapter3-bindings/piechart.h 2
\dots
-\snippet tutorials/extending/chapter3-bindings/piechart.h 3
+\snippet tutorials/extending-qml/chapter3-bindings/piechart.h 3
Then, we emit this signal in \c setPieSlice():
-\snippet tutorials/extending/chapter3-bindings/piechart.cpp 0
+\snippet tutorials/extending-qml/chapter3-bindings/piechart.cpp 0
It's important for \c setColor() to check that the color value has actually changed
before emitting \c colorChanged(). This ensures the signal is not emitted unnecessarily and
@@ -254,12 +237,9 @@ automatically updated and cannot be used as flexibly in QML. Also, since
bindings are invoked so often and relied upon in QML usage, users of your
custom QML types may see unexpected behavior if bindings are not implemented.
-*/
-
-/*!
-\title Chapter 4: Using Custom Property Types
+\section1 Chapter 4: Using Custom Property Types
-\example tutorials/extending/chapter4-customPropertyTypes
+\c extending-qml/chapter4-customPropertyTypes
The \c PieChart type currently has a string-type property and a color-type property.
It could have many other types of properties. For example, it could have an
@@ -299,57 +279,49 @@ For example, let's replace the use of the \c property with a type called
"PieSlice" that has a \c color property. Instead of assigning a color,
we assign an \c PieSlice value which itself contains a \c color:
-\snippet tutorials/extending/chapter4-customPropertyTypes/app.qml 0
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/app.qml 0
Like \c PieChart, this new \c PieSlice type inherits from QQuickPaintedItem and declares
its properties with Q_PROPERTY():
-\snippet tutorials/extending/chapter4-customPropertyTypes/pieslice.h 0
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/pieslice.h 0
To use it in \c PieChart, we modify the \c color property declaration
and associated method signatures:
-\snippet tutorials/extending/chapter4-customPropertyTypes/piechart.h 0
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h 0
\dots
-\snippet tutorials/extending/chapter4-customPropertyTypes/piechart.h 1
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h 1
\dots
-\snippet tutorials/extending/chapter4-customPropertyTypes/piechart.h 2
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h 2
\dots
-\snippet tutorials/extending/chapter4-customPropertyTypes/piechart.h 3
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/piechart.h 3
There is one thing to be aware of when implementing \c setPieSlice(). The \c PieSlice
is a visual item, so it must be set as a child of the \c PieChart using
QQuickItem::setParentItem() so that the \c PieChart knows to paint this child
item when its contents are drawn:
-\snippet tutorials/extending/chapter4-customPropertyTypes/piechart.cpp 0
-
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp 0
Like the \c PieChart type, the \c PieSlice type has to be registered
using qmlRegisterType() to be used from QML. As with \c PieChart, we'll add the
type to the "Charts" type namespace, version 1.0:
-\snippet tutorials/extending/chapter4-customPropertyTypes/main.cpp 0
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp 0
\dots
-\snippet tutorials/extending/chapter4-customPropertyTypes/main.cpp 1
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp 1
\dots
-\snippet tutorials/extending/chapter4-customPropertyTypes/main.cpp 2
-
-Try it out with the code in Qt's \c examples/qml/tutorials/extending/chapter4-customPropertyTypes directory.
-
-*/
-
+\snippet tutorials/extending-qml/chapter4-customPropertyTypes/main.cpp 2
-/*!
-\title Chapter 5: Using List Property Types
-
-\example tutorials/extending/chapter5-listproperties
+\section1 Chapter 5: Using List Property Types
+\c extending-qml/chapter5-listproperties
Right now, a \c PieChart can only have one \c PieSlice. Ideally a chart would
have multiple slices, with different colors and sizes. To do this, we could
have a \c slices property that accepts a list of \c PieSlice items:
-\snippet tutorials/extending/chapter5-listproperties/app.qml 0
+\snippet tutorials/extending-qml/chapter5-listproperties/app.qml 0
\image extending-tutorial-chapter5.png
@@ -360,11 +332,11 @@ function with a \c slices() function that returns a list of slices, and add
an internal \c append_slice() function (discussed below). We also use a QList to
store the internal list of slices as \c m_slices:
-\snippet tutorials/extending/chapter5-listproperties/piechart.h 0
+\snippet tutorials/extending-qml/chapter5-listproperties/piechart.h 0
\dots
-\snippet tutorials/extending/chapter5-listproperties/piechart.h 1
+\snippet tutorials/extending-qml/chapter5-listproperties/piechart.h 1
\dots
-\snippet tutorials/extending/chapter5-listproperties/piechart.h 2
+\snippet tutorials/extending-qml/chapter5-listproperties/piechart.h 2
Although the \c slices property does not have an associated \c WRITE function,
it is still modifiable because of the way QQmlListProperty works.
@@ -373,7 +345,7 @@ return a QQmlListProperty value and indicate that the internal
\c PieChart::append_slice() function is to be called whenever a request is made from QML
to add items to the list:
-\snippet tutorials/extending/chapter5-listproperties/piechart.cpp 0
+\snippet tutorials/extending-qml/chapter5-listproperties/piechart.cpp 0
The \c append_slice() function simply sets the parent item as before,
and adds the new item to the \c m_slices list. As you can see, the append function for a
@@ -384,15 +356,9 @@ The \c PieSlice class has also been modified to include \c fromAngle and \c angl
properties and to draw the slice according to these values. This is a straightforward
modification if you have read the previous pages in this tutorial, so the code is not shown here.
-The complete code can be seen in the updated \c examples/qml/tutorials/extending/chapter5-listproperties directory.
-
-*/
-
+\section1 Chapter 6: Writing an Extension Plugin
-/*!
-\title Chapter 6: Writing an Extension Plugin
-
-\example tutorials/extending/chapter6-plugins
+\c extending-qml/chapter6-plugins
Currently the \c PieChart and \c PieSlice types are used by \c app.qml,
which is displayed using a QQuickView in a C++ application. An alternative
@@ -408,17 +374,17 @@ and registers our QML types in the inherited \l{QQmlExtensionPlugin::}{registerT
Here is the \c ChartsPlugin definition in \c chartsplugin.h:
-\snippet tutorials/extending/chapter6-plugins/import/chartsplugin.h 0
+\snippet tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h 0
And its implementation in \c chartsplugin.cpp:
-\snippet tutorials/extending/chapter6-plugins/import/chartsplugin.cpp 0
+\snippet tutorials/extending-qml/chapter6-plugins/import/chartsplugin.cpp 0
Then, we write a \c .pro project file that defines the project as a plugin library
and specifies with DESTDIR that library files should be built into a \c {../Charts}
directory.
-\quotefile tutorials/extending/chapter6-plugins/import/import.pro
+\quotefile tutorials/extending-qml/chapter6-plugins/import/import.pro
In this example, the \c Charts directory is located at the same level as the application
that uses our new import module. This way, the QML engine will find our module
@@ -434,7 +400,7 @@ to the same location as the plugin binary.
The \c qmldir file declares the module name and the plugin that is made available
by the module:
-\quotefile tutorials/extending/chapter6-plugins/import/qmldir
+\quotefile tutorials/extending-qml/chapter6-plugins/import/qmldir
Now we have a QML module that can be imported to any application, provided that the
QML engine knows where to find it. The example contains an executable that loads
@@ -448,31 +414,29 @@ import path to the current directory so that it finds the \c qmldir file:
The module "Charts" will be loaded by the QML engine, and the types provided by that
module will be available for use in any QML document which imports it.
-*/
-
-/*!
-\page qml-extending-tutorial7.html
-\title Chapter 7: In Summary
+\section1 Chapter 7: Summary
In this tutorial, we've shown the basic steps for creating a QML extension:
\list
-\li Define new QML types by subclassing QObject and registering them with qmlRegisterType()
-\li Add callable methods using Q_INVOKABLE or Qt slots, and connect to Qt signals with an \c onSignal syntax
+\li Define new QML types by subclassing QObject and registering them with
+ qmlRegisterType()
+\li Add callable methods using \l Q_INVOKABLE or Qt slots, and connect to Qt signals
+ with an \c onSignal syntax
\li Add property bindings by defining \l{Qt's Property System}{NOTIFY} signals
\li Define custom property types if the built-in types are not sufficient
\li Define list property types using QQmlListProperty
-\li Create a plugin library by defining a Qt plugin and writing a \c qmldir file
+\li Create a plugin library by defining a Qt plugin and writing a
+ \l {Module Definition qmldir Files}{qmldir} file
\endlist
-
The \l{Integrating QML and C++} documentation shows
other useful features that can be added to QML extensions. For example, we
could use \l{Default Properties}{default properties} to allow
slices to be added without using the \c slices property:
-\code
+\badcode
PieChart {
PieSlice { ... }
PieSlice { ... }
@@ -482,13 +446,11 @@ slices to be added without using the \c slices property:
Or randomly add and remove slices from time to time using \l{Property Value Sources}{property value sources}:
-\code
+\badcode
PieChart {
PieSliceRandomizer on slices {}
}
\endcode
-
-See the \l{Integrating QML and C++} documentation for more information.
-
+\sa {Integrating QML and C++}
*/
diff --git a/src/qml/doc/src/qmllanguageref/documents/scope.qdoc b/src/qml/doc/src/qmllanguageref/documents/scope.qdoc
index af59afe1fb..67ae881908 100644
--- a/src/qml/doc/src/qmllanguageref/documents/scope.qdoc
+++ b/src/qml/doc/src/qmllanguageref/documents/scope.qdoc
@@ -163,14 +163,14 @@ Item {
property string title
Text {
- id: title
+ id: titletype
text: "<b>" + title + "</b>"
font.pixelSize: 22
anchors.top: parent.top
}
Text {
- text: title.text
+ text: titletype.text
font.pixelSize: 18
anchors.bottom: parent.bottom
}
diff --git a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
index a3ea25c005..def2216cbd 100644
--- a/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
+++ b/src/qml/doc/src/qmllanguageref/modules/qmldir.qdoc
@@ -210,6 +210,25 @@ typeinfo mymodule.qmltypes
as code completion for the types defined in your plugins.
\row
+ \li Dependency Declaration
+ \li
+ \code
+depends <ModuleIdentifier> <InitialVersion>
+ \endcode
+ \li Declares that this module depends on another.
+
+ Example:
+ \code
+depends MyOtherModule 1.0
+ \endcode
+
+ This declaration is necessary only in cases when the dependency is
+ hidden: for example, when the C++ code for one module is used to
+ load QML (perhaps conditionally) which then depends on other
+ modules. In such cases, the \c depends declaration is necessary
+ to include the other modules in application packages.
+
+ \row
\li Comment
\li
\code
diff --git a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
index 16e36f6f6d..1a154e5d5a 100644
--- a/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/typesystem/basictypes.qdoc
@@ -646,7 +646,7 @@ property is only invoked when the property is reassigned to a different object v
This basic type is provided by the QML language. Some enumeration values
are provided by the QtQuick import.
- \section1 Using the enumeration type in QML
+ \section1 Using the enumeration Type in QML
The \c enumeration type is a representation of a C++ \c enum type. It is
not possible to refer to the \c enumeration type in QML itself; instead, the
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 753626c811..5cf00f6d60 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -86,7 +86,7 @@ public:
void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0)
{
- const int written = vsnprintf(buf.data(), buf.size(), format, argList);
+ const int written = qvsnprintf(buf.data(), buf.size(), format, argList);
if (written > 0)
dest->write(buf.constData(), written);
memset(buf.data(), 0, qMin(written, buf.size()));
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 58251fac96..0d2b394cd6 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -420,17 +420,19 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
QV4::ScopedValue v(scope, vp->getValue(engine->m_v4Engine));
return engine->metaTypeFromJS(v, type, ptr);
} else if (vp->value.isEmpty()) {
- // have a string based value without engine. Do conversion manually
- if (type == QMetaType::Bool) {
- *reinterpret_cast<bool*>(ptr) = vp->string.length() != 0;
- return true;
- }
- if (type == QMetaType::QString) {
- *reinterpret_cast<QString*>(ptr) = vp->string;
- return true;
- }
- double d = QV4::RuntimeHelpers::stringToNumber(vp->string);
- switch (type) {
+ if (vp->unboundData.userType() == QMetaType::QString) {
+ QString string = vp->unboundData.toString();
+ // have a string based value without engine. Do conversion manually
+ if (type == QMetaType::Bool) {
+ *reinterpret_cast<bool*>(ptr) = string.length() != 0;
+ return true;
+ }
+ if (type == QMetaType::QString) {
+ *reinterpret_cast<QString*>(ptr) = string;
+ return true;
+ }
+ double d = QV4::RuntimeHelpers::stringToNumber(string);
+ switch (type) {
case QMetaType::Int:
*reinterpret_cast<int*>(ptr) = QV4::Primitive::toInt32(d);
return true;
@@ -466,6 +468,9 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
return true;
default:
return false;
+ }
+ } else {
+ return QMetaType::convert(&vp->unboundData.data_ptr(), vp->unboundData.userType(), ptr, type);
}
} else {
switch (type) {
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 891f17762c..47a764e641 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -58,14 +58,14 @@ QV4::ReturnedValue QJSValuePrivate::getValue(QV4::ExecutionEngine *e)
}
if (value.isEmpty()) {
- value = QV4::Encode(engine->newString(string));
+ value = QV4::Encode(engine->v8Engine->fromVariant(unboundData));
PersistentValuePrivate **listRoot = &engine->memoryManager->m_persistentValues;
prev = listRoot;
next = *listRoot;
*prev = this;
if (next)
next->prev = &this->next;
- string = QString();
+ unboundData.clear();
}
return value.asReturnedValue();
}
@@ -353,8 +353,21 @@ bool QJSValue::isVariant() const
*/
QString QJSValue::toString() const
{
- if (d->value.isEmpty())
- return d->string;
+ if (d->value.isEmpty()) {
+ if (d->unboundData.type() == QVariant::Map)
+ return QStringLiteral("[object Object]");
+ else if (d->unboundData.type() == QVariant::List) {
+ const QVariantList list = d->unboundData.toList();
+ QString result;
+ for (int i = 0; i < list.count(); ++i) {
+ if (i > 0)
+ result.append(QLatin1Char(','));
+ result.append(list.at(i).toString());
+ }
+ return result;
+ }
+ return d->unboundData.toString();
+ }
return d->value.toQStringNoThrow();
}
@@ -372,8 +385,14 @@ QString QJSValue::toString() const
*/
double QJSValue::toNumber() const
{
- if (d->value.isEmpty())
- return RuntimeHelpers::stringToNumber(d->string);
+ if (d->value.isEmpty()) {
+ if (d->unboundData.type() == QVariant::String)
+ return RuntimeHelpers::stringToNumber(d->unboundData.toString());
+ else if (d->unboundData.canConvert<double>())
+ return d->unboundData.value<double>();
+ else
+ return std::numeric_limits<double>::quiet_NaN();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
double dbl = d->value.toNumber();
@@ -398,8 +417,12 @@ double QJSValue::toNumber() const
*/
bool QJSValue::toBool() const
{
- if (d->value.isEmpty())
- return d->string.length() > 0;
+ if (d->value.isEmpty()) {
+ if (d->unboundData.userType() == QMetaType::QString)
+ return d->unboundData.toString().length() > 0;
+ else
+ return d->unboundData.toBool();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
bool b = d->value.toBoolean();
@@ -424,8 +447,12 @@ bool QJSValue::toBool() const
*/
qint32 QJSValue::toInt() const
{
- if (d->value.isEmpty())
- return QV4::Primitive::toInt32(RuntimeHelpers::stringToNumber(d->string));
+ if (d->value.isEmpty()) {
+ if (d->unboundData.userType() == QMetaType::QString)
+ return QV4::Primitive::toInt32(RuntimeHelpers::stringToNumber(d->unboundData.toString()));
+ else
+ return d->unboundData.toInt();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
qint32 i = d->value.toInt32();
@@ -450,8 +477,12 @@ qint32 QJSValue::toInt() const
*/
quint32 QJSValue::toUInt() const
{
- if (d->value.isEmpty())
- return QV4::Primitive::toUInt32(RuntimeHelpers::stringToNumber(d->string));
+ if (d->value.isEmpty()) {
+ if (d->unboundData.userType() == QMetaType::QString)
+ return QV4::Primitive::toUInt32(RuntimeHelpers::stringToNumber(d->unboundData.toString()));
+ else
+ return d->unboundData.toUInt();
+ }
QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
quint32 u = d->value.toUInt32();
@@ -487,7 +518,7 @@ quint32 QJSValue::toUInt() const
QVariant QJSValue::toVariant() const
{
if (d->value.isEmpty())
- return QVariant(d->string);
+ return d->unboundData;
return QV4::VariantObject::toVariant(d->value);
}
@@ -775,8 +806,10 @@ bool QJSValue::equals(const QJSValue& other) const
{
if (d->value.isEmpty()) {
if (other.d->value.isEmpty())
- return d->string == other.d->string;
- return js_equal(d->string, QV4::ValueRef(other.d->value));
+ return d->unboundData == other.d->unboundData;
+ if (d->unboundData.type() == QVariant::Map || d->unboundData.type() == QVariant::List)
+ return false;
+ return js_equal(d->unboundData.toString(), QV4::ValueRef(other.d->value));
}
if (other.d->value.isEmpty())
return other.equals(*this);
@@ -810,9 +843,11 @@ bool QJSValue::strictlyEquals(const QJSValue& other) const
{
if (d->value.isEmpty()) {
if (other.d->value.isEmpty())
- return d->string == other.d->string;
+ return d->unboundData == other.d->unboundData;
+ if (d->unboundData.type() == QVariant::Map || d->unboundData.type() == QVariant::List)
+ return false;
if (other.d->value.isString())
- return d->string == other.d->value.stringValue()->toQString();
+ return d->unboundData.toString() == other.d->value.stringValue()->toQString();
return false;
}
if (other.d->value.isEmpty())
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index e66c1bcde4..43a3a74e38 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -51,6 +51,7 @@
#include <private/qv4string_p.h>
#include <private/qv4engine_p.h>
#include <private/qv4object_p.h>
+#include <private/qflagpointer_p.h>
QT_BEGIN_NAMESPACE
@@ -72,8 +73,8 @@ public:
Q_ASSERT(!value.isEmpty());
}
QJSValuePrivate(const QString &s)
- : PersistentValuePrivate(QV4::Primitive::emptyValue().asReturnedValue())
- , string(s)
+ : PersistentValuePrivate(QV4::Primitive::emptyValue().asReturnedValue()),
+ unboundData(s)
{
}
@@ -81,7 +82,7 @@ public:
static QJSValuePrivate *get(const QJSValue &v) { return v.d; }
- QString string;
+ QVariant unboundData;
};
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index f7940c9602..d58dbb91d4 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -678,6 +678,60 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const
return p1s->toQString() < p2s->toQString();
}
+template <typename RandomAccessIterator, typename T, typename LessThan>
+void sortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan)
+{
+top:
+ int span = int(end - start);
+ if (span < 2)
+ return;
+
+ --end;
+ RandomAccessIterator low = start, high = end - 1;
+ RandomAccessIterator pivot = start + span / 2;
+
+ if (lessThan(*end, *start))
+ qSwap(*end, *start);
+ if (span == 2)
+ return;
+
+ if (lessThan(*pivot, *start))
+ qSwap(*pivot, *start);
+ if (lessThan(*end, *pivot))
+ qSwap(*end, *pivot);
+ if (span == 3)
+ return;
+
+ qSwap(*pivot, *end);
+
+ while (low < high) {
+ while (low < high && lessThan(*low, *end))
+ ++low;
+
+ while (high > low && lessThan(*end, *high))
+ --high;
+
+ if (low < high) {
+ qSwap(*low, *high);
+ ++low;
+ --high;
+ } else {
+ break;
+ }
+ }
+
+ if (lessThan(*low, *end))
+ ++low;
+
+ qSwap(*end, *low);
+ sortHelper(start, low, t, lessThan);
+
+ start = low + 1;
+ ++end;
+ goto top;
+}
+
+
void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint len)
{
if (!len)
@@ -769,7 +823,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR
ArrayElementLessThan lessThan(context, thisObject, comparefn);
Value *begin = thisObject->arrayData()->arrayData();
- std::sort(begin, begin + len, lessThan);
+ sortHelper(begin, begin + len, *begin, lessThan);
#ifdef CHECK_SPARSE_ARRAYS
thisObject->initSparseArray();
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 67d247de28..66601b64e5 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -550,16 +550,7 @@ static inline QDateTime ToDateTime(double t, Qt::TimeSpec spec)
{
if (std::isnan(t))
return QDateTime();
- if (spec == Qt::LocalTime)
- t = LocalTime(t);
- int year = int(YearFromTime(t));
- int month = int(MonthFromTime(t) + 1);
- int day = int(DateFromTime(t));
- int hours = HourFromTime(t);
- int mins = MinFromTime(t);
- int secs = SecFromTime(t);
- int ms = msFromTime(t);
- return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec);
+ return QDateTime::fromMSecsSinceEpoch(t, spec);
}
static inline QString ToString(double t)
@@ -586,7 +577,7 @@ static inline QString ToUTCString(double t)
{
if (std::isnan(t))
return QStringLiteral("Invalid Date");
- return ToDateTime(t, Qt::UTC).toString() + QStringLiteral(" GMT");
+ return ToDateTime(t, Qt::UTC).toString();
}
static inline QString ToDateString(double t)
@@ -1029,7 +1020,7 @@ ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
double t = self->date().asDouble();
double ms = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
- self->date().setDouble(TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)))));
+ self->date().setDouble(TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms))));
return self->date().asReturnedValue();
}
@@ -1056,7 +1047,7 @@ ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
double t = self->date().asDouble();
double sec = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
double ms = (ctx->d()->callData->argc < 2) ? msFromTime(t) : ctx->d()->callData->args[1].toNumber();
- t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms))));
+ t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)));
self->date().setDouble(t);
return self->date().asReturnedValue();
}
@@ -1086,7 +1077,7 @@ ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
double min = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
double sec = (ctx->d()->callData->argc < 2) ? SecFromTime(t) : ctx->d()->callData->args[1].toNumber();
double ms = (ctx->d()->callData->argc < 3) ? msFromTime(t) : ctx->d()->callData->args[2].toNumber();
- t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms))));
+ t = TimeClip(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)));
self->date().setDouble(t);
return self->date().asReturnedValue();
}
@@ -1118,7 +1109,7 @@ ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
double min = (ctx->d()->callData->argc < 2) ? MinFromTime(t) : ctx->d()->callData->args[1].toNumber();
double sec = (ctx->d()->callData->argc < 3) ? SecFromTime(t) : ctx->d()->callData->args[2].toNumber();
double ms = (ctx->d()->callData->argc < 4) ? msFromTime(t) : ctx->d()->callData->args[3].toNumber();
- t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms))));
+ t = TimeClip(MakeDate(Day(t), MakeTime(hour, min, sec, ms)));
self->date().setDouble(t);
return self->date().asReturnedValue();
}
@@ -1144,7 +1135,7 @@ ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
double t = self->date().asDouble();
double date = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
- t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t))));
+ t = TimeClip(MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), date), TimeWithinDay(t)));
self->date().setDouble(t);
return self->date().asReturnedValue();
}
@@ -1172,7 +1163,7 @@ ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
double t = self->date().asDouble();
double month = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
double date = (ctx->d()->callData->argc < 2) ? DateFromTime(t) : ctx->d()->callData->args[1].toNumber();
- t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t))));
+ t = TimeClip(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)));
self->date().setDouble(t);
return self->date().asReturnedValue();
}
@@ -1213,7 +1204,7 @@ ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
double month = (ctx->d()->callData->argc < 2) ? MonthFromTime(t) : ctx->d()->callData->args[1].toNumber();
double date = (ctx->d()->callData->argc < 3) ? DateFromTime(t) : ctx->d()->callData->args[2].toNumber();
- t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t))));
+ t = TimeClip(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)));
self->date().setDouble(t);
return self->date().asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 88cd043d1e..ea075f9cbd 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -90,6 +90,8 @@ static ReturnedValue throwTypeError(CallContext *ctx)
return ctx->throwTypeError();
}
+const int MinimumStackSize = 256; // in kbytes
+
quintptr getStackLimit()
{
quintptr stackLimit;
@@ -149,7 +151,7 @@ quintptr getStackLimit()
#endif
// 256k slack
- return stackLimit + 256*1024;
+ return stackLimit + MinimumStackSize*1024;
}
@@ -203,6 +205,8 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
// set up stack limits
jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value);
cStackLimit = getStackLimit();
+ if (!recheckCStackLimits())
+ qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize);
Scope scope(this);
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 36cf8f9424..ce0ee973e8 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -212,6 +212,7 @@ struct Q_QML_PRIVATE_EXPORT Managed
void *operator new(size_t, Managed *m) { return m; }
void *operator new(size_t, Managed::Data *m) { return m; }
+ void operator delete(void *, Managed::Data *) {}
};
Data data;
V4_MANAGED(Managed)
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index 693af854da..f1bd1d55d9 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -53,7 +53,7 @@ FunctionCallProperties FunctionCall::resolve() const
}
-Profiler::Profiler(QV4::ExecutionEngine *engine) : enabled(false), m_engine(engine)
+Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine)
{
static int metatype = qRegisterMetaType<QList<QV4::Profiling::FunctionCallProperties> >();
static int metatype2 = qRegisterMetaType<QList<QV4::Profiling::MemoryAllocationProperties> >();
@@ -69,7 +69,7 @@ struct FunctionCallComparator {
void Profiler::stopProfiling()
{
- enabled = false;
+ featuresEnabled = 0;
reportData();
}
@@ -85,27 +85,29 @@ void Profiler::reportData()
emit dataReady(resolved, m_memory_data);
}
-void Profiler::startProfiling()
+void Profiler::startProfiling(quint64 features)
{
- if (!enabled) {
+ if (featuresEnabled == 0) {
m_data.clear();
m_memory_data.clear();
- qint64 timestamp = m_timer.nsecsElapsed();
- MemoryAllocationProperties heap = {timestamp,
- (qint64)m_engine->memoryManager->getAllocatedMem(),
- HeapPage};
- m_memory_data.append(heap);
- MemoryAllocationProperties small = {timestamp,
- (qint64)m_engine->memoryManager->getUsedMem(),
- SmallItem};
- m_memory_data.append(small);
- MemoryAllocationProperties large = {timestamp,
- (qint64)m_engine->memoryManager->getLargeItemsMem(),
- LargeItem};
- m_memory_data.append(large);
+ if (features & (1 << FeatureMemoryAllocation)) {
+ qint64 timestamp = m_timer.nsecsElapsed();
+ MemoryAllocationProperties heap = {timestamp,
+ (qint64)m_engine->memoryManager->getAllocatedMem(),
+ HeapPage};
+ m_memory_data.append(heap);
+ MemoryAllocationProperties small = {timestamp,
+ (qint64)m_engine->memoryManager->getUsedMem(),
+ SmallItem};
+ m_memory_data.append(small);
+ MemoryAllocationProperties large = {timestamp,
+ (qint64)m_engine->memoryManager->getLargeItemsMem(),
+ LargeItem};
+ m_memory_data.append(large);
+ }
- enabled = true;
+ featuresEnabled = features;
}
}
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index f115137c86..8224f8a851 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -46,6 +46,11 @@ namespace QV4 {
namespace Profiling {
+enum Features {
+ FeatureFunctionCall,
+ FeatureMemoryAllocation
+};
+
enum MemoryType {
HeapPage,
LargeItem,
@@ -106,15 +111,18 @@ private:
};
#define Q_V4_PROFILE_ALLOC(engine, size, type)\
- (engine->profiler && engine->profiler->enabled ?\
+ (engine->profiler &&\
+ (engine->profiler->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler->trackAlloc(size, type) : size)
#define Q_V4_PROFILE_DEALLOC(engine, pointer, size, type) \
- (engine->profiler && engine->profiler->enabled ?\
+ (engine->profiler &&\
+ (engine->profiler->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler->trackDealloc(pointer, size, type) : pointer)
#define Q_V4_PROFILE(engine, ctx, function)\
- ((engine->profiler && engine->profiler->enabled) ?\
+ (engine->profiler &&\
+ (engine->profiler->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\
Profiling::FunctionCallProfiler::profileCall(engine->profiler, ctx, function) :\
function->code(ctx, function->codeData))
@@ -138,11 +146,11 @@ public:
return pointer;
}
- bool enabled;
+ quint64 featuresEnabled;
public slots:
void stopProfiling();
- void startProfiling();
+ void startProfiling(quint64 features);
void reportData();
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index ff51ee6c6f..32379f7f1e 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1665,17 +1665,13 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
type = -1;
QQmlEnginePrivate *ep = engine->engine() ? QQmlEnginePrivate::get(engine->engine()) : 0;
- QVariant v = engine->toVariant(value, -1); // why -1 instead of callType?
+ QVariant v = engine->toVariant(value, callType);
if (v.userType() == callType) {
*qvariantPtr = v;
} else if (v.canConvert(callType)) {
*qvariantPtr = v;
qvariantPtr->convert(callType);
- } else if (QV4::SequencePrototype::isSequenceType(callType) && v.userType() == qMetaTypeId<QVariantList>()) {
- // convert the JS array to a sequence of the correct type.
- QVariant seqV = engine->toVariant(value, callType);
- *qvariantPtr = seqV;
} else {
QQmlMetaObject mo = ep ? ep->rawMetaObjectForType(callType) : QQmlMetaObject();
if (!mo.isNull()) {
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index a4378cf49a..8e91c0e6a5 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -320,7 +320,7 @@ QV4::CompiledData::CompilationUnit *Script::precompile(IR::Module *module, Compi
QQmlJS::Engine ee;
QQmlJS::Lexer lexer(&ee);
- lexer.setCode(source, /*line*/1, /*qml mode*/true);
+ lexer.setCode(source, /*line*/1, /*qml mode*/false);
QQmlJS::Parser parser(&ee);
parser.parseProgram();
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 63a8e93878..bd8a5ffccb 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -119,7 +119,7 @@ const ObjectVTable String::static_vtbl =
void String::destroy(Managed *that)
{
- static_cast<String*>(that)->~String();
+ static_cast<String*>(that)->d()->~Data();
}
void String::markObjects(Managed *that, ExecutionEngine *e)
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 34657501e8..68b08fb3ca 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -59,7 +59,7 @@ VariantObject::Data::Data(ExecutionEngine *engine, const QVariant &value)
QVariant VariantObject::toVariant(const QV4::ValueRef v)
{
if (v->asObject())
- return v->engine()->v8Engine->variantFromJS(v);
+ return v->engine()->v8Engine->toVariant(v, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
if (v->isString())
return QVariant(v->stringValue()->toQString());
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 397b4851cf..b3d7bddff7 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -139,6 +139,7 @@ void QQmlThreadPrivate::run()
q->startupThread();
exec();
+ q->shutdownThread();
}
void QQmlThreadPrivate::mainEvent()
@@ -177,7 +178,6 @@ void QQmlThreadPrivate::threadEvent()
quit();
wakeOne();
unlock();
- q->shutdownThread();
return;
} else if (!threadList.isEmpty()) {
@@ -207,12 +207,6 @@ void QQmlThreadPrivate::threadEvent()
QQmlThread::QQmlThread()
: d(new QQmlThreadPrivate(this))
{
- d->lock();
- d->start();
- d->wait();
- d->unlock();
- d->moveToThread(d);
-
}
QQmlThread::~QQmlThread()
@@ -220,13 +214,29 @@ QQmlThread::~QQmlThread()
delete d;
}
+void QQmlThread::startup()
+{
+ d->lock();
+ d->start();
+ d->wait();
+ d->unlock();
+ d->moveToThread(d);
+}
+
void QQmlThread::shutdown()
{
d->lock();
Q_ASSERT(!d->m_shutdown);
d->m_shutdown = true;
if (d->threadList.isEmpty() && d->m_threadProcessing == false) {
- d->triggerThreadEvent();
+ if (QCoreApplication::closingDown()) {
+ d->quit();
+ d->unlock();
+ d->QThread::wait();
+ return;
+ } else {
+ d->triggerThreadEvent();
+ }
} else if (d->mainSync) {
d->wakeOne();
}
diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h
index 995fcd4824..95d32d4fd2 100644
--- a/src/qml/qml/ftw/qqmlthread_p.h
+++ b/src/qml/qml/ftw/qqmlthread_p.h
@@ -60,6 +60,8 @@ class QQmlThread
public:
QQmlThread();
virtual ~QQmlThread();
+
+ void startup();
void shutdown();
bool isShutdown() const;
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 56eddfa478..9ccaee7cd7 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -65,7 +65,8 @@ void QQmlApplicationEnginePrivate::init()
q->connect(q, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
#ifndef QT_NO_TRANSLATION
QTranslator* qtTranslator = new QTranslator;
- if (qtTranslator->load(QLatin1String("qt_") + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ QLocale locale;
+ if (qtTranslator->load(locale, QLatin1String("qt"), QLatin1String("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
QCoreApplication::installTranslator(qtTranslator);
translators << qtTranslator;
#endif
@@ -82,7 +83,8 @@ void QQmlApplicationEnginePrivate::loadTranslations(const QUrl &rootFile)
QFileInfo fi(rootFile.toLocalFile());
QTranslator *translator = new QTranslator;
- if (translator->load(QLatin1String("qml_") + QLocale::system().name(), fi.path() + QLatin1String("/i18n"))) {
+ QLocale locale;
+ if (translator->load(locale, QLatin1String("qml"), QLatin1String("_"), fi.path() + QLatin1String("/i18n"))) {
QCoreApplication::installTranslator(translator);
translators << translator;
} else {
@@ -160,6 +162,10 @@ void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o)
}
\endcode
+ Unlike QQuickView, QQmlApplicationEngine does not automatically create a root
+ window. If you are using visual items from Qt Quick, you will need to place
+ them inside of a \l [QML] {Window}.
+
You can also use QCoreApplication with QQmlApplicationEngine, if you are not using any QML modules which require a QGuiApplication (such as \c QtQuick).
List of configuration changes from a default QQmlEngine:
@@ -167,7 +173,7 @@ void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o)
\list
\li Connecting Qt.quit() to QCoreApplication::quit()
\li Automatically loads translation files from an i18n directory adjacent to the main QML file.
- \li Automatically sets an incubuation controller if the scene contains a QQuickWindow.
+ \li Automatically sets an incubation controller if the scene contains a QQuickWindow.
\li Automatically sets a \c QQmlFileSelector as the url interceptor, applying file selectors to all
QML files and assets.
\endlist
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 7068818f15..83e1c9c757 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -231,6 +231,28 @@ bool QQmlDirParser::parse(const QString &source)
reportError(lineNumber, 0, QString::fromLatin1("designersupported does not expect any argument"));
else
_designerSupported = true;
+ } else if (sections[0] == QLatin1String("depends")) {
+ if (sectionCount != 3) {
+ reportError(lineNumber, 0,
+ QString::fromLatin1("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1));
+ continue;
+ }
+
+ const QString &version = sections[2];
+ const int dotIndex = version.indexOf(QLatin1Char('.'));
+ bool validVersionNumber = false;
+ const int majorVersion = parseInt(QStringRef(&version, 0, dotIndex), &validVersionNumber);
+ if (validVersionNumber) {
+ const int minorVersion = parseInt(QStringRef(&version, dotIndex+1, version.length()-dotIndex-1), &validVersionNumber);
+
+ if (validVersionNumber) {
+ Component entry(sections[1], QString(), majorVersion, minorVersion);
+ entry.internal = true;
+ _dependencies.insert(entry.typeName, entry);
+ }
+ } else {
+ reportError(lineNumber, 0, QString(QLatin1String("invalid version %1")).arg(version));
+ }
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
const Component entry(sections[0], sections[1], -1, -1);
@@ -348,6 +370,11 @@ QHash<QString, QQmlDirParser::Component> QQmlDirParser::components() const
return _components;
}
+QHash<QString, QQmlDirParser::Component> QQmlDirParser::dependencies() const
+{
+ return _dependencies;
+}
+
QList<QQmlDirParser::Script> QQmlDirParser::scripts() const
{
return _scripts;
diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h
index 54843a13b0..bbe61dfb96 100644
--- a/src/qml/qml/qqmldirparser_p.h
+++ b/src/qml/qml/qqmldirparser_p.h
@@ -119,6 +119,7 @@ public:
};
QHash<QString,Component> components() const;
+ QHash<QString,Component> dependencies() const;
QList<Script> scripts() const;
QList<Plugin> plugins() const;
bool designerSupported() const;
@@ -137,12 +138,14 @@ public:
#endif
private:
+ bool maybeAddComponent(const QString &typeName, const QString &fileName, const QString &version, QHash<QString,Component> &hash, int lineNumber = -1, bool multi = true);
void reportError(quint16 line, quint16 column, const QString &message);
private:
QList<QQmlJS::DiagnosticMessage> _errors;
QString _typeNamespace;
QHash<QString,Component> _components; // multi hash
+ QHash<QString,Component> _dependencies;
QList<Script> _scripts;
QList<Plugin> _plugins;
bool _designerSupported;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index e54e23813d..2b69661c4b 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -1247,42 +1247,38 @@ void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
/*!
\enum QQmlEngine::ObjectOwnership
- Ownership controls whether or not QML automatically destroys the
- QObject when the object is garbage collected by the JavaScript
- engine. The two ownership options are:
-
- \value CppOwnership The object is owned by C++ code, and will
- never be deleted by QML. The JavaScript destroy() method cannot be
- used on objects with CppOwnership. This option is similar to
- QScriptEngine::QtOwnership.
-
- \value JavaScriptOwnership The object is owned by JavaScript.
- When the object is returned to QML as the return value of a method
- call or property access, QML will track it, and delete the object
- if there are no remaining JavaScript references to it and it has no
- QObject::parent(). An object tracked by one QQmlEngine
- will be deleted during that QQmlEngine's destructor, and thus
- JavaScript references between objects with JavaScriptOwnership from
- two different engines will not be valid after the deletion of one of
- those engines. This option is similar to QScriptEngine::ScriptOwnership.
+ ObjectOwnership controls whether or not QML automatically destroys the
+ QObject when the corresponding JavaScript object is garbage collected by the
+ engine. The two ownership options are:
+
+ \value CppOwnership The object is owned by C++ code and QML will never delete
+ it. The JavaScript destroy() method cannot be used on these objects. This
+ option is similar to QScriptEngine::QtOwnership.
+
+ \value JavaScriptOwnership The object is owned by JavaScript. When the object
+ is returned to QML as the return value of a method call, QML will track it
+ and delete it if there are no remaining JavaScript references to it and
+ it has no QObject::parent(). An object tracked by one QQmlEngine will be
+ deleted during that QQmlEngine's destructor. Thus, JavaScript references
+ between objects with JavaScriptOwnership from two different engines will
+ not be valid if one of these engines is deleted. This option is similar to
+ QScriptEngine::ScriptOwnership.
Generally an application doesn't need to set an object's ownership
- explicitly. QML uses a heuristic to set the default object
- ownership. By default, an object that is created by QML has
- JavaScriptOwnership. The exception to this are the root objects
- created by calling QQmlComponent::create() or
- QQmlComponent::beginCreate() which have CppOwnership by
- default. The ownership of these root-level objects is considered to
- have been transferred to the C++ caller.
-
- Objects not-created by QML have CppOwnership by default. The
- exception to this is objects returned from C++ method calls; in these cases,
- the ownership of the returned objects will be set to JavaScriptOwnerShip.
- Note this applies only to explicit invocations of Q_INVOKABLE methods or slots,
- and not to property getter invocations.
-
- Calling setObjectOwnership() overrides the default ownership
- heuristic used by QML.
+ explicitly. QML uses a heuristic to set the default ownership. By default, an
+ object that is created by QML has JavaScriptOwnership. The exception to this
+ are the root objects created by calling QQmlComponent::create() or
+ QQmlComponent::beginCreate(), which have CppOwnership by default. The
+ ownership of these root-level objects is considered to have been transferred
+ to the C++ caller.
+
+ Objects not-created by QML have CppOwnership by default. The exception to this
+ are objects returned from C++ method calls; their ownership will be set to
+ JavaScriptOwnership. This applies only to explicit invocations of Q_INVOKABLE
+ methods or slots, but not to property getter invocations.
+
+ Calling setObjectOwnership() overrides the default ownership heuristic used by
+ QML.
*/
/*!
diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp
index d84a7804f4..e48224333c 100644
--- a/src/qml/qml/qqmlextensionplugin.cpp
+++ b/src/qml/qml/qqmlextensionplugin.cpp
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
or other issues in the library user's code.
- \section1 An example
+ \section1 An Example
Suppose there is a new \c TimeModel C++ class that should be made available
as a new QML element. It provides the current time through \c hour and \c minute
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index c09ab69424..d20fe72d09 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -98,7 +98,7 @@ struct QQmlMetaTypeData
QBitArray lists;
QList<QQmlPrivate::AutoParentFunction> parentFunctions;
- QQmlPrivate::QmlUnitCacheLookupFunction lookupCachedQmlUnit;
+ QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit;
QSet<QString> protectedNamespaces;
@@ -135,7 +135,6 @@ static uint qHash(const QQmlMetaTypeData::VersionedUri &v)
}
QQmlMetaTypeData::QQmlMetaTypeData()
- : lookupCachedQmlUnit(0)
{
}
@@ -1347,7 +1346,7 @@ int registerQmlUnitCacheHook(const QQmlPrivate::RegisterQmlUnitCacheHook &hookRe
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
QWriteLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- data->lookupCachedQmlUnit = hookRegistration.lookupCachedQmlUnit;
+ data->lookupCachedQmlUnit << hookRegistration.lookupCachedQmlUnit;
return 0;
}
@@ -1877,8 +1876,11 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const
{
QReadLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- if (data->lookupCachedQmlUnit)
- return data->lookupCachedQmlUnit(uri);
+ for (QVector<QQmlPrivate::QmlUnitCacheLookupFunction>::ConstIterator it = data->lookupCachedQmlUnit.constBegin(), end = data->lookupCachedQmlUnit.constEnd();
+ it != end; ++it) {
+ if (const QQmlPrivate::CachedQmlUnit *unit = (*it)(uri))
+ return unit;
+ }
return 0;
}
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 0ad60e01ab..a827e96ab1 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -93,7 +93,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
sharedState->rootContext = 0;
QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
- Q_QML_PROFILE_IF_ENABLED(profiler,
+ Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
sharedState->profiler.init(profiler, compiledData->totalParserStatusCount));
}
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 42bf0dd657..09b735ae9e 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1585,11 +1585,14 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
propertyType = propertyMetaObject.className();
}
} else if (value.userType() != QVariant::Invalid) {
- valueType = QMetaType::typeName(value.userType());
+ if (value.userType() == QMetaType::VoidStar)
+ valueType = "null";
+ else
+ valueType = QMetaType::typeName(value.userType());
}
if (!valueType)
- valueType = "null";
+ valueType = "undefined";
if (!propertyType)
propertyType = QMetaType::typeName(type);
if (!propertyType)
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 0b7cc8e911..0e2d4d027a 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -728,6 +728,8 @@ void QQmlDataBlob::ThreadData::setProgress(quint8 v)
QQmlDataLoaderThread::QQmlDataLoaderThread(QQmlDataLoader *loader)
: m_loader(loader), m_networkAccessManager(0), m_networkReplyProxy(0)
{
+ // Do that after initializing all the members.
+ startup();
}
QNetworkAccessManager *QQmlDataLoaderThread::networkAccessManager() const
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 35d31e4f1f..39b816f97c 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -79,6 +79,41 @@ Q_DECLARE_METATYPE(QList<int>)
// QQmlEngine is not available
QT_BEGIN_NAMESPACE
+template <typename ReturnType>
+ReturnType convertJSValueToVariantType(const QJSValue &value)
+{
+ return value.toVariant().value<ReturnType>();
+}
+
+static void saveJSValue(QDataStream &stream, const void *data)
+{
+ const QJSValue *jsv = reinterpret_cast<const QJSValue *>(data);
+ quint32 isNullOrUndefined = 0;
+ if (jsv->isNull())
+ isNullOrUndefined |= 0x1;
+ if (jsv->isUndefined())
+ isNullOrUndefined |= 0x2;
+ stream << isNullOrUndefined;
+ if (!isNullOrUndefined)
+ reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
+}
+
+static void restoreJSValue(QDataStream &stream, void *data)
+{
+ QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
+ QJSValuePrivate *d = QJSValuePrivate::get(*jsv);
+
+ quint32 isNullOrUndefined;
+ stream >> isNullOrUndefined;
+ if (isNullOrUndefined & 0x1) {
+ d->value = QV4::Primitive::nullValue().asReturnedValue();
+ } else if (isNullOrUndefined & 0x2) {
+ d->value = QV4::Primitive::undefinedValue().asReturnedValue();
+ } else {
+ d->value = QV4::Primitive::emptyValue().asReturnedValue();
+ d->unboundData.load(stream);
+ }
+}
QV8Engine::QV8Engine(QJSEngine* qq)
: q(qq)
@@ -96,6 +131,14 @@ QV8Engine::QV8Engine(QJSEngine* qq)
qMetaTypeId<QJSValue>();
qMetaTypeId<QList<int> >();
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantMap>())
+ QMetaType::registerConverter<QJSValue, QVariantMap>(convertJSValueToVariantType<QVariantMap>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QVariantList>())
+ QMetaType::registerConverter<QJSValue, QVariantList>(convertJSValueToVariantType<QVariantList>);
+ if (!QMetaType::hasRegisteredConverterFunction<QJSValue, QStringList>())
+ QMetaType::registerConverter<QJSValue, QStringList>(convertJSValueToVariantType<QStringList>);
+ QMetaType::registerStreamOperators(qMetaTypeId<QJSValue>(), saveJSValue, restoreJSValue);
+
m_v4Engine = new QV4::ExecutionEngine;
m_v4Engine->v8Engine = this;
@@ -116,7 +159,7 @@ QV8Engine::~QV8Engine()
delete m_v4Engine;
}
-QVariant QV8Engine::toVariant(const QV4::ValueRef value, int typeHint)
+QVariant QV8Engine::toVariant(const QV4::ValueRef value, int typeHint, bool createJSValueForObjects, V8ObjectSet *visitedObjects)
{
Q_ASSERT (!value->isEmpty());
QV4::Scope scope(m_v4Engine);
@@ -178,7 +221,88 @@ QVariant QV8Engine::toVariant(const QV4::ValueRef value, int typeHint)
return retn;
}
- return toBasicVariant(value);
+ if (value->isUndefined())
+ return QVariant();
+ if (value->isNull())
+ return QVariant(QMetaType::VoidStar, (void *)0);
+ if (value->isBoolean())
+ return value->booleanValue();
+ if (value->isInteger())
+ return value->integerValue();
+ if (value->isNumber())
+ return value->asDouble();
+ if (value->isString())
+ return value->stringValue()->toQString();
+ if (QQmlLocaleData *ld = value->as<QQmlLocaleData>())
+ return ld->d()->locale;
+ if (QV4::DateObject *d = value->asDateObject())
+ return d->toQDateTime();
+ // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
+
+ QV4::ScopedObject o(scope, value);
+ Q_ASSERT(o);
+
+ if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
+ return re->toQRegExp();
+
+ if (createJSValueForObjects)
+ return QVariant::fromValue(QJSValue(new QJSValuePrivate(o->asReturnedValue())));
+
+ return objectToVariant(o, visitedObjects);
+}
+
+QVariant QV8Engine::objectToVariant(QV4::Object *o, V8ObjectSet *visitedObjects)
+{
+ Q_ASSERT(o);
+
+ V8ObjectSet recursionGuardSet;
+ if (!visitedObjects) {
+ visitedObjects = &recursionGuardSet;
+ } else if (visitedObjects->contains(o)) {
+ // Avoid recursion.
+ // For compatibility with QVariant{List,Map} conversion, we return an
+ // empty object (and no error is thrown).
+ if (o->asArrayObject())
+ return QVariantList();
+ return QVariantMap();
+ }
+ visitedObjects->insert(o);
+
+ QVariant result;
+
+ if (o->asArrayObject()) {
+ QV4::Scope scope(m_v4Engine);
+ QV4::ScopedArrayObject a(scope, o->asReturnedValue());
+ QV4::ScopedValue v(scope);
+ QVariantList list;
+
+ int length = a->getLength();
+ for (int ii = 0; ii < length; ++ii) {
+ v = a->getIndexed(ii);
+ list << toVariant(v, -1, /*createJSValueForObjects*/false, visitedObjects);
+ }
+
+ result = list;
+ } else if (!o->asFunctionObject()) {
+ QVariantMap map;
+ QV4::Scope scope(m_v4Engine);
+ QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
+ QV4::ScopedValue name(scope);
+ QV4::ScopedValue val(scope);
+ while (1) {
+ name = it.nextPropertyNameAsString(val);
+ if (name->isNull())
+ break;
+
+ QString key = name->toQStringNoThrow();
+ map.insert(key, toVariant(val, /*type hint*/-1, /*createJSValueForObjects*/false, visitedObjects));
+ }
+
+ result = map;
+ }
+
+ visitedObjects->remove(o);
+ return result;
}
static QV4::ReturnedValue arrayFromStringList(QV8Engine *engine, const QStringList &list)
@@ -240,6 +364,8 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant)
case QMetaType::UnknownType:
case QMetaType::Void:
return QV4::Encode::undefined();
+ case QMetaType::VoidStar:
+ return QV4::Encode::null();
case QMetaType::Bool:
return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
case QMetaType::Int:
@@ -368,59 +494,6 @@ QQmlContextData *QV8Engine::callingContext()
return QV4::QmlContextWrapper::callingContext(m_v4Engine);
}
-// Converts a JS value to a QVariant.
-// Null, Undefined -> QVariant() (invalid)
-// Boolean -> QVariant(bool)
-// Number -> QVariant(double)
-// String -> QVariant(QString)
-// Array -> QVariantList(...)
-// Date -> QVariant(QDateTime)
-// RegExp -> QVariant(QRegExp)
-// [Any other object] -> QVariantMap(...)
-QVariant QV8Engine::toBasicVariant(const QV4::ValueRef value)
-{
- if (value->isNullOrUndefined())
- return QVariant();
- if (value->isBoolean())
- return value->booleanValue();
- if (value->isInteger())
- return value->integerValue();
- if (value->isNumber())
- return value->asDouble();
- if (value->isString())
- return value->stringValue()->toQString();
- if (QQmlLocaleData *ld = value->as<QQmlLocaleData>())
- return ld->d()->locale;
- if (QV4::DateObject *d = value->asDateObject())
- return d->toQDateTime();
- // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
-
- QV4::Scope scope(value->engine());
- QV4::ScopedObject o(scope, value);
- Q_ASSERT(o);
-
- if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
- return re->toQRegExp();
- if (o->asArrayObject()) {
- QV4::ScopedArrayObject a(scope, o);
- QV4::ScopedValue v(scope);
- QVariantList rv;
-
- int length = a->getLength();
- for (int ii = 0; ii < length; ++ii) {
- v = a->getIndexed(ii);
- rv << toVariant(v, -1);
- }
- return rv;
- }
- if (!value->asFunctionObject())
- return variantMapFromJS(o);
-
- return QVariant();
-}
-
-
-
void QV8Engine::initializeGlobal()
{
QV4::Scope scope(m_v4Engine);
@@ -543,36 +616,6 @@ QV4::ReturnedValue QV8Engine::variantListToJS(const QVariantList &lst)
return a.asReturnedValue();
}
-// Converts a JS Array object to a QVariantList.
-// The result is a QVariantList with length equal to the length
-// of the JS Array, and elements being the JS Array's elements
-// converted to QVariants, recursively.
-QVariantList QV8Engine::variantListFromJS(QV4::ArrayObject *a, V8ObjectSet &visitedObjects)
-{
- QVariantList result;
- if (!a)
- return result;
-
- if (visitedObjects.contains(a))
- // Avoid recursion.
- return result;
-
- visitedObjects.insert(a);
-
- QV4::Scope scope(a->engine());
- QV4::ScopedValue v(scope);
-
- quint32 length = a->getLength();
- for (quint32 i = 0; i < length; ++i) {
- v = a->getIndexed(i);
- result.append(variantFromJS(v, visitedObjects));
- }
-
- visitedObjects.remove(a);
-
- return result;
-}
-
// Converts a QVariantMap to JS.
// The result is a new Object object with property names being
// the keys of the QVariantMap, and values being the values of
@@ -596,43 +639,6 @@ QV4::ReturnedValue QV8Engine::variantMapToJS(const QVariantMap &vmap)
return o.asReturnedValue();
}
-// Converts a JS Object to a QVariantMap.
-// The result is a QVariantMap with keys being the property names
-// of the object, and values being the values of the JS object's
-// properties converted to QVariants, recursively.
-QVariantMap QV8Engine::variantMapFromJS(QV4::Object *o, V8ObjectSet &visitedObjects)
-{
- QVariantMap result;
-
- if (!o || o->asFunctionObject())
- return result;
-
- if (visitedObjects.contains(o)) {
- // Avoid recursion.
- // For compatibility with QVariant{List,Map} conversion, we return an
- // empty object (and no error is thrown).
- return result;
- }
- QV4::Scope scope(o->engine());
-
- visitedObjects.insert(o);
-
- QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedValue name(scope);
- QV4::ScopedValue val(scope);
- while (1) {
- name = it.nextPropertyNameAsString(val);
- if (name->isNull())
- break;
-
- QString key = name->toQStringNoThrow();
- result.insert(key, variantFromJS(val, visitedObjects));
- }
-
- visitedObjects.remove(o);
- return result;
-}
-
// Converts the meta-type defined by the given type and data to JS.
// Returns the value if conversion succeeded, an empty handle otherwise.
QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data)
@@ -644,6 +650,8 @@ QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data)
case QMetaType::UnknownType:
case QMetaType::Void:
return QV4::Encode::undefined();
+ case QMetaType::VoidStar:
+ return QV4::Encode::null();
case QMetaType::Bool:
return QV4::Encode(*reinterpret_cast<const bool*>(data));
case QMetaType::Int:
@@ -805,7 +813,7 @@ bool QV8Engine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data)
case QMetaType::QVariantList: {
QV4::ScopedArrayObject a(scope, value);
if (a) {
- *reinterpret_cast<QVariantList *>(data) = variantListFromJS(a);
+ *reinterpret_cast<QVariantList *>(data) = toVariant(a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
return true;
}
break;
@@ -819,7 +827,7 @@ bool QV8Engine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data)
break;
}
case QMetaType::QVariant:
- *reinterpret_cast<QVariant*>(data) = variantFromJS(value);
+ *reinterpret_cast<QVariant*>(data) = toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
return true;
case QMetaType::QJsonValue:
*reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
@@ -915,55 +923,6 @@ QV4::ReturnedValue QV8Engine::variantToJS(const QVariant &value)
return metaTypeToJS(value.userType(), value.constData());
}
-// Converts a JS value to a QVariant.
-// Undefined -> QVariant() (invalid)
-// Null -> QVariant((void*)0)
-// Boolean -> QVariant(bool)
-// Number -> QVariant(double)
-// String -> QVariant(QString)
-// Array -> QVariantList(...)
-// Date -> QVariant(QDateTime)
-// RegExp -> QVariant(QRegExp)
-// [Any other object] -> QVariantMap(...)
-QVariant QV8Engine::variantFromJS(const QV4::ValueRef value,
- V8ObjectSet &visitedObjects)
-{
- Q_ASSERT(!value->isEmpty());
- if (value->isUndefined())
- return QVariant();
- if (value->isNull())
- return QVariant(QMetaType::VoidStar, 0);
- if (value->isBoolean())
- return value->booleanValue();
- if (value->isInteger())
- return value->integerValue();
- if (value->isNumber())
- return value->asDouble();
- if (value->isString())
- return value->stringValue()->toQString();
-
- Q_ASSERT(value->isObject());
- QV4::Scope scope(value->engine());
-
- if (value->asArrayObject()) {
- QV4::ScopedArrayObject a(scope, value);
- return variantListFromJS(a, visitedObjects);
- }
- if (QV4::DateObject *d = value->asDateObject())
- return d->toQDateTime();
- if (QV4::RegExpObject *re = value->as<QV4::RegExpObject>())
- return re->toQRegExp();
- if (QV4::VariantObject *v = value->as<QV4::VariantObject>())
- return v->d()->data;
- if (value->as<QV4::QObjectWrapper>())
- return qVariantFromValue(qtObjectFromJS(value));
- if (QV4::QmlValueTypeWrapper *v = value->as<QV4::QmlValueTypeWrapper>())
- return v->toVariant();
- QV4::ScopedObject o(scope, value);
- return variantMapFromJS(o, visitedObjects);
-}
-
-
bool QV8Engine::convertToNativeQObject(const QV4::ValueRef value, const QByteArray &targetType, void **result)
{
if (!targetType.endsWith('*'))
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index e2c96ffc87..51e857c8a2 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -197,9 +197,13 @@ public:
void freezeObject(const QV4::ValueRef value);
- QVariant toVariant(const QV4::ValueRef value, int typeHint);
+ QVariant toVariant(const QV4::ValueRef value, int typeHint, bool createJSValueForObjects = true, V8ObjectSet *visitedObjects = 0);
+ QVariant objectToVariant(QV4::Object *o, V8ObjectSet *visitedObjects = 0);
QV4::ReturnedValue fromVariant(const QVariant &);
+ QVariantMap variantMapFromJS(QV4::Object *o)
+ { return objectToVariant(o).toMap(); }
+
// Return a JS string for the given QString \a string
QV4::ReturnedValue toString(const QString &string);
@@ -218,16 +222,8 @@ public:
void setExtensionData(int, Deletable *);
QV4::ReturnedValue variantListToJS(const QVariantList &lst);
- inline QVariantList variantListFromJS(QV4::ArrayObject *array)
- { V8ObjectSet visitedObjects; return variantListFromJS(array, visitedObjects); }
-
QV4::ReturnedValue variantMapToJS(const QVariantMap &vmap);
- inline QVariantMap variantMapFromJS(QV4::Object *object)
- { V8ObjectSet visitedObjects; return variantMapFromJS(object, visitedObjects); }
-
QV4::ReturnedValue variantToJS(const QVariant &value);
- inline QVariant variantFromJS(const QV4::ValueRef value)
- { V8ObjectSet visitedObjects; return variantFromJS(value, visitedObjects); }
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
bool metaTypeFromJS(const QV4::ValueRef value, int type, void *data);
@@ -265,15 +261,9 @@ protected:
QHash<QString, quint32> m_consoleCount;
- QVariant toBasicVariant(const QV4::ValueRef);
-
void initializeGlobal();
private:
- QVariantList variantListFromJS(QV4::ArrayObject *array, V8ObjectSet &visitedObjects);
- QVariantMap variantMapFromJS(QV4::Object *object, V8ObjectSet &visitedObjects);
- QVariant variantFromJS(const QV4::ValueRef value, V8ObjectSet &visitedObjects);
-
Q_DISABLE_COPY(QV8Engine)
};
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 602e5cf14e..9ba610b9ba 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -72,7 +72,7 @@ public:
\ingroup qtquick-interceptors
\brief Enables the arbitrary creation of property bindings
- \section1 Binding to an inaccessible property
+ \section1 Binding to an Inaccessible Property
Sometimes it is necessary to bind to a property of an object that wasn't
directly instantiated by QML - generally a property of a class exported
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 25879972ca..142625d7ae 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -1330,6 +1330,11 @@ void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int>
QVariant value = object[key];
+ // A JS array/object is translated into a (hierarchical) QQmlListModel,
+ // so translate to a variant map/list first with toVariant().
+ if (value.userType() == qMetaTypeId<QJSValue>())
+ value = value.value<QJSValue>().toVariant();
+
if (value.type() == QVariant::List) {
QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);
@@ -1392,6 +1397,12 @@ void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
QQmlListModel *parentModel = m_owner->m_owner;
QVariant v = value(index);
+
+ // A JS array/object is translated into a (hierarchical) QQmlListModel,
+ // so translate to a variant map/list first with toVariant().
+ if (v.userType() == qMetaTypeId<QJSValue>())
+ v= v.value<QJSValue>().toVariant();
+
if (v.type() == QVariant::List) {
QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
index cdc8f2393f..d2f47c41b2 100644
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ b/src/qml/types/qqmlobjectmodel.cpp
@@ -138,6 +138,7 @@ public:
The example below places three colored rectangles in a ListView.
\code
import QtQuick 2.0
+ import QtQml.Models 2.1
Rectangle {
ObjectModel {
diff --git a/src/qml/util/qqmllistaccessor.cpp b/src/qml/util/qqmllistaccessor.cpp
index e434d6cef4..5a199abf44 100644
--- a/src/qml/util/qqmllistaccessor.cpp
+++ b/src/qml/util/qqmllistaccessor.cpp
@@ -61,6 +61,11 @@ void QQmlListAccessor::setList(const QVariant &v, QQmlEngine *engine)
{
d = v;
+ // An incoming JS array as model is treated as a variant list, so we need to
+ // convert it first with toVariant().
+ if (d.userType() == qMetaTypeId<QJSValue>())
+ d = d.value<QJSValue>().toVariant();
+
QQmlEnginePrivate *enginePrivate = engine?QQmlEnginePrivate::get(engine):0;
if (!d.isValid()) {
@@ -73,7 +78,7 @@ void QQmlListAccessor::setList(const QVariant &v, QQmlEngine *engine)
m_type = Integer;
} else if ((!enginePrivate && QQmlMetaType::isQObject(d.userType())) ||
(enginePrivate && enginePrivate->isQObject(d.userType()))) {
- QObject *data = enginePrivate?enginePrivate->toQObject(v):QQmlMetaType::toQObject(v);
+ QObject *data = enginePrivate?enginePrivate->toQObject(d):QQmlMetaType::toQObject(d);
d = QVariant::fromValue(data);
m_type = Instance;
} else if (d.userType() == qMetaTypeId<QQmlListReference>()) {
diff --git a/src/quick/doc/images/qml-blending-layered.png b/src/quick/doc/images/qml-blending-layered.png
new file mode 100644
index 0000000000..fa1c24a98e
--- /dev/null
+++ b/src/quick/doc/images/qml-blending-layered.png
Binary files differ
diff --git a/src/quick/doc/images/qml-blending-nonlayered.png b/src/quick/doc/images/qml-blending-nonlayered.png
new file mode 100644
index 0000000000..265abf6530
--- /dev/null
+++ b/src/quick/doc/images/qml-blending-nonlayered.png
Binary files differ
diff --git a/src/quick/doc/images/qml-shadereffect-layereffect.png b/src/quick/doc/images/qml-shadereffect-layereffect.png
new file mode 100644
index 0000000000..44b05a9949
--- /dev/null
+++ b/src/quick/doc/images/qml-shadereffect-layereffect.png
Binary files differ
diff --git a/src/quick/doc/images/qml-shadereffect-nolayereffect.png b/src/quick/doc/images/qml-shadereffect-nolayereffect.png
new file mode 100644
index 0000000000..f21e3f0c4e
--- /dev/null
+++ b/src/quick/doc/images/qml-shadereffect-nolayereffect.png
Binary files differ
diff --git a/src/quick/doc/images/qml-shadereffect-opacitymask.png b/src/quick/doc/images/qml-shadereffect-opacitymask.png
new file mode 100644
index 0000000000..e056aa763b
--- /dev/null
+++ b/src/quick/doc/images/qml-shadereffect-opacitymask.png
Binary files differ
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index 5b8388f977..d54e5feecb 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -62,9 +62,9 @@ headerdirs += ../../plugins
sourcedirs += ../../plugins
#exclude certain directories
-excludedirs += ../../imports/dialogs \
- ../../imports/models \
- ../../../examples/quick/dialogs
+excludedirs += ../../imports/models
+
+examples.fileextensions += "*.qm"
manifestmeta.thumbnail.names += "QtQuick/Threaded ListModel Example"
diff --git a/src/quick/doc/snippets/qml/layerblending.qml b/src/quick/doc/snippets/qml/layerblending.qml
new file mode 100644
index 0000000000..0ef23465a5
--- /dev/null
+++ b/src/quick/doc/snippets/qml/layerblending.qml
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Gunnar Sletta <gunnar@sletta.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation 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 Digia Plc 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
+
+Item {
+ width: 300
+ height: 200
+
+ // The checkers background
+ ShaderEffect {
+ id: tileBackground
+ anchors.fill: parent
+
+ property real tileSize: 10
+ property color color1: Qt.rgba(0.9, 0.9, 0.9, 1);
+ property color color2: Qt.rgba(0.85, 0.85, 0.85, 1);
+
+ property size pixelSize: Qt.size(width / tileSize, height / tileSize);
+
+ fragmentShader:
+ "
+ uniform lowp vec4 color1;
+ uniform lowp vec4 color2;
+ uniform highp vec2 pixelSize;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ if (tc.x != tc.y)
+ gl_FragColor = color1;
+ else
+ gl_FragColor = color2;
+ }
+ "
+ }
+
+
+ Row {
+ height: 100
+ anchors.centerIn: parent
+ spacing: 50
+
+//! [non-layered]
+Item {
+ id: nonLayered
+
+ opacity: 0.5
+
+ width: 100
+ height: 100
+
+ Rectangle { width: 80; height: 80; border.width: 1 }
+ Rectangle { x: 20; y: 20; width: 80; height: 80; border.width: 1 }
+}
+//! [non-layered]
+
+//! [layered]
+Item {
+ id: layered
+
+ opacity: 0.5
+
+ layer.enabled: true
+
+ width: 100
+ height: 100
+
+ Rectangle { width: 80; height: 80; border.width: 1 }
+ Rectangle { x: 20; y: 20; width: 80; height: 80; border.width: 1 }
+}
+//! [layered]
+
+ }
+}
diff --git a/src/quick/doc/snippets/qml/layerwitheffect.qml b/src/quick/doc/snippets/qml/layerwitheffect.qml
new file mode 100644
index 0000000000..8cfac0bb19
--- /dev/null
+++ b/src/quick/doc/snippets/qml/layerwitheffect.qml
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Gunnar Sletta <gunnar@sletta.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation 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 Digia Plc 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.2
+
+Rectangle {
+ id: root
+ width: 320
+ height: 320
+
+ gradient: Gradient {
+ GradientStop { position: 0; color: "steelblue" }
+ GradientStop { position: 1; color: "black" }
+ }
+
+ property real cx: width / 2;
+ property real cy: height / 2;
+ property real boxSize: root.width * 0.2;
+ property real radius: width / 4;
+
+
+//! [1]
+Item {
+ id: layerRoot
+ layer.enabled: true
+ layer.effect: ShaderEffect {
+ fragmentShader: "
+ uniform lowp sampler2D source; // this item
+ uniform lowp float qt_Opacity; // inherited opacity of this item
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ lowp vec4 p = texture2D(source, qt_TexCoord0);
+ lowp float g = dot(p.xyz, vec3(0.344, 0.5, 0.156));
+ gl_FragColor = vec4(g, g, g, p.a) * qt_Opacity;
+ }"
+ }
+//! [1]
+
+ anchors.fill: parent
+
+
+ Repeater {
+ id: repeater
+ model: 200
+
+ Rectangle {
+ id: box
+
+ property real t: index / (repeater.model - 1);
+
+ width: 0
+ height: 0
+ x: root.cx - Math.sin(Math.PI * 2 * t) * root.radius;
+ y: root.cy - Math.cos(Math.PI * 2 * t) * root.radius;
+
+ Rectangle {
+ width: root.boxSize
+ height: root.boxSize
+ anchors.centerIn: parent
+ color: Qt.hsla(box.t, 0.5, 0.5);
+ border.color: "white"
+ antialiasing: true;
+ rotation: box.t * 360;
+// RotationAnimator on rotation {
+// from: box.t * 360;
+// to: box.t * 360 + 360;
+// duration: 7592;
+// loops: Animation.Infinite
+// }
+ }
+ }
+ }
+ }
+}
diff --git a/src/quick/doc/snippets/qml/opacitymask.qml b/src/quick/doc/snippets/qml/opacitymask.qml
new file mode 100644
index 0000000000..e458f810ea
--- /dev/null
+++ b/src/quick/doc/snippets/qml/opacitymask.qml
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Gunnar Sletta <gunnar@sletta.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the documentation 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 Digia Plc 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
+
+Item {
+ id: root
+ width: 480
+ height: 320
+
+ // The checkers background
+ ShaderEffect {
+ id: tileBackground
+ anchors.fill: parent
+
+ property real tileSize: 20
+ property color color1: Qt.hsla(0, 0, 0.1);
+ property color color2: Qt.hsla(0, 0, 0.2);
+
+ property size pixelSize: Qt.size(width / tileSize, height / tileSize);
+
+ fragmentShader:
+ "
+ uniform lowp vec4 color1;
+ uniform lowp vec4 color2;
+ uniform highp vec2 pixelSize;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ highp vec2 tc = sign(sin(3.14152 * qt_TexCoord0 * pixelSize));
+ if (tc.x != tc.y)
+ gl_FragColor = color1;
+ else
+ gl_FragColor = color2;
+ }
+ "
+ }
+
+//! [1]
+ Rectangle {
+ id: gradientRect;
+ width: 10
+ height: 10
+ gradient: Gradient {
+ GradientStop { position: 0; color: "white" }
+ GradientStop { position: 1; color: "steelblue" }
+ }
+ visible: false; // should not be visible on screen.
+ layer.enabled: true;
+ layer.smooth: true
+ }
+
+ Text {
+ id: textItem
+ font.pixelSize: 48
+ text: "Gradient Text"
+ anchors.centerIn: parent
+ layer.enabled: true
+ // This item should be used as the 'mask'
+ layer.samplerName: "maskSource"
+ layer.effect: ShaderEffect {
+ property var colorSource: gradientRect;
+ fragmentShader: "
+ uniform lowp sampler2D colorSource;
+ uniform lowp sampler2D maskSource;
+ uniform lowp float qt_Opacity;
+ varying highp vec2 qt_TexCoord0;
+ void main() {
+ gl_FragColor =
+ texture2D(colorSource, qt_TexCoord0)
+ * texture2D(maskSource, qt_TexCoord0).a
+ * qt_Opacity;
+ }
+ "
+ }
+ }
+//! [1]
+}
diff --git a/src/quick/doc/src/concepts/input/focus.qdoc b/src/quick/doc/src/concepts/input/focus.qdoc
index 065651c826..748c8eb53c 100644
--- a/src/quick/doc/src/concepts/input/focus.qdoc
+++ b/src/quick/doc/src/concepts/input/focus.qdoc
@@ -172,7 +172,7 @@ See \l{Qt Quick Examples - Key Interaction} for a
demonstration of moving keyboard focus between multiple areas using FocusScope
types.
-\section1 Advanced uses of Focus Scopes
+\section1 Advanced Uses of Focus Scopes
Focus scopes allow focus to allocation to be easily partitioned. Several
QML items use it to this effect.
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index 49e4998ee1..dcc7a592e6 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -146,14 +146,14 @@ within the Qt install directory.
QAbstractItemModel presents a hierarchy of tables, but the views currently provided by QML
can only display list data.
In order to display the child lists of a hierarchical model,
-use the VisualDataModel type, which provides the following properties and functions to be used
+use the DelegateModel QML type, which provides the following properties and functions to be used
with list models of QAbstractItemModel type:
\list
\li \e hasModelChildren role property to determine whether a node has child nodes.
-\li \l VisualDataModel::rootIndex allows the root node to be specified
-\li \l VisualDataModel::modelIndex() returns a QModelIndex which can be assigned to VisualDataModel::rootIndex
-\li \l VisualDataModel::parentModelIndex() returns a QModelIndex which can be assigned to VisualDataModel::rootIndex
+\li \l DelegateModel::rootIndex allows the root node to be specified
+\li \l DelegateModel::modelIndex() returns a QModelIndex which can be assigned to DelegateModel::rootIndex
+\li \l DelegateModel::parentModelIndex() returns a QModelIndex which can be assigned to DelegateModel::rootIndex
\endlist
\section2 Exposing C++ Data Models to QML
diff --git a/src/quick/doc/src/concepts/positioning/righttoleft.qdoc b/src/quick/doc/src/concepts/positioning/righttoleft.qdoc
index 8f55cc8dd7..d6b1753ee3 100644
--- a/src/quick/doc/src/concepts/positioning/righttoleft.qdoc
+++ b/src/quick/doc/src/concepts/positioning/righttoleft.qdoc
@@ -69,7 +69,7 @@ the effective alignment of the text element that takes the mirroring into accoun
\snippet qml/righttoleft.qml 0
-\section1 Layout direction of positioners and views
+\section1 Layout Direction of Positioners and Views
(This applies to the \l Row, \l Grid, \l Flow, \l ListView and \l GridView types.)
@@ -85,7 +85,7 @@ views that takes the mirroring into account can be read from the \c effectiveLay
\snippet qml/righttoleft.qml 1
-\section1 Layout mirroring
+\section1 Layout Mirroring
The attached property \l LayoutMirroring is provided as a convenience for easily implementing right-to-left
support for existing left-to-right Qt Quick applications. It mirrors the behavior of \l {anchor-layout}
@@ -127,7 +127,7 @@ the animations and transitions continue to work as expected. If you do not have
right-to-left support for your application, it may be better to just keep the application layouts left
aligned and just make sure that text is translated and aligned properly.
-\section1 Mirroring icons
+\section1 Mirroring Icons
(This applies to \l Image, \l BorderImage and \l AnimatedImage types.)
@@ -136,7 +136,7 @@ The painting of these icons can be mirrored with a dedicated \c mirror property
\snippet qml/righttoleft.qml 5
-\section1 Default layout direction
+\section1 Default Layout Direction
The \l {QtQml::Qt::application}{Qt.application.layoutDirection} property can be used to query the active layout direction of the
application. It is based on QGuiApplication::layoutDirection(), which most commonly determines the layout
diff --git a/src/quick/doc/src/dynamicview-tutorial.qdoc b/src/quick/doc/src/dynamicview-tutorial.qdoc
index cf1115cf4a..619f0abd4b 100644
--- a/src/quick/doc/src/dynamicview-tutorial.qdoc
+++ b/src/quick/doc/src/dynamicview-tutorial.qdoc
@@ -136,7 +136,7 @@ so that is above other items in the stacking order and isn't obscured as it is d
The next step in our application to move items within the list as they're dragged so that we
can re-order the list. To achieve this we introduce three new types to our application;
-VisualDataModel, \l Drag and DropArea.
+DelegateModel, \l Drag and DropArea.
\snippet tutorials/dynamicview/dynamicview3/dynamicview.qml 0
\snippet tutorials/dynamicview/dynamicview3/dynamicview.qml 1
@@ -162,17 +162,17 @@ to the index of the item it was dragged over.
\snippet tutorials/dynamicview/dynamicview3/dynamicview.qml 3
-To move the items within the view we use a VisualDataModel. The VisualDataModel type is used by
+To move the items within the view we use a DelegateModel. The DelegateModel type is used by
the view types to instantiate delegate items from model data and when constructed explicitly can
be used to filter and re-order the model items provided to ListView. The
-\l {QtQuick::VisualDataModel::items}{items} property of VisualDataModel provides access to the
+\l {QtQuick::DelegateModel::items}{items} property of DelegateModel provides access to the
view's items and allows us to change the visible order without modifying the source model. To
-determine the current visible index of the items we use \l {QtQuick::VisualDataModel::itemsIndex}
-{itemsIndex} property on the VisualDataModel attached property of the delegate item.
+determine the current visible index of the items we use \l {QtQuick::DelegateModel::itemsIndex}
+{itemsIndex} property on the DelegateModel attached property of the delegate item.
-To utilize a VisualDataModel with a ListView we bind it to the \l {QtQuick::ListView::model}{model}
-property of the view and bind the \l {QtQuick::VisualDataModel::model}{model} and
-\l {QtQuick::VisualDataModel::delegate}{delegate} to the VisualDataModel.
+To utilize a DelegateModel with a ListView we bind it to the \l {QtQuick::ListView::model}{model}
+property of the view and bind the \l {QtQuick::DelegateModel::model}{model} and
+\l {QtQuick::DelegateModel::delegate}{delegate} to the DelegateModel.
\snippet tutorials/dynamicview/dynamicview3/dynamicview.qml 4
@@ -185,16 +185,16 @@ property of the view and bind the \l {QtQuick::VisualDataModel::model}{model} an
\example tutorials/dynamicview/dynamicview4
-Drag and drop isn't the only way items in a view can be re-ordered, using a VisualDataModel it is
-also possible to sort items based on model data. To do that we extend our VisualDataModel instance
+Drag and drop isn't the only way items in a view can be re-ordered, using a DelegateModel it is
+also possible to sort items based on model data. To do that we extend our DelegateModel instance
like this:
\snippet tutorials/dynamicview/dynamicview4/dynamicview.qml 0
\section2 Walkthrough
-Items in a VisualDataModel are filtered into groups represented by the VisualDataGroup type,
-normally all items in the model belong to a default \l {QtQuick::VisualDataModel::items}{items}
+Items in a DelegateModel are filtered into groups represented by the DelegateModelGroup type,
+normally all items in the model belong to a default \l {QtQuick::DelegateModel::items}{items}
group but this default can be changed with the includeByDefault property. To implement our sorting
we want items to first be added to an unsorted group from where we can transfer them to a sorted
position in the items group. To do that we clear includeByDefault on the items group and set it on
@@ -208,7 +208,7 @@ item and then transfer the item to the items group before moving it to the pre-d
repeat until the unsorted group is empty.
To find the insert position for an item we request a handle for the item from the unsorted group
-with the \l {QtQuick::VisualDataModel::get} {get} function. Through the model property on this
+with the \l {QtQuick::DelegateModel::get} {get} function. Through the model property on this
handle we can access the same model data that is available in a delegate instance of that item and
compare against other items to determine relative position.
@@ -219,8 +219,8 @@ of the list. In this example it can be one of the following:
\snippet tutorials/dynamicview/dynamicview4/dynamicview.qml 4
-A sort is triggered whenever new items are added to the unsorted VisualDataGroup which we are
-notified of by the \l {QtQuick::VisualDataGroup::onChanged}{onChanged} handler. If no sort
+A sort is triggered whenever new items are added to the unsorted DelegateModel which we are
+notified of by the \l {QtQuick::DelegateModelGroup::onChanged}{onChanged} handler. If no sort
function is currently selected we simply transfer all items from the unsorted group to the items
group, otherwise we call sort with the selected sort function.
@@ -228,8 +228,8 @@ group, otherwise we call sort with the selected sort function.
Finally when the selected sort order changes we can trigger a full re-sort of the list by moving
all items from the items group to the unsorted group, which will trigger the
-\l {QtQuick::VisualDataGroup::onChanged}{onChanged} handler and transfer the items back to the
-items group in correct order. Note that the \l {QtQuick::VisualDataGroup::onChanged}{onChanged}
+\l {QtQuick::DelegateModelGroup::onChanged}{onChanged} handler and transfer the items back to the
+items group in correct order. Note that the \l {QtQuick::DelegateModelGroup::onChanged}{onChanged}
handler will not be invoked recursively so there's no issue with it being invoked during a sort.
\snippet tutorials/dynamicview/dynamicview4/dynamicview.qml 6
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 8249e268e8..15eb28350e 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -275,7 +275,7 @@ QQuickCanvasItemPrivate::~QQuickCanvasItemPrivate()
\l{http://en.wikipedia.org/wiki/Screen_tearing}{screen tearing}) which will further
impact pixel operations with \c Canvas.FrambufferObject render target.
- \section1 Tips for Porting Existing HTML5 Canvas applications
+ \section1 Tips for Porting Existing HTML5 Canvas Applications
Although the Canvas item is provides a HTML5 like API, HTML5 canvas
applications need to be modified to run in the Canvas item:
@@ -667,7 +667,10 @@ void QQuickCanvasItem::itemChange(QQuickItem::ItemChange change, const QQuickIte
return;
d->window = value.window;
- if (d->window->isSceneGraphInitialized())
+ QSGRenderContext *context = QQuickWindowPrivate::get(d->window)->context;
+
+ // Rendering to FramebufferObject needs a valid OpenGL context.
+ if (context != 0 && (d->renderTarget != FramebufferObject || context->isValid()))
sceneGraphInitialized();
else
connect(d->window, SIGNAL(sceneGraphInitialized()), SLOT(sceneGraphInitialized()));
@@ -746,7 +749,7 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
QQuickContext2D *ctx = qobject_cast<QQuickContext2D *>(d->context);
QQuickContext2DTexture *factory = ctx->texture();
- QSGTexture *texture = factory->textureForNextFrame(node->texture());
+ QSGTexture *texture = factory->textureForNextFrame(node->texture(), window());
if (!texture) {
delete node;
d->node = 0;
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 28c84facb5..d9ac3abdc3 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -3548,7 +3548,7 @@ void QQuickContext2D::clip()
state.clip = true;
state.clipPath = clipPath;
}
- buffer()->clip(state.clipPath);
+ buffer()->clip(state.clip, state.clipPath);
}
void QQuickContext2D::stroke()
@@ -4283,8 +4283,8 @@ void QQuickContext2D::popState()
if (newState.miterLimit != state.miterLimit)
buffer()->setMiterLimit(newState.miterLimit);
- if (newState.clip && (!state.clip || newState.clipPath != state.clipPath))
- buffer()->clip(newState.clipPath);
+ if (newState.clip != state.clip || newState.clipPath != state.clipPath)
+ buffer()->clip(newState.clip, newState.clipPath);
if (newState.shadowBlur != state.shadowBlur)
buffer()->setShadowBlur(newState.shadowBlur);
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index 3fb230b928..eac5e2cef8 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -207,6 +207,7 @@ void QQuickContext2DCommandBuffer::setPainterState(QPainter* p, const QQuickCont
if (state.globalCompositeOperation != p->compositionMode())
p->setCompositionMode(state.globalCompositeOperation);
+ p->setClipping(state.clip);
if (state.clip)
p->setClipPath(state.clipPath);
}
@@ -383,9 +384,11 @@ void QQuickContext2DCommandBuffer::replay(QPainter* p, QQuickContext2D::State& s
}
case QQuickContext2D::Clip:
{
+ state.clip = takeBool();
state.clipPath = takePath();
- p->setClipping(true);
- p->setClipPath(state.clipPath);
+ p->setClipping(state.clip);
+ if (state.clip)
+ p->setClipPath(state.clipPath);
break;
}
case QQuickContext2D::GlobalAlpha:
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
index 9b2fde33d8..4e6232ac7f 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -145,9 +145,10 @@ public:
pathes << path;
}
- inline void clip(const QPainterPath& path)
+ inline void clip(bool enabled, const QPainterPath& path)
{
commands << QQuickContext2D::Clip;
+ bools << enabled;
pathes << path;
}
diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp
index a3b316a217..1dd8e50387 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture.cpp
+++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp
@@ -427,7 +427,7 @@ QVector2D QQuickContext2DFBOTexture::scaleFactor() const
m_fbo->height() / m_fboSize.height());
}
-QSGTexture *QQuickContext2DFBOTexture::textureForNextFrame(QSGTexture *lastTexture)
+QSGTexture *QQuickContext2DFBOTexture::textureForNextFrame(QSGTexture *lastTexture, QQuickWindow *)
{
QSGPlainTexture *texture = static_cast<QSGPlainTexture *>(lastTexture);
@@ -666,22 +666,15 @@ void QQuickContext2DImageTexture::grabImage(const QRectF& rf)
QQuickContext2D::mutex.unlock();
}
-QSGTexture *QQuickContext2DImageTexture::textureForNextFrame(QSGTexture *last)
+QSGTexture *QQuickContext2DImageTexture::textureForNextFrame(QSGTexture *last, QQuickWindow *window)
{
- QSGPlainTexture *texture = static_cast<QSGPlainTexture *>(last);
-
if (m_onCustomThread)
m_mutex.lock();
- if (!texture) {
- texture = new QSGPlainTexture();
- texture->setHasAlphaChannel(true);
- m_dirtyTexture = true;
- }
- if (m_dirtyTexture) {
- texture->setImage(m_displayImage);
- m_dirtyTexture = false;
- }
+ delete last;
+
+ QSGTexture *texture = window->createTextureFromImage(m_displayImage, QQuickWindow::TextureCanUseAtlas);
+ m_dirtyTexture = false;
if (m_onCustomThread)
m_mutex.unlock();
diff --git a/src/quick/items/context2d/qquickcontext2dtexture_p.h b/src/quick/items/context2d/qquickcontext2dtexture_p.h
index 10ac246d1b..3ff0cb12c1 100644
--- a/src/quick/items/context2d/qquickcontext2dtexture_p.h
+++ b/src/quick/items/context2d/qquickcontext2dtexture_p.h
@@ -102,7 +102,7 @@ public:
bool isOnCustomThread() const { return m_onCustomThread; }
// Called during sync() on the scene graph thread while GUI is blocked.
- virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame) = 0;
+ virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame, QQuickWindow *window) = 0;
bool event(QEvent *e);
void initializeOpenGL(QOpenGLContext *gl, QOffscreenSurface *s) {
@@ -173,7 +173,7 @@ public:
virtual void compositeTile(QQuickContext2DTile* tile);
QSize adjustedTileSize(const QSize &ts);
- QSGTexture *textureForNextFrame(QSGTexture *);
+ QSGTexture *textureForNextFrame(QSGTexture *, QQuickWindow *window);
protected:
QVector2D scaleFactor() const Q_DECL_OVERRIDE;
@@ -209,7 +209,7 @@ public:
virtual void endPainting();
virtual void compositeTile(QQuickContext2DTile* tile);
- virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame);
+ virtual QSGTexture *textureForNextFrame(QSGTexture *lastFrame, QQuickWindow *window);
public Q_SLOTS:
virtual void grabImage(const QRectF& region = QRectF());
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 50a0a76267..8d8e4b6a02 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -562,7 +562,9 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
// Don't implicitly create the scalegrid in the rendering thread...
QRectF innerSourceRect(0, 0, 1, 1);
QRectF innerTargetRect(0, 0, width(), height());
- int borderLeft, borderTop, borderRight, borderBottom;
+ int borderLeft = 0, borderTop = 0, borderRight = 0, borderBottom = 0;
+
+ bool updateNode = !oldNode;
if (d->border) {
const QQuickScaleGrid *border = d->getScaleGrid();
@@ -579,11 +581,17 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
borderTop,
qMax<qreal>(0, width() - border->right() - border->left()),
qMax<qreal>(0, height() - border->bottom() - border->top()));
+
+ if (innerSourceRect != d->oldInnerSourceRect || innerTargetRect != d->oldInnerTargetRect)
+ updateNode = true;
+ d->oldInnerSourceRect = innerSourceRect;
+ d->oldInnerTargetRect = innerTargetRect;
}
bool updatePixmap = d->pixmapChanged;
d->pixmapChanged = false;
- if (!oldNode) {
+ if (updateNode) {
+ delete oldNode;
oldNode = new QSGNode;
updatePixmap = true;
@@ -591,33 +599,130 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
d->regions[i].node = 0;
if (innerSourceRect.left() > 0) {
- if (innerSourceRect.top() > 0)
- d->regions[0].node = d->sceneGraphContext()->createImageNode();
- if (innerSourceRect.bottom() < 1)
- d->regions[6].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.top() > 0) {
+ QRectF rect(0,
+ 0,
+ innerTargetRect.left(),
+ innerTargetRect.top());
+
+ if (!rect.isEmpty()) {
+ d->regions[0].node = d->sceneGraphContext()->createImageNode();
+ d->regions[0].node->setTargetRect(rect);
+ d->regions[0].node->setInnerTargetRect(rect);
+ d->regions[0].targetRect = rect;
+ }
+ }
+
+ if (innerSourceRect.bottom() < 1) {
+ QRectF rect(0,
+ innerTargetRect.bottom(),
+ innerTargetRect.left(),
+ height() - innerTargetRect.height() - innerTargetRect.top());
+
+ if (!rect.isEmpty()) {
+ d->regions[6].node = d->sceneGraphContext()->createImageNode();
+ d->regions[6].node->setTargetRect(rect);
+ d->regions[6].node->setInnerTargetRect(rect);
+ d->regions[6].targetRect = rect;
+ }
+ }
- if (innerSourceRect.top() < innerSourceRect.bottom())
- d->regions[3].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.top() < innerSourceRect.bottom()) {
+ QRectF rect(0,
+ innerTargetRect.top(),
+ innerTargetRect.left(),
+ innerTargetRect.height());
+
+ if (!rect.isEmpty()) {
+ d->regions[3].node = d->sceneGraphContext()->createImageNode();
+ d->regions[3].node->setTargetRect(rect);
+ d->regions[3].node->setInnerTargetRect(rect);
+ d->regions[3].targetRect = rect;
+ }
+ }
}
if (innerSourceRect.right() < 1) {
- if (innerSourceRect.top() > 0)
- d->regions[2].node = d->sceneGraphContext()->createImageNode();
- if (innerSourceRect.bottom() < 1)
- d->regions[8].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.top() > 0) {
+ QRectF rect(innerTargetRect.right(),
+ 0,
+ width() - innerTargetRect.width() - innerTargetRect.left(),
+ innerTargetRect.top());
+
+ if (!rect.isEmpty()) {
+ d->regions[2].node = d->sceneGraphContext()->createImageNode();
+ d->regions[2].node->setTargetRect(rect);
+ d->regions[2].node->setInnerTargetRect(rect);
+ d->regions[2].targetRect = rect;
+ }
+ }
- if (innerSourceRect.top() < innerSourceRect.bottom())
- d->regions[5].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.bottom() < 1) {
+ QRectF rect(innerTargetRect.right(),
+ innerTargetRect.bottom(),
+ width() - innerTargetRect.width() - innerTargetRect.left(),
+ height() - innerTargetRect.height() - innerTargetRect.top());
+
+ if (!rect.isEmpty()) {
+ d->regions[8].node = d->sceneGraphContext()->createImageNode();
+ d->regions[8].node->setTargetRect(rect);
+ d->regions[8].node->setInnerTargetRect(rect);
+ d->regions[8].targetRect = rect;
+ }
+ }
+
+ if (innerSourceRect.top() < innerSourceRect.bottom()) {
+ QRectF rect(innerTargetRect.right(),
+ innerTargetRect.top(),
+ width() - innerTargetRect.width() - innerTargetRect.left(),
+ innerTargetRect.height());
+
+ if (!rect.isEmpty()) {
+ d->regions[5].node = d->sceneGraphContext()->createImageNode();
+ d->regions[5].node->setTargetRect(rect);
+ d->regions[5].node->setInnerTargetRect(rect);
+ d->regions[5].targetRect = rect;
+ }
+ }
}
- if (innerSourceRect.top() > 0 && innerSourceRect.left() < innerSourceRect.right())
- d->regions[1].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.top() > 0 && innerSourceRect.left() < innerSourceRect.right()) {
+ QRectF rect(innerTargetRect.left(),
+ 0,
+ innerTargetRect.width(),
+ innerTargetRect.top());
+
+ if (!rect.isEmpty()) {
+ d->regions[1].node = d->sceneGraphContext()->createImageNode();
+ d->regions[1].node->setTargetRect(rect);
+ d->regions[1].node->setInnerTargetRect(rect);
+ d->regions[1].targetRect = rect;
+ }
+ }
- if (innerSourceRect.bottom() < 1 && innerSourceRect.left() < innerSourceRect.right())
- d->regions[7].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.bottom() < 1 && innerSourceRect.left() < innerSourceRect.right()) {
+ QRectF rect(innerTargetRect.left(),
+ innerTargetRect.bottom(),
+ innerTargetRect.width(),
+ height() - innerTargetRect.height() - innerTargetRect.top());
+
+ if (!rect.isEmpty()) {
+ d->regions[7].node = d->sceneGraphContext()->createImageNode();
+ d->regions[7].node->setTargetRect(rect);
+ d->regions[7].node->setInnerTargetRect(rect);
+ d->regions[7].targetRect = rect;
+ }
+ }
- if (innerSourceRect.left() < innerSourceRect.right() && innerSourceRect.top() < innerSourceRect.bottom())
- d->regions[4].node = d->sceneGraphContext()->createImageNode();
+ if (innerSourceRect.left() < innerSourceRect.right()
+ && innerSourceRect.top() < innerSourceRect.bottom()) {
+ if (!innerTargetRect.isEmpty()) {
+ d->regions[4].node = d->sceneGraphContext()->createImageNode();
+ d->regions[4].node->setInnerTargetRect(innerTargetRect);
+ d->regions[4].node->setTargetRect(innerTargetRect);
+ d->regions[4].targetRect = innerTargetRect;
+ }
+ }
for (int i=0; i<9; ++i) {
if (d->regions[i].node != 0)
@@ -638,14 +743,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[3].node == 0 && d->regions[6].node == 0)
antialiasing |= QSGImageNode::AntialiasingBottom;
d->regions[0].node->setAntialiasing(antialiasing);
-
- QRectF rect(0,
- 0,
- innerTargetRect.left(),
- innerTargetRect.top());
- d->regions[0].node->setTargetRect(rect);
- d->regions[0].node->setInnerTargetRect(rect);
- d->regions[0].targetRect = rect;
}
if (d->regions[1].node != 0) {
@@ -660,14 +757,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[4].node == 0 && d->regions[7].node == 0)
antialiasing |= QSGImageNode::AntialiasingBottom;
d->regions[1].node->setAntialiasing(antialiasing);
-
- QRectF rect(innerTargetRect.left(),
- 0,
- innerTargetRect.width(),
- innerTargetRect.top());
- d->regions[1].node->setTargetRect(rect);
- d->regions[1].node->setInnerTargetRect(rect);
- d->regions[1].targetRect = rect;
}
if (d->regions[2].node != 0) {
@@ -680,14 +769,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[5].node == 0 && d->regions[8].node == 0)
antialiasing |= QSGImageNode::AntialiasingBottom;
d->regions[2].node->setAntialiasing(antialiasing);
-
- QRectF rect(innerTargetRect.right(),
- 0,
- width() - innerTargetRect.width() - innerTargetRect.left(),
- innerTargetRect.top());
- d->regions[2].node->setTargetRect(rect);
- d->regions[2].node->setInnerTargetRect(rect);
- d->regions[2].targetRect = rect;
}
if (d->regions[3].node != 0) {
@@ -702,14 +783,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[0].node == 0)
antialiasing |= QSGImageNode::AntialiasingTop;
d->regions[3].node->setAntialiasing(antialiasing);
-
- QRectF rect(0,
- innerTargetRect.top(),
- innerTargetRect.left(),
- innerTargetRect.height());
- d->regions[3].node->setTargetRect(rect);
- d->regions[3].node->setInnerTargetRect(rect);
- d->regions[3].targetRect = rect;
}
if (d->regions[4].node != 0) {
@@ -731,10 +804,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[7].node == 0)
antialiasing |= QSGImageNode::AntialiasingBottom;
d->regions[4].node->setAntialiasing(antialiasing);
-
- d->regions[4].node->setInnerTargetRect(innerTargetRect);
- d->regions[4].node->setTargetRect(innerTargetRect);
- d->regions[4].targetRect = innerTargetRect;
}
if (d->regions[5].node != 0) {
@@ -749,14 +818,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[8].node == 0)
antialiasing |= QSGImageNode::AntialiasingBottom;
d->regions[5].node->setAntialiasing(antialiasing);
-
- QRectF rect(innerTargetRect.right(),
- innerTargetRect.top(),
- width() - innerTargetRect.width() - innerTargetRect.left(),
- innerTargetRect.height());
- d->regions[5].node->setTargetRect(rect);
- d->regions[5].node->setInnerTargetRect(rect);
- d->regions[5].targetRect = rect;
}
if (d->regions[6].node != 0) {
@@ -769,14 +830,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[3].node == 0 && d->regions[0].node == 0)
antialiasing |= QSGImageNode::AntialiasingTop;
d->regions[6].node->setAntialiasing(antialiasing);
-
- QRectF rect(0,
- innerTargetRect.bottom(),
- innerTargetRect.left(),
- height() - innerTargetRect.height() - innerTargetRect.top());
- d->regions[6].node->setTargetRect(rect);
- d->regions[6].node->setInnerTargetRect(rect);
- d->regions[6].targetRect = rect;
}
if (d->regions[7].node != 0) {
@@ -791,14 +844,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[4].node == 0 && d->regions[1].node == 0)
antialiasing |= QSGImageNode::AntialiasingTop;
d->regions[7].node->setAntialiasing(antialiasing);
-
- QRectF rect(innerTargetRect.left(),
- innerTargetRect.bottom(),
- innerTargetRect.width(),
- height() - innerTargetRect.height() - innerTargetRect.top());
- d->regions[7].node->setTargetRect(rect);
- d->regions[7].node->setInnerTargetRect(rect);
- d->regions[7].targetRect = rect;
}
if (d->regions[8].node != 0) {
@@ -811,14 +856,6 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->regions[5].node == 0 && d->regions[2].node == 0)
antialiasing |= QSGImageNode::AntialiasingTop;
d->regions[8].node->setAntialiasing(antialiasing);
-
- QRectF rect(innerTargetRect.right(),
- innerTargetRect.bottom(),
- width() - innerTargetRect.width() - innerTargetRect.left(),
- height() - innerTargetRect.height() - innerTargetRect.top());
- d->regions[8].node->setTargetRect(rect);
- d->regions[8].node->setInnerTargetRect(rect);
- d->regions[8].targetRect = rect;
}
for (int i=0; i<9; ++i) {
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index c85b1416f6..e49347351c 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -112,23 +112,23 @@ public:
\ingroup qtquick-input
\brief For specifying drag and drop events for moved Items
- Using the Drag attached property any Item can be made a source of drag and drop
+ Using the Drag attached property, any Item can be made a source of drag and drop
events within a scene.
- When a drag is \l active on an item any change in that item's position will
+ When a drag is \l active on an item, any change in that item's position will
generate a drag event that will be sent to any DropArea that intersects
with the new position of the item. Other items which implement drag and
drop event handlers can also receive these events.
The following snippet shows how an item can be dragged with a MouseArea.
- However, dragging is not limited to mouse drags, anything that can move an item
- can generate drag events, this can include touch events, animations and bindings.
+ However, dragging is not limited to mouse drags; anything that can move an item
+ can generate drag events, including touch events, animations and bindings.
\snippet qml/drag.qml 0
A drag can be terminated either by canceling it with Drag.cancel() or setting
Drag.active to false, or it can be terminated with a drop event by calling
- Drag.drop(). If the drop event is accepted Drag.drop() will return the
+ Drag.drop(). If the drop event is accepted, Drag.drop() will return the
\l {supportedActions}{drop action} chosen by the recipient of the event,
otherwise it will return Qt.IgnoreAction.
@@ -314,7 +314,8 @@ void QQuickDragAttached::setActive(bool active)
\qmlattachedproperty Object QtQuick::Drag::source
This property holds an object that is identified to recipients of drag events as
- the source of the events. By default this is the item Drag property is attached to.
+ the source of the events. By default this is the item that the Drag
+ property is attached to.
Changing the source while a drag is active will reset the sequence of drag events by
sending a drag leave event followed by a drag enter event with the new source.
diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp
index da1709f055..dc4668be3f 100644
--- a/src/quick/items/qquickframebufferobject.cpp
+++ b/src/quick/items/qquickframebufferobject.cpp
@@ -254,6 +254,7 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode
n->fbo = 0;
delete n->msDisplayFbo;
n->msDisplayFbo = 0;
+ n->invalidatePending = false;
}
}
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index db8cc0532e..e3af926e22 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -1173,7 +1173,7 @@ bool QQuickGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
fully outside the view.
- \section1 GridView layouts
+ \section1 GridView Layouts
The layout of the items in a GridView can be controlled by these properties:
diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h
index f30eacb4ac..ec2f0bb73e 100644
--- a/src/quick/items/qquickimagebase_p_p.h
+++ b/src/quick/items/qquickimagebase_p_p.h
@@ -75,6 +75,8 @@ public:
QSize sourcesize;
QSize oldSourceSize;
qreal devicePixelRatio;
+ QRectF oldInnerSourceRect;
+ QRectF oldInnerTargetRect;
bool async : 1;
bool cache : 1;
bool mirror: 1;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index d45fb31fd9..b8362c9dac 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -397,7 +397,7 @@ void QQuickItemKeyFilter::componentComplete()
\c KeyNavigation.BeforeItem allows the event to be used for key navigation
before the item, rather than after.
- If item to which the focus is switching is not enabled or visible, an attempt will
+ If the item to which the focus is switching is not enabled or visible, an attempt will
be made to skip this item and focus on the next. This is possible if there are
a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled
or visible, they will also be skipped.
@@ -405,7 +405,7 @@ void QQuickItemKeyFilter::componentComplete()
KeyNavigation will implicitly set the other direction to return focus to this item. So if you set
\l left to another item, \l right will be set on that item's KeyNavigation to set focus back to this
item. However, if that item's KeyNavigation has had right explicitly set then no change will occur.
- This means that the above example could have been written, with the same behaviour, without specifying
+ This means that the example above could achieve the same behavior without specifying
KeyNavigation.right or KeyNavigation.down for any of the items.
\sa {Keys}{Keys attached property}
@@ -887,6 +887,8 @@ bool QQuickKeysAttached::isConnected(const char *signalName)
handling. If the item accepts the key event it will not be
handled by the Keys attached property handler.
\endlist
+
+ \sa {Key Handling Priorities}
*/
/*!
@@ -914,6 +916,9 @@ bool QQuickKeysAttached::isConnected(const char *signalName)
focus: true
}
\endqml
+
+ To see the order in which events are received when using forwardTo, see
+ \l {Key Handling Priorities}.
*/
/*!
@@ -1833,6 +1838,101 @@ void QQuickItemPrivate::updateSubFocusItem(QQuickItem *scope, bool focus)
their layouts.
See LayoutMirroring for more details.
+
+ \section1 Item Layers
+
+ An Item will normally be rendered directly into the window it
+ belongs to. However, by setting \l layer.enabled, it is possible
+ to delegate the item and its entire subtree into an offscreen
+ surface. Only the offscreen surface, a texture, will be then drawn
+ into the window.
+
+ If it is desired to have a texture size different from that of the
+ item, this is possible using \l layer.textureSize. To render only
+ a section of the item into the texture, use \l
+ layer.sourceRect. It is also possible to specify \l
+ layer.sourceRect so it extends beyond the bounds of the item. In
+ this case, the exterior will be padded with transparent pixels.
+
+ The item will use linear interpolation for scaling if
+ \l layer.smooth is set to \c true and will use mipmap for
+ downsampling if \l layer.mipmap is set to \c true. Mipmapping may
+ improve visual quality of downscaled items. For mipmapping of
+ single Image items, prefer Image::mipmap.
+
+ \section2 Layer Opacity vs Item Opacity
+
+ When applying \l opacity to an item hierarchy the opacity is
+ applied to each item individually. This can lead to undesired
+ visual results when the opacity is applied to a subtree. Consider
+ the following example:
+
+ \table
+ \row
+ \li \inlineimage qml-blending-nonlayered.png
+ \li \b {Non-layered Opacity} \snippet qml/layerblending.qml non-layered
+ \endtable
+
+ A layer is rendered with the root item's opacity being 1, and then
+ the root item's opacity is applied to the texture when it is
+ drawn. This means that fading in a large item hierarchy from
+ transparent to opaque, or vice versa, can be done without the
+ overlap artifacts that the normal item by item alpha blending
+ has. Here is the same example with layer enabled:
+
+ \table
+ \row
+ \li \image qml-blending-layered.png
+ \li \b {Layered Opacity} \snippet qml/layerblending.qml layered
+ \endtable
+
+ \section2 Combined with ShaderEffects
+
+ Setting \l layer.enabled to true will turn the item into a \l
+ {QQuickItem::isTextureProvider}{texture provider}, making it
+ possible to use the item directly as a texture, for instance
+ in combination with the ShaderEffect type.
+
+ It is possible to apply an effect on a layer at runtime using
+ layer.effect:
+
+ \snippet qml/layerwitheffect.qml 1
+
+ In this example, we implement the shader effect manually. The \l
+ {Qt Graphical Effects} module contains a suite of ready-made
+ effects for use with Qt Quick.
+
+ See ShaderEffect for more information about using effects.
+
+ \note \l layer.enabled is actually just a more convenient way of using
+ ShaderEffectSource.
+
+
+ \section2 Memory and Performance
+
+ When an item's layer is enabled, the scene graph will allocate memory
+ in the GPU equal to \c {width x height x 4}. In memory constrained
+ configurations, large layers should be used with care.
+
+ In the QPainter / QWidget world, it is some times favorable to
+ cache complex content in a pixmap, image or texture. In Qt Quick,
+ because of the techniques already applied by the \l {Qt Quick
+ Scene Graph Renderer} {scene graph renderer}, this will in most
+ cases not be the case. Excessive draw calls are already reduced
+ because of batching and a cache will in most cases end up blending
+ more pixels than the original content. The overhead of rendering
+ to an offscreen and the blending involved with drawing the
+ resulting texture is therefore often more costly than simply
+ letting the item and its children be drawn normally.
+
+ Also, an item using a layer can not be \l {Batching} {batched} during
+ rendering. This means that a scene with many layered items may
+ have performance problems.
+
+ Layering can be convenient and useful for visual effects, but
+ should in most cases be enabled for the duration of the effect and
+ disabled afterwards.
+
*/
/*!
@@ -7481,12 +7581,15 @@ void QQuickItemLayer::setMipmap(bool mipmap)
allow you to save some texture memory.
\list
- \li ShaderEffectSource.Alpha - GL_ALPHA
+ \li ShaderEffectSource.Alpha - GL_ALPHA;
\li ShaderEffectSource.RGB - GL_RGB
\li ShaderEffectSource.RGBA - GL_RGBA
\endlist
- \note Some OpenGL implementations do not support the GL_ALPHA format.
+ \note ShaderEffectSource.RGB and ShaderEffectSource.Alpha should
+ be used with caution, as support for these formats in the underlying
+ hardare and driver is often not present.
+
*/
void QQuickItemLayer::setFormat(QQuickShaderEffectSource::Format f)
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 0037879fb3..851204ccde 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1742,7 +1742,7 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
nicely.
- \section1 ListView layouts
+ \section1 ListView Layouts
The layout of the items in a ListView can be controlled by these properties:
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index 0d9226d77f..926ac7b4ee 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -171,6 +171,9 @@ QT_BEGIN_NAMESPACE
change, then probably you are using a device which does not rotate its own
display. In that case you may need to use \l {Item::rotation}{Item.rotation} or
\l {Item::transform}{Item.transform} to rotate your content.
+
+ \note This property does not update unless a Screen::orientationUpdateMask
+ is set to a value other than \c 0.
*/
/*!
\qmlattachedmethod int Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
@@ -178,10 +181,21 @@ QT_BEGIN_NAMESPACE
Returns the rotation angle, in degrees, between the two specified angles.
*/
+/*!
+ \qmlattachedproperty Qt::ScreenOrientations Screen::orientationUpdateMask
+ \since 5.4
+
+ This contains the update mask for the orientation. Screen::orientation
+ only emits changes for the screen orientations matching this mask.
+
+ The default, \c 0, means Screen::orientation never updates.
+*/
+
QQuickScreenAttached::QQuickScreenAttached(QObject* attachee)
: QObject(attachee)
, m_screen(NULL)
, m_window(NULL)
+ , m_updateMask(0)
{
m_attachee = qobject_cast<QQuickItem*>(attachee);
@@ -260,6 +274,24 @@ Qt::ScreenOrientation QQuickScreenAttached::orientation() const
return m_screen->orientation();
}
+Qt::ScreenOrientations QQuickScreenAttached::orientationUpdateMask() const
+{
+ return m_updateMask;
+}
+
+void QQuickScreenAttached::setOrientationUpdateMask(Qt::ScreenOrientations mask)
+{
+ if (m_updateMask == mask)
+ return;
+
+ m_updateMask = mask;
+
+ if (m_screen)
+ m_screen->setOrientationUpdateMask(m_updateMask);
+
+ emit orientationUpdateMaskChanged();
+}
+
int QQuickScreenAttached::angleBetween(int a, int b)
{
if (!m_screen)
@@ -290,6 +322,8 @@ void QQuickScreenAttached::screenChanged(QScreen *screen)
if (!screen)
return; //Don't bother emitting signals, because the new values are garbage anyways
+ screen->setOrientationUpdateMask(m_updateMask);
+
if (!oldScreen || screen->size() != oldScreen->size()) {
emit widthChanged();
emit heightChanged();
diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h
index 884995a67e..d661cc6f56 100644
--- a/src/quick/items/qquickscreen_p.h
+++ b/src/quick/items/qquickscreen_p.h
@@ -50,15 +50,19 @@ class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QObject
{
Q_OBJECT
- Q_PROPERTY(QString name READ name NOTIFY nameChanged);
+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(int width READ width NOTIFY widthChanged)
Q_PROPERTY(int height READ height NOTIFY heightChanged)
Q_PROPERTY(int desktopAvailableWidth READ desktopAvailableWidth NOTIFY desktopGeometryChanged)
Q_PROPERTY(int desktopAvailableHeight READ desktopAvailableHeight NOTIFY desktopGeometryChanged)
Q_PROPERTY(qreal logicalPixelDensity READ logicalPixelDensity NOTIFY logicalPixelDensityChanged)
Q_PROPERTY(qreal pixelDensity READ pixelDensity NOTIFY pixelDensityChanged)
+ // TODO Qt 6 Rename primaryOrientation to orientation
Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY primaryOrientationChanged)
+ // TODO Qt 6 Remove this orientation -> incomplete device orientation -> better use OrientationSensor
Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged)
+ Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask
+ WRITE setOrientationUpdateMask NOTIFY orientationUpdateMaskChanged)
public:
QQuickScreenAttached(QObject* attachee);
@@ -72,6 +76,8 @@ public:
qreal pixelDensity() const;
Qt::ScreenOrientation primaryOrientation() const;
Qt::ScreenOrientation orientation() const;
+ Qt::ScreenOrientations orientationUpdateMask() const;
+ void setOrientationUpdateMask(Qt::ScreenOrientations mask);
//Treats int as Qt::ScreenOrientation, due to QTBUG-20639
Q_INVOKABLE int angleBetween(int a, int b);
@@ -87,6 +93,7 @@ Q_SIGNALS:
void pixelDensityChanged();
void primaryOrientationChanged();
void orientationChanged();
+ void orientationUpdateMaskChanged();
protected Q_SLOTS:
void screenChanged(QScreen*);
@@ -95,6 +102,7 @@ private:
QScreen* m_screen;
QQuickWindow* m_window;
QQuickItem* m_attachee;
+ Qt::ScreenOrientations m_updateMask;
};
class Q_AUTOTEST_EXPORT QQuickScreen : public QObject
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index fb5dac1080..0358495a3b 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -641,10 +641,34 @@ void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId,
corner. For non-linear vertex transformations, like page curl, you can
specify a fine grid of vertices by specifying a \l mesh resolution.
+ \section1 ShaderEffect and Item Layers
+
+ The ShaderEffect type can be combined with \l {Item Layers} {layered items}.
+
+ \table
+ \row
+ \li \b {Layer with effect disabled} \inlineimage qml-shadereffect-nolayereffect.png
+ \li \b {Layer with effect enabled} \inlineimage qml-shadereffect-layereffect.png
+ \li \snippet qml/layerwitheffect.qml 1
+ \endtable
+
+ It is also possible to combine multiple layered items:
+
+ \table
+ \row
+ \li \inlineimage qml-shadereffect-opacitymask.png
+ \li \snippet qml/opacitymask.qml 1
+ \endtable
+
+ The \l {Qt Graphical Effects} module contains several ready-made effects
+ for using with Qt Quick applications.
+
\note Scene Graph textures have origin in the top-left corner rather than
bottom-left which is common in OpenGL.
For information about the GLSL version being used, see \l QtQuick::OpenGLInfo.
+
+ \sa {Item Layers}
*/
QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index 80be283443..52e5ba2464 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -74,7 +74,6 @@ public:
QSGTexture::WrapMode horizontalWrap;
QSGTexture::WrapMode verticalWrap;
};
-#include "qquickshadereffectsource.moc"
class QQuickShaderEffectSourceCleanup : public QRunnable
{
@@ -322,24 +321,28 @@ void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
d->derefWindow();
}
- if (window() == item->window()) {
- m_sourceItem = item;
- } else {
- qWarning("ShaderEffectSource: sourceItem and ShaderEffectSource must both be children of the same window.");
- m_sourceItem = 0;
- }
+ m_sourceItem = item;
if (m_sourceItem) {
- QQuickItemPrivate *d = QQuickItemPrivate::get(item);
- // 'item' needs a window 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.
- // "sourceItem: Item { }" instead of "sourceItem: foo" -- it will not get a parent.
- // In those cases, 'item' should get the window from 'this'.
- if (window())
- d->refWindow(window());
- d->refFromEffectItem(m_hideSource);
- d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
- connect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*)));
+ if (window() == m_sourceItem->window()
+ || (window() == 0 && m_sourceItem->window())
+ || (m_sourceItem->window() == 0 && window())) {
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+ // 'item' needs a window 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.
+ // "sourceItem: Item { }" instead of "sourceItem: foo" -- it will not get a parent.
+ // In those cases, 'item' should get the window from 'this'.
+ if (window())
+ d->refWindow(window());
+ else if (m_sourceItem->window())
+ d->refWindow(m_sourceItem->window());
+ d->refFromEffectItem(m_hideSource);
+ d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+ connect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*)));
+ } else {
+ qWarning("ShaderEffectSource: sourceItem and ShaderEffectSource must both be children of the same window.");
+ m_sourceItem = 0;
+ }
}
update();
emit sourceItemChanged();
@@ -586,13 +589,24 @@ void QQuickShaderEffectSource::releaseResources()
}
}
+class QQuickShaderSourceAttachedNode : public QObject, public QSGNode
+{
+ Q_OBJECT
+public:
+ Q_SLOT void markTextureDirty() {
+ QSGNode *pn = QSGNode::parent();
+ if (pn) {
+ Q_ASSERT(pn->type() == QSGNode::GeometryNodeType);
+ pn->markDirty(DirtyMaterial);
+ }
+ }
+};
+
QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
if (!m_sourceItem || m_sourceItem->width() <= 0 || m_sourceItem->height() <= 0) {
- if (m_texture) {
+ if (m_texture)
m_texture->setItem(0);
- m_texture->setShaderSourceNode(0);
- }
delete oldNode;
return 0;
}
@@ -658,7 +672,9 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
node = d->sceneGraphContext()->createImageNode();
node->setFlag(QSGNode::UsePreprocess);
node->setTexture(m_texture);
- m_texture->setShaderSourceNode(node);
+ QQuickShaderSourceAttachedNode *attached = new QQuickShaderSourceAttachedNode;
+ node->appendChildNode(attached);
+ connect(m_texture, SIGNAL(updateRequested()), attached, SLOT(markTextureDirty()));
}
// If live and recursive, update continuously.
@@ -698,4 +714,6 @@ void QQuickShaderEffectSource::itemChange(ItemChange change, const ItemChangeDat
QQuickItem::itemChange(change, value);
}
+#include "qquickshadereffectsource.moc"
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index a263a890b5..2585caefb5 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -435,12 +435,12 @@ void QQuickTextControlPrivate::setClipboardSelection()
}
#endif
-void QQuickTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someCursor)
+void QQuickTextControlPrivate::_q_updateCursorPosChanged(const QTextCursor &someCursor)
{
Q_Q(QQuickTextControl);
if (someCursor.isCopyOf(cursor)) {
emit q->cursorPositionChanged();
- cursorRectangleChanged = true;
+ q->updateCursorRectangle(true);
}
}
@@ -578,7 +578,7 @@ QQuickTextControl::QQuickTextControl(QTextDocument *doc, QObject *parent)
qmlobject_connect(layout, QAbstractTextDocumentLayout, SIGNAL(updateBlock(QTextBlock)), this, QQuickTextControl, SIGNAL(updateRequest()));
qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SIGNAL(textChanged()));
qmlobject_connect(doc, QTextDocument, SIGNAL(contentsChanged()), this, QQuickTextControl, SLOT(_q_updateCurrentCharFormatAndSelection()));
- qmlobject_connect(doc, QTextDocument, SIGNAL(cursorPositionChanged(QTextCursor)), this, QQuickTextControl, SLOT(_q_emitCursorPosChanged(QTextCursor)));
+ qmlobject_connect(doc, QTextDocument, SIGNAL(cursorPositionChanged(QTextCursor)), this, QQuickTextControl, SLOT(_q_updateCursorPosChanged(QTextCursor)));
connect(doc, &QTextDocument::contentsChange, this, &QQuickTextControl::contentsChange);
layout->setProperty("cursorWidth", textCursorWidth);
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index 3cb1590be8..2fe083f1d2 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -169,7 +169,7 @@ protected:
private:
Q_DISABLE_COPY(QQuickTextControl)
Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentCharFormatAndSelection())
- Q_PRIVATE_SLOT(d_func(), void _q_emitCursorPosChanged(const QTextCursor &))
+ Q_PRIVATE_SLOT(d_func(), void _q_updateCursorPosChanged(const QTextCursor &))
};
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index a3b7c7be99..bd07d86f9c 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -88,7 +88,7 @@ public:
void setClipboardSelection();
#endif
- void _q_emitCursorPosChanged(const QTextCursor &someCursor);
+ void _q_updateCursorPosChanged(const QTextCursor &someCursor);
void setBlinkingCursorEnabled(bool enable);
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index f746fe8b1b..67ff79d20f 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -46,12 +46,37 @@
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextimagehandler_p.h>
#include <private/qrawfont_p.h>
+#include <private/qglyphrun_p.h>
QT_BEGIN_NAMESPACE
+QQuickTextNodeEngine::BinaryTreeNode::BinaryTreeNode(const QGlyphRun &g,
+ SelectionState selState,
+ const QRectF &brect,
+ const QQuickTextNode::Decorations &decs,
+ const QColor &c,
+ const QColor &bc,
+ const QPointF &pos, qreal a)
+ : glyphRun(g)
+ , boundingRect(brect)
+ , selectionState(selState)
+ , clipNode(0)
+ , decorations(decs)
+ , color(c)
+ , backgroundColor(bc)
+ , position(pos)
+ , ascent(a)
+ , leftChildIndex(-1)
+ , rightChildIndex(-1)
+{
+ QGlyphRunPrivate *d = QGlyphRunPrivate::get(g);
+ ranges.append(qMakePair(d->textRangeStart, d->textRangeEnd));
+}
+
+
void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState,
QQuickTextNode::Decorations decorations, const QColor &textColor,
- const QColor &backgroundColor, const QPointF &position, int rangeStart, int rangeEnd)
+ const QColor &backgroundColor, const QPointF &position)
{
QRectF searchRect = glyphRun.boundingRect();
searchRect.translate(position);
@@ -65,8 +90,14 @@ void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode
decorations |= (backgroundColor.isValid() ? QQuickTextNode::Background : QQuickTextNode::NoDecoration);
qreal ascent = glyphRun.rawFont().ascent();
- insert(binaryTree, BinaryTreeNode(glyphRun, selectionState, searchRect, decorations,
- textColor, backgroundColor, position, ascent, rangeStart, rangeEnd));
+ insert(binaryTree, BinaryTreeNode(glyphRun,
+ selectionState,
+ searchRect,
+ decorations,
+ textColor,
+ backgroundColor,
+ position,
+ ascent));
}
void QQuickTextNodeEngine::BinaryTreeNode::insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const BinaryTreeNode &binaryTreeNode)
@@ -441,19 +472,27 @@ void QQuickTextNodeEngine::addTextObject(const QPointF &position, const QTextCha
}
}
-void QQuickTextNodeEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun, int rangeStart, int rangeEnd)
+void QQuickTextNodeEngine::addUnselectedGlyphs(const QGlyphRun &glyphRun)
{
- BinaryTreeNode::insert(&m_currentLineTree, glyphRun, Unselected,
- QQuickTextNode::NoDecoration, m_textColor, m_backgroundColor, m_position,
- rangeStart, rangeEnd);
+ BinaryTreeNode::insert(&m_currentLineTree,
+ glyphRun,
+ Unselected,
+ QQuickTextNode::NoDecoration,
+ m_textColor,
+ m_backgroundColor,
+ m_position);
}
-void QQuickTextNodeEngine::addSelectedGlyphs(const QGlyphRun &glyphRun, int rangeStart, int rangeEnd)
+void QQuickTextNodeEngine::addSelectedGlyphs(const QGlyphRun &glyphRun)
{
int currentSize = m_currentLineTree.size();
- BinaryTreeNode::insert(&m_currentLineTree, glyphRun, Selected,
- QQuickTextNode::NoDecoration, m_textColor, m_backgroundColor, m_position,
- rangeStart, rangeEnd);
+ BinaryTreeNode::insert(&m_currentLineTree,
+ glyphRun,
+ Selected,
+ QQuickTextNode::NoDecoration,
+ m_textColor,
+ m_backgroundColor,
+ m_position);
m_hasSelection = m_hasSelection || m_currentLineTree.size() > currentSize;
}
@@ -526,7 +565,7 @@ void QQuickTextNodeEngine::addGlyphsInRange(int rangeStart, int rangeLength,
QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart, rangeLength);
for (int j=0; j<glyphRuns.size(); ++j) {
const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun, rangeStart, rangeEnd - 1);
+ addUnselectedGlyphs(glyphRun);
}
} else {
if (rangeStart < selectionStart) {
@@ -534,7 +573,7 @@ void QQuickTextNodeEngine::addGlyphsInRange(int rangeStart, int rangeLength,
QList<QGlyphRun> glyphRuns = line.glyphRuns(rangeStart, length);
for (int j=0; j<glyphRuns.size(); ++j) {
const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun, rangeStart, rangeStart + length - 1);
+ addUnselectedGlyphs(glyphRun);
}
}
@@ -545,8 +584,8 @@ void QQuickTextNodeEngine::addGlyphsInRange(int rangeStart, int rangeLength,
for (int j=0; j<glyphRuns.size(); ++j) {
const QGlyphRun &glyphRun = glyphRuns.at(j);
- addSelectedGlyphs(glyphRun, start, start + length - 1);
- addUnselectedGlyphs(glyphRun, start, start + length - 1);
+ addSelectedGlyphs(glyphRun);
+ addUnselectedGlyphs(glyphRun);
}
}
@@ -556,7 +595,7 @@ void QQuickTextNodeEngine::addGlyphsInRange(int rangeStart, int rangeLength,
QList<QGlyphRun> glyphRuns = line.glyphRuns(start, length);
for (int j=0; j<glyphRuns.size(); ++j) {
const QGlyphRun &glyphRun = glyphRuns.at(j);
- addUnselectedGlyphs(glyphRun, start, start + length - 1);
+ addUnselectedGlyphs(glyphRun);
}
}
}
@@ -927,7 +966,7 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
for (int i=0; i<glyphRuns.size(); ++i)
- addUnselectedGlyphs(glyphRuns.at(i), 0, layout.text().length() - 1);
+ addUnselectedGlyphs(glyphRuns.at(i));
}
}
diff --git a/src/quick/items/qquicktextnodeengine_p.h b/src/quick/items/qquicktextnodeengine_p.h
index 142375b5a3..f0d52683c6 100644
--- a/src/quick/items/qquicktextnodeengine_p.h
+++ b/src/quick/items/qquicktextnodeengine_p.h
@@ -75,12 +75,7 @@ public:
BinaryTreeNode(const QGlyphRun &g, SelectionState selState, const QRectF &brect,
const QQuickTextNode::Decorations &decs, const QColor &c, const QColor &bc,
- const QPointF &pos, qreal a, int rangeStart, int rangeEnd)
- : glyphRun(g), boundingRect(brect), selectionState(selState), clipNode(0), decorations(decs)
- , color(c), backgroundColor(bc), position(pos), ascent(a), leftChildIndex(-1), rightChildIndex(-1)
- {
- ranges.append(qMakePair(rangeStart, rangeEnd));
- }
+ const QPointF &pos, qreal a);
QGlyphRun glyphRun;
QRectF boundingRect;
@@ -102,8 +97,7 @@ public:
{ insert(binaryTree, BinaryTreeNode(rect, image, selectionState, ascent)); }
static void insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const QGlyphRun &glyphRun, SelectionState selectionState,
- QQuickTextNode::Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QPointF &position,
- int rangeStart, int rangeEnd);
+ QQuickTextNode::Decorations decorations, const QColor &textColor, const QColor &backgroundColor, const QPointF &position);
static void insert(QVarLengthArray<BinaryTreeNode, 16> *binaryTree, const BinaryTreeNode &binaryTreeNode);
static void inOrder(const QVarLengthArray<BinaryTreeNode, 16> &binaryTree, QVarLengthArray<int> *sortedIndexes, int currentIndex = 0);
};
@@ -138,8 +132,8 @@ public:
SelectionState selectionState,
QTextDocument *textDocument, int pos,
QTextFrameFormat::Position layoutPosition = QTextFrameFormat::InFlow);
- void addSelectedGlyphs(const QGlyphRun &glyphRun, int rangeStart, int rangeEnd);
- void addUnselectedGlyphs(const QGlyphRun &glyphRun, int rangeStart, int rangeEnd);
+ void addSelectedGlyphs(const QGlyphRun &glyphRun);
+ void addUnselectedGlyphs(const QGlyphRun &glyphRun);
void addGlyphsInRange(int rangeStart, int rangeEnd,
const QColor &color, const QColor &backgroundColor,
int selectionStart, int selectionEnd);
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index 91a6468593..a55d056c75 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -594,7 +594,7 @@ void QQuickView::resizeEvent(QResizeEvent *e)
/*! \reimp */
void QQuickView::keyPressEvent(QKeyEvent *e)
{
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
QQuickWindow::keyPressEvent(e);
}
@@ -602,7 +602,7 @@ void QQuickView::keyPressEvent(QKeyEvent *e)
/*! \reimp */
void QQuickView::keyReleaseEvent(QKeyEvent *e)
{
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
QQuickWindow::keyReleaseEvent(e);
}
@@ -610,7 +610,7 @@ void QQuickView::keyReleaseEvent(QKeyEvent *e)
/*! \reimp */
void QQuickView::mouseMoveEvent(QMouseEvent *e)
{
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
QQuickWindow::mouseMoveEvent(e);
}
@@ -618,7 +618,7 @@ void QQuickView::mouseMoveEvent(QMouseEvent *e)
/*! \reimp */
void QQuickView::mousePressEvent(QMouseEvent *e)
{
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
QQuickWindow::mousePressEvent(e);
}
@@ -626,7 +626,7 @@ void QQuickView::mousePressEvent(QMouseEvent *e)
/*! \reimp */
void QQuickView::mouseReleaseEvent(QMouseEvent *e)
{
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
QQuickWindow::mouseReleaseEvent(e);
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index ca0a81f2f4..5548017ddc 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1654,8 +1654,8 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
// Leaving from previous hovered items until we reach the item or one of its ancestors.
while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
- sendHoverEvent(QEvent::HoverLeave, hoverItems[0], scenePos, lastScenePos, modifiers, accepted);
- hoverItems.removeFirst();
+ QQuickItem *hoverLeaveItem = hoverItems.takeFirst();
+ sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, accepted);
}
if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
@@ -2922,7 +2922,7 @@ void QQuickWindow::setTransientParent_helper(QQuickWindow *window)
QOpenGLContext *QQuickWindow::openglContext() const
{
Q_D(const QQuickWindow);
- return d->context->openglContext();
+ return d->context ? d->context->openglContext() : 0;
}
/*!
@@ -3530,7 +3530,7 @@ void QQuickWindow::setColor(const QColor &color)
}
d->clearColor = color;
emit colorChanged(color);
- d->dirtyItem(contentItem());
+ update();
}
QColor QQuickWindow::color() const
@@ -3914,11 +3914,6 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
d->renderJobMutex.unlock();
}
-QQuickWindowAttached *QQuickWindow::qmlAttachedProperties(QObject *object)
-{
- return new QQuickWindowAttached(object);
-}
-
void QQuickWindowPrivate::runAndClearJobs(QList<QRunnable *> *jobs)
{
renderJobMutex.lock();
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 82f2e29d9d..8d75a4767c 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -143,8 +143,6 @@ public:
void scheduleRenderJob(QRunnable *job, RenderStage schedule);
- static QQuickWindowAttached *qmlAttachedProperties(QObject *object);
-
Q_SIGNALS:
void frameSwapped();
Q_REVISION(2) void openglContextCreated(QOpenGLContext *context);
@@ -209,7 +207,6 @@ private:
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QQuickWindow *)
-QML_DECLARE_TYPEINFO(QQuickWindow, QML_HAS_ATTACHED_PROPERTIES)
#endif // QQUICKWINDOW_H
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index dbd0628db2..bf41bc136f 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -79,6 +79,11 @@ public:
QQuickWindow::setVisibility(visibility);
}
+ static QQuickWindowAttached *qmlAttachedProperties(QObject *object)
+ {
+ return new QQuickWindowAttached(object);
+ }
+
Q_SIGNALS:
void visibleChanged(bool arg);
void visibilityChanged(QWindow::Visibility visibility);
@@ -166,16 +171,13 @@ void QQuickWindowModule::defineModule()
{
const char uri[] = "QtQuick.Window";
- // Since Window is both an attached property and a createable type,
- // the attached property declaration must come first so that it can
- // be overridden below.
- qmlRegisterUncreatableType<QQuickWindow>(uri, 2, 2, "Window", QQuickWindow::tr("Window is available via attached properties"));
qmlRegisterType<QQuickWindow>(uri, 2, 0, "Window");
qmlRegisterRevision<QWindow,1>(uri, 2, 1);
qmlRegisterRevision<QWindow,2>(uri, 2, 2);
qmlRegisterRevision<QQuickWindow,1>(uri, 2, 1);//Type moved to a subclass, but also has new members
qmlRegisterRevision<QQuickWindow,2>(uri, 2, 2);
qmlRegisterType<QQuickWindowQmlImpl>(uri, 2, 1, "Window");
+ qmlRegisterType<QQuickWindowQmlImpl,1>(uri, 2, 2, "Window");
qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property."));
}
@@ -183,3 +185,4 @@ void QQuickWindowModule::defineModule()
QT_END_NAMESPACE
+QML_DECLARE_TYPEINFO(QQuickWindowQmlImpl, QML_HAS_ATTACHED_PROPERTIES)
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 173858b21d..ac45cf70db 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -63,15 +63,19 @@ extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfac
namespace QSGBatchRenderer
{
-const bool debug_render = qgetenv("QSG_RENDERER_DEBUG").contains("render");
-const bool debug_build = qgetenv("QSG_RENDERER_DEBUG").contains("build");
-const bool debug_change = qgetenv("QSG_RENDERER_DEBUG").contains("change");
-const bool debug_upload = qgetenv("QSG_RENDERER_DEBUG").contains("upload");
-const bool debug_roots = qgetenv("QSG_RENDERER_DEBUG").contains("roots");
-const bool debug_dump = qgetenv("QSG_RENDERER_DEBUG").contains("dump");
-const bool debug_noalpha = qgetenv("QSG_RENDERER_DEBUG").contains("noalpha");
-const bool debug_noopaque = qgetenv("QSG_RENDERER_DEBUG").contains("noopaque");
-const bool debug_noclip = qgetenv("QSG_RENDERER_DEBUG").contains("noclip");
+#define DECLARE_DEBUG_VAR(variable) \
+ static bool debug_ ## variable() \
+ { static bool value = qgetenv("QSG_RENDERER_DEBUG").contains(QT_STRINGIFY(variable)); return value; }
+DECLARE_DEBUG_VAR(render)
+DECLARE_DEBUG_VAR(build)
+DECLARE_DEBUG_VAR(change)
+DECLARE_DEBUG_VAR(upload)
+DECLARE_DEBUG_VAR(roots)
+DECLARE_DEBUG_VAR(dump)
+DECLARE_DEBUG_VAR(noalpha)
+DECLARE_DEBUG_VAR(noopaque)
+DECLARE_DEBUG_VAR(noclip)
+#undef DECLARE_DEBUG_VAR
static QElapsedTimer qsg_renderer_timer;
@@ -268,10 +272,10 @@ void Updater::updateStates(QSGNode *n)
Node *sn = renderer->m_nodes.value(n, 0);
Q_ASSERT(sn);
- if (Q_UNLIKELY(debug_roots))
+ if (Q_UNLIKELY(debug_roots()))
qsg_dumpShadowRoots(sn);
- if (Q_UNLIKELY(debug_build)) {
+ if (Q_UNLIKELY(debug_build())) {
qDebug() << "Updater::updateStates()";
if (sn->dirtyState & (QSGNode::DirtyNodeAdded << 16))
qDebug() << " - nodes have been added";
@@ -785,7 +789,7 @@ Renderer::Renderer(QSGRenderContext *ctx)
if (ok)
m_batchVertexThreshold = threshold;
}
- if (Q_UNLIKELY(debug_build || debug_render)) {
+ if (Q_UNLIKELY(debug_build() || debug_render())) {
qDebug() << "Batch thresholds: nodes:" << m_batchNodeThreshold << " vertices:" << m_batchVertexThreshold;
qDebug() << "Using buffer strategy:" << (m_bufferStrategy == GL_STATIC_DRAW ? "static" : (m_bufferStrategy == GL_DYNAMIC_DRAW ? "dynamic" : "stream"));
}
@@ -1048,7 +1052,7 @@ void Renderer::nodeWasRemoved(Node *node)
void Renderer::turnNodeIntoBatchRoot(Node *node)
{
- if (Q_UNLIKELY(debug_change)) qDebug() << " - new batch root";
+ if (Q_UNLIKELY(debug_change())) qDebug() << " - new batch root";
m_rebuild |= FullRebuild;
node->isBatchRoot = true;
node->becameBatchRoot = true;
@@ -1069,7 +1073,7 @@ void Renderer::turnNodeIntoBatchRoot(Node *node)
void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
{
- if (Q_UNLIKELY(debug_change)) {
+ if (Q_UNLIKELY(debug_change())) {
QDebug debug = qDebug();
debug << "dirty:";
if (state & QSGNode::DirtyGeometry)
@@ -1616,7 +1620,7 @@ void Renderer::prepareAlphaBatches()
void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, quint16 *iBase, int *indexCount)
{
- if (Q_UNLIKELY(debug_upload)) qDebug() << " - uploading element:" << e << e->node << (void *) *vertexData << (qintptr) (*zData - *vertexData) << (qintptr) (*indexData - *vertexData);
+ if (Q_UNLIKELY(debug_upload())) qDebug() << " - uploading element:" << e << e->node << (void *) *vertexData << (qintptr) (*zData - *vertexData) << (qintptr) (*indexData - *vertexData);
QSGGeometry *g = e->node->geometry();
const QMatrix4x4 &localx = *e->node->matrix();
@@ -1689,17 +1693,17 @@ void Renderer::uploadBatch(Batch *b)
{
// Early out if nothing has changed in this batch..
if (!b->needsUpload) {
- if (Q_UNLIKELY(debug_upload)) qDebug() << " Batch:" << b << "already uploaded...";
+ if (Q_UNLIKELY(debug_upload())) qDebug() << " Batch:" << b << "already uploaded...";
return;
}
if (!b->first) {
- if (Q_UNLIKELY(debug_upload)) qDebug() << " Batch:" << b << "is invalid...";
+ if (Q_UNLIKELY(debug_upload())) qDebug() << " Batch:" << b << "is invalid...";
return;
}
if (b->isRenderNode) {
- if (Q_UNLIKELY(debug_upload)) qDebug() << " Batch: " << b << "is a render node...";
+ if (Q_UNLIKELY(debug_upload())) qDebug() << " Batch: " << b << "is a render node...";
return;
}
@@ -1778,7 +1782,7 @@ void Renderer::uploadBatch(Batch *b)
#endif
map(&b->vbo, bufferSize);
- if (Q_UNLIKELY(debug_upload)) qDebug() << " - batch" << b << " first:" << b->first << " root:"
+ if (Q_UNLIKELY(debug_upload())) qDebug() << " - batch" << b << " first:" << b->first << " root:"
<< b->root << " merged:" << b->merged << " positionAttribute" << b->positionAttribute
<< " vbo:" << b->vbo.id << ":" << b->vbo.size;
@@ -1844,7 +1848,7 @@ void Renderer::uploadBatch(Batch *b)
}
}
- if (Q_UNLIKELY(debug_upload)) {
+ if (Q_UNLIKELY(debug_upload())) {
const char *vd = b->vbo.data;
qDebug() << " -- Vertex Data, count:" << b->vertexCount << " - " << g->sizeOfVertex() << "bytes/vertex";
for (int i=0; i<b->vertexCount; ++i) {
@@ -1875,9 +1879,12 @@ void Renderer::uploadBatch(Batch *b)
vd += g->sizeOfVertex();
}
- const quint16 *id = (const quint16 *) (b->vbo.data
- + b->vertexCount * g->sizeOfVertex()
- + (b->merged ? b->vertexCount * sizeof(float) : 0));
+ const quint16 *id =
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ (const quint16 *) (b->ibo.data);
+#else
+ (const quint16 *) (b->vbo.data + b->drawSets.at(0).indices);
+#endif
{
QDebug iDump = qDebug();
iDump << " -- Index Data, count:" << b->indexCount;
@@ -1899,11 +1906,11 @@ void Renderer::uploadBatch(Batch *b)
unmap(&b->ibo, true);
#endif
- if (Q_UNLIKELY(debug_upload)) qDebug() << " --- vertex/index buffers unmapped, batch upload completed...";
+ if (Q_UNLIKELY(debug_upload())) qDebug() << " --- vertex/index buffers unmapped, batch upload completed...";
b->needsUpload = false;
- if (Q_UNLIKELY(debug_render))
+ if (Q_UNLIKELY(debug_render()))
b->uploadedThisFrame = true;
}
@@ -2035,7 +2042,7 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip)
void Renderer::updateClip(const QSGClipNode *clipList, const Batch *batch)
{
- if (clipList != m_currentClip && Q_LIKELY(!debug_noclip)) {
+ if (clipList != m_currentClip && Q_LIKELY(!debug_noclip())) {
m_currentClip = clipList;
// updateClip sets another program, so force-reactivate our own
if (m_currentShader)
@@ -2114,7 +2121,7 @@ void Renderer::renderMergedBatch(const Batch *batch)
Element *e = batch->first;
Q_ASSERT(e);
- if (Q_UNLIKELY(debug_render)) {
+ if (Q_UNLIKELY(debug_render())) {
QDebug debug = qDebug();
debug << " -"
<< batch
@@ -2223,7 +2230,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
Element *e = batch->first;
Q_ASSERT(e);
- if (Q_UNLIKELY(debug_render)) {
+ if (Q_UNLIKELY(debug_render())) {
qDebug() << " -"
<< batch
<< (batch->uploadedThisFrame ? "[ upload]" : "[retained]")
@@ -2353,7 +2360,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
void Renderer::renderBatches()
{
- if (Q_UNLIKELY(debug_render)) {
+ if (Q_UNLIKELY(debug_render())) {
qDebug().nospace() << "Rendering:" << endl
<< " -> Opaque: " << qsg_countNodesInBatches(m_opaqueBatches) << " nodes in " << m_opaqueBatches.size() << " batches..." << endl
<< " -> Alpha: " << qsg_countNodesInBatches(m_alphaBatches) << " nodes in " << m_alphaBatches.size() << " batches...";
@@ -2386,8 +2393,8 @@ void Renderer::renderBatches()
m_currentProgram = 0;
m_currentClip = 0;
- bool renderOpaque = !debug_noopaque;
- bool renderAlpha = !debug_noalpha;
+ bool renderOpaque = !debug_noopaque();
+ bool renderAlpha = !debug_noalpha();
if (Q_LIKELY(renderOpaque)) {
for (int i=0; i<m_opaqueBatches.size(); ++i) {
@@ -2463,12 +2470,12 @@ void Renderer::preprocess()
void Renderer::render()
{
- if (Q_UNLIKELY(debug_dump)) {
+ if (Q_UNLIKELY(debug_dump())) {
qDebug("\n");
QSGNodeDumper::dump(rootNode());
}
- if (Q_UNLIKELY(debug_render || debug_build)) {
+ if (Q_UNLIKELY(debug_render() || debug_build())) {
QByteArray type("rebuild:");
if (m_rebuild == 0)
@@ -2495,7 +2502,7 @@ void Renderer::render()
buildRenderListsForTaggedRoots();
m_rebuild |= BuildBatches;
- if (Q_UNLIKELY(debug_build)) {
+ if (Q_UNLIKELY(debug_build())) {
qDebug() << "Opaque render lists" << (complete ? "(complete)" : "(partial)") << ":";
for (int i=0; i<m_opaqueRenderList.size(); ++i) {
Element *e = m_opaqueRenderList.at(i);
@@ -2522,7 +2529,7 @@ void Renderer::render()
prepareOpaqueBatches();
prepareAlphaBatches();
- if (Q_UNLIKELY(debug_build)) {
+ if (Q_UNLIKELY(debug_build())) {
qDebug() << "Opaque Batches:";
for (int i=0; i<m_opaqueBatches.size(); ++i) {
Batch *b = m_opaqueBatches.at(i);
@@ -2558,11 +2565,11 @@ void Renderer::render()
}
- if (Q_UNLIKELY(debug_upload)) qDebug() << "Uploading Opaque Batches:";
+ if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Opaque Batches:";
for (int i=0; i<m_opaqueBatches.size(); ++i)
uploadBatch(m_opaqueBatches.at(i));
- if (Q_UNLIKELY(debug_upload)) qDebug() << "Uploading Alpha Batches:";
+ if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Alpha Batches:";
for (int i=0; i<m_alphaBatches.size(); ++i)
uploadBatch(m_alphaBatches.at(i));
@@ -2581,7 +2588,7 @@ void Renderer::render()
void Renderer::renderRenderNode(Batch *batch)
{
- if (Q_UNLIKELY(debug_render))
+ if (Q_UNLIKELY(debug_render()))
qDebug() << " -" << batch << "rendernode";
Q_ASSERT(batch->first->isRenderNode);
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index db32f656e1..e0b96a45b6 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -338,25 +338,4 @@ void QSGNodeVisitorEx::visitChildren(QSGNode *node)
}
}
-void QSGLayer::markDirtyTextureLater()
-{
- QCoreApplication::postEvent(this, new QEvent(static_cast<QEvent::Type>(markDirtyEventType())));
-}
-
-void QSGLayer::customEvent(QEvent *event)
-{
- if (event->type() == markDirtyEventType())
- markDirtyTexture();
- else
- QObject::customEvent(event);
-}
-
-int QSGLayer::markDirtyEventType()
-{
- static int type = QEvent::None;
- if (type == QEvent::None)
- type = QEvent::registerEventType();
- return type;
-}
-
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 71033bd6d0..a63299fcde 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -198,7 +198,6 @@ class Q_QUICK_EXPORT QSGLayer : public QSGDynamicTexture
Q_OBJECT
public:
virtual void setItem(QSGNode *item) = 0;
- virtual void setShaderSourceNode(QSGNode *node) = 0;
virtual void setRect(const QRectF &rect) = 0;
virtual void setSize(const QSize &size) = 0;
virtual void scheduleUpdate() = 0;
@@ -211,17 +210,9 @@ public:
Q_SLOT virtual void markDirtyTexture() = 0;
Q_SLOT virtual void invalidated() = 0;
- Q_SLOT void markDirtyTextureLater();
-
Q_SIGNALS:
void updateRequested();
void scheduledUpdateCompleted();
-
-protected:
- virtual void customEvent(QEvent *);
-
-private:
- int markDirtyEventType();
};
class Q_QUICK_PRIVATE_EXPORT QSGGlyphNode : public QSGVisitableNode
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index e7b37e50d2..b87ab3686f 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -50,6 +50,7 @@
#include <QtQuick/private/qquickpixmapcache_p.h>
#include <QGuiApplication>
+#include <QScreen>
#include <QOpenGLContext>
#include <QQuickWindow>
#include <QtGui/qopenglframebufferobject.h>
@@ -58,6 +59,7 @@
#include <QtQuick/private/qsgtexture_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtCore/private/qabstractanimation_p.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformsharedgraphicscache.h>
@@ -134,6 +136,135 @@ public:
bool distanceFieldAntialiasingDecided;
};
+static bool qsg_useConsistentTiming()
+{
+ static int use = -1;
+ if (use < 0) {
+ QByteArray fixed = qgetenv("QSG_FIXED_ANIMATION_STEP");
+ use = !(fixed.isEmpty() || fixed == "no");
+ qCDebug(QSG_LOG_INFO, "Using %s", bool(use) ? "fixed animation steps" : "sg animation driver");
+ }
+ return bool(use);
+}
+
+class QSGAnimationDriver : public QAnimationDriver
+{
+ Q_OBJECT
+public:
+ enum Mode {
+ VSyncMode,
+ TimerMode
+ };
+
+ QSGAnimationDriver(QObject *parent)
+ : QAnimationDriver(parent)
+ , m_time(0)
+ , m_vsync(0)
+ , m_mode(VSyncMode)
+ , m_bad(0)
+ , m_reallyBad(0)
+ , m_good(0)
+ {
+ QScreen *screen = QGuiApplication::primaryScreen();
+ if (screen && !qsg_useConsistentTiming()) {
+ m_vsync = 1000.0 / screen->refreshRate();
+ if (m_vsync <= 0)
+ m_mode = TimerMode;
+ } else {
+ m_mode = TimerMode;
+ if (qsg_useConsistentTiming())
+ QUnifiedTimer::instance(true)->setConsistentTiming(true);
+ }
+ if (m_mode == VSyncMode)
+ qCDebug(QSG_LOG_INFO, "Animation Driver: using vsync: %.2f ms", m_vsync);
+ else
+ qCDebug(QSG_LOG_INFO, "Animation Driver: using walltime");
+ }
+
+ void start() Q_DECL_OVERRIDE
+ {
+ m_time = 0;
+ m_timer.start();
+ QAnimationDriver::start();
+ }
+
+ qint64 elapsed() const Q_DECL_OVERRIDE
+ {
+ return m_mode == VSyncMode
+ ? qint64(m_time)
+ : QAnimationDriver::elapsed();
+ }
+
+ void advance() Q_DECL_OVERRIDE
+ {
+ qint64 delta = m_timer.restart();
+
+ if (m_mode == VSyncMode) {
+ // If a frame is skipped, either because rendering was slow or because
+ // the QML was slow, we accept it and continue advancing with a single
+ // vsync tick. The reason for this is that by the time we notice this
+ // on the GUI thread, the temporal distortion has already gone to screen
+ // and by catching up, we will introduce a second distortion which will
+ // worse. We accept that the animation time falls behind wall time because
+ // it comes out looking better.
+ // Only when multiple bad frames are hit in a row, do we consider
+ // switching. A few really bad frames and we switch right away. For frames
+ // just above the vsync delta, we tolerate a bit more since a buffered
+ // driver can have vsync deltas on the form: 4, 21, 21, 2, 23, 16, and
+ // still manage to put the frames to screen at 16 ms intervals. In addition
+ // to that, we tolerate a 25% margin of error on the value of m_vsync
+ // reported from the system as this value is often not precise.
+
+ m_time += m_vsync;
+
+ if (delta > m_vsync * 5) {
+ ++m_reallyBad;
+ ++m_bad;
+ } else if (delta > m_vsync * 1.25) {
+ ++m_bad;
+ } else {
+ // reset counters on a good frame.
+ m_reallyBad = 0;
+ m_bad = 0;
+ }
+
+ // rational for the 3 and 50. If we have several really bad frames
+ // in a row, that would indicate a huge performance problem and we should
+ // switch right away. For the case of m_bad, we're a bit more tolerant.
+ if (m_reallyBad > 3 || m_bad > 50) {
+ m_mode = TimerMode;
+ qCDebug(QSG_LOG_INFO, "animation driver switched to timer mode");
+ }
+
+ } else {
+ if (delta < 1.25 * m_vsync) {
+ ++m_good;
+ } else {
+ m_good = 0;
+ }
+
+ // We've been solid for a while, switch back to vsync mode. Tolerance
+ // for switching back is lower than switching to timer mode, as we
+ // want to stay in vsync mode as much as possible.
+ if (m_good > 10 && !qsg_useConsistentTiming()) {
+ m_time = elapsed();
+ m_mode = VSyncMode;
+ qCDebug(QSG_LOG_INFO, "animation driver switched to vsync mode");
+ }
+ }
+
+ advanceAnimation();
+ }
+
+ float m_time;
+ float m_vsync;
+ Mode m_mode;
+ QElapsedTimer m_timer;
+ int m_bad;
+ int m_reallyBad;
+ int m_good;
+};
+
class QSGTextureCleanupEvent : public QEvent
{
public:
@@ -389,7 +520,7 @@ bool QSGContext::isDistanceFieldEnabled() const
QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
{
- return new QAnimationDriver(parent);
+ return new QSGAnimationDriver(parent);
}
QSGRenderContext::QSGRenderContext(QSGContext *context)
@@ -730,4 +861,6 @@ void QSGRenderContext::initialize(QSGMaterialShader *shader)
shader->initialize();
}
+#include "qsgcontext.moc"
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 16feafe02f..802c92be9f 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -128,28 +128,8 @@ void QSGTextMaskShader::updateState(const RenderState &state, QSGMaterial *newEf
}
}
- if (state.isMatrixDirty()) {
- QMatrix4x4 transform = state.modelViewMatrix();
- qreal xTranslation = transform(0, 3);
- qreal yTranslation = transform(1, 3);
-
- // Remove translation and check identity to see if matrix is only translating.
- // If it is, we can round the translation to make sure the text is pixel aligned,
- // which is the only thing that works with GL_NEAREST filtering. Adding rotations
- // and scales to native rendered text is not a prioritized use case, since the
- // default rendering type is designed for that.
- transform(0, 3) = 0.0;
- transform(1, 3) = 0.0;
- if (transform.isIdentity()) {
- transform(0, 3) = qRound(xTranslation);
- transform(1, 3) = qRound(yTranslation);
-
- transform = state.projectionMatrix() * transform;
- program()->setUniformValue(m_matrix_id, transform);
- } else {
- program()->setUniformValue(m_matrix_id, state.combinedMatrix());
- }
- }
+ if (state.isMatrixDirty())
+ program()->setUniformValue(m_matrix_id, state.combinedMatrix());
}
class QSG8BitTextMaskShader : public QSGTextMaskShader
diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
index 29f125e0be..2d114aebd5 100644
--- a/src/quick/scenegraph/qsgdefaultlayer.cpp
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -88,7 +88,6 @@ namespace
QSGDefaultLayer::QSGDefaultLayer(QSGRenderContext *context)
: QSGLayer()
, m_item(0)
- , m_shaderSourceNode(0)
, m_device_pixel_ratio(1)
, m_format(GL_RGBA)
, m_renderer(0)
@@ -259,11 +258,8 @@ void QSGDefaultLayer::scheduleUpdate()
if (m_grab)
return;
m_grab = true;
- if (m_dirtyTexture) {
+ if (m_dirtyTexture)
emit updateRequested();
- if (m_shaderSourceNode)
- m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial);
- }
}
void QSGDefaultLayer::setRecursive(bool recursive)
@@ -274,11 +270,8 @@ void QSGDefaultLayer::setRecursive(bool recursive)
void QSGDefaultLayer::markDirtyTexture()
{
m_dirtyTexture = true;
- if (m_live || m_grab) {
+ if (m_live || m_grab)
emit updateRequested();
- if (m_shaderSourceNode)
- m_shaderSourceNode->markDirty(QSGNode::DirtyMaterial);
- }
}
void QSGDefaultLayer::grab()
@@ -299,7 +292,7 @@ void QSGDefaultLayer::grab()
if (!m_renderer) {
m_renderer = m_context->createRenderer();
- connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTextureLater()));
+ connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
}
m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
index b4a5adab5a..0615045d60 100644
--- a/src/quick/scenegraph/qsgdefaultlayer_p.h
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -60,8 +60,6 @@ public:
QSGNode *item() const { return m_item; }
void setItem(QSGNode *item);
- void setShaderSourceNode(QSGNode *node) { m_shaderSourceNode = node; }
-
QRectF rect() const { return m_rect; }
void setRect(const QRectF &rect);
@@ -100,7 +98,6 @@ private:
void grab();
QSGNode *m_item;
- QSGNode *m_shaderSourceNode;
QRectF m_rect;
QSize m_size;
qreal m_device_pixel_ratio;
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 0de3c84491..6381c3160f 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -147,19 +147,6 @@ public:
bool eventPending;
};
-bool QSGRenderLoop::useConsistentTiming()
-{
- bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL);
- // Enable fixed animation steps...
- QByteArray fixed = qgetenv("QSG_FIXED_ANIMATION_STEP");
- bool fixedAnimationSteps = bufferQueuing;
- if (fixed == "no")
- fixedAnimationSteps = false;
- else if (fixed.length())
- fixedAnimationSteps = true;
- return fixedAnimationSteps;
-}
-
QSGRenderLoop *QSGRenderLoop::instance()
{
if (!s_instance) {
@@ -170,11 +157,6 @@ QSGRenderLoop *QSGRenderLoop::instance()
s_instance = QSGContext::createWindowManager();
- if (useConsistentTiming()) {
- QUnifiedTimer::instance(true)->setConsistentTiming(true);
- qCDebug(QSG_LOG_INFO, "using fixed animation steps");
- }
-
if (!s_instance) {
enum RenderLoopType {
@@ -283,37 +265,24 @@ void QSGGuiThreadRenderLoop::show(QQuickWindow *window)
void QSGGuiThreadRenderLoop::hide(QQuickWindow *window)
{
- if (!m_windows.contains(window))
- return;
-
- m_windows.remove(window);
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
- if (gl)
- gl->makeCurrent(window);
cd->fireAboutToStop();
- cd->cleanupNodesOnShutdown();
-
- if (m_windows.size() == 0) {
- if (!cd->persistentSceneGraph) {
- rc->invalidate();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- if (!cd->persistentGLContext) {
- delete gl;
- gl = 0;
- }
- }
- }
}
void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
{
+ m_windows.remove(window);
hide(window);
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
+ if (gl)
+ gl->makeCurrent(window);
+ d->cleanupNodesOnShutdown();
if (m_windows.size() == 0) {
rc->invalidate();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete gl;
gl = 0;
- } else if (window == gl->surface()) {
+ } else if (gl && window == gl->surface()) {
gl->doneCurrent();
}
}
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index daba3bc69d..e9b58c60ba 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -82,8 +82,6 @@ public:
static QSGRenderLoop *instance();
static void setInstance(QSGRenderLoop *instance);
- static bool useConsistentTiming();
-
virtual bool interleaveIncubation() const { return false; }
static void cleanup();
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 92c478b54f..29bee67f69 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -189,9 +189,15 @@ public:
class WMSyncEvent : public WMWindowEvent
{
public:
- WMSyncEvent(QQuickWindow *c, bool inExpose) : WMWindowEvent(c, WM_RequestSync), size(c->size()), syncInExpose(inExpose) { }
+ WMSyncEvent(QQuickWindow *c, bool inExpose, bool force)
+ : WMWindowEvent(c, WM_RequestSync)
+ , size(c->size())
+ , syncInExpose(inExpose)
+ , forceRenderPass(force)
+ {}
QSize size;
bool syncInExpose;
+ bool forceRenderPass;
};
@@ -368,6 +374,10 @@ bool QSGRenderThread::event(QEvent *e)
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- triggered from expose";
pendingUpdate |= ExposeRequest;
}
+ if (se->forceRenderPass) {
+ qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- repaint regardless";
+ pendingUpdate |= RepaintRequest;
+ }
return true; }
case WM_TryRelease: {
@@ -641,7 +651,6 @@ void QSGRenderThread::run()
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "run()";
animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0);
animatorDriver->install();
- QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming());
if (QQmlDebugService::isDebuggingEnabled())
QQuickProfiler::registerAnimationCallback();
@@ -855,6 +864,7 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context);
win.timerId = 0;
win.updateDuringSync = false;
+ win.forceRenderPass = true; // also covered by polishAndSync(inExpose=true), but doesn't hurt
m_windows << win;
w = &m_windows.last();
}
@@ -998,7 +1008,9 @@ void QSGThreadedRenderLoop::update(QQuickWindow *window)
}
qCDebug(QSG_LOG_RENDERLOOP) << "update on window" << w->window;
- w->thread->postEvent(new QEvent(WM_RequestRepaint));
+ // We set forceRenderPass because we want to make sure the QQuickWindow
+ // actually does a full render pass after the next sync.
+ w->forceRenderPass = true;
maybeUpdate(w);
}
@@ -1107,7 +1119,8 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
qCDebug(QSG_LOG_RENDERLOOP) << "- lock for sync";
w->thread->mutex.lock();
m_lockedForSync = true;
- w->thread->postEvent(new WMSyncEvent(window, inExpose));
+ w->thread->postEvent(new WMSyncEvent(window, inExpose, w->forceRenderPass));
+ w->forceRenderPass = false;
qCDebug(QSG_LOG_RENDERLOOP) << "- wait for sync";
if (profileFrames)
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
index 0e4da27fc6..82f314a6af 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h
+++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
@@ -82,6 +82,7 @@ private:
QSurfaceFormat actualWindowFormat;
int timerId;
uint updateDuringSync : 1;
+ uint forceRenderPass : 1;
};
friend class QSGRenderThread;
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index b55977296c..11e3376af5 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -189,14 +189,6 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window)
void QSGWindowsRenderLoop::hide(QQuickWindow *window)
{
RLDEBUG("hide");
-
- for (int i=0; i<m_windows.size(); ++i) {
- if (m_windows.at(i).window == window) {
- m_windows.removeAt(i);
- break;
- }
- }
-
// The expose event is queued while hide is sent synchronously, so
// the value might not be updated yet. (plus that the windows plugin
// sends exposed=true when it goes to hidden, so it is doubly broken)
@@ -204,47 +196,41 @@ void QSGWindowsRenderLoop::hide(QQuickWindow *window)
// anyoneShowing will report the right value.
if (window->isExposed())
handleObscurity();
-
if (!m_gl)
return;
-
- QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
- m_gl->makeCurrent(window);
- cd->fireAboutToStop();
- cd->cleanupNodesOnShutdown();
-
- // If this is the last tracked window, check for persistent SG and GL and
- // potentially clean up.
- if (m_windows.size() == 0) {
- if (!cd->persistentSceneGraph) {
- QQuickWindowPrivate::get(window)->context->invalidate();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- if (!cd->persistentGLContext) {
- delete m_gl;
- m_gl = 0;
- }
- }
- }
+ QQuickWindowPrivate::get(window)->fireAboutToStop();
}
void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window)
{
RLDEBUG("windowDestroyed");
+ for (int i=0; i<m_windows.size(); ++i) {
+ if (m_windows.at(i).window == window) {
+ m_windows.removeAt(i);
+ break;
+ }
+ }
+
hide(window);
- // If this is the last tracked window, clean up SG and GL.
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
+ if (m_gl)
+ m_gl->makeCurrent(window);
+ d->cleanupNodesOnShutdown();
if (m_windows.size() == 0) {
- QQuickWindowPrivate::get(window)->context->invalidate();
+ d->context->invalidate();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete m_gl;
m_gl = 0;
+ } else if (m_gl) {
+ m_gl->doneCurrent();
}
}
bool QSGWindowsRenderLoop::anyoneShowing() const
{
foreach (const WindowData &wd, m_windows)
- if (wd.window->isExposed() && wd.window->size().isValid())
+ if (wd.window->isVisible() && wd.window->isExposed() && wd.window->size().isValid())
return true;
return false;
}
@@ -255,7 +241,7 @@ void QSGWindowsRenderLoop::exposureChanged(QQuickWindow *window)
if (windowData(window) == 0)
return;
- if (window->isExposed()) {
+ if (window->isExposed() && window->isVisible()) {
// Stop non-visual animation timer as we now have a window rendering
if (m_animationTimer && anyoneShowing()) {
diff --git a/src/quick/scenegraph/shaders/styledtext.vert b/src/quick/scenegraph/shaders/styledtext.vert
index 3ad9497b65..14fefc2564 100644
--- a/src/quick/scenegraph/shaders/styledtext.vert
+++ b/src/quick/scenegraph/shaders/styledtext.vert
@@ -12,5 +12,5 @@ void main()
{
sampleCoord = tCoord * textureScale;
shiftedSampleCoord = (tCoord - shift) * textureScale;
- gl_Position = matrix * vCoord;
-} \ No newline at end of file
+ gl_Position = matrix * floor(vCoord + 0.5);
+}
diff --git a/src/quick/scenegraph/shaders/styledtext_core.vert b/src/quick/scenegraph/shaders/styledtext_core.vert
index b7a3ecc667..65bdb66814 100644
--- a/src/quick/scenegraph/shaders/styledtext_core.vert
+++ b/src/quick/scenegraph/shaders/styledtext_core.vert
@@ -14,5 +14,5 @@ void main()
{
sampleCoord = tCoord * textureScale;
shiftedSampleCoord = (tCoord - shift) * textureScale;
- gl_Position = matrix * vCoord;
-} \ No newline at end of file
+ gl_Position = matrix * round(vCoord);
+}
diff --git a/src/quick/scenegraph/shaders/textmask.vert b/src/quick/scenegraph/shaders/textmask.vert
index 1f45e9cf71..dd8918839e 100644
--- a/src/quick/scenegraph/shaders/textmask.vert
+++ b/src/quick/scenegraph/shaders/textmask.vert
@@ -9,5 +9,5 @@ varying highp vec2 sampleCoord;
void main()
{
sampleCoord = tCoord * textureScale;
- gl_Position = matrix * vCoord;
+ gl_Position = matrix * floor(vCoord + 0.5);
}
diff --git a/src/quick/scenegraph/shaders/textmask_core.vert b/src/quick/scenegraph/shaders/textmask_core.vert
index 619248dccb..d145d33195 100644
--- a/src/quick/scenegraph/shaders/textmask_core.vert
+++ b/src/quick/scenegraph/shaders/textmask_core.vert
@@ -11,5 +11,5 @@ uniform vec2 textureScale;
void main()
{
sampleCoord = tCoord * textureScale;
- gl_Position = matrix * vCoord;
+ gl_Position = matrix * round(vCoord);
}
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index bc091edffe..cb82d721ca 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -307,7 +307,16 @@ void Atlas::uploadBgra(Texture *texture)
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + iw + 1, r.y() + 1, 1, ih, m_externalFormat, GL_UNSIGNED_BYTE, dst);
// Inner part of the image....
- funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ if (bpl != iw) {
+ int sy = r.y() + 1;
+ int ey = sy + r.height() - 2;
+ for (int y = sy; y < ey; ++y) {
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, y, r.width() - 2, 1, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ src += bpl;
+ }
+ } else {
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2, m_externalFormat, GL_UNSIGNED_BYTE, src);
+ }
}
void Atlas::bind(QSGTexture::Filtering filtering)
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 3bb0cb0074..673323baa2 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -563,7 +563,7 @@ QSGPlainTexture::QSGPlainTexture()
QSGPlainTexture::~QSGPlainTexture()
{
- if (m_texture_id && m_owns_texture)
+ if (m_texture_id && m_owns_texture && QOpenGLContext::currentContext())
QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &m_texture_id);
}
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index 01f182c35d..e009de205c 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -184,8 +184,6 @@ void QQuickAnimatorController::beforeNodeSync()
m_nodesAreInvalid = false;
}
-
-
foreach (QQuickAnimatorJob *job, m_activeLeafAnimations) {
if (!job->target())
continue;
@@ -197,9 +195,9 @@ void QQuickAnimatorController::beforeNodeSync()
}
}
foreach (QQuickItem *wiped, m_deletedSinceLastFrame) {
- QQuickTransformAnimatorJob::Helper *helper = m_transforms.value(wiped);
- if (helper)
- helper->item = 0;
+ QQuickTransformAnimatorJob::Helper *helper = m_transforms.take(wiped);
+ // Helper will now already have been reset in all animators referencing it.
+ delete helper;
}
m_deletedSinceLastFrame.clear();
@@ -254,6 +252,7 @@ void QQuickAnimatorController::requestSync()
// These functions are called on the GUI thread.
void QQuickAnimatorController::startJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job)
{
+ proxy->markJobManagedByController();
m_starting[job] = proxy;
requestSync();
}
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 741fa9bb7f..fdbffd4709 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -49,6 +49,7 @@ QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObje
: m_controller(0)
, m_job(job)
, m_internalState(State_Stopped)
+ , m_jobManagedByController(false)
{
m_isRenderThreadProxy = true;
m_animation = qobject_cast<QQuickAbstractAnimation *>(item);
@@ -93,7 +94,10 @@ void QQuickAnimatorProxyJob::deleteJob()
// so delete it through the controller to clean up properly.
if (m_controller)
m_controller->deleteJob(m_job);
- else
+
+ // We explicitly delete the job if the animator controller has never touched
+ // it. If it has, it will have ownership as well.
+ else if (!m_jobManagedByController)
delete m_job;
m_job = 0;
}
@@ -141,11 +145,13 @@ void QQuickAnimatorProxyJob::controllerWasDeleted()
void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
{
if (!window) {
- // Stop will trigger syncBackCurrentValues so best to do it before
- // we delete m_job.
stop();
deleteJob();
- return;
+
+ // Upon leaving a window, we reset the controller. This means that
+ // animators will only enter the Starting phase and won't be making
+ // calls to QQuickAnimatorController::startjob().
+ m_controller = 0;
} else if (!m_controller && m_job) {
m_controller = QQuickWindowPrivate::get(window)->animationController;
@@ -250,6 +256,10 @@ QQuickTransformAnimatorJob::QQuickTransformAnimatorJob()
QQuickTransformAnimatorJob::~QQuickTransformAnimatorJob()
{
if (m_helper && --m_helper->ref == 0) {
+ // The only condition for not having a controller is when target was
+ // destroyed, in which case we have neither m_helper nor m_contorller.
+ Q_ASSERT(m_controller);
+ Q_ASSERT(m_helper->item);
m_controller->m_transforms.remove(m_helper->item);
delete m_helper;
}
@@ -260,6 +270,7 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller
QQuickAnimatorJob::initialize(controller);
if (m_controller) {
+ bool newHelper = m_helper == 0;
m_helper = m_controller->m_transforms.value(m_target);
if (!m_helper) {
m_helper = new Helper();
@@ -267,7 +278,8 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller
m_controller->m_transforms.insert(m_target, m_helper);
QObject::connect(m_target, SIGNAL(destroyed(QObject*)), m_controller, SLOT(itemDestroyed(QObject*)), Qt::DirectConnection);
} else {
- ++m_helper->ref;
+ if (newHelper) // only add reference the first time around..
+ ++m_helper->ref;
// Make sure leftovers from previous runs are being used...
m_helper->wasSynced = false;
}
@@ -281,6 +293,12 @@ void QQuickTransformAnimatorJob::nodeWasDestroyed()
m_helper->node = 0;
}
+void QQuickTransformAnimatorJob::targetWasDeleted()
+{
+ m_helper = 0;
+ QQuickAnimatorJob::targetWasDeleted();
+}
+
void QQuickTransformAnimatorJob::Helper::sync()
{
const quint32 mask = QQuickItemPrivate::Position
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index 7c6ad823b3..4bdcd6917d 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -69,6 +69,7 @@ public:
void startedByController();
void controllerWasDeleted();
+ void markJobManagedByController() { m_jobManagedByController = true; }
protected:
bool event(QEvent *);
@@ -87,7 +88,7 @@ private:
void setWindow(QQuickWindow *window);
static QObject *findAnimationContext(QQuickAbstractAnimation *);
- QQuickAnimatorController *m_controller;
+ QPointer<QQuickAnimatorController> m_controller;
QQuickAbstractAnimation *m_animation;
QAbstractAnimationJob *m_job;
int m_duration;
@@ -100,6 +101,7 @@ private:
};
InternalState m_internalState;
+ bool m_jobManagedByController;
};
class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorJob : public QAbstractAnimationJob
@@ -120,7 +122,7 @@ public:
QEasingCurve easingCurve() const { return m_easing; }
void setEasingCurve(const QEasingCurve &curve) { m_easing = curve; }
- void targetWasDeleted();
+ virtual void targetWasDeleted();
virtual void initialize(QQuickAnimatorController *controller);
virtual void writeBack() = 0;
virtual void nodeWasDestroyed() = 0;
@@ -202,6 +204,7 @@ protected:
QQuickTransformAnimatorJob();
void initialize(QQuickAnimatorController *controller);
void nodeWasDestroyed();
+ void targetWasDeleted() Q_DECL_OVERRIDE;
Helper *m_helper;
};
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 3e94d0cea6..a2a8ef03c7 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -40,6 +40,7 @@
#include <private/qqmlengine_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qimage_p.h>
#include <qpa/qplatformintegration.h>
#include <QtQuick/private/qsgtexture_p.h>
@@ -70,6 +71,8 @@
#define CACHE_EXPIRE_TIME 30
#define CACHE_REMOVAL_FRACTION 4
+#define PIXMAP_PROFILE(Code) Q_QUICK_PROFILE(QQuickProfiler::ProfilePixmapCache, Code)
+
QT_BEGIN_NAMESPACE
@@ -329,6 +332,29 @@ QNetworkAccessManager *QQuickPixmapReader::networkAccessManager()
return accessManager;
}
+static void maybeRemoveAlpha(QImage *image)
+{
+ // If the image
+ if (image->hasAlphaChannel() && image->data_ptr()
+ && !image->data_ptr()->checkForAlphaPixels()) {
+ switch (image->format()) {
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ *image = image->convertToFormat(QImage::Format_RGBX8888);
+ break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ *image = image->convertToFormat(QImage::Format_BGR30);
+ break;
+ case QImage::Format_A2RGB30_Premultiplied:
+ *image = image->convertToFormat(QImage::Format_RGB30);
+ break;
+ default:
+ *image = image->convertToFormat(QImage::Format_RGB32);
+ break;
+ }
+ }
+}
+
static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize,
const QSize &requestSize)
{
@@ -358,6 +384,7 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
*impsize = imgio.size();
if (imgio.read(image)) {
+ maybeRemoveAlpha(image);
if (impsize && impsize->width() < 0)
*impsize = image->size();
return true;
@@ -500,7 +527,7 @@ void QQuickPixmapReader::processJobs()
replies.remove(reply);
reply->close();
}
- Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url));
+ PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(job->url));
// deleteLater, since not owned by this thread
job->deleteLater();
}
@@ -512,7 +539,7 @@ void QQuickPixmapReader::processJobs()
runningJob->loading = true;
QUrl url = runningJob->url;
- Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
+ PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
QSize requestSize = runningJob->requestSize;
locker.unlock();
@@ -660,7 +687,7 @@ void QQuickPixmapReader::cancel(QQuickPixmapReply *reply)
// If loading was started (reply removed from jobs) but the reply was never processed
// (otherwise it would have deleted itself) we need to profile an error.
if (jobs.removeAll(reply) == 0) {
- Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(reply->url));
+ PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(reply->url));
}
delete reply;
}
@@ -896,12 +923,12 @@ bool QQuickPixmapReply::event(QEvent *event)
if (data->pixmapStatus == QQuickPixmap::Ready) {
data->textureFactory = de->textureFactory;
data->implicitSize = de->implicitSize;
- Q_QUICK_PROFILE(pixmapLoadingFinished(data->url,
+ PIXMAP_PROFILE(pixmapLoadingFinished(data->url,
data->textureFactory != 0 && data->textureFactory->textureSize().isValid() ?
data->textureFactory->textureSize() :
(data->requestSize.isValid() ? data->requestSize : data->implicitSize)));
} else {
- Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(data->url));
+ PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(data->url));
data->errorString = de->errorString;
data->removeFromCache(); // We don't continue to cache error'd pixmaps
}
@@ -909,7 +936,7 @@ bool QQuickPixmapReply::event(QEvent *event)
data->reply = 0;
emit finished();
} else {
- Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(url));
+ PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(url));
}
delete this;
@@ -929,7 +956,7 @@ int QQuickPixmapData::cost() const
void QQuickPixmapData::addref()
{
++refCount;
- Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
+ PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
if (prevUnreferencedPtr)
pixmapStore()->referencePixmap(this);
}
@@ -938,7 +965,7 @@ void QQuickPixmapData::release()
{
Q_ASSERT(refCount > 0);
--refCount;
- Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
+ PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapReferenceCountChanged>(url, refCount));
if (refCount == 0) {
if (reply) {
QQuickPixmapReply *cancelReply = reply;
@@ -969,7 +996,7 @@ void QQuickPixmapData::addToCache()
QQuickPixmapKey key = { &url, &requestSize };
pixmapStore()->m_cache.insert(key, this);
inCache = true;
- Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
+ PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
url, pixmapStore()->m_cache.count()));
}
}
@@ -980,7 +1007,7 @@ void QQuickPixmapData::removeFromCache()
QQuickPixmapKey key = { &url, &requestSize };
pixmapStore()->m_cache.remove(key);
inCache = false;
- Q_QUICK_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
+ PIXMAP_PROFILE(pixmapCountChanged<QQuickProfiler::PixmapCacheCountChanged>(
url, pixmapStore()->m_cache.count()));
}
}
@@ -1259,16 +1286,16 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques
if (!(options & QQuickPixmap::Asynchronous)) {
bool ok = false;
- Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
+ PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingStarted>(url));
d = createPixmapDataSync(this, engine, url, requestSize, &ok);
if (ok) {
- Q_QUICK_PROFILE(pixmapLoadingFinished(url, QSize(width(), height())));
+ PIXMAP_PROFILE(pixmapLoadingFinished(url, QSize(width(), height())));
if (options & QQuickPixmap::Cache)
d->addToCache();
return;
}
if (d) { // loadable, but encountered error while loading
- Q_QUICK_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(url));
+ PIXMAP_PROFILE(pixmapStateChanged<QQuickProfiler::PixmapLoadingError>(url));
return;
}
}
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index 7cb64bbeeb..c4441ed5dd 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE
// instance will be set, unset in constructor. Allows static methods to be inlined.
QQuickProfiler *QQuickProfiler::s_instance = 0;
-bool QQuickProfiler::enabled = false;
+quint64 QQuickProfiler::featuresEnabled = 0;
// convert to QByteArrays that can be sent to the debug client
// use of QDataStream can skew results
@@ -129,7 +129,7 @@ void QQuickProfiler::initialize()
void animationTimerCallback(qint64 delta)
{
- Q_QUICK_PROFILE(animationFrame(delta,
+ Q_QUICK_PROFILE(QQuickProfiler::ProfileAnimations, animationFrame(delta,
QThread::currentThread() == QCoreApplication::instance()->thread() ?
QQuickProfiler::GuiThread : QQuickProfiler::RenderThread));
}
@@ -158,10 +158,10 @@ QQuickProfiler::QQuickProfiler(QQmlProfilerService *service) :
m_timer.start();
// We can always do DirectConnection here as all methods are protected by mutexes
- connect(this, SIGNAL(profilingEnabled()), this, SLOT(startProfilingImpl()),
- Qt::DirectConnection);
- connect(this, SIGNAL(profilingEnabledWhileWaiting()), this, SLOT(startProfilingImpl()),
+ connect(this, SIGNAL(profilingEnabled(quint64)), this, SLOT(startProfilingImpl(quint64)),
Qt::DirectConnection);
+ connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
+ this, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)), this, SLOT(setTimer(QElapsedTimer)),
Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabled()), this, SLOT(stopProfilingImpl()),
@@ -179,23 +179,23 @@ QQuickProfiler::QQuickProfiler(QQmlProfilerService *service) :
QQuickProfiler::~QQuickProfiler()
{
QMutexLocker lock(&m_dataMutex);
- enabled = false;
+ featuresEnabled = 0;
s_instance = 0;
}
-void QQuickProfiler::startProfilingImpl()
+void QQuickProfiler::startProfilingImpl(quint64 features)
{
QMutexLocker lock(&m_dataMutex);
next = 0;
m_data.clear();
- enabled = true;
+ featuresEnabled = features;
}
void QQuickProfiler::stopProfilingImpl()
{
{
QMutexLocker lock(&m_dataMutex);
- enabled = false;
+ featuresEnabled = 0;
next = 0;
}
service->dataReady(this);
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index 6796fab912..ea37558741 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -55,40 +55,50 @@
QT_BEGIN_NAMESPACE
-#define Q_QUICK_PROFILE_IF_ENABLED(Code)\
- if (QQuickProfiler::enabled) {\
+#define Q_QUICK_PROFILE_IF_ENABLED(feature, Code)\
+ if (QQuickProfiler::featuresEnabled & (1 << feature)) {\
Code;\
} else\
(void)0
-#define Q_QUICK_PROFILE(Method)\
- Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::Method)
+#define Q_QUICK_PROFILE(feature, Method)\
+ Q_QUICK_PROFILE_IF_ENABLED(feature, QQuickProfiler::Method)
#define Q_QUICK_SG_PROFILE_START(Type)\
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::startSceneGraphFrame<Type>()))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::startSceneGraphFrame<Type>()))
#define Q_QUICK_SG_PROFILE_RECORD(Type)\
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::recordSceneGraphTimestamp<Type>()))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::recordSceneGraphTimestamp<Type>()))
#define Q_QUICK_SG_PROFILE_SKIP(Type, Skip)\
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>()))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>()))
#define Q_QUICK_SG_PROFILE_START_SYNCHRONIZED(Type1, Type2)\
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::startSceneGraphFrame<Type1, Type2>()))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::startSceneGraphFrame<Type1, Type2>()))
#define Q_QUICK_SG_PROFILE_SWITCH(Type1, Type2) \
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>()))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>()))
#define Q_QUICK_SG_PROFILE_REPORT(Type)\
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::reportSceneGraphFrame<Type, false>()))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, false>()))
#define Q_QUICK_SG_PROFILE_END(Type)\
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::reportSceneGraphFrame<Type, true>()))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>()))
#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, Payload)\
- Q_QUICK_PROFILE_IF_ENABLED((QQuickProfiler::reportSceneGraphFrame<Type, true>(Payload)))
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>(Payload)))
+#define Q_QUICK_INPUT_PROFILE(Method)\
+ Q_QUICK_PROFILE(QQuickProfiler::ProfileInputEvents, Method)
// This struct is somewhat dangerous to use:
// You can save values either with 32 or 64 bit precision. toByteArrays will
@@ -302,7 +312,11 @@ public:
qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
- static bool enabled;
+ static quint64 featuresEnabled;
+ static bool profilingSceneGraph()
+ {
+ return featuresEnabled & (1 << QQuickProfiler::ProfileSceneGraph);
+ }
static void initialize();
@@ -325,7 +339,7 @@ protected:
}
protected slots:
- void startProfilingImpl();
+ void startProfilingImpl(quint64 features);
void stopProfilingImpl();
void reportDataImpl();
void setTimer(const QElapsedTimer &t);
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 8d93bf389b..ef6c174b88 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -200,6 +200,26 @@ void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRec
QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
}
+void QQuickWidgetPrivate::render(bool needsSync)
+{
+ context->makeCurrent(offscreenSurface);
+
+ if (needsSync) {
+ renderControl->polishItems();
+ renderControl->sync();
+ }
+
+ renderControl->render();
+ context->functions()->glFlush();
+
+ if (resolvedFbo) {
+ QRect rect(QPoint(0, 0), fbo->size());
+ QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect);
+ }
+
+ context->doneCurrent();
+}
+
void QQuickWidgetPrivate::renderSceneGraph()
{
Q_Q(QQuickWidget);
@@ -215,19 +235,8 @@ void QQuickWidgetPrivate::renderSceneGraph()
}
Q_ASSERT(offscreenSurface);
- context->makeCurrent(offscreenSurface);
- renderControl->polishItems();
- renderControl->sync();
- renderControl->render();
- context->functions()->glFlush();
-
- if (resolvedFbo) {
- QRect rect(QPoint(0, 0), fbo->size());
- QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect);
- }
-
- context->doneCurrent();
- q->update();
+ render(true);
+ q->update(); // schedule composition
}
QImage QQuickWidgetPrivate::grabFramebuffer()
@@ -294,6 +303,11 @@ QImage QQuickWidgetPrivate::grabFramebuffer()
some of the benefits of threaded rendering, for example \l Animator classes and vsync driven
animations, will not be available.
+ \note Avoid calling winId() on a QQuickWidget. This function triggers the creation of
+ a native window, resulting in reduced performance and possibly rendering glitches. The
+ entire purpose of QQuickWidget is to render Quick scenes without a separate native
+ window, hence making it a native widget should always be avoided.
+
\section1 Limitations
Putting other widgets underneath and making the QQuickWidget transparent will not lead
@@ -937,29 +951,14 @@ void QQuickWidget::resizeEvent(QResizeEvent *e)
return;
}
- context->makeCurrent(d->offscreenSurface);
-
- if (needsSync) {
- d->renderControl->polishItems();
- d->renderControl->sync();
- }
-
- d->renderControl->render();
- context->functions()->glFlush();
-
- if (d->resolvedFbo) {
- QRect rect(QPoint(0, 0), d->fbo->size());
- QOpenGLFramebufferObject::blitFramebuffer(d->resolvedFbo, rect, d->fbo, rect);
- }
-
- context->doneCurrent();
+ d->render(needsSync);
}
/*! \reimp */
void QQuickWidget::keyPressEvent(QKeyEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
QCoreApplication::sendEvent(d->offscreenWindow, e);
}
@@ -968,7 +967,7 @@ void QQuickWidget::keyPressEvent(QKeyEvent *e)
void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Key>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Key>());
QCoreApplication::sendEvent(d->offscreenWindow, e);
}
@@ -977,7 +976,7 @@ void QQuickWidget::keyReleaseEvent(QKeyEvent *e)
void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
// Use the constructor taking localPos and screenPos. That puts localPos into the
// event's localPos and windowPos, and screenPos into the event's screenPos. This way
@@ -992,7 +991,7 @@ void QQuickWidget::mouseMoveEvent(QMouseEvent *e)
void QQuickWidget::mouseDoubleClickEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
// As the second mouse press is suppressed in widget windows we emulate it here for QML.
// See QTBUG-25831
@@ -1025,7 +1024,7 @@ void QQuickWidget::hideEvent(QHideEvent *)
void QQuickWidget::mousePressEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
@@ -1036,7 +1035,7 @@ void QQuickWidget::mousePressEvent(QMouseEvent *e)
void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
QMouseEvent mappedEvent(e->type(), e->localPos(), e->screenPos(), e->button(), e->buttons(), e->modifiers());
QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent);
@@ -1048,7 +1047,7 @@ void QQuickWidget::mouseReleaseEvent(QMouseEvent *e)
void QQuickWidget::wheelEvent(QWheelEvent *e)
{
Q_D(QQuickWidget);
- Q_QUICK_PROFILE(addEvent<QQuickProfiler::Mouse>());
+ Q_QUICK_INPUT_PROFILE(addEvent<QQuickProfiler::Mouse>());
// Wheel events only have local and global positions, no need to map.
QCoreApplication::sendEvent(d->offscreenWindow, e);
@@ -1099,6 +1098,16 @@ bool QQuickWidget::event(QEvent *e)
case QEvent::WindowChangeInternal:
d->handleWindowChange();
break;
+
+ case QEvent::ScreenChangeInternal:
+ if (d->fbo) {
+ // This will check the size taking the devicePixelRatio into account
+ // and recreate if needed.
+ createFramebufferObject();
+ d->render(true);
+ }
+ break;
+
default:
break;
}
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index 2289b18d72..2ff9601f77 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -75,6 +75,7 @@ public:
void updateSize();
void updateFrambufferObjectSize();
void setRootObject(QObject *);
+ void render(bool needsSync);
void renderSceneGraph();
void createContext();
void destroyContext();
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 87549d2019..741fa9f04d 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -127,6 +127,7 @@ private slots:
void reentrancy_objectCreation();
void jsIncDecNonObjectProperty();
void JSONparse();
+ void arraySort();
void qRegExpInport_data();
void qRegExpInport();
@@ -2742,6 +2743,24 @@ void tst_QJSEngine::JSONparse()
QVERIFY(ret.isObject());
}
+void tst_QJSEngine::arraySort()
+{
+ // tests that calling Array.sort with a bad sort function doesn't cause issues
+ // Using std::sort is e.g. not safe when used with a bad sort function and causes
+ // crashes
+ QJSEngine eng;
+ eng.evaluate("function crashMe() {"
+ " var data = [];"
+ " for (var i = 0; i < 50; i++) {"
+ " data[i] = 'whatever';"
+ " }"
+ " data.sort(function(a, b) {"
+ " return -1;"
+ " });"
+ "}"
+ "crashMe();");
+}
+
static QRegExp minimal(QRegExp r) { r.setMinimal(true); return r; }
void tst_QJSEngine::qRegExpInport_data()
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 837403d391..9c615cfc15 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -34,10 +34,6 @@
#include "tst_qjsvalue.h"
#include <QtWidgets/QPushButton>
-QT_BEGIN_NAMESPACE
-extern bool qt_script_isJITEnabled();
-QT_END_NAMESPACE
-
tst_QJSValue::tst_QJSValue()
: engine(0)
{
@@ -45,8 +41,7 @@ tst_QJSValue::tst_QJSValue()
tst_QJSValue::~tst_QJSValue()
{
- if (engine)
- delete engine;
+ delete engine;
}
void tst_QJSValue::ctor_invalid()
@@ -308,6 +303,19 @@ void tst_QJSValue::ctor_copyAndAssign()
QCOMPARE(v5.toNumber(), 1.0);
}
+static QJSValue createUnboundValue(const QJSValue &value)
+{
+ QVariant variant = QVariant::fromValue(value);
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ QDataStream stream(&buffer);
+ variant.save(stream);
+ buffer.seek(0);
+ QVariant resultVariant;
+ resultVariant.load(stream);
+ return resultVariant.value<QJSValue>();
+}
+
void tst_QJSValue::toString()
{
QJSEngine eng;
@@ -406,6 +414,28 @@ void tst_QJSValue::toString()
variant = eng.toScriptValue(QUrl());
QVERIFY(variant.isVariant());
QVERIFY(variant.toString().isEmpty());
+
+ {
+ QJSValue o = eng.newObject();
+ o.setProperty(QStringLiteral("test"), 42);
+ QCOMPARE(o.toString(), QStringLiteral("[object Object]"));
+
+ o = createUnboundValue(o);
+ QVERIFY(!o.engine());
+ QCOMPARE(o.toString(), QStringLiteral("[object Object]"));
+ }
+
+ {
+ QJSValue o = eng.newArray();
+ o.setProperty(0, 1);
+ o.setProperty(1, 2);
+ o.setProperty(2, 3);
+ QCOMPARE(o.toString(), QStringLiteral("1,2,3"));
+
+ o = createUnboundValue(o);
+ QVERIFY(!o.engine());
+ QCOMPARE(o.toString(), QStringLiteral("1,2,3"));
+ }
}
void tst_QJSValue::toNumber()
@@ -419,35 +449,43 @@ void tst_QJSValue::toNumber()
QJSValue null = eng.evaluate("null");
QCOMPARE(null.toNumber(), 0.0);
QCOMPARE(qjsvalue_cast<qreal>(null), 0.0);
+ QCOMPARE(createUnboundValue(null).toNumber(), 0.0);
{
QJSValue falskt = eng.toScriptValue(false);
QCOMPARE(falskt.toNumber(), 0.0);
+ QCOMPARE(createUnboundValue(falskt).toNumber(), 0.0);
QCOMPARE(qjsvalue_cast<qreal>(falskt), 0.0);
QJSValue sant = eng.toScriptValue(true);
QCOMPARE(sant.toNumber(), 1.0);
+ QCOMPARE(createUnboundValue(sant).toNumber(), 1.0);
QCOMPARE(qjsvalue_cast<qreal>(sant), 1.0);
QJSValue number = eng.toScriptValue(123.0);
QCOMPARE(number.toNumber(), 123.0);
QCOMPARE(qjsvalue_cast<qreal>(number), 123.0);
+ QCOMPARE(createUnboundValue(number).toNumber(), 123.0);
QJSValue str = eng.toScriptValue(QString("ciao"));
QCOMPARE(qIsNaN(str.toNumber()), true);
QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(str)), true);
+ QCOMPARE(qIsNaN(createUnboundValue(str).toNumber()), true);
QJSValue str2 = eng.toScriptValue(QString("123"));
QCOMPARE(str2.toNumber(), 123.0);
QCOMPARE(qjsvalue_cast<qreal>(str2), 123.0);
+ QCOMPARE(createUnboundValue(str2).toNumber(), 123.0);
}
QJSValue object = eng.newObject();
QCOMPARE(qIsNaN(object.toNumber()), true);
+ QCOMPARE(qIsNaN(createUnboundValue(object).toNumber()), true);
QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(object)), true);
QJSValue inv = QJSValue();
QVERIFY(qIsNaN(inv.toNumber()));
+ QCOMPARE(qIsNaN(createUnboundValue(inv).toNumber()), true);
QVERIFY(qIsNaN(qjsvalue_cast<qreal>(inv)));
// V2 constructors
diff --git a/tests/auto/qml/qqmldirparser/data/dependency/qmldir b/tests/auto/qml/qqmldirparser/data/dependency/qmldir
new file mode 100644
index 0000000000..0754dbceea
--- /dev/null
+++ b/tests/auto/qml/qqmldirparser/data/dependency/qmldir
@@ -0,0 +1,3 @@
+plugin foo
+depends bar 1.0
+
diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
index 017a92b590..615df08d5c 100644
--- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
+++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
@@ -125,6 +125,7 @@ void tst_qqmldirparser::parse_data()
QTest::addColumn<QStringList>("plugins");
QTest::addColumn<QStringList>("components");
QTest::addColumn<QStringList>("scripts");
+ QTest::addColumn<QStringList>("dependencies");
QTest::addColumn<bool>("designerSupported");
QTest::newRow("empty")
@@ -133,6 +134,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("no-content")
@@ -141,6 +143,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("one-section")
@@ -149,6 +152,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("four-sections")
@@ -157,6 +161,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("incomplete-module")
@@ -165,6 +170,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("excessive-module")
@@ -173,6 +179,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("repeated-module")
@@ -181,6 +188,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("non-first-module")
@@ -189,6 +197,7 @@ void tst_qqmldirparser::parse_data()
<< (QStringList() << "foo|")
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("incomplete-plugin")
@@ -197,6 +206,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("excessive-plugin")
@@ -205,6 +215,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("name-plugin")
@@ -213,6 +224,7 @@ void tst_qqmldirparser::parse_data()
<< (QStringList() << "foo|")
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("name-path-plugin")
@@ -221,6 +233,7 @@ void tst_qqmldirparser::parse_data()
<< (QStringList() << "foo|bar")
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("unversioned-component")
@@ -229,6 +242,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< (QStringList() << "foo|bar|-1|-1|false")
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("invalid-versioned-component")
@@ -237,6 +251,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("versioned-component")
@@ -245,6 +260,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< (QStringList() << "foo|bar|33|66|false")
<< QStringList()
+ << QStringList()
<< false;
QTest::newRow("versioned-script")
@@ -253,6 +269,7 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< (QStringList() << "foo|bar.js|33|66")
+ << QStringList()
<< false;
QTest::newRow("multiple")
@@ -263,6 +280,7 @@ void tst_qqmldirparser::parse_data()
<< "ComponentA|componenta-1_5.qml|1|5|false"
<< "ComponentB|componentb-1_5.qml|1|5|false")
<< (QStringList() << "ScriptA|scripta-1_0.js|1|0")
+ << QStringList()
<< false;
QTest::newRow("designersupported-yes")
@@ -271,6 +289,7 @@ void tst_qqmldirparser::parse_data()
<< (QStringList() << "foo|")
<< QStringList()
<< QStringList()
+ << QStringList()
<< true;
QTest::newRow("designersupported-no")
@@ -279,7 +298,17 @@ void tst_qqmldirparser::parse_data()
<< (QStringList() << "foo|")
<< QStringList()
<< QStringList()
+ << QStringList()
<< false;
+
+ QTest::newRow("dependency")
+ << "dependency/qmldir"
+ << QStringList()
+ << (QStringList() << "foo|")
+ << QStringList()
+ << QStringList()
+ << (QStringList() << "bar||1|0|true")
+ << false;
}
void tst_qqmldirparser::parse()
@@ -289,6 +318,7 @@ void tst_qqmldirparser::parse()
QFETCH(QStringList, plugins);
QFETCH(QStringList, components);
QFETCH(QStringList, scripts);
+ QFETCH(QStringList, dependencies);
QFETCH(bool, designerSupported);
QFile f(testFile(file));
@@ -307,6 +337,8 @@ void tst_qqmldirparser::parse()
QCOMPARE(toStringList(p.plugins()), plugins);
QCOMPARE(toStringList(p.components()), components);
QCOMPARE(toStringList(p.scripts()), scripts);
+ QCOMPARE(toStringList(p.dependencies()), dependencies);
+
QCOMPARE(p.designerSupported(), designerSupported);
}
diff --git a/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js
new file mode 100644
index 0000000000..aabcc9f3b8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.js
@@ -0,0 +1,7 @@
+.pragma library
+
+var as = undefined
+function isLegal() {
+ var as = true;
+ return as;
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml
new file mode 100644
index 0000000000..17d12199d7
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/importScriptsWithoutQmlMode.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+import "importScriptsWithoutQmlMode.js" as Export
+
+Rectangle {
+ id: root
+ property bool success: false
+
+ Component.onCompleted: success = Export.isLegal()
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml
index 23e4c8d15e..bb6ddc7876 100644
--- a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.var.qml
@@ -17,7 +17,7 @@ QtObject {
}
function releaseScarceResource() {
- root.scarceResourceCopy = null;
+ root.scarceResourceCopy = undefined;
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml
index fe3707b5d3..e147188230 100644
--- a/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml
+++ b/tests/auto/qml/qqmlecmascript/data/scarceResourceFunction.variant.qml
@@ -17,7 +17,7 @@ QtObject {
}
function releaseScarceResource() {
- root.scarceResourceCopy = null;
+ root.scarceResourceCopy = undefined;
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
index 5e2892a31d..b130408c18 100644
--- a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
+++ b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
@@ -23,7 +23,7 @@ Item {
}
function compareStrings(a, b) {
- return (a < b) ? 1 : -1;
+ return (a == b) ? 0 : ((a < b) ? 1 : -1);
}
function compareNumbers(a, b) {
diff --git a/tests/auto/qml/qqmlecmascript/data/utcdate.qml b/tests/auto/qml/qqmlecmascript/data/utcdate.qml
new file mode 100644
index 0000000000..7f66ee3f23
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/utcdate.qml
@@ -0,0 +1,34 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ MyDateClass {
+ id: mdc
+ }
+
+ function check_utc(utcstr) {
+ var datetimeutc = utcstr.split('T')
+ var dateutc = datetimeutc[0].split('-')
+ var timeutc = datetimeutc[1].split(':')
+ var utcDate = new Date(0)
+ utcDate.setUTCFullYear(Number(dateutc[0]))
+ utcDate.setUTCMonth(Number(dateutc[1])-1)
+ utcDate.setUTCDate(Number(dateutc[2]))
+ utcDate.setUTCHours(Number(timeutc[0]))
+ utcDate.setUTCMinutes(Number(timeutc[1]))
+ utcDate.setUTCSeconds(Number(timeutc[2]))
+ if (utcDate.getUTCFullYear() != Number(dateutc[0]))
+ return false;
+ if (utcDate.getUTCMonth() != Number(dateutc[1])-1)
+ return false;
+ if (utcDate.getUTCDate() != Number(dateutc[2]))
+ return false;
+ if (utcDate.getUTCHours() != Number(timeutc[0]))
+ return false;
+ if (utcDate.getUTCMinutes() != Number(timeutc[1]))
+ return false;
+ if (utcDate.getUTCSeconds() != Number(timeutc[2]))
+ return false;
+ return true;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/variants.qml b/tests/auto/qml/qqmlecmascript/data/variants.qml
new file mode 100644
index 0000000000..d38c5a1b49
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/variants.qml
@@ -0,0 +1,55 @@
+import QtQuick 2.2
+
+ListView
+{
+ property variant undefinedVariant: undefined
+ property variant nullVariant: null
+ property variant intVariant: 1
+ property variant doubleVariant: 1.2
+
+ property var testVar
+ property variant testVariant
+
+ function checkNull() {
+ var result = [{'test': null}];
+ model = result;
+ if (model[0].test !== null)
+ return false;
+ testVar = null;
+ testVariant = testVar;
+ if (testVariant !== null)
+ return false;
+ testVar = testVariant;
+ if (testVar !== null)
+ return false;
+ return true;
+ }
+ function checkUndefined() {
+ var result = [{'test': undefined}];
+ model = result;
+ if (model[0].test !== undefined)
+ return false;
+ testVar = undefined;
+ testVariant = testVar;
+ if (testVariant !== undefined)
+ return false;
+ testVar = testVariant;
+ if (testVar !== undefined)
+ return false;
+ return true;
+ }
+ function checkNumber() {
+ var result = [{'test': 1}];
+ model = result;
+ if (model[0].test !== 1)
+ return false;
+ testVar = 1;
+ testVariant = testVar;
+ if (testVariant !== 1)
+ return false;
+ testVar = testVariant;
+ if (testVar !== 1)
+ return false;
+ return true;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 7273cfbe5d..196f6b96f9 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -199,6 +199,7 @@ private slots:
void sequenceSort_data();
void sequenceSort();
void dateParse();
+ void utcDate();
void qtbug_22464();
void qtbug_21580();
void singleV8BindingDestroyedDuringEvaluation();
@@ -213,6 +214,7 @@ private slots:
void deletedEngine();
void libraryScriptAssert();
void variantsAssignedUndefined();
+ void variants();
void qtbug_9792();
void qtcreatorbug_1289();
void noSpuriousWarningsAtShutdown();
@@ -315,6 +317,7 @@ private slots:
void lazyBindingEvaluation();
void varPropertyAccessOnObjectWithInvalidContext();
void importedScriptsAccessOnObjectWithInvalidContext();
+ void importedScriptsWithoutQmlMode();
void contextObjectOnLazyBindings();
void garbageCollectionDuringCreation();
void qtbug_39520();
@@ -743,13 +746,13 @@ void tst_qqmlecmascript::arrayExpressions()
MyExpression expr(&context, "[a, b, c, 10]");
QVariant result = expr.evaluate();
- QCOMPARE(result.userType(), qMetaTypeId<QVariantList>());
- QVariantList list = qvariant_cast<QVariantList>(result);
- QCOMPARE(list.count(), 4);
- QCOMPARE(list.at(0).value<QObject*>(), &obj1);
- QCOMPARE(list.at(1).value<QObject*>(), &obj2);
- QCOMPARE(list.at(2).value<QObject*>(), &obj3);
- QCOMPARE(list.at(3).value<int>(), 10);
+ QCOMPARE(result.userType(), qMetaTypeId<QJSValue>());
+ QJSValue list = qvariant_cast<QJSValue>(result);
+ QCOMPARE(list.property("length").toInt(), 4);
+ QCOMPARE(list.property(0).toQObject(), &obj1);
+ QCOMPARE(list.property(1).toQObject(), &obj2);
+ QCOMPARE(list.property(2).toQObject(), &obj3);
+ QCOMPARE(list.property(3).toInt(), 10);
}
// Tests that modifying a context property will reevaluate expressions
@@ -4808,7 +4811,7 @@ void tst_qqmlecmascript::propertyVarCpp()
QCOMPARE(object->property("varProperty2"), QVariant(QLatin1String("randomString")));
QCOMPARE(object->property("varProperty2").userType(), (int)QVariant::String);
// now enforce behaviour when accessing JavaScript objects from cpp.
- QCOMPARE(object->property("jsobject").userType(), (int)QVariant::Map);
+ QCOMPARE(object->property("jsobject").userType(), qMetaTypeId<QJSValue>());
delete object;
}
@@ -5163,7 +5166,7 @@ void tst_qqmlecmascript::objectConversion()
QVERIFY(object != 0);
QVariant retn;
QMetaObject::invokeMethod(object, "circularObject", Q_RETURN_ARG(QVariant, retn));
- QCOMPARE(retn.value<QVariantMap>().value("test"), QVariant(100));
+ QCOMPARE(retn.value<QJSValue>().property("test").toInt(), int(100));
delete object;
}
@@ -5431,7 +5434,7 @@ void tst_qqmlecmascript::sequenceConversionWrite()
QVERIFY(seq != 0);
// we haven't registered QList<QPoint> as a sequence type, so writing shouldn't work.
- QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QVariantList to an unregistered type");
+ QString warningOne = qmlFile.toString() + QLatin1String(":16: Error: Cannot assign QJSValue to an unregistered type");
QTest::ignoreMessage(QtWarningMsg, warningOne.toLatin1().constData());
QMetaObject::invokeMethod(object, "performTest");
@@ -5736,6 +5739,29 @@ void tst_qqmlecmascript::variantsAssignedUndefined()
delete object;
}
+void tst_qqmlecmascript::variants()
+{
+ QQmlComponent component(&engine, testFileUrl("variants.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(object->property("undefinedVariant").type() == QVariant::Invalid);
+ QVERIFY(object->property("nullVariant").type() == (int)QMetaType::VoidStar);
+ QVERIFY(object->property("intVariant").type() == QVariant::Int);
+ QVERIFY(object->property("doubleVariant").type() == QVariant::Double);
+
+ QVariant result;
+ QMetaObject::invokeMethod(object, "checkNull", Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result.toBool(), true);
+
+ QMetaObject::invokeMethod(object, "checkUndefined", Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result.toBool(), true);
+
+ QMetaObject::invokeMethod(object, "checkNumber", Q_RETURN_ARG(QVariant, result));
+ QCOMPARE(result.toBool(), true);
+}
+
void tst_qqmlecmascript::qtbug_9792()
{
QQmlComponent component(&engine, testFileUrl("qtbug_9792.qml"));
@@ -7337,6 +7363,21 @@ void tst_qqmlecmascript::dateParse()
}
+void tst_qqmlecmascript::utcDate()
+{
+ QQmlComponent component(&engine, testFileUrl("utcdate.qml"));
+
+ QObject *object = component.create();
+ if (object == 0)
+ qDebug() << component.errorString();
+ QVERIFY(object != 0);
+
+ QVariant q;
+ QVariant val = QString::fromLatin1("2014-07-16T23:30:31");
+ QMetaObject::invokeMethod(object, "check_utc", Q_RETURN_ARG(QVariant, q), Q_ARG(QVariant, val));
+ QVERIFY(q.toBool() == true);
+}
+
void tst_qqmlecmascript::concatenatedStringPropertyAccess()
{
QQmlComponent component(&engine, testFileUrl("concatenatedStringPropertyAccess.qml"));
@@ -7636,6 +7677,16 @@ void tst_qqmlecmascript::importedScriptsAccessOnObjectWithInvalidContext()
QTRY_VERIFY(obj->property("success") == true);
}
+void tst_qqmlecmascript::importedScriptsWithoutQmlMode()
+{
+ QQmlComponent component(&engine, testFileUrl("importScriptsWithoutQmlMode.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (obj.isNull())
+ qDebug() << component.errors().first().toString();
+ QVERIFY(!obj.isNull());
+ QTRY_VERIFY(obj->property("success") == true);
+}
+
void tst_qqmlecmascript::contextObjectOnLazyBindings()
{
QQmlComponent component(&engine, testFileUrl("contextObjectOnLazyBindings.qml"));
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index 320333f889..4ee75f8df5 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -486,7 +486,7 @@ void tst_qqmllocale::weekDays()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("weekDays");
- QVERIFY(val.type() == QVariant::List);
+ QVERIFY(val.userType() == qMetaTypeId<QJSValue>());
QList<QVariant> qmlDays = val.toList();
QList<Qt::DayOfWeek> days = QLocale(locale).weekdays();
@@ -528,7 +528,7 @@ void tst_qqmllocale::uiLanguages()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("uiLanguages");
- QVERIFY(val.type() == QVariant::List);
+ QVERIFY(val.userType() == qMetaTypeId<QJSValue>());
QList<QVariant> qmlLangs = val.toList();
QStringList langs = QLocale(locale).uiLanguages();
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index 510a76cc06..ffaab792a7 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -249,16 +249,22 @@ void tst_QQmlMetaObject::property()
QSignalSpy changedSpy(object, SIGNAL(testChanged()));
QObject::connect(object, SIGNAL(testChanged()), object, SLOT(deleteLater()));
+ QVariant value = prop.read(object);
+ if (value.userType() == qMetaTypeId<QJSValue>())
+ value = value.value<QJSValue>().toVariant();
if (expectedValue.isValid())
- QCOMPARE(prop.read(object), expectedValue);
+ QCOMPARE(value, expectedValue);
else
- QVERIFY(prop.read(object).isValid());
+ QVERIFY(value.isValid());
QCOMPARE(changedSpy.count(), 0);
if (isWritable) {
QVERIFY(prop.write(object, newValue));
QCOMPARE(changedSpy.count(), 1);
- QCOMPARE(prop.read(object), newValue);
+ QVariant value = prop.read(object);
+ if (value.userType() == qMetaTypeId<QJSValue>())
+ value = value.value<QJSValue>().toVariant();
+ QCOMPARE(value, newValue);
} else {
QVERIFY(!prop.write(object, prop.read(object)));
QCOMPARE(changedSpy.count(), 0);
@@ -321,11 +327,11 @@ void tst_QQmlMetaObject::method_data()
<< (QList<QByteArray>() << "int" << "bool" << "double")
<< (QList<QByteArray>() << "foo" << "bar" << "baz");
QTest::newRow("testSignal(variant foo, var bar)") << "signal.4.qml"
- << "testSignal(QVariant,QJSValue)"
+ << "testSignal(QVariant,QVariant)"
<< QMetaMethod::Signal
<< int(QMetaType::Void) << "void"
- << (QList<int>() << QMetaType::QVariant << qMetaTypeId<QJSValue>())
- << (QList<QByteArray>() << "QVariant" << "QJSValue")
+ << (QList<int>() << QMetaType::QVariant << QMetaType::QVariant)
+ << (QList<QByteArray>() << "QVariant" << "QVariant")
<< (QList<QByteArray>() << "foo" << "bar");
QTest::newRow("testSignal(color foo, date bar, url baz)") << "signal.5.qml"
<< "testSignal(QColor,QDateTime,QUrl)"
diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
index 66ddb392f9..801707f2ec 100644
--- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
+++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
@@ -115,7 +115,10 @@ void tst_QQuickWorkerScript::messaging()
waitForEchoMessage(worker);
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), value);
+ QVariant response = mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>();
+ if (response.userType() == qMetaTypeId<QJSValue>())
+ response = response.value<QJSValue>().toVariant();
+ QCOMPARE(response, value);
qApp->processEvents();
delete worker;
diff --git a/tests/auto/qmltest/animators/tst_targetdestroyed.qml b/tests/auto/qmltest/animators/tst_targetdestroyed.qml
new file mode 100644
index 0000000000..92b14d0594
--- /dev/null
+++ b/tests/auto/qmltest/animators/tst_targetdestroyed.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Gunnar Sletta <gunnar@sletta.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+
+Item {
+ id: root;
+ width: 200
+ height: 200
+
+ TestCase {
+ id: testcase
+ name: "animators-targetdestroyed"
+ when: false
+ function test_endresult() {
+ verify(true, "Got here :)");
+ }
+ }
+
+ Rectangle {
+ id: box
+ width: 10
+ height: 10
+ color: "steelblue"
+ }
+
+ YAnimator {
+ id: anim
+ target: box
+ from: 0;
+ to: 100
+ duration: 100
+ loops: Animation.Infinite
+ running: true
+ }
+
+ SequentialAnimation {
+ running: true
+ PauseAnimation { duration: 150 }
+ ScriptAction { script: box.destroy(); }
+ PauseAnimation { duration: 50 }
+ ScriptAction { script: anim.destroy(); }
+ PauseAnimation { duration: 50 }
+ ScriptAction { script: testcase.when = true }
+ }
+}
diff --git a/tests/auto/qmltest/selftests/tst_findChild.qml b/tests/auto/qmltest/selftests/tst_findChild.qml
index 1ed4c94423..69bcb390e9 100644
--- a/tests/auto/qmltest/selftests/tst_findChild.qml
+++ b/tests/auto/qmltest/selftests/tst_findChild.qml
@@ -82,6 +82,33 @@ TestCase {
objectName: "nestedChildItem2"
}
+ Loader {
+ id: loader
+
+ sourceComponent: Item {
+ id: loaderItem
+ objectName: "loaderItem"
+
+ Item {
+ objectName: "nestedLoaderItem"
+ }
+
+ Repeater {
+ model: 5
+ delegate: Item {
+ objectName: "repeaterItem" + index
+ }
+ }
+
+ ListView {
+ model: 5
+ delegate: Item {
+ objectName: "listViewItem" + index
+ }
+ }
+ }
+ }
+
function test_findChild() {
compare(findChild(null, ""), null);
compare(findChild(undefined, ""), null);
@@ -99,6 +126,14 @@ TestCase {
var mostDirectChild = duplicateNestedChildItem2Component.createObject(nestedChildItem0);
compare(nestedChildItem0.children.length, 2);
- compare(findChild(nestedChildrenItem, "nestedChildItem2"), mostDirectChild);
+ compare(findChild(nestedChildrenItem, "nestedChildItem2"), mostDirectChild,
+ "Dynamically created nested child items are found");
+
+ compare(findChild(loader, "loaderItem"), loader.item);
+ verify(findChild(loader, "nestedLoaderItem"));
+
+ // These don't make their delegate items QObject children, only visual.
+ verify(findChild(loader, "repeaterItem0"));
+ verify(findChild(loader, "listViewItem0"));
}
}
diff --git a/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
index dad6ff84b9..bbfa08f443 100644
--- a/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
+++ b/tests/auto/qmltest/shadersource/tst_DynamicallyCreated.qml
@@ -70,7 +70,9 @@ Item {
name: "shadersource-dynamic-sourceobject"
function test_endresult() {
var image = grabImage(shaderSource);
- compare(image.pixel(0, 0), Qt.rgba(1, 0, 0, 1));
+ compare(image.red(0,0), 255);
+ compare(image.green(0,0), 0);
+ compare(image.blue(0,0), 0);
}
}
}
diff --git a/tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml b/tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml
new file mode 100644
index 0000000000..2042afa2c5
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_DynamicallyCreatedSource.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Gunnar Sletta <gunnar@sletta.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+
+Item {
+ id: root
+
+ width: 100
+ height: 62
+
+ Rectangle {
+ id: rect
+ anchors.fill: parent
+ color: "red"
+ visible: false
+ }
+
+ Component {
+ id: component;
+ ShaderEffectSource { anchors.fill: parent }
+ }
+
+ property var source: undefined;
+
+ Timer {
+ id: timer
+ interval: 100
+ running: true
+ onTriggered: {
+ var source = component.createObject();
+ source.sourceItem = rect;
+ source.parent = root;
+ root.source = source;
+ }
+ }
+
+ TestCase {
+ id: testcase
+ name: "shadersource-dynamic-shadersource"
+ when: root.source != undefined
+
+ function test_endresult() {
+ var image = grabImage(root);
+ compare(image.red(0,0), 255);
+ compare(image.green(0,0), 0);
+ compare(image.blue(0,0), 0);
+ }
+
+ }
+}
diff --git a/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
index 4ca687bdb6..b00cfbc5f8 100644
--- a/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
+++ b/tests/auto/qmltest/shadersource/tst_SourceInOtherWindow.qml
@@ -37,6 +37,9 @@ import QtQuick.Window 2.0
import QtTest 1.0
Item {
+ width: 100
+ height: 100
+
Rectangle {
id: box
color: "red"
@@ -65,7 +68,7 @@ Item {
TestCase {
name: "shadersource-from-other-window"
- when: childWindow.isRendered
+ when: childWindow.rendered
function test_endresult() {
verify(true); // that we got here without problems...
}
diff --git a/tests/auto/qmltest/shadersource/tst_SourceItem.qml b/tests/auto/qmltest/shadersource/tst_SourceItem.qml
new file mode 100644
index 0000000000..822b53d6fa
--- /dev/null
+++ b/tests/auto/qmltest/shadersource/tst_SourceItem.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+
+Item {
+ id: root
+
+ Rectangle {
+ id: box
+ color: "red"
+ }
+
+ ShaderEffectSource {
+ id: theSource
+ }
+
+ TestCase {
+ name: "shadersource-something-to-null"
+ function test_null() {
+ theSource.sourceItem = box
+ theSource.sourceItem = null
+ verify(true); // that we got here without problems...
+ }
+ }
+}
diff --git a/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml b/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml
index dc13481bf9..2906de2986 100644
--- a/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml
+++ b/tests/auto/qmltest/statemachine/tst_nestedinitialstates.qml
@@ -52,8 +52,7 @@ TestCase {
name: "nestedInitalStates"
function test_nestedInitalStates() {
- // uncomment me after vm problems are fixed.
- // compare(myStateMachine.running, false);
+ compare(myStateMachine.running, false);
compare(parentState.active, false);
compare(childState1.active, false);
compare(childState2.active, false);
diff --git a/tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml b/tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml
new file mode 100644
index 0000000000..41a2c2a852
--- /dev/null
+++ b/tests/auto/qmltest/statemachine/tst_nestedstatemachine.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Ford Motor Company
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml.StateMachine 1.0
+import QtTest 1.0
+
+TestCase {
+ StateMachine {
+ id: myStateMachine
+ initialState: parentState
+ StateBase {
+ id: parentState
+ initialState: childStateMachine
+ StateMachine {
+ id: childStateMachine
+ initialState: childState2
+ StateBase {
+ id: childState1
+ }
+ StateBase {
+ id: childState2
+ }
+ }
+ }
+ }
+ name: "nestedStateMachine"
+
+ function test_nestedStateMachine() {
+ compare(myStateMachine.running, false);
+ compare(parentState.active, false);
+ compare(childStateMachine.running, false);
+ compare(childState1.active, false);
+ compare(childState2.active, false);
+ myStateMachine.start();
+ tryCompare(myStateMachine, "running", true);
+ tryCompare(parentState, "active", true);
+ tryCompare(childStateMachine, "running", true);
+ tryCompare(childState1, "active", false);
+ tryCompare(childState2, "active", true);
+ }
+}
diff --git a/tests/auto/quick/dialogs/data/RectWithFileDialog.qml b/tests/auto/quick/dialogs/data/RectWithFileDialog.qml
deleted file mode 100644
index ca7ecc948a..0000000000
--- a/tests/auto/quick/dialogs/data/RectWithFileDialog.qml
+++ /dev/null
@@ -1,33 +0,0 @@
-import QtQuick 2.0
-import QtQuick.Dialogs 1.0
-
-Rectangle {
- width: 1024
- height: 320
- property alias fileDialog: fileDialog
- property alias label: label
- property alias mouseArea: mouseArea
-
- FileDialog {
- id: fileDialog
- title: "Choose some files"
- selectMultiple: true
- nameFilters: [ "QML files (*.qml)", "All files (*)" ]
- selectedNameFilter: "QML files (*.qml)"
- onAccepted: label.text = fileDialog.filePaths
- }
-
- MouseArea {
- id: mouseArea
- anchors.fill: parent
- onClicked: fileDialog.visible = !fileDialog.visible
- }
-
- Text {
- id: label
- text: "Click to open a file dialog"
- wrapMode: Text.Wrap
- anchors.fill: parent
- anchors.margins: 10
- }
-}
diff --git a/tests/auto/quick/dialogs/dialogs.pro b/tests/auto/quick/dialogs/dialogs.pro
deleted file mode 100644
index 4069ad4c68..0000000000
--- a/tests/auto/quick/dialogs/dialogs.pro
+++ /dev/null
@@ -1,20 +0,0 @@
-CONFIG += testcase
-TARGET = tst_dialogs
-SOURCES += tst_dialogs.cpp
-
-include (../../shared/util.pri)
-
-macx:CONFIG -= app_bundle
-macx:CONFIG+=insignificant_test # QTBUG-30513 - test is unstable
-linux-*:CONFIG+=insignificant_test # QTBUG-30513 - test is unstable
-win32:CONFIG+=insignificant_test # QTBUG-30513 - test is unstable
-
-CONFIG += parallel_test
-QT += core-private gui-private qml-private quick-private testlib
-
-TESTDATA = data/*
-
-OTHER_FILES += \
- data/FileDialog.qml \
-
-DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/quick/dialogs/tst_dialogs.cpp b/tests/auto/quick/dialogs/tst_dialogs.cpp
deleted file mode 100644
index 01fe6c3722..0000000000
--- a/tests/auto/quick/dialogs/tst_dialogs.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qtest.h>
-#include "../../shared/util.h"
-#include <QtQuick/QQuickItem>
-#include <QtQuick/QQuickView>
-#include <QSignalSpy>
-
-class tst_dialogs : public QQmlDataTest
-{
- Q_OBJECT
-public:
-
-private slots:
- void initTestCase()
- {
- QQmlDataTest::initTestCase();
- }
-
- // FileDialog
- void fileDialogDefaultModality();
- void fileDialogNonModal();
- void fileDialogNameFilters();
-
-private:
-};
-
-void tst_dialogs::fileDialogDefaultModality()
-{
- QQuickView *window = new QQuickView;
- QScopedPointer<QQuickWindow> cleanup(window);
-
- window->setSource(testFileUrl("RectWithFileDialog.qml"));
- window->setGeometry(240,240,1024,320);
- window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject());
-
- // Click to show
- QObject *dlg = qvariant_cast<QObject *>(window->rootObject()->property("fileDialog"));
- QSignalSpy spyVisibilityChanged(dlg, SIGNAL(visibilityChanged()));
- QTest::mouseClick(window, Qt::LeftButton, 0, QPoint(1000, 100)); // show
- QTRY_VERIFY(spyVisibilityChanged.count() > 0);
- int visibilityChangedCount = spyVisibilityChanged.count();
- // Can't hide by clicking the main window, because dialog is modal.
- QTest::mouseClick(window, Qt::LeftButton, 0, QPoint(1000, 100));
- /*
- On the Mac, if you send an event directly to a window, the modal dialog
- doesn't block the event, so the window will process it normally. This
- is a different code path compared to having a user click the mouse and
- generate a native event; in that case the OS does the filtering itself,
- and Qt will not even see the event. But simulating real events in the
- test framework is generally unstable. So there isn't a good way to test
- modality on the mac.
- This test sometimes fails on other platforms too. Maybe it's not reliable
- to try to click the main window in a location which is outside the
- dialog, without checking or guaranteeing it somehow.
- */
- QSKIP("Modality test is flaky in general and doesn't work at all on MacOS");
- // So we expect no change in visibility.
- QCOMPARE(spyVisibilityChanged.count(), visibilityChangedCount);
-
- QCOMPARE(dlg->property("visible").toBool(), true);
- QMetaObject::invokeMethod(dlg, "close");
- QTRY_VERIFY(spyVisibilityChanged.count() > visibilityChangedCount);
- visibilityChangedCount = spyVisibilityChanged.count();
- QCOMPARE(dlg->property("visible").toBool(), false);
- QMetaObject::invokeMethod(dlg, "open");
- QTRY_VERIFY(spyVisibilityChanged.count() > visibilityChangedCount);
- QCOMPARE(dlg->property("visible").toBool(), true);
- QCOMPARE(dlg->property("modality").toInt(), (int)Qt::WindowModal);
-}
-
-void tst_dialogs::fileDialogNonModal()
-{
- QQuickView *window = new QQuickView;
- QScopedPointer<QQuickWindow> cleanup(window);
-
- window->setSource(testFileUrl("RectWithFileDialog.qml"));
- window->setGeometry(240,240,1024,320);
- window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject());
-
- // Click to toggle visibility
- QObject *dlg = qvariant_cast<QObject *>(window->rootObject()->property("fileDialog"));
- dlg->setProperty("modality", QVariant((int)Qt::NonModal));
- QSignalSpy spyVisibilityChanged(dlg, SIGNAL(visibilityChanged()));
- QTest::mouseClick(window, Qt::LeftButton, 0, QPoint(1000, 100)); // show
- QTRY_VERIFY(spyVisibilityChanged.count() > 0);
- int visibilityChangedCount = spyVisibilityChanged.count();
- QCOMPARE(dlg->property("visible").toBool(), true);
- QTest::mouseClick(window, Qt::LeftButton, 0, QPoint(1000, 100)); // hide
- QTRY_VERIFY(spyVisibilityChanged.count() > visibilityChangedCount);
- QCOMPARE(dlg->property("visible").toBool(), false);
- QCOMPARE(dlg->property("modality").toInt(), (int)Qt::NonModal);
-}
-
-void tst_dialogs::fileDialogNameFilters()
-{
- QQuickView *window = new QQuickView;
- QScopedPointer<QQuickWindow> cleanup(window);
-
- window->setSource(testFileUrl("RectWithFileDialog.qml"));
- window->setGeometry(240,240,1024,320);
- window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
- QVERIFY(window->rootObject());
-
- QObject *dlg = qvariant_cast<QObject *>(window->rootObject()->property("fileDialog"));
- QStringList filters;
- filters << "QML files (*.qml)";
- filters << "Image files (*.jpg, *.png, *.gif)";
- filters << "All files (*)";
- dlg->setProperty("nameFilters", QVariant(filters));
- QCOMPARE(dlg->property("selectedNameFilter").toString(), filters.first());
-}
-
-QTEST_MAIN(tst_dialogs)
-
-#include "tst_dialogs.moc"
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index c908e8c9bf..f86c8fb36a 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -569,12 +569,26 @@ void tst_qquickanimations::alwaysRunToEnd()
animation.setAlwaysRunToEnd(true);
QVERIFY(animation.loops() == -1);
QVERIFY(animation.alwaysRunToEnd() == true);
+
+ QElapsedTimer timer;
+ timer.start();
animation.start();
- QTest::qWait(1500);
+
+ // Make sure the animation has started but is not finished, yet.
+ QTRY_VERIFY(rect.x() > qreal(0) && rect.x() != qreal(200));
+
animation.stop();
- QVERIFY(rect.x() != qreal(200));
- QTest::qWait(500);
- QTIMED_COMPARE(rect.x(), qreal(200));
+
+ // Make sure it didn't just jump to the end and also didn't revert to the start.
+ QVERIFY(rect.x() > qreal(0) && rect.x() != qreal(200));
+
+ // Make sure it eventually reaches the end.
+ QTRY_COMPARE(rect.x(), qreal(200));
+
+ // This should have taken at least 1s but less than 2s
+ // (otherwise it has run the animation twice).
+ qint64 elapsed = timer.elapsed();
+ QVERIFY(elapsed >= 1000 && elapsed < 2000);
}
void tst_qquickanimations::complete()
@@ -592,8 +606,7 @@ void tst_qquickanimations::complete()
animation.stop();
QVERIFY(rect.x() != qreal(200));
animation.start();
- QTest::qWait(50);
- QVERIFY(animation.isRunning());
+ QTRY_VERIFY(animation.isRunning());
animation.complete();
QCOMPARE(rect.x(), qreal(200));
}
@@ -718,10 +731,10 @@ void tst_qquickanimations::badTypes()
QVERIFY(rect);
QQuickItemPrivate::get(rect)->setState("state1");
- QTest::qWait(1000 + 50);
- QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
- QVERIFY(myRect);
- QCOMPARE(myRect->x(),qreal(200));
+
+ QQuickRectangle *myRect = 0;
+ QTRY_VERIFY(myRect = rect->findChild<QQuickRectangle*>("MyRect"));
+ QTRY_COMPARE(myRect->x(),qreal(200));
}
}
@@ -764,7 +777,7 @@ void tst_qquickanimations::mixedTypes()
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
QVERIFY(myRect);
- //rather inexact -- is there a better way?
+ // We cannot get that more exact than that without dependable real-time behavior.
QVERIFY(myRect->x() > 100 && myRect->x() < 200);
QVERIFY(myRect->border()->width() > 1 && myRect->border()->width() < 10);
}
@@ -780,7 +793,7 @@ void tst_qquickanimations::mixedTypes()
QQuickRectangle *myRect = rect->findChild<QQuickRectangle*>("MyRect");
QVERIFY(myRect);
- //rather inexact -- is there a better way?
+ // We cannot get that more exact than that without dependable real-time behavior.
QVERIFY(myRect->x() > 100 && myRect->x() < 200);
QVERIFY(myRect->color() != QColor("red") && myRect->color() != QColor("blue"));
}
@@ -1215,42 +1228,33 @@ void tst_qquickanimations::startStopSignals()
QCOMPARE(root->property("startedCount").toInt(), 1);
QCOMPARE(root->property("stoppedCount").toInt(), 1);
+ QElapsedTimer timer;
+ timer.start();
QMetaObject::invokeMethod(root, "start");
QCOMPARE(root->property("startedCount").toInt(), 2);
QCOMPARE(root->property("stoppedCount").toInt(), 1);
- QTest::qWait(100);
-
- QCOMPARE(root->property("startedCount").toInt(), 2);
- QCOMPARE(root->property("stoppedCount").toInt(), 1);
-
- QTest::qWait(100);
-
QTRY_COMPARE(root->property("stoppedCount").toInt(), 2);
QCOMPARE(root->property("startedCount").toInt(), 2);
+ QVERIFY(timer.elapsed() >= 200);
root->setProperty("alwaysRunToEnd", true);
+ timer.restart();
QMetaObject::invokeMethod(root, "start");
QCOMPARE(root->property("startedCount").toInt(), 3);
QCOMPARE(root->property("stoppedCount").toInt(), 2);
- QTest::qWait(100);
-
- QCOMPARE(root->property("startedCount").toInt(), 3);
- QCOMPARE(root->property("stoppedCount").toInt(), 2);
-
QMetaObject::invokeMethod(root, "stop");
QCOMPARE(root->property("startedCount").toInt(), 3);
QCOMPARE(root->property("stoppedCount").toInt(), 2);
- QTest::qWait(100);
-
QTRY_COMPARE(root->property("stoppedCount").toInt(), 3);
QCOMPARE(root->property("startedCount").toInt(), 3);
+ QVERIFY(timer.elapsed() >= 200);
}
void tst_qquickanimations::runningTrueBug()
@@ -1352,10 +1356,13 @@ void tst_qquickanimations::alwaysRunToEndRestartBug()
animation.stop();
animation.start();
animation.stop();
- QTest::qWait(500);
- QVERIFY(rect.x() != qreal(200));
- QTest::qWait(800);
- QTIMED_COMPARE(rect.x(), qreal(200));
+
+ // Waiting for a fixed time here would be dangerous as the starting and stopping itself takes
+ // time and clocks are unreliable. The only thing we do know is that the animation should
+ // eventually start and eventually stop. As its duration is 1000ms we can be pretty sure to hit
+ // an in between state with the 50ms iterations QTRY_VERIFY does.
+ QTRY_VERIFY(rect.x() != qreal(200));
+ QTRY_COMPARE(rect.x(), qreal(200));
QCOMPARE(static_cast<QQuickAbstractAnimation*>(&animation)->qtAnimation()->state(), QAbstractAnimationJob::Stopped);
}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
index 23fd5192f3..31413c23cd 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_canvas.qml
@@ -368,7 +368,12 @@ CanvasTestCase {
test: function(ctx) {
ctx.font = "100px sans-serif";
ctx.fillText("Hello", -10, 10, extra);
- comparePixel(ctx, 0, 0, 255, 0, 0, 255);
+ for (var x = 0; x < 100; ++x) {
+ var c = ctx.getImageData(x,0,1,1).data;
+ if (c[0] === 255 && c[1] === 0 && c[2] === 0 && c[3] === 255)
+ return;
+ }
+ qtest_fail("No red pixel found");
}
},
{
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml
index ca95f2aec1..46a038a13c 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml
@@ -11,7 +11,7 @@ CanvasTestCase {
canvas.loadImage('rgrg-256x256.png');
canvas.loadImage('ggrr-256x256.png');
canvas.loadImage('broken.png');
- if (!canvas.isImageLoaded('green.png'))
+ while (!canvas.isImageLoaded('green.png'))
wait(200);
}
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_state.qml b/tests/auto/quick/qquickcanvasitem/data/tst_state.qml
index 1ceb17b31b..18464def7c 100644
--- a/tests/auto/quick/qquickcanvasitem/data/tst_state.qml
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_state.qml
@@ -30,7 +30,7 @@ CanvasTestCase {
ctx.restore();
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 50);
- //comparePixel(ctx, 50,25, 0,255,0,255);
+ comparePixel(ctx, 50,25, 0,255,0,255);
canvas.destroy()
}
function test_fillStyle(row) {
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index 844f5d6778..25203417ba 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -173,6 +173,10 @@ void tst_QQuickFramebufferObject::testThatStuffWorks()
QFETCH(bool, msaa);
QFETCH(QSize, textureSize);
+#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
+ QSKIP("QTBUG-41815");
+#endif
+
frameInfo.renderCount = 0;
frameInfo.msaaEnabled = false;
frameInfo.msaaSupported = false;
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index a6011a252f..68a8260827 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -2806,9 +2806,6 @@ void tst_QQuickItem::childAt()
void tst_QQuickItem::grab()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
QQuickView view;
view.setSource(testFileUrl("grabToImage.qml"));
view.show();
diff --git a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
index 9f69dcb83e..eb720e5109 100644
--- a/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
+++ b/tests/auto/quick/qquickitemlayer/tst_qquickitemlayer.cpp
@@ -130,9 +130,6 @@ tst_QQuickItemLayer::tst_QQuickItemLayer()
void tst_QQuickItemLayer::layerSmooth()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("Smooth.qml");
@@ -152,9 +149,6 @@ void tst_QQuickItemLayer::layerSmooth()
void tst_QQuickItemLayer::layerEnabled()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("Enabled.qml");
@@ -171,9 +165,6 @@ void tst_QQuickItemLayer::layerEnabled()
void tst_QQuickItemLayer::layerMipmap()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer)
QSKIP("Mipmapping does not work with the Mesa Software Rasterizer.");
QImage fb = runTest("Mipmap.qml");
@@ -188,9 +179,6 @@ void tst_QQuickItemLayer::layerMipmap()
void tst_QQuickItemLayer::layerEffect()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("Effect.qml");
@@ -205,9 +193,6 @@ void tst_QQuickItemLayer::layerEffect()
// a shader that pads transparent to blue. Everything else is red.
void tst_QQuickItemLayer::layerSourceRect()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -229,9 +214,6 @@ void tst_QQuickItemLayer::layerSourceRect()
// directly in a stand alone ShaderEffect
void tst_QQuickItemLayer::layerIsTextureProvider()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("TextureProvider.qml");
@@ -264,9 +246,6 @@ void tst_QQuickItemLayer::layerVisibility_data()
void tst_QQuickItemLayer::layerVisibility()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -315,9 +294,6 @@ void tst_QQuickItemLayer::layerZOrder_data()
void tst_QQuickItemLayer::layerZOrder()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -352,9 +328,6 @@ void tst_QQuickItemLayer::changeZOrder_data()
void tst_QQuickItemLayer::changeZOrder()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
@@ -423,9 +396,6 @@ void tst_QQuickItemLayer::disableLayer()
void tst_QQuickItemLayer::changeSamplerName()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("SamplerNameChange.qml");
@@ -434,9 +404,6 @@ void tst_QQuickItemLayer::changeSamplerName()
void tst_QQuickItemLayer::itemEffect()
{
-#if defined(Q_OS_WIN32) && defined(QT_OPENGL_ES_2_ANGLE)
- QSKIP("QTBUG-40649");
-#endif
if (m_isMesaSoftwareRasterizer && m_mesaVersion < QT_VERSION_CHECK(7, 11, 0))
QSKIP("Mesa Software Rasterizer below version 7.11 does not render this test correctly.");
QImage fb = runTest("ItemEffect.qml");
diff --git a/tests/auto/quick/qquickscreen/data/screen.qml b/tests/auto/quick/qquickscreen/data/screen.qml
index 780b22f23d..dc3803f4e3 100644
--- a/tests/auto/quick/qquickscreen/data/screen.qml
+++ b/tests/auto/quick/qquickscreen/data/screen.qml
@@ -8,4 +8,7 @@ Item {
property int h: Window.Screen.height
property int curOrientation: Window.Screen.orientation
property int priOrientation: Window.Screen.primaryOrientation
+ property int updateMask: Window.Screen.orientationUpdateMask
+
+ Window.Screen.orientationUpdateMask: Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation
}
diff --git a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
index dc6fe061c3..be543e8022 100644
--- a/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
+++ b/tests/auto/quick/qquickscreen/tst_qquickscreen.cpp
@@ -62,6 +62,7 @@ void tst_qquickscreen::basicProperties()
QCOMPARE(screen->size().height(), root->property("h").toInt());
QCOMPARE(int(screen->orientation()), root->property("curOrientation").toInt());
QCOMPARE(int(screen->primaryOrientation()), root->property("priOrientation").toInt());
+ QCOMPARE(int(screen->orientationUpdateMask()), root->property("updateMask").toInt());
}
QTEST_MAIN(tst_qquickscreen)
diff --git a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
index afc4787cdb..6cfdc90364 100644
--- a/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
+++ b/tests/auto/quick/qquickspritesequence/tst_qquickspritesequence.cpp
@@ -109,9 +109,6 @@ void tst_qquickspritesequence::test_framerateAdvance()
void tst_qquickspritesequence::test_jumpToCrash()
{
-#if defined(QT_OPENGL_ES_2_ANGLE) && _MSC_VER==1600
- QSKIP("QTBUG-40658");
-#endif
QQuickView *window = new QQuickView(0);
window->setSource(testFileUrl("crashonstart.qml"));
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 143c10435d..b7335ccc4a 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -2675,14 +2675,15 @@ void tst_qquicktext::lineLaidOutRelayout()
qreal maxH = 0;
for (int i = 0; i < textPrivate->layout.lineCount(); ++i) {
- QRectF r = textPrivate->layout.lineAt(i).rect();
-
+ QTextLine line = textPrivate->layout.lineAt(i);
+ const QRectF r = line.rect();
+ const qreal h = line.height();
if (r.x() == 0) {
- QCOMPARE(r.y(), i * r.height());
- maxH = qMax(maxH, r.y() + r.height());
+ QCOMPARE(r.y(), i * h);
+ maxH = qMax(maxH, r.y() + h);
} else {
QCOMPARE(r.x(), myText->width() / 2);
- QCOMPARE(r.y(), (i * r.height()) - maxH);
+ QCOMPARE(r.y(), i * h - maxH);
}
}
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 096a191398..5c8d86f840 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -50,7 +50,7 @@
#include <math.h>
#include <qmath.h>
-#ifdef Q_OS_MAC
+#ifdef Q_OS_OSX
#include <Carbon/Carbon.h>
#endif
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index aecd28f44b..5bd7492d70 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -1188,6 +1188,7 @@ void tst_qquickwindow::headless()
QVERIFY(QTest::qWaitForWindowExposed(window));
QVERIFY(window->isVisible());
+ bool threaded = window->openglContext()->thread() != QThread::currentThread();
QSignalSpy initialized(window, SIGNAL(sceneGraphInitialized()));
QSignalSpy invalidated(window, SIGNAL(sceneGraphInvalidated()));
@@ -1202,8 +1203,10 @@ void tst_qquickwindow::headless()
window->hide();
window->releaseResources();
- QTRY_COMPARE(invalidated.size(), 1);
- QVERIFY(window->openglContext() == 0);
+ if (threaded) {
+ QTRY_COMPARE(invalidated.size(), 1);
+ QVERIFY(window->openglContext() == 0);
+ }
// Destroy the native windowing system buffers
window->destroy();
@@ -1213,7 +1216,8 @@ void tst_qquickwindow::headless()
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
- QTRY_COMPARE(initialized.size(), 1);
+ if (threaded)
+ QTRY_COMPARE(initialized.size(), 1);
QVERIFY(window->openglContext() != 0);
// Verify that the visual output is the same
@@ -1536,6 +1540,7 @@ void tst_qquickwindow::hideThenDelete()
QSignalSpy *openglDestroyed = 0;
QSignalSpy *sgInvalidated = 0;
+ bool threaded = false;
{
QQuickWindow window;
@@ -1548,6 +1553,7 @@ void tst_qquickwindow::hideThenDelete()
window.show();
QTest::qWaitForWindowExposed(&window);
+ threaded = window.openglContext()->thread() != QThread::currentThread();
openglDestroyed = new QSignalSpy(window.openglContext(), SIGNAL(aboutToBeDestroyed()));
sgInvalidated = new QSignalSpy(&window, SIGNAL(sceneGraphInvalidated()));
@@ -1556,15 +1562,17 @@ void tst_qquickwindow::hideThenDelete()
QTRY_VERIFY(!window.isExposed());
- if (!persistentSG) {
- QVERIFY(sgInvalidated->size() > 0);
- if (!persistentGL)
- QVERIFY(openglDestroyed->size() > 0);
- else
+ if (threaded) {
+ if (!persistentSG) {
+ QVERIFY(sgInvalidated->size() > 0);
+ if (!persistentGL)
+ QVERIFY(openglDestroyed->size() > 0);
+ else
+ QVERIFY(openglDestroyed->size() == 0);
+ } else {
+ QVERIFY(sgInvalidated->size() == 0);
QVERIFY(openglDestroyed->size() == 0);
- } else {
- QVERIFY(sgInvalidated->size() == 0);
- QVERIFY(openglDestroyed->size() == 0);
+ }
}
}
@@ -1706,9 +1714,6 @@ void tst_qquickwindow::testWindowVisibilityOrder()
window5->hide();
window3->hide();
-#if defined(Q_OS_OSX)
- QEXPECT_FAIL("","Focus is not transferred to transient parent on window close (QTBUG-33423)", Continue);
-#endif
QTRY_COMPARE(window2 == QGuiApplication::focusWindow(), true);
window2->hide();
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 0a887534bd..e400556b67 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -73,8 +73,7 @@ QUICKTESTS = \
qquickview \
qquickcanvasitem \
qquickscreen \
- touchmouse \
- dialogs \
+ touchmouse
SUBDIRS += $$PUBLICTESTS
diff --git a/tests/auto/shared/platformquirks.h b/tests/auto/shared/platformquirks.h
index d5413f9db9..70a3e016a6 100644
--- a/tests/auto/shared/platformquirks.h
+++ b/tests/auto/shared/platformquirks.h
@@ -36,7 +36,7 @@
#include <qglobal.h>
-#ifdef Q_OS_MAC
+#ifdef Q_OS_OSX
#include <Carbon/Carbon.h>
#endif
@@ -46,7 +46,7 @@ struct PlatformQuirks
{
#if defined(QT_NO_CLIPBOARD)
return false;
-#elif defined(Q_OS_MAC)
+#elif defined(Q_OS_OSX)
PasteboardRef pasteboard;
OSStatus status = PasteboardCreate(0, &pasteboard);
if (status == noErr)
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_height.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_height.qml
new file mode 100644
index 0000000000..c4321d25bb
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_height.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/world.png"
+
+ width: 10
+ height: 10
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+
+ border.bottom: 5
+ border.left: 0
+ border.right: 0
+ border.top: 5
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_width.qml b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_width.qml
new file mode 100644
index 0000000000..328ff40008
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/borderimages/borderimage_borders_exceed_width.qml
@@ -0,0 +1,32 @@
+import QtQuick 2.2
+
+Rectangle {
+ width: 320
+ height: 480
+
+ color: "red"
+
+ Item {
+ x: 80
+ y: 80
+
+ BorderImage {
+ source: "../shared/world.png"
+
+ width: 10
+ height: 10
+
+ antialiasing: true
+
+ horizontalTileMode: BorderImage.Repeat
+ verticalTileMode: BorderImage.Repeat
+
+ smooth: false
+
+ border.bottom: 0
+ border.left: 5
+ border.right: 5
+ border.top: 0
+ }
+ }
+}
diff --git a/tests/manual/scenegraph_lancelot/data/text/textinput_selected_fallback_font.qml b/tests/manual/scenegraph_lancelot/data/text/textinput_selected_fallback_font.qml
new file mode 100644
index 0000000000..2c5b152ea1
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/textinput_selected_fallback_font.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+
+Item {
+ width: 320
+ height: 480
+ TextInput {
+ anchors.centerIn: parent
+ id: textInput
+ font.family: "Arial"
+ font.pixelSize: 14
+ text: "∯AA≨"
+
+ Component.onCompleted: {
+ textInput.select(2, 4)
+ }
+ }
+}
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 69ccd7a316..7a08562a13 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -450,10 +450,8 @@ int main(int argc, char *argv[])
verboseMode = false;
#ifndef QT_NO_TRANSLATION
- //qt_ translations loaded by QQmlApplicationEngine
- QString sysLocale = QLocale::system().name();
-
- if (!translationFile.isEmpty()) { //Note: installed before QQmlApplicationEngine's automatic translation loading
+ // qt_ translations are loaded by QQmlApplicationEngine
+ if (!translationFile.isEmpty()) { // Note: installed before QQmlApplicationEngine's automatic translation loading
QTranslator translator;
if (translator.load(translationFile)) {
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index ac4f6ae437..6f5ec28c4d 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -124,6 +124,7 @@ QVariantMap pluginsForModulePath(const QString &modulePath) {
// a qml import may contain several plugins
QString plugins;
QString classnames;
+ QStringList dependencies;
QByteArray line;
do {
line = qmldirFile.readLine();
@@ -133,6 +134,12 @@ QVariantMap pluginsForModulePath(const QString &modulePath) {
} else if (line.startsWith("classname")) {
classnames += QString::fromUtf8(line.split(' ').at(1));
classnames += QStringLiteral(" ");
+ } else if (line.startsWith("depends")) {
+ QList<QByteArray> dep = line.split(' ');
+ if (dep.length() != 3)
+ std::cerr << "depends: expected 2 arguments: module identifier and version" << std::endl;
+ else
+ dependencies << QString::fromUtf8(dep[1]) + QStringLiteral(" ") + QString::fromUtf8(dep[2]).simplified();
}
} while (line.length() > 0);
@@ -140,6 +147,8 @@ QVariantMap pluginsForModulePath(const QString &modulePath) {
QVariantMap pluginInfo;
pluginInfo[QStringLiteral("plugins")] = plugins.simplified();
pluginInfo[QStringLiteral("classnames")] = classnames.simplified();
+ if (dependencies.length())
+ pluginInfo[QStringLiteral("dependencies")] = dependencies;
return pluginInfo;
}
@@ -173,9 +182,10 @@ QString resolveImportPath(const QString &uri, const QString &version)
QVariantList findPathsForModuleImports(const QVariantList &imports)
{
QVariantList done;
+ QVariantList importsCopy(imports);
- foreach (QVariant importVariant, imports) {
- QVariantMap import = qvariant_cast<QVariantMap>(importVariant);
+ for (int i = 0; i < importsCopy.length(); ++i) {
+ QVariantMap import = qvariant_cast<QVariantMap>(importsCopy[i]);
if (import[QStringLiteral("type")] == QStringLiteral("module")) {
QString path = resolveImportPath(import.value(QStringLiteral("name")).toString(), import.value(QStringLiteral("version")).toString());
if (!path.isEmpty())
@@ -187,6 +197,17 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
import[QStringLiteral("plugin")] = plugins;
if (!classnames.isEmpty())
import[QStringLiteral("classname")] = classnames;
+ if (plugininfo.contains(QStringLiteral("dependencies"))) {
+ QStringList dependencies = plugininfo.value(QStringLiteral("dependencies")).toStringList();
+ foreach (QString line, dependencies) {
+ QList<QString> dep = line.split(QStringLiteral(" "));
+ QVariantMap depImport;
+ depImport[QStringLiteral("type")] = QStringLiteral("module");
+ depImport[QStringLiteral("name")] = dep[0];
+ depImport[QStringLiteral("version")] = dep[1];
+ importsCopy.append(depImport);
+ }
+ }
}
done.append(import);
}
@@ -194,16 +215,8 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
}
// Scan a single qml file for import statements
-QVariantList findQmlImportsInQmlFile(const QString &filePath)
+static QVariantList findQmlImportsInQmlCode(const QString &filePath, const QString &code)
{
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- std::cerr << "Cannot open input file " << QDir::toNativeSeparators(file.fileName()).toStdString()
- << ':' << file.errorString().toStdString() << std::endl;
- return QVariantList();
- }
- QString code = QString::fromUtf8(file.readAll());
-
QQmlJS::Engine engine;
QQmlJS::Lexer lexer(&engine);
lexer.setCode(code, /*line = */ 1);
@@ -212,12 +225,25 @@ QVariantList findQmlImportsInQmlFile(const QString &filePath)
if (!parser.parse() || !parser.diagnosticMessages().isEmpty()) {
// Extract errors from the parser
foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
- std::cerr << QDir::toNativeSeparators(file.fileName()).toStdString() << ':'
+ std::cerr << QDir::toNativeSeparators(filePath).toStdString() << ':'
<< m.loc.startLine << ':' << m.message.toStdString() << std::endl;
}
return QVariantList();
}
- return findImportsInAst(parser.ast()->headers, code, file.fileName());
+ return findImportsInAst(parser.ast()->headers, code, filePath);
+}
+
+// Scan a single qml file for import statements
+static QVariantList findQmlImportsInQmlFile(const QString &filePath)
+{
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ std::cerr << "Cannot open input file " << QDir::toNativeSeparators(file.fileName()).toStdString()
+ << ':' << file.errorString().toStdString() << std::endl;
+ return QVariantList();
+ }
+ QString code = QString::fromUtf8(file.readAll());
+ return findQmlImportsInQmlCode(filePath, code);
}
// Scan a single javascrupt file for import statements
@@ -272,10 +298,15 @@ QVariantList findQmlImportsInJavascriptFile(const QString &filePath)
QVariantList findQmlImportsInFile(const QString &filePath)
{
QVariantList imports;
- if (filePath.endsWith(QStringLiteral(".qml")))
- imports = findQmlImportsInQmlFile(filePath);
- else if (filePath.endsWith(QStringLiteral(".js")))
+ if (filePath == QLatin1String("-")) {
+ QFile f;
+ if (f.open(stdin, QIODevice::ReadOnly))
+ imports = findQmlImportsInQmlCode(QLatin1String("<stdin>"), QString::fromUtf8(f.readAll()));
+ } else if (filePath.endsWith(QStringLiteral(".qml"))) {
+ imports = findQmlImportsInQmlFile(filePath);
+ } else if (filePath.endsWith(QStringLiteral(".js"))) {
imports = findQmlImportsInJavascriptFile(filePath);
+ }
return findPathsForModuleImports(imports);
}
@@ -390,7 +421,7 @@ int main(int argc, char *argv[])
const QString &arg = args.at(i);
++i;
QStringList *argReceiver = 0;
- if (!arg.startsWith(QLatin1Char('-'))) {
+ if (!arg.startsWith(QLatin1Char('-')) || arg == QLatin1String("-")) {
qmlRootPaths += arg;
} else if (arg == QLatin1String("-rootPath")) {
if (i >= args.count())
@@ -415,7 +446,7 @@ int main(int argc, char *argv[])
while (i < args.count()) {
const QString arg = args.at(i);
- if (arg.startsWith(QLatin1Char('-')))
+ if (arg.startsWith(QLatin1Char('-')) && arg != QLatin1String("-"))
break;
++i;
*argReceiver += arg;
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 3f38a66da4..b387e4ff6e 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -728,13 +728,13 @@ void printDebugMessage(QtMsgType, const QMessageLogContext &, const QString &msg
int main(int argc, char *argv[])
{
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW)
// we do not want windows popping up if the module loaded triggers an assert
SetErrorMode(SEM_NOGPFAULTERRORBOX);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
-#endif
+#endif // Q_OS_WIN && !Q_CC_MINGW
// The default message handler might not print to console on some systems. Enforce this.
qInstallMessageHandler(printDebugMessage);
#ifdef Q_OS_UNIX
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 208226c8aa..7c2fd9fc32 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -307,7 +307,8 @@ static void displayFileDialog(Options *options)
#ifndef QT_NO_TRANSLATION
static void loadTranslationFile(QTranslator &translator, const QString& directory)
{
- translator.load(QLatin1String("qml_" )+QLocale::system().name(), directory + QLatin1String("/i18n"));
+ QLocale locale;
+ translator.load(locale, QLatin1String("qml"), QLatin1String("_"), directory + QLatin1String("/i18n"));
QCoreApplication::installTranslator(&translator);
}
#endif
@@ -415,17 +416,18 @@ int main(int argc, char ** argv)
app.setOrganizationDomain("qt-project.org");
#ifndef QT_NO_TRANSLATION
- QTranslator translator;
+ QLocale locale;
QTranslator qtTranslator;
- QString sysLocale = QLocale::system().name();
- if (qtTranslator.load(QLatin1String("qt_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ if (qtTranslator.load(locale, QLatin1String("qt"), QLatin1String("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
app.installTranslator(&qtTranslator);
- if (translator.load(QLatin1String("qmlscene_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+
+ QTranslator translator;
+ if (translator.load(locale, QLatin1String("qmlscene"), QLatin1String("_"), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
app.installTranslator(&translator);
QTranslator qmlTranslator;
if (!options.translationFile.isEmpty()) {
- if (qmlTranslator.load(options.translationFile)) {
+ if (qmlTranslator.load(locale, options.translationFile)) {
app.installTranslator(&qmlTranslator);
} else {
qWarning() << "Could not load the translation file" << options.translationFile;