aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.2.011
-rw-r--r--examples/quick/dialogs/systemdialogs/FileDialogs.qml10
-rw-r--r--examples/quick/shared/shared.h8
-rw-r--r--examples/quick/window/window.qml1
-rw-r--r--src/imports/dialogs/DefaultColorDialog.qml20
-rw-r--r--src/imports/dialogs/DefaultFileDialog.qml129
-rw-r--r--src/imports/dialogs/plugins.qmltypes524
-rw-r--r--src/imports/dialogs/qquickplatformfontdialog.cpp1
-rw-r--r--src/imports/localstorage/plugins.qmltypes3
-rw-r--r--src/imports/particles/plugins.qmltypes3
-rw-r--r--src/imports/qtquick2/plugins.qmltypes324
-rw-r--r--src/imports/settings/plugins.qmltypes3
-rw-r--r--src/imports/testlib/plugins.qmltypes5
-rw-r--r--src/imports/widgets/plugins.qmltypes191
-rw-r--r--src/imports/window/plugin.cpp2
-rw-r--r--src/imports/window/plugins.qmltypes36
-rw-r--r--src/imports/xmllistmodel/plugins.qmltypes3
-rw-r--r--src/particles/particles.pri7
-rw-r--r--src/particles/particles.qrc5
-rw-r--r--src/particles/qquickcustomparticle.cpp6
-rw-r--r--src/particles/qquickimageparticle.cpp87
-rw-r--r--src/particles/shaders/customparticle.frag2
-rw-r--r--src/particles/shaders/customparticle_core.frag13
-rw-r--r--src/particles/shaders/customparticle_core.vert4
-rw-r--r--src/particles/shaders/customparticletemplate.vert2
-rw-r--r--src/particles/shaders/customparticletemplate_core.vert28
-rw-r--r--src/particles/shaders/imageparticle.frag2
-rw-r--r--src/particles/shaders/imageparticle.vert2
-rw-r--r--src/particles/shaders/imageparticle_core.frag44
-rw-r--r--src/particles/shaders/imageparticle_core.vert145
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp42
-rw-r--r--src/qml/compiler/qv4codegen.cpp15
-rw-r--r--src/qml/compiler/qv4codegen_p.h4
-rw-r--r--src/qml/compiler/qv4compiler.cpp16
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h1
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp80
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h3
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp100
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h7
-rw-r--r--src/qml/compiler/qv4isel_p.cpp7
-rw-r--r--src/qml/compiler/qv4isel_p.h5
-rw-r--r--src/qml/compiler/qv4isel_util_p.h65
-rw-r--r--src/qml/compiler/qv4jsir.cpp25
-rw-r--r--src/qml/compiler/qv4jsir_p.h83
-rw-r--r--src/qml/compiler/qv4regalloc.cpp34
-rw-r--r--src/qml/compiler/qv4ssa.cpp285
-rw-r--r--src/qml/debugger/qv4debugservice.cpp6
-rw-r--r--src/qml/jsruntime/qv4alloca_p.h8
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4context.cpp7
-rw-r--r--src/qml/jsruntime/qv4context_p.h1
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp49
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h15
-rw-r--r--src/qml/jsruntime/qv4engine.cpp65
-rw-r--r--src/qml/jsruntime/qv4engine_p.h14
-rw-r--r--src/qml/jsruntime/qv4function.cpp27
-rw-r--r--src/qml/jsruntime/qv4function_p.h2
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp39
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h98
-rw-r--r--src/qml/jsruntime/qv4object.cpp18
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp36
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h7
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp10
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h2
-rw-r--r--src/qml/jsruntime/qv4script.cpp2
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp6
-rw-r--r--src/qml/jsruntime/qv4string.cpp5
-rw-r--r--src/qml/jsruntime/qv4value_def_p.h48
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp2
-rw-r--r--src/qml/qml/qml.pri2
-rw-r--r--src/qml/qml/qqmlabstracturlinterceptor.cpp3
-rw-r--r--src/qml/qml/qqmlabstracturlinterceptor_p.h (renamed from src/qml/qml/qqmlabstracturlinterceptor.h)4
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp2
-rw-r--r--src/qml/qml/qqmlcompiler.cpp7
-rw-r--r--src/qml/qml/qqmlcontext.cpp2
-rw-r--r--src/qml/qml/qqmlengine.cpp2
-rw-r--r--src/qml/qml/qqmlfileselector.cpp69
-rw-r--r--src/qml/qml/qqmlfileselector.h12
-rw-r--r--src/qml/qml/qqmlfileselector_p.h14
-rw-r--r--src/qml/qml/qqmlimport.cpp3
-rw-r--r--src/qml/qml/qqmltypeloader.cpp2
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp16
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h5
-rw-r--r--src/quick/doc/src/concepts/statesanimations/animations.qdoc11
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp4
-rw-r--r--src/quick/items/items.pri8
-rw-r--r--src/quick/items/items.qrc6
-rw-r--r--src/quick/items/qquickitem.cpp7
-rw-r--r--src/quick/items/qquickscreen.cpp35
-rw-r--r--src/quick/items/qquickwindow.cpp46
-rw-r--r--src/quick/items/shaders/shadereffect_core.frag13
-rw-r--r--src/quick/items/shaders/shadereffect_core.vert14
-rw-r--r--src/quick/items/shaders/shadereffectfallback_core.frag8
-rw-r--r--src/quick/items/shaders/shadereffectfallback_core.vert10
-rw-r--r--src/quick/items/shaders/sprite_core.frag16
-rw-r--r--src/quick/items/shaders/sprite_core.vert24
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp69
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h15
-rw-r--r--src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp29
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp4
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h6
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp3
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp84
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h9
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp4
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h1
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp194
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/scenegraph.pri34
-rw-r--r--src/quick/scenegraph/scenegraph.qrc32
-rw-r--r--src/quick/scenegraph/shaders/24bittextmask.frag4
-rw-r--r--src/quick/scenegraph/shaders/24bittextmask_core.frag14
-rw-r--r--src/quick/scenegraph/shaders/8bittextmask.frag4
-rw-r--r--src/quick/scenegraph/shaders/8bittextmask_core.frag13
-rw-r--r--src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag20
-rw-r--r--src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag20
-rw-r--r--src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert18
-rw-r--r--src/quick/scenegraph/shaders/distancefieldtext_core.frag16
-rw-r--r--src/quick/scenegraph/shaders/distancefieldtext_core.vert15
-rw-r--r--src/quick/scenegraph/shaders/flatcolor_core.frag10
-rw-r--r--src/quick/scenegraph/shaders/flatcolor_core.vert10
-rw-r--r--src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag32
-rw-r--r--src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert36
-rw-r--r--src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag21
-rw-r--r--src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert29
-rw-r--r--src/quick/scenegraph/shaders/opaquetexture_core.frag12
-rw-r--r--src/quick/scenegraph/shaders/opaquetexture_core.vert14
-rw-r--r--src/quick/scenegraph/shaders/outlinedtext_core.frag25
-rw-r--r--src/quick/scenegraph/shaders/outlinedtext_core.vert24
-rw-r--r--src/quick/scenegraph/shaders/rendernode_core.frag12
-rw-r--r--src/quick/scenegraph/shaders/rendernode_core.vert12
-rw-r--r--src/quick/scenegraph/shaders/smoothcolor_core.frag10
-rw-r--r--src/quick/scenegraph/shaders/smoothcolor_core.vert47
-rw-r--r--src/quick/scenegraph/shaders/smoothtexture_core.frag13
-rw-r--r--src/quick/scenegraph/shaders/smoothtexture_core.vert54
-rw-r--r--src/quick/scenegraph/shaders/stencilclip_core.frag8
-rw-r--r--src/quick/scenegraph/shaders/stencilclip_core.vert10
-rw-r--r--src/quick/scenegraph/shaders/styledtext_core.frag18
-rw-r--r--src/quick/scenegraph/shaders/styledtext_core.vert18
-rw-r--r--src/quick/scenegraph/shaders/textmask_core.frag14
-rw-r--r--src/quick/scenegraph/shaders/textmask_core.vert15
-rw-r--r--src/quick/scenegraph/shaders/texture_core.frag13
-rw-r--r--src/quick/scenegraph/shaders/vertexcolor_core.frag10
-rw-r--r--src/quick/scenegraph/shaders/vertexcolor_core.vert15
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp5
-rw-r--r--src/quick/scenegraph/util/qsgshadersourcebuilder.cpp307
-rw-r--r--src/quick/scenegraph/util/qsgshadersourcebuilder_p.h5
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp16
-rw-r--r--src/quick/util/qquickanimation.cpp3
-rw-r--r--src/quick/util/qquickspringanimation.cpp3
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp3
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp7
-rw-r--r--tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp1
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/idAsLValue.qml7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/misctypetest.qml28
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug34792.qml14
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_33754.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_34493.qml19
-rw-r--r--tests/auto/qml/qqmlecmascript/data/sequenceConversion.indexes.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/setPropertyOnNull.qml5
-rw-r--r--tests/auto/qml/qqmlecmascript/data/setPropertyOnUndefined.qml5
-rw-r--r--tests/auto/qml/qqmlecmascript/data/singletonTest.qml48
-rw-r--r--tests/auto/qml/qqmlecmascript/data/singletonTest2.qml74
-rw-r--r--tests/auto/qml/qqmlecmascript/data/updateCall.qml10
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp40
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h28
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp170
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp2
-rw-r--r--tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp22
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp7
-rw-r--r--tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp3
-rw-r--r--tests/auto/quick/nodes/tst_nodestest.cpp20
-rw-r--r--tests/auto/quick/qquickanimations/data/parallelAnimationNullChildBug.qml6
-rw-r--r--tests/auto/quick/qquickanimations/data/sequentialAnimationNullChildBug.qml6
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp26
-rw-r--r--tests/auto/quick/qquickspringanimation/data/inTransition.qml22
-rw-r--r--tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp10
-rw-r--r--tests/auto/quick/scenegraph/data/render_StackingOrder.qml65
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp1
-rw-r--r--tools/qml/main.cpp13
-rw-r--r--tools/qml/qml.pro2
-rw-r--r--tools/qmlimportscanner/main.cpp224
189 files changed, 4520 insertions, 1051 deletions
diff --git a/dist/changes-5.2.0 b/dist/changes-5.2.0
index 9db8458319..8b044d6932 100644
--- a/dist/changes-5.2.0
+++ b/dist/changes-5.2.0
@@ -46,6 +46,13 @@ Third party components
the engine now truncates instead of rounding. This is consistent with the
ECMAScript specification's way of converting doubles to ints.
+ - Comparing value based types with the JS strictly equal operator will
+ now behave similar to the corresponding C++ == operator. Ie. two
+ QPoints exposed on the JS side will be strictly equal if their values
+ are equal. This brings the behavior of value based types in JS closer
+ to what one would expect and more inline with primitive values in
+ Javascript.
+
****************************************************************************
* Library *
****************************************************************************
@@ -53,6 +60,10 @@ Third party components
QtQml
------
+- New class QQmlFileSelectors allows applying a QFileSelector to QML assets
+ and types. One is automatically set on QQmlApplicationEngines from now on,
+ plain QQmlEngines must set their own in order to be affected.
+
QtQuick
------
diff --git a/examples/quick/dialogs/systemdialogs/FileDialogs.qml b/examples/quick/dialogs/systemdialogs/FileDialogs.qml
index dca47ae1fd..bfc160fa45 100644
--- a/examples/quick/dialogs/systemdialogs/FileDialogs.qml
+++ b/examples/quick/dialogs/systemdialogs/FileDialogs.qml
@@ -175,16 +175,6 @@ Rectangle {
// TODO: QTBUG-29814 This isn't portable, but we don't expose QDir::tempPath to QML yet.
onClicked: fileDialog.folder = "/tmp" // file:///tmp would also be OK
}
- Button {
- text: "set geometry"
- anchors.verticalCenter: parent.verticalCenter
- onClicked: {
- fileDialog.width = Math.min(512, Screen.width * 0.9)
- fileDialog.height = Math.min(340, Screen.height * 0.9)
- fileDialog.x = (Screen.width - fileDialog.width) / 2
- fileDialog.y = (Screen.height - fileDialog.height) / 2
- }
- }
}
}
}
diff --git a/examples/quick/shared/shared.h b/examples/quick/shared/shared.h
index 5cf1333c02..d2f7c98311 100644
--- a/examples/quick/shared/shared.h
+++ b/examples/quick/shared/shared.h
@@ -49,8 +49,14 @@
app.setOrganizationDomain("qt-project.org");\
app.setApplicationName(QFileInfo(app.applicationFilePath()).baseName());\
QQuickView view;\
+ if (qgetenv("QT_QUICK_CORE_PROFILE").toInt()) {\
+ QSurfaceFormat f = view.format();\
+ f.setProfile(QSurfaceFormat::CoreProfile);\
+ f.setVersion(4, 4);\
+ view.setFormat(f);\
+ }\
view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));\
- view.engine()->setUrlInterceptor(new QQmlFileSelector(&view));\
+ new QQmlFileSelector(view.engine(), &view);\
view.setSource(QUrl("qrc:///" #NAME ".qml")); \
view.setResizeMode(QQuickView::SizeRootObjectToView);\
if (QGuiApplication::platformName() == QLatin1String("qnx") || \
diff --git a/examples/quick/window/window.qml b/examples/quick/window/window.qml
index 67e2ba40ff..00daec7ff1 100644
--- a/examples/quick/window/window.qml
+++ b/examples/quick/window/window.qml
@@ -140,6 +140,7 @@ QtObject {
height: 240
color: "#215400"
title: "Test Window with color " + color
+ flags: Qt.Window | Qt.WindowFullscreenButtonHint
Rectangle {
anchors.fill: parent
anchors.margins: defaultSpacing
diff --git a/src/imports/dialogs/DefaultColorDialog.qml b/src/imports/dialogs/DefaultColorDialog.qml
index a0efb6ccf1..4913e332d7 100644
--- a/src/imports/dialogs/DefaultColorDialog.qml
+++ b/src/imports/dialogs/DefaultColorDialog.qml
@@ -45,18 +45,18 @@ import "qml"
AbstractColorDialog {
id: root
- property bool _valueSet: true // guard to prevent binding loops
- function _setControlsFromColor() {
- _valueSet = false
+ property bool __valueSet: true // guard to prevent binding loops
+ function __setControlsFromColor() {
+ __valueSet = false
hueSlider.value = root.currentHue
saturationSlider.value = root.currentSaturation
lightnessSlider.value = root.currentLightness
alphaSlider.value = root.currentAlpha
crosshairs.x = root.currentLightness * paletteMap.width
crosshairs.y = (1.0 - root.currentSaturation) * paletteMap.height
- _valueSet = true
+ __valueSet = true
}
- onCurrentColorChanged: _setControlsFromColor()
+ onCurrentColorChanged: __setControlsFromColor()
onSelectionAccepted: root.color = root.currentColor
Rectangle {
@@ -119,7 +119,7 @@ AbstractColorDialog {
id: paletteMap
x: (parent.width - width) / 2
width: height
- onWidthChanged: root._setControlsFromColor()
+ onWidthChanged: root.__setControlsFromColor()
height: parent.height
source: "images/checkers.png"
fillMode: Image.Tile
@@ -234,7 +234,7 @@ AbstractColorDialog {
ColorSlider {
id: hueSlider
value: 0.5
- onValueChanged: if (_valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
+ onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
text: qsTr("Hue")
trackDelegate: Rectangle {
rotation: -90
@@ -255,7 +255,7 @@ AbstractColorDialog {
id: saturationSlider
visible: !content.usePaletteMap
value: 0.5
- onValueChanged: if (_valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
+ onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
text: qsTr("Saturation")
trackDelegate: Rectangle {
rotation: -90
@@ -271,7 +271,7 @@ AbstractColorDialog {
id: lightnessSlider
visible: !content.usePaletteMap
value: 0.5
- onValueChanged: if (_valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
+ onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
text: qsTr("Luminosity")
trackDelegate: Rectangle {
rotation: -90
@@ -289,7 +289,7 @@ AbstractColorDialog {
minimum: 0.0
maximum: 1.0
value: 1.0
- onValueChanged: if (_valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
+ onValueChanged: if (__valueSet) root.currentColor = Qt.hsla(hueSlider.value, saturationSlider.value, lightnessSlider.value, alphaSlider.value)
text: qsTr("Alpha")
visible: root.showAlphaChannel
trackDelegate: Item {
diff --git a/src/imports/dialogs/DefaultFileDialog.qml b/src/imports/dialogs/DefaultFileDialog.qml
index 8eb76966c7..0a5eabddf2 100644
--- a/src/imports/dialogs/DefaultFileDialog.qml
+++ b/src/imports/dialogs/DefaultFileDialog.qml
@@ -48,63 +48,62 @@ AbstractFileDialog {
id: root
onVisibleChanged: {
if (visible) {
- selectedIndices = []
- lastClickedIdx = -1
+ __selectedIndices = []
+ __lastClickedIdx = -1
currentPathField.visible = false
}
}
onFolderChanged: view.model.folder = folder
- property bool showFocusHighlight: false
- property real textX: titleBar.height
- property SystemPalette palette
- property var selectedIndices: []
- property int lastClickedIdx: -1
+ property real __textX: titleBar.height
+ property SystemPalette __palette
+ property var __selectedIndices: []
+ property int __lastClickedIdx: -1
- function dirDown(path) {
+ function __dirDown(path) {
view.model.folder = path
- lastClickedIdx = -1
- selectedIndices = []
+ __lastClickedIdx = -1
+ __selectedIndices = []
}
- function dirUp() {
+ function __dirUp() {
view.model.folder = view.model.parentFolder
- lastClickedIdx = -1
- selectedIndices = []
+ __lastClickedIdx = -1
+ __selectedIndices = []
}
- function up(extend) {
+ function __up(extend) {
if (view.currentIndex > 0)
--view.currentIndex
else
view.currentIndex = 0
if (extend) {
- if (selectedIndices.indexOf(view.currentIndex) < 0) {
- var selCopy = selectedIndices
+ if (__selectedIndices.indexOf(view.currentIndex) < 0) {
+ var selCopy = __selectedIndices
selCopy.push(view.currentIndex)
- selectedIndices = selCopy
+ __selectedIndices = selCopy
}
} else
- selectedIndices = [view.currentIndex]
+ __selectedIndices = [view.currentIndex]
}
- function down(extend) {
+ function __down(extend) {
if (view.currentIndex < view.model.count - 1)
++view.currentIndex
else
view.currentIndex = view.model.count - 1
if (extend) {
- if (selectedIndices.indexOf(view.currentIndex) < 0) {
- var selCopy = selectedIndices
+ if (__selectedIndices.indexOf(view.currentIndex) < 0) {
+ var selCopy = __selectedIndices
selCopy.push(view.currentIndex)
- selectedIndices = selCopy
+ __selectedIndices = selCopy
}
} else
- selectedIndices = [view.currentIndex]
+ __selectedIndices = [view.currentIndex]
}
- function acceptSelection() {
+ function __acceptSelection() {
clearSelection()
- if (selectFolder && selectedIndices.length == 0)
+ if (selectFolder && __selectedIndices.length == 0)
addSelection(folder)
- else if (selectedIndices.length > 0) {
- selectedIndices.map(function(idx) {
+ else if (__selectedIndices.length > 0) {
+ __selectedIndices.map(function(idx) {
if (view.model.isFolder(idx)) {
if (selectFolder)
addSelection(view.model.get(idx, "fileURL"))
@@ -125,11 +124,11 @@ AbstractFileDialog {
// TODO: QTBUG-29817 geometry from AbstractFileDialog
implicitWidth: Math.min(maxSize, Screen.pixelDensity * 100)
implicitHeight: Math.min(maxSize, Screen.pixelDensity * 80)
- color: palette.window
+ color: __palette.window
focus: root.visible && !currentPathField.visible
property real spacing: 6
property real outerSpacing: 12
- SystemPalette { id: palette }
+ SystemPalette { id: __palette }
Component {
id: folderDelegate
@@ -137,9 +136,9 @@ AbstractFileDialog {
id: wrapper
function launch() {
if (view.model.isFolder(index)) {
- dirDown(filePath)
+ __dirDown(filePath)
} else {
- root.acceptSelection()
+ root.__acceptSelection()
}
}
width: content.width
@@ -147,15 +146,15 @@ AbstractFileDialog {
color: "transparent"
Rectangle {
id: itemHighlight
- visible: root.selectedIndices.indexOf(index) >= 0
+ visible: root.__selectedIndices.indexOf(index) >= 0
anchors.fill: parent
- color: palette.highlight
+ color: __palette.highlight
}
Image {
id: icon
source: "images/folder.png"
height: wrapper.height - y * 2; width: height
- x: (root.textX - width) / 2
+ x: (root.__textX - width) / 2
y: 2
visible: view.model.isFolder(index)
}
@@ -163,45 +162,45 @@ AbstractFileDialog {
id: nameText
anchors.fill: parent; verticalAlignment: Text.AlignVCenter
text: fileName
- anchors.leftMargin: root.textX
- color: itemHighlight.visible ? palette.highlightedText : palette.windowText
+ anchors.leftMargin: root.__textX
+ color: itemHighlight.visible ? __palette.highlightedText : __palette.windowText
elide: Text.ElideRight
}
MouseArea {
id: mouseRegion
anchors.fill: parent
onDoubleClicked: {
- selectedIndices = [index]
- root.lastClickedIdx = index
+ __selectedIndices = [index]
+ root.__lastClickedIdx = index
launch()
}
onClicked: {
view.currentIndex = index
if (mouse.modifiers & Qt.ControlModifier && root.selectMultiple) {
- // modifying the contents of selectedIndices doesn't notify,
+ // modifying the contents of __selectedIndices doesn't notify,
// so we have to re-assign the variable
- var selCopy = selectedIndices
+ var selCopy = __selectedIndices
var existingIdx = selCopy.indexOf(index)
if (existingIdx >= 0)
selCopy.splice(existingIdx, 1)
else
selCopy.push(index)
- selectedIndices = selCopy
+ __selectedIndices = selCopy
} else if (mouse.modifiers & Qt.ShiftModifier && root.selectMultiple) {
- if (root.lastClickedIdx >= 0) {
+ if (root.__lastClickedIdx >= 0) {
var sel = []
- if (index > lastClickedIdx) {
- for (var i = root.lastClickedIdx; i <= index; i++)
+ if (index > __lastClickedIdx) {
+ for (var i = root.__lastClickedIdx; i <= index; i++)
sel.push(i)
} else {
- for (var i = root.lastClickedIdx; i >= index; i--)
+ for (var i = root.__lastClickedIdx; i >= index; i--)
sel.push(i)
}
- selectedIndices = sel
+ __selectedIndices = sel
}
} else {
- selectedIndices = [index]
- root.lastClickedIdx = index
+ __selectedIndices = [index]
+ root.__lastClickedIdx = index
}
}
}
@@ -212,13 +211,13 @@ AbstractFileDialog {
event.accepted = true
switch (event.key) {
case Qt.Key_Up:
- root.up(event.modifiers & Qt.ShiftModifier && root.selectMultiple)
+ root.__up(event.modifiers & Qt.ShiftModifier && root.selectMultiple)
break
case Qt.Key_Down:
- root.down(event.modifiers & Qt.ShiftModifier && root.selectMultiple)
+ root.__down(event.modifiers & Qt.ShiftModifier && root.selectMultiple)
break
case Qt.Key_Left:
- root.dirUp()
+ root.__dirUp()
break
case Qt.Key_Return:
case Qt.Key_Select:
@@ -226,7 +225,7 @@ AbstractFileDialog {
if (view.currentItem)
view.currentItem.launch()
else
- root.acceptSelection()
+ root.__acceptSelection()
break
case Qt.Key_Back:
case Qt.Key_Escape:
@@ -265,7 +264,7 @@ AbstractFileDialog {
delegate: folderDelegate
highlight: Rectangle {
color: "transparent"
- border.color: Qt.darker(palette.window, 1.3)
+ border.color: Qt.darker(__palette.window, 1.3)
}
highlightMoveDuration: 0
highlightMoveVelocity: -1
@@ -284,12 +283,12 @@ AbstractFileDialog {
height: currentPathField.height * 1.5
Rectangle {
anchors.fill: parent
- color: Qt.darker(palette.window, 1.1)
- border.color: Qt.darker(palette.window, 1.3)
+ color: Qt.darker(__palette.window, 1.1)
+ border.color: Qt.darker(__palette.window, 1.3)
}
Rectangle {
id: upButton
- width: root.textX
+ width: root.__textX
height: titleBar.height
color: "transparent"
@@ -300,22 +299,22 @@ AbstractFileDialog {
MouseArea { id: upRegion; anchors.centerIn: parent
width: 56
height: parent.height
- onClicked: if (view.model.parentFolder != "") dirUp()
+ onClicked: if (view.model.parentFolder !== "") __dirUp()
}
states: [
State {
name: "pressed"
when: upRegion.pressed
- PropertyChanges { target: upButton; color: palette.highlight }
+ PropertyChanges { target: upButton; color: __palette.highlight }
}
]
}
Text {
id: currentPathText
anchors.left: parent.left; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: textX; anchors.rightMargin: content.spacing
+ anchors.leftMargin: __textX; anchors.rightMargin: content.spacing
text: root.urlToPath(view.model.folder)
- color: palette.text
+ color: __palette.text
elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
MouseArea {
anchors.fill: parent
@@ -325,7 +324,7 @@ AbstractFileDialog {
TextField {
id: currentPathField
anchors.left: parent.left; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: textX; anchors.rightMargin: content.spacing
+ anchors.leftMargin: __textX; anchors.rightMargin: content.spacing
visible: false
focus: visible
onAccepted: {
@@ -345,8 +344,8 @@ AbstractFileDialog {
width: parent.width
height: buttonRow.height + buttonRow.spacing * 2
anchors.bottom: parent.bottom
- color: Qt.darker(palette.window, 1.1)
- border.color: Qt.darker(palette.window, 1.3)
+ color: Qt.darker(__palette.window, 1.1)
+ border.color: Qt.darker(__palette.window, 1.3)
Row {
id: buttonRow
@@ -375,9 +374,9 @@ AbstractFileDialog {
text: "OK"
onClicked: {
if (view.model.isFolder(view.currentIndex) && !selectFolder)
- dirDown(view.model.get(view.currentIndex, "filePath"))
+ __dirDown(view.model.get(view.currentIndex, "filePath"))
else
- root.acceptSelection()
+ root.__acceptSelection()
}
}
}
diff --git a/src/imports/dialogs/plugins.qmltypes b/src/imports/dialogs/plugins.qmltypes
index c52d355cad..d5db4b93bd 100644
--- a/src/imports/dialogs/plugins.qmltypes
+++ b/src/imports/dialogs/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable QtQuick.Dialogs 1.0'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable -omit-prefix=__ QtQuick.Dialogs 1.1'
Module {
Component {
@@ -124,15 +125,530 @@ Module {
}
}
Component {
- name: "QQuickPlatformColorDialog"
+ name: "QQuickAbstractFontDialog"
+ prototype: "QQuickAbstractDialog"
+ Property { name: "scalableFonts"; type: "bool" }
+ Property { name: "nonScalableFonts"; type: "bool" }
+ Property { name: "monospacedFonts"; type: "bool" }
+ Property { name: "proportionalFonts"; type: "bool" }
+ Property { name: "font"; type: "QFont" }
+ Signal { name: "selectionAccepted" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setModality"
+ Parameter { name: "m"; type: "Qt::WindowModality" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "t"; type: "string" }
+ }
+ Method {
+ name: "setFont"
+ Parameter { name: "arg"; type: "QFont" }
+ }
+ Method {
+ name: "setScalableFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setNonScalableFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setMonospacedFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setProportionalFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ }
+ Component {
+ name: "QQuickAbstractMessageDialog"
+ prototype: "QQuickAbstractDialog"
+ Enum {
+ name: "Icon"
+ values: {
+ "NoIcon": 0,
+ "Information": 1,
+ "Warning": 2,
+ "Critical": 3,
+ "Question": 4
+ }
+ }
+ Enum {
+ name: "StandardButton"
+ values: {
+ "NoButton": 0,
+ "Ok": 1024,
+ "Save": 2048,
+ "SaveAll": 4096,
+ "Open": 8192,
+ "Yes": 16384,
+ "YesToAll": 32768,
+ "No": 65536,
+ "NoToAll": 131072,
+ "Abort": 262144,
+ "Retry": 524288,
+ "Ignore": 1048576,
+ "Close": 2097152,
+ "Cancel": 4194304,
+ "Discard": 8388608,
+ "Help": 16777216,
+ "Apply": 33554432,
+ "Reset": 67108864,
+ "RestoreDefaults": 134217728
+ }
+ }
+ Enum {
+ name: "StandardButtons"
+ values: {
+ "NoButton": 0,
+ "Ok": 1024,
+ "Save": 2048,
+ "SaveAll": 4096,
+ "Open": 8192,
+ "Yes": 16384,
+ "YesToAll": 32768,
+ "No": 65536,
+ "NoToAll": 131072,
+ "Abort": 262144,
+ "Retry": 524288,
+ "Ignore": 1048576,
+ "Close": 2097152,
+ "Cancel": 4194304,
+ "Discard": 8388608,
+ "Help": 16777216,
+ "Apply": 33554432,
+ "Reset": 67108864,
+ "RestoreDefaults": 134217728
+ }
+ }
+ Property { name: "text"; type: "string" }
+ Property { name: "informativeText"; type: "string" }
+ Property { name: "detailedText"; type: "string" }
+ Property { name: "icon"; type: "Icon" }
+ Property { name: "standardIconSource"; type: "QUrl"; isReadonly: true }
+ Property { name: "standardButtons"; type: "StandardButtons" }
+ Property { name: "clickedButton"; type: "StandardButton"; isReadonly: true }
+ Signal { name: "buttonClicked" }
+ Signal { name: "discard" }
+ Signal { name: "help" }
+ Signal { name: "yes" }
+ Signal { name: "no" }
+ Signal { name: "apply" }
+ Signal { name: "reset" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setInformativeText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setDetailedText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setIcon"
+ Parameter { name: "icon"; type: "Icon" }
+ }
+ Method {
+ name: "setStandardButtons"
+ Parameter { name: "buttons"; type: "StandardButtons" }
+ }
+ Method {
+ name: "click"
+ Parameter { name: "button"; type: "QMessageDialogOptions::StandardButton" }
+ Parameter { type: "QMessageDialogOptions::ButtonRole" }
+ }
+ Method {
+ name: "click"
+ Parameter { name: "button"; type: "QQuickAbstractMessageDialog::StandardButton" }
+ }
+ }
+ Component {
+ name: "QQuickColorDialog"
+ defaultProperty: "implementation"
prototype: "QQuickAbstractColorDialog"
- exports: ["QtQuick.Dialogs/ColorDialog 1.0"]
+ exports: ["QtQuick.Dialogs/AbstractColorDialog 1.0"]
exportMetaObjectRevisions: [0]
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
}
Component {
- name: "QQuickPlatformFileDialog"
+ name: "QQuickFileDialog"
+ defaultProperty: "implementation"
prototype: "QQuickAbstractFileDialog"
+ exports: ["QtQuick.Dialogs/AbstractFileDialog 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
+ Method { name: "clearSelection" }
+ Method {
+ name: "addSelection"
+ type: "bool"
+ Parameter { name: "path"; type: "QUrl" }
+ }
+ }
+ Component {
+ name: "QQuickFontDialog"
+ defaultProperty: "implementation"
+ prototype: "QQuickAbstractFontDialog"
+ exports: ["QtQuick.Dialogs/AbstractFontDialog 1.1"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
+ }
+ Component {
+ name: "QQuickMessageDialog"
+ defaultProperty: "implementation"
+ prototype: "QQuickAbstractMessageDialog"
+ exports: ["QtQuick.Dialogs/AbstractMessageDialog 1.1"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
+ }
+ Component {
+ name: "QQuickStandardButton"
+ exports: ["QtQuick.Dialogs/StandardButton 1.1"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "QQuickStandardIcon"
+ exports: ["QtQuick.Dialogs/StandardIcon 1.1"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ prototype: "QObject"
+ name: "QtQuick.Dialogs/ColorDialog"
+ exports: ["QtQuick.Dialogs/ColorDialog 1.0"]
+ exportMetaObjectRevisions: [0]
+ defaultProperty: "implementation"
+ Property { name: "showAlphaChannel"; type: "bool" }
+ Property { name: "color"; type: "QColor" }
+ Property { name: "currentColor"; type: "QColor" }
+ Property { name: "currentHue"; type: "double"; isReadonly: true }
+ Property { name: "currentSaturation"; type: "double"; isReadonly: true }
+ Property { name: "currentLightness"; type: "double"; isReadonly: true }
+ Property { name: "currentAlpha"; type: "double"; isReadonly: true }
+ Signal { name: "selectionAccepted" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setModality"
+ Parameter { name: "m"; type: "Qt::WindowModality" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "t"; type: "string" }
+ }
+ Method {
+ name: "setColor"
+ Parameter { name: "arg"; type: "QColor" }
+ }
+ Method {
+ name: "setCurrentColor"
+ Parameter { name: "currentColor"; type: "QColor" }
+ }
+ Method {
+ name: "setShowAlphaChannel"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Property { name: "visible"; type: "bool" }
+ Property { name: "modality"; type: "Qt::WindowModality" }
+ Property { name: "title"; type: "string" }
+ Property { name: "isWindow"; type: "bool"; isReadonly: true }
+ Property { name: "x"; type: "int" }
+ Property { name: "y"; type: "int" }
+ Property { name: "width"; type: "int" }
+ Property { name: "height"; type: "int" }
+ Signal { name: "visibilityChanged" }
+ Signal { name: "geometryChanged" }
+ Signal { name: "accepted" }
+ Signal { name: "rejected" }
+ Method { name: "open" }
+ Method { name: "close" }
+ Method {
+ name: "setX"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setY"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setWidth"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setHeight"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
+ }
+ Component {
+ prototype: "QObject"
+ name: "QtQuick.Dialogs/FileDialog"
exports: ["QtQuick.Dialogs/FileDialog 1.0"]
exportMetaObjectRevisions: [0]
+ defaultProperty: "implementation"
+ Property { name: "visible"; type: "bool" }
+ Property { name: "modality"; type: "Qt::WindowModality" }
+ Property { name: "title"; type: "string" }
+ Property { name: "isWindow"; type: "bool"; isReadonly: true }
+ Property { name: "x"; type: "int" }
+ Property { name: "y"; type: "int" }
+ Property { name: "width"; type: "int" }
+ Property { name: "height"; type: "int" }
+ Signal { name: "visibilityChanged" }
+ Signal { name: "geometryChanged" }
+ Signal { name: "accepted" }
+ Signal { name: "rejected" }
+ Method { name: "open" }
+ Method { name: "close" }
+ Method {
+ name: "setX"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setY"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setWidth"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setHeight"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Property { name: "selectExisting"; type: "bool" }
+ Property { name: "selectMultiple"; type: "bool" }
+ Property { name: "selectFolder"; type: "bool" }
+ Property { name: "folder"; type: "QUrl" }
+ Property { name: "nameFilters"; type: "QStringList" }
+ Property { name: "selectedNameFilter"; type: "string" }
+ Property { name: "fileUrl"; type: "QUrl"; isReadonly: true }
+ Property { name: "fileUrls"; type: "QList<QUrl>"; isReadonly: true }
+ Signal { name: "filterSelected" }
+ Signal { name: "fileModeChanged" }
+ Signal { name: "selectionAccepted" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "t"; type: "string" }
+ }
+ Method {
+ name: "setSelectExisting"
+ Parameter { name: "s"; type: "bool" }
+ }
+ Method {
+ name: "setSelectMultiple"
+ Parameter { name: "s"; type: "bool" }
+ }
+ Method {
+ name: "setSelectFolder"
+ Parameter { name: "s"; type: "bool" }
+ }
+ Method {
+ name: "setFolder"
+ Parameter { name: "f"; type: "QUrl" }
+ }
+ Method {
+ name: "setNameFilters"
+ Parameter { name: "f"; type: "QStringList" }
+ }
+ Method {
+ name: "selectNameFilter"
+ Parameter { name: "f"; type: "string" }
+ }
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
+ Method { name: "clearSelection" }
+ Method {
+ name: "addSelection"
+ type: "bool"
+ Parameter { name: "path"; type: "QUrl" }
+ }
+ }
+ Component {
+ prototype: "QObject"
+ name: "QtQuick.Dialogs/FontDialog"
+ exports: ["QtQuick.Dialogs/FontDialog 1.1"]
+ exportMetaObjectRevisions: [1]
+ defaultProperty: "implementation"
+ Property { name: "font"; type: "QFont" }
+ Property { name: "visible"; type: "bool" }
+ Property { name: "modality"; type: "Qt::WindowModality" }
+ Property { name: "title"; type: "string" }
+ Property { name: "isWindow"; type: "bool"; isReadonly: true }
+ Property { name: "x"; type: "int" }
+ Property { name: "y"; type: "int" }
+ Property { name: "width"; type: "int" }
+ Property { name: "height"; type: "int" }
+ Signal { name: "visibilityChanged" }
+ Signal { name: "geometryChanged" }
+ Signal { name: "accepted" }
+ Signal { name: "rejected" }
+ Method { name: "open" }
+ Method { name: "close" }
+ Method {
+ name: "setX"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setY"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setWidth"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setHeight"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Property { name: "scalableFonts"; type: "bool" }
+ Property { name: "nonScalableFonts"; type: "bool" }
+ Property { name: "monospacedFonts"; type: "bool" }
+ Property { name: "proportionalFonts"; type: "bool" }
+ Property { name: "font"; type: "QFont" }
+ Signal { name: "selectionAccepted" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setModality"
+ Parameter { name: "m"; type: "Qt::WindowModality" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "t"; type: "string" }
+ }
+ Method {
+ name: "setFont"
+ Parameter { name: "arg"; type: "QFont" }
+ }
+ Method {
+ name: "setScalableFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setNonScalableFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setMonospacedFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setProportionalFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
+ }
+ Component {
+ prototype: "QObject"
+ name: "QtQuick.Dialogs/MessageDialog"
+ exports: ["QtQuick.Dialogs/MessageDialog 1.1"]
+ exportMetaObjectRevisions: [1]
+ defaultProperty: "implementation"
+ Method { name: "calculateImplicitWidth"; type: "QVariant" }
+ Property { name: "visible"; type: "bool" }
+ Property { name: "modality"; type: "Qt::WindowModality" }
+ Property { name: "title"; type: "string" }
+ Property { name: "isWindow"; type: "bool"; isReadonly: true }
+ Property { name: "x"; type: "int" }
+ Property { name: "y"; type: "int" }
+ Property { name: "width"; type: "int" }
+ Property { name: "height"; type: "int" }
+ Signal { name: "visibilityChanged" }
+ Signal { name: "geometryChanged" }
+ Signal { name: "accepted" }
+ Signal { name: "rejected" }
+ Method { name: "open" }
+ Method { name: "close" }
+ Method {
+ name: "setX"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setY"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setWidth"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setHeight"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Property { name: "text"; type: "string" }
+ Property { name: "informativeText"; type: "string" }
+ Property { name: "detailedText"; type: "string" }
+ Property { name: "icon"; type: "Icon" }
+ Property { name: "standardIconSource"; type: "QUrl"; isReadonly: true }
+ Property { name: "standardButtons"; type: "StandardButtons" }
+ Property { name: "clickedButton"; type: "StandardButton"; isReadonly: true }
+ Signal { name: "buttonClicked" }
+ Signal { name: "discard" }
+ Signal { name: "help" }
+ Signal { name: "yes" }
+ Signal { name: "no" }
+ Signal { name: "apply" }
+ Signal { name: "reset" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setInformativeText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setDetailedText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setIcon"
+ Parameter { name: "icon"; type: "Icon" }
+ }
+ Method {
+ name: "setStandardButtons"
+ Parameter { name: "buttons"; type: "StandardButtons" }
+ }
+ Method {
+ name: "click"
+ Parameter { name: "button"; type: "QMessageDialogOptions::StandardButton" }
+ Parameter { type: "QMessageDialogOptions::ButtonRole" }
+ }
+ Method {
+ name: "click"
+ Parameter { name: "button"; type: "QQuickAbstractMessageDialog::StandardButton" }
+ }
+ Property { name: "implementation"; type: "QObject"; isPointer: true }
}
}
diff --git a/src/imports/dialogs/qquickplatformfontdialog.cpp b/src/imports/dialogs/qquickplatformfontdialog.cpp
index 8b2e0e0501..46ad5eb8df 100644
--- a/src/imports/dialogs/qquickplatformfontdialog.cpp
+++ b/src/imports/dialogs/qquickplatformfontdialog.cpp
@@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
\instantiates QQuickPlatformFontDialog
\inqmlmodule QtQuick.Dialogs 1
\ingroup qtquick-visual
+ \ingroup dialogs
\brief Dialog component for choosing a font.
\since 5.2
diff --git a/src/imports/localstorage/plugins.qmltypes b/src/imports/localstorage/plugins.qmltypes
index bcd516c25e..05bcc875f7 100644
--- a/src/imports/localstorage/plugins.qmltypes
+++ b/src/imports/localstorage/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable QtQuick.LocalStorage 2.0'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.LocalStorage 2.0'
Module {
Component {
diff --git a/src/imports/particles/plugins.qmltypes b/src/imports/particles/plugins.qmltypes
index 495c072a41..712d4fd844 100644
--- a/src/imports/particles/plugins.qmltypes
+++ b/src/imports/particles/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable QtQuick.Particles 2.0'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.Particles 2.0'
Module {
Component {
diff --git a/src/imports/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes
index 02c7d61536..cadef10370 100644
--- a/src/imports/qtquick2/plugins.qmltypes
+++ b/src/imports/qtquick2/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable -builtins'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable -builtins'
Module {
Component {
@@ -222,6 +223,85 @@ Module {
}
}
Component {
+ name: "QKeySequence"
+ exports: ["QtQuick/StandardKey 2.2"]
+ exportMetaObjectRevisions: [2]
+ Enum {
+ name: "StandardKey"
+ values: {
+ "UnknownKey": 0,
+ "HelpContents": 1,
+ "WhatsThis": 2,
+ "Open": 3,
+ "Close": 4,
+ "Save": 5,
+ "New": 6,
+ "Delete": 7,
+ "Cut": 8,
+ "Copy": 9,
+ "Paste": 10,
+ "Undo": 11,
+ "Redo": 12,
+ "Back": 13,
+ "Forward": 14,
+ "Refresh": 15,
+ "ZoomIn": 16,
+ "ZoomOut": 17,
+ "Print": 18,
+ "AddTab": 19,
+ "NextChild": 20,
+ "PreviousChild": 21,
+ "Find": 22,
+ "FindNext": 23,
+ "FindPrevious": 24,
+ "Replace": 25,
+ "SelectAll": 26,
+ "Bold": 27,
+ "Italic": 28,
+ "Underline": 29,
+ "MoveToNextChar": 30,
+ "MoveToPreviousChar": 31,
+ "MoveToNextWord": 32,
+ "MoveToPreviousWord": 33,
+ "MoveToNextLine": 34,
+ "MoveToPreviousLine": 35,
+ "MoveToNextPage": 36,
+ "MoveToPreviousPage": 37,
+ "MoveToStartOfLine": 38,
+ "MoveToEndOfLine": 39,
+ "MoveToStartOfBlock": 40,
+ "MoveToEndOfBlock": 41,
+ "MoveToStartOfDocument": 42,
+ "MoveToEndOfDocument": 43,
+ "SelectNextChar": 44,
+ "SelectPreviousChar": 45,
+ "SelectNextWord": 46,
+ "SelectPreviousWord": 47,
+ "SelectNextLine": 48,
+ "SelectPreviousLine": 49,
+ "SelectNextPage": 50,
+ "SelectPreviousPage": 51,
+ "SelectStartOfLine": 52,
+ "SelectEndOfLine": 53,
+ "SelectStartOfBlock": 54,
+ "SelectEndOfBlock": 55,
+ "SelectStartOfDocument": 56,
+ "SelectEndOfDocument": 57,
+ "DeleteStartOfWord": 58,
+ "DeleteEndOfWord": 59,
+ "DeleteEndOfLine": 60,
+ "InsertParagraphSeparator": 61,
+ "InsertLineSeparator": 62,
+ "SaveAs": 63,
+ "Preferences": 64,
+ "Quit": 65,
+ "FullScreen": 66,
+ "Deselect": 67,
+ "DeleteCompleteLine": 68
+ }
+ }
+ }
+ Component {
name: "QObject"
exports: ["QtQml/QtObject 2.0", "QtQuick/QtObject 2.0"]
exportMetaObjectRevisions: [0, 0]
@@ -243,6 +323,8 @@ Module {
Property { name: "arguments"; type: "QStringList"; isReadonly: true }
Property { name: "name"; type: "string" }
Property { name: "version"; type: "string" }
+ Property { name: "organization"; type: "string" }
+ Property { name: "domain"; type: "string" }
Signal { name: "aboutToQuit" }
Method {
name: "setName"
@@ -252,6 +334,14 @@ Module {
name: "setVersion"
Parameter { name: "arg"; type: "string" }
}
+ Method {
+ name: "setOrganization"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setDomain"
+ Parameter { name: "arg"; type: "string" }
+ }
}
Component {
name: "QQmlBind"
@@ -378,44 +468,44 @@ Module {
Signal { name: "defaultIncludeChanged" }
Signal {
name: "changed"
- Parameter { name: "removed"; type: "QQmlV8Handle" }
- Parameter { name: "inserted"; type: "QQmlV8Handle" }
+ Parameter { name: "removed"; type: "QQmlV4Handle" }
+ Parameter { name: "inserted"; type: "QQmlV4Handle" }
}
Method {
name: "insert"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "create"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "resolve"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "remove"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "addGroups"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "removeGroups"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "setGroups"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "move"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "get"
- type: "QQmlV8Handle"
+ type: "QQmlV4Handle"
Parameter { name: "index"; type: "int" }
}
}
@@ -550,25 +640,25 @@ Module {
Method { name: "clear" }
Method {
name: "remove"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "append"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "insert"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "get"
- type: "QQmlV8Handle"
+ type: "QQmlV4Handle"
Parameter { name: "index"; type: "int" }
}
Method {
name: "set"
Parameter { name: "index"; type: "int" }
- Parameter { type: "QQmlV8Handle" }
+ Parameter { type: "QQmlV4Handle" }
}
Method {
name: "setProperty"
@@ -586,8 +676,8 @@ Module {
}
Component {
name: "QQmlLocale"
- exports: ["QtQuick/Locale 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQml/Locale 2.2", "QtQuick/Locale 2.0"]
+ exportMetaObjectRevisions: [0, 0]
Enum {
name: "MeasurementSystem"
values: {
@@ -958,6 +1048,37 @@ Module {
Property { name: "animations"; type: "QQuickAbstractAnimation"; isList: true; isReadonly: true }
}
Component {
+ name: "QQuickAnimator"
+ prototype: "QQuickAbstractAnimation"
+ exports: ["QtQuick/Animator 2.2"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "target"; type: "QQuickItem"; isPointer: true }
+ Property { name: "easing"; type: "QEasingCurve" }
+ Property { name: "duration"; type: "int" }
+ Property { name: "to"; type: "double" }
+ Property { name: "from"; type: "double" }
+ Signal {
+ name: "targetItemChanged"
+ Parameter { type: "QQuickItem"; isPointer: true }
+ }
+ Signal {
+ name: "durationChanged"
+ Parameter { name: "duration"; type: "int" }
+ }
+ Signal {
+ name: "easingChanged"
+ Parameter { name: "curve"; type: "QEasingCurve" }
+ }
+ Signal {
+ name: "toChanged"
+ Parameter { name: "to"; type: "double" }
+ }
+ Signal {
+ name: "fromChanged"
+ Parameter { name: "from"; type: "double" }
+ }
+ }
+ Component {
name: "QQuickApplication"
prototype: "QQmlApplication"
exports: ["QtQuick/Application 2.0"]
@@ -965,6 +1086,11 @@ Module {
Property { name: "active"; type: "bool"; isReadonly: true }
Property { name: "layoutDirection"; type: "Qt::LayoutDirection"; isReadonly: true }
Property { name: "supportsMultipleWindows"; type: "bool"; isReadonly: true }
+ Property { name: "state"; type: "Qt::ApplicationState"; isReadonly: true }
+ Signal {
+ name: "stateChanged"
+ Parameter { name: "state"; type: "Qt::ApplicationState" }
+ }
}
Component {
name: "QQuickBasePositioner"
@@ -1066,15 +1192,15 @@ Module {
}
Method {
name: "getContext"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "requestAnimationFrame"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "cancelRequestAnimationFrame"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method { name: "requestPaint" }
Method {
@@ -1132,6 +1258,14 @@ Module {
exportMetaObjectRevisions: [0]
attachedType: "QQuickDragAttached"
Enum {
+ name: "DragType"
+ values: {
+ "None": 0,
+ "Automatic": 1,
+ "Internal": 2
+ }
+ }
+ Enum {
name: "Axis"
values: {
"XAxis": 1,
@@ -1148,6 +1282,7 @@ Module {
Property { name: "maximumY"; type: "double" }
Property { name: "active"; type: "bool"; isReadonly: true }
Property { name: "filterChildren"; type: "bool" }
+ Property { name: "threshold"; type: "double" }
}
Component {
name: "QQuickDragAttached"
@@ -1157,11 +1292,22 @@ Module {
Property { name: "target"; type: "QObject"; isReadonly: true; isPointer: true }
Property { name: "hotSpot"; type: "QPointF" }
Property { name: "keys"; type: "QStringList" }
+ Property { name: "mimeData"; type: "QVariantMap" }
Property { name: "supportedActions"; type: "Qt::DropActions" }
Property { name: "proposedAction"; type: "Qt::DropAction" }
+ Property { name: "dragType"; type: "QQuickDrag::DragType" }
+ Signal { name: "dragStarted" }
+ Signal {
+ name: "dragFinished"
+ Parameter { name: "dropAction"; type: "Qt::DropAction" }
+ }
Method {
name: "start"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "startDrag"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method { name: "cancel" }
Method { name: "drop"; type: "int" }
@@ -1743,11 +1889,11 @@ Module {
}
Method {
name: "mapFromItem"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "mapToItem"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
Method { name: "forceActiveFocus" }
Method {
@@ -1756,10 +1902,11 @@ Module {
}
Method {
name: "nextItemInFocusChain"
+ revision: 1
type: "QQuickItem*"
Parameter { name: "forward"; type: "bool" }
}
- Method { name: "nextItemInFocusChain"; type: "QQuickItem*" }
+ Method { name: "nextItemInFocusChain"; revision: 1; type: "QQuickItem*" }
Method {
name: "childAt"
type: "QQuickItem*"
@@ -2195,7 +2342,7 @@ Module {
Signal { name: "loaded" }
Method {
name: "setSource"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
}
Component {
@@ -2312,6 +2459,12 @@ Module {
Property { name: "to"; type: "double" }
}
Component {
+ name: "QQuickOpacityAnimator"
+ prototype: "QQuickAnimator"
+ exports: ["QtQuick/OpacityAnimator 2.2"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "QQuickPackage"
defaultProperty: "data"
prototype: "QObject"
@@ -2825,6 +2978,26 @@ Module {
Property { name: "direction"; type: "RotationDirection" }
}
Component {
+ name: "QQuickRotationAnimator"
+ prototype: "QQuickAnimator"
+ exports: ["QtQuick/RotationAnimator 2.2"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "RotationDirection"
+ values: {
+ "Numerical": 0,
+ "Shortest": 1,
+ "Clockwise": 2,
+ "Counterclockwise": 3
+ }
+ }
+ Property { name: "direction"; type: "RotationDirection" }
+ Signal {
+ name: "directionChanged"
+ Parameter { name: "dir"; type: "RotationDirection" }
+ }
+ }
+ Component {
name: "QQuickRow"
defaultProperty: "data"
prototype: "QQuickBasePositioner"
@@ -2845,6 +3018,12 @@ Module {
Signal { name: "scaleChanged" }
}
Component {
+ name: "QQuickScaleAnimator"
+ prototype: "QQuickAnimator"
+ exports: ["QtQuick/ScaleAnimator 2.2"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "QQuickScaleGrid"
prototype: "QObject"
Property { name: "left"; type: "int" }
@@ -3251,8 +3430,8 @@ Module {
name: "QQuickText"
defaultProperty: "data"
prototype: "QQuickImplicitSizeItem"
- exports: ["QtQuick/Text 2.0"]
- exportMetaObjectRevisions: [0]
+ exports: ["QtQuick/Text 2.0", "QtQuick/Text 2.2"]
+ exportMetaObjectRevisions: [0, 2]
Enum {
name: "HAlignment"
values: {
@@ -3356,6 +3535,7 @@ Module {
Property { name: "minimumPointSize"; type: "int" }
Property { name: "fontSizeMode"; type: "FontSizeMode" }
Property { name: "renderType"; type: "RenderType" }
+ Property { name: "hoveredLink"; revision: 2; type: "string"; isReadonly: true }
Signal {
name: "textChanged"
Parameter { name: "text"; type: "string" }
@@ -3365,6 +3545,11 @@ Module {
Parameter { name: "link"; type: "string" }
}
Signal {
+ name: "linkHovered"
+ revision: 2
+ Parameter { name: "link"; type: "string" }
+ }
+ Signal {
name: "fontChanged"
Parameter { name: "font"; type: "QFont" }
}
@@ -3408,8 +3593,12 @@ Module {
name: "QQuickTextEdit"
defaultProperty: "data"
prototype: "QQuickImplicitSizeItem"
- exports: ["QtQuick/TextEdit 2.0", "QtQuick/TextEdit 2.1"]
- exportMetaObjectRevisions: [0, 1]
+ exports: [
+ "QtQuick/TextEdit 2.0",
+ "QtQuick/TextEdit 2.1",
+ "QtQuick/TextEdit 2.2"
+ ]
+ exportMetaObjectRevisions: [0, 1, 2]
Enum {
name: "HAlignment"
values: {
@@ -3503,6 +3692,7 @@ Module {
isReadonly: true
isPointer: true
}
+ Property { name: "hoveredLink"; revision: 2; type: "string"; isReadonly: true }
Signal { name: "contentSizeChanged" }
Signal {
name: "colorChanged"
@@ -3569,6 +3759,11 @@ Module {
name: "linkActivated"
Parameter { name: "link"; type: "string" }
}
+ Signal {
+ name: "linkHovered"
+ revision: 2
+ Parameter { name: "link"; type: "string" }
+ }
Method { name: "selectAll" }
Method { name: "selectWord" }
Method {
@@ -3599,6 +3794,11 @@ Module {
Parameter { name: "end"; type: "int" }
}
Method {
+ name: "append"
+ revision: 2
+ Parameter { name: "text"; type: "string" }
+ }
+ Method {
name: "positionToRectangle"
type: "QRectF"
Parameter { type: "int" }
@@ -3812,7 +4012,7 @@ Module {
}
Method {
name: "positionAt"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "positionToRectangle"
@@ -3877,6 +4077,17 @@ Module {
Property { name: "y"; type: "double" }
}
Component {
+ name: "QQuickUniformAnimator"
+ prototype: "QQuickAnimator"
+ exports: ["QtQuick/UniformAnimator 2.2"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "uniform"; type: "string" }
+ Signal {
+ name: "uniformChanged"
+ Parameter { type: "string" }
+ }
+ }
+ Component {
name: "QQuickVector3dAnimation"
prototype: "QQuickPropertyAnimation"
exports: ["QtQuick/Vector3dAnimation 2.0"]
@@ -3933,10 +4144,22 @@ Module {
}
Method {
name: "sendMessage"
- Parameter { type: "QQmlV8Function"; isPointer: true }
+ Parameter { type: "QQmlV4Function"; isPointer: true }
}
}
Component {
+ name: "QQuickXAnimator"
+ prototype: "QQuickAnimator"
+ exports: ["QtQuick/XAnimator 2.2"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "QQuickYAnimator"
+ prototype: "QQuickAnimator"
+ exports: ["QtQuick/YAnimator 2.2"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "QRegExpValidator"
prototype: "QValidator"
exports: ["QtQuick/RegExpValidator 2.0"]
@@ -4079,7 +4302,8 @@ Module {
"AlignTop": 32,
"AlignBottom": 64,
"AlignVCenter": 128,
- "AlignVertical_Mask": 224,
+ "AlignBaseline": 256,
+ "AlignVertical_Mask": 480,
"AlignCenter": 132
}
}
@@ -4107,6 +4331,7 @@ Module {
"Desktop": 17,
"SubWindow": 18,
"ForeignWindow": 33,
+ "CoverWindow": 65,
"WindowType_Mask": 255,
"MSWindowsFixedSizeDialogHint": 256,
"MSWindowsOwnDC": 512,
@@ -4150,6 +4375,7 @@ Module {
"Desktop": 17,
"SubWindow": 18,
"ForeignWindow": 33,
+ "CoverWindow": 65,
"WindowType_Mask": 255,
"MSWindowsFixedSizeDialogHint": 256,
"MSWindowsOwnDC": 512,
@@ -4199,6 +4425,15 @@ Module {
}
}
Enum {
+ name: "ApplicationState"
+ values: {
+ "ApplicationSuspended": 0,
+ "ApplicationHidden": 1,
+ "ApplicationInactive": 2,
+ "ApplicationActive": 4
+ }
+ }
+ Enum {
name: "ScreenOrientation"
values: {
"PrimaryOrientation": 0,
@@ -4785,6 +5020,13 @@ Module {
"Key_TouchpadToggle": 16777488,
"Key_TouchpadOn": 16777489,
"Key_TouchpadOff": 16777490,
+ "Key_MicMute": 16777491,
+ "Key_Red": 16777492,
+ "Key_Green": 16777493,
+ "Key_Yellow": 16777494,
+ "Key_Blue": 16777495,
+ "Key_ChannelUp": 16777496,
+ "Key_ChannelDown": 16777497,
"Key_MediaLast": 16842751,
"Key_Select": 16842752,
"Key_Yes": 16842753,
@@ -4987,7 +5229,8 @@ Module {
"SystemLocaleShortDate": 4,
"SystemLocaleLongDate": 5,
"DefaultLocaleShortDate": 6,
- "DefaultLocaleLongDate": 7
+ "DefaultLocaleLongDate": 7,
+ "RFC2822Date": 8
}
}
Enum {
@@ -4995,7 +5238,8 @@ Module {
values: {
"LocalTime": 0,
"UTC": 1,
- "OffsetFromUTC": 2
+ "OffsetFromUTC": 2,
+ "TimeZone": 3
}
}
Enum {
@@ -5366,6 +5610,14 @@ Module {
"VeryCoarseTimer": 2
}
}
+ Enum {
+ name: "ScrollPhase"
+ values: {
+ "ScrollBegin": 1,
+ "ScrollUpdate": 2,
+ "ScrollEnd": 3
+ }
+ }
}
Component { name: "QEasingCurve"; prototype: "QQmlEasingValueType" }
}
diff --git a/src/imports/settings/plugins.qmltypes b/src/imports/settings/plugins.qmltypes
index 290c4c5570..87503fbda5 100644
--- a/src/imports/settings/plugins.qmltypes
+++ b/src/imports/settings/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable Qt.labs.settings 1.0'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable Qt.labs.settings 1.0'
Module {
Component {
diff --git a/src/imports/testlib/plugins.qmltypes b/src/imports/testlib/plugins.qmltypes
index 2865812eb2..94203df4dc 100644
--- a/src/imports/testlib/plugins.qmltypes
+++ b/src/imports/testlib/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable QtTest 1.0'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtTest 1.0'
Module {
Component {
@@ -147,7 +148,7 @@ Module {
Method { name: "finishTestFunction" }
Method {
name: "stringify"
- Parameter { name: "args"; type: "QQmlV8Function"; isPointer: true }
+ Parameter { name: "args"; type: "QQmlV4Function"; isPointer: true }
}
Method {
name: "fail"
diff --git a/src/imports/widgets/plugins.qmltypes b/src/imports/widgets/plugins.qmltypes
index 9e73330c12..a67443c5b7 100644
--- a/src/imports/widgets/plugins.qmltypes
+++ b/src/imports/widgets/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable QtQuick.PrivateWidgets 1.0'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.PrivateWidgets 1.1'
Module {
Component {
@@ -11,6 +12,11 @@ Module {
prototype: "QQuickAbstractDialog"
Property { name: "showAlphaChannel"; type: "bool" }
Property { name: "color"; type: "QColor" }
+ Property { name: "currentColor"; type: "QColor" }
+ Property { name: "currentHue"; type: "double"; isReadonly: true }
+ Property { name: "currentSaturation"; type: "double"; isReadonly: true }
+ Property { name: "currentLightness"; type: "double"; isReadonly: true }
+ Property { name: "currentAlpha"; type: "double"; isReadonly: true }
Signal { name: "selectionAccepted" }
Method {
name: "setVisible"
@@ -29,6 +35,10 @@ Module {
Parameter { name: "arg"; type: "QColor" }
}
Method {
+ name: "setCurrentColor"
+ Parameter { name: "currentColor"; type: "QColor" }
+ }
+ Method {
name: "setShowAlphaChannel"
Parameter { name: "arg"; type: "bool" }
}
@@ -50,6 +60,22 @@ Module {
Signal { name: "rejected" }
Method { name: "open" }
Method { name: "close" }
+ Method {
+ name: "setX"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setY"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setWidth"
+ Parameter { name: "arg"; type: "int" }
+ }
+ Method {
+ name: "setHeight"
+ Parameter { name: "arg"; type: "int" }
+ }
}
Component {
name: "QQuickAbstractFileDialog"
@@ -99,6 +125,163 @@ Module {
}
}
Component {
+ name: "QQuickAbstractFontDialog"
+ prototype: "QQuickAbstractDialog"
+ Property { name: "scalableFonts"; type: "bool" }
+ Property { name: "nonScalableFonts"; type: "bool" }
+ Property { name: "monospacedFonts"; type: "bool" }
+ Property { name: "proportionalFonts"; type: "bool" }
+ Property { name: "font"; type: "QFont" }
+ Signal { name: "selectionAccepted" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setModality"
+ Parameter { name: "m"; type: "Qt::WindowModality" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "t"; type: "string" }
+ }
+ Method {
+ name: "setFont"
+ Parameter { name: "arg"; type: "QFont" }
+ }
+ Method {
+ name: "setScalableFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setNonScalableFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setMonospacedFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ Method {
+ name: "setProportionalFonts"
+ Parameter { name: "arg"; type: "bool" }
+ }
+ }
+ Component {
+ name: "QQuickAbstractMessageDialog"
+ prototype: "QQuickAbstractDialog"
+ exports: ["QtQuick.PrivateWidgets/QtMessageDialog 1.1"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Icon"
+ values: {
+ "NoIcon": 0,
+ "Information": 1,
+ "Warning": 2,
+ "Critical": 3,
+ "Question": 4
+ }
+ }
+ Enum {
+ name: "StandardButton"
+ values: {
+ "NoButton": 0,
+ "Ok": 1024,
+ "Save": 2048,
+ "SaveAll": 4096,
+ "Open": 8192,
+ "Yes": 16384,
+ "YesToAll": 32768,
+ "No": 65536,
+ "NoToAll": 131072,
+ "Abort": 262144,
+ "Retry": 524288,
+ "Ignore": 1048576,
+ "Close": 2097152,
+ "Cancel": 4194304,
+ "Discard": 8388608,
+ "Help": 16777216,
+ "Apply": 33554432,
+ "Reset": 67108864,
+ "RestoreDefaults": 134217728
+ }
+ }
+ Enum {
+ name: "StandardButtons"
+ values: {
+ "NoButton": 0,
+ "Ok": 1024,
+ "Save": 2048,
+ "SaveAll": 4096,
+ "Open": 8192,
+ "Yes": 16384,
+ "YesToAll": 32768,
+ "No": 65536,
+ "NoToAll": 131072,
+ "Abort": 262144,
+ "Retry": 524288,
+ "Ignore": 1048576,
+ "Close": 2097152,
+ "Cancel": 4194304,
+ "Discard": 8388608,
+ "Help": 16777216,
+ "Apply": 33554432,
+ "Reset": 67108864,
+ "RestoreDefaults": 134217728
+ }
+ }
+ Property { name: "text"; type: "string" }
+ Property { name: "informativeText"; type: "string" }
+ Property { name: "detailedText"; type: "string" }
+ Property { name: "icon"; type: "Icon" }
+ Property { name: "standardIconSource"; type: "QUrl"; isReadonly: true }
+ Property { name: "standardButtons"; type: "StandardButtons" }
+ Property { name: "clickedButton"; type: "StandardButton"; isReadonly: true }
+ Signal { name: "buttonClicked" }
+ Signal { name: "discard" }
+ Signal { name: "help" }
+ Signal { name: "yes" }
+ Signal { name: "no" }
+ Signal { name: "apply" }
+ Signal { name: "reset" }
+ Method {
+ name: "setVisible"
+ Parameter { name: "v"; type: "bool" }
+ }
+ Method {
+ name: "setTitle"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setInformativeText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setDetailedText"
+ Parameter { name: "arg"; type: "string" }
+ }
+ Method {
+ name: "setIcon"
+ Parameter { name: "icon"; type: "Icon" }
+ }
+ Method {
+ name: "setStandardButtons"
+ Parameter { name: "buttons"; type: "StandardButtons" }
+ }
+ Method {
+ name: "click"
+ Parameter { name: "button"; type: "QMessageDialogOptions::StandardButton" }
+ Parameter { type: "QMessageDialogOptions::ButtonRole" }
+ }
+ Method {
+ name: "click"
+ Parameter { name: "button"; type: "QQuickAbstractMessageDialog::StandardButton" }
+ }
+ }
+ Component {
name: "QQuickQColorDialog"
prototype: "QQuickAbstractColorDialog"
exports: ["QtQuick.PrivateWidgets/QtColorDialog 1.0"]
@@ -110,4 +293,10 @@ Module {
exports: ["QtQuick.PrivateWidgets/QtFileDialog 1.0"]
exportMetaObjectRevisions: [0]
}
+ Component {
+ name: "QQuickQFontDialog"
+ prototype: "QQuickAbstractFontDialog"
+ exports: ["QtQuick.PrivateWidgets/QtFontDialog 1.1"]
+ exportMetaObjectRevisions: [0]
+ }
}
diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp
index 059044e9ad..31c7899027 100644
--- a/src/imports/window/plugin.cpp
+++ b/src/imports/window/plugin.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
/*!
- \qmlmodule QtQuick.Window 2
+ \qmlmodule QtQuick.Window 2.1
\title Qt Quick Window QML Types
\ingroup qmlmodules
\brief Provides QML types for window management
diff --git a/src/imports/window/plugins.qmltypes b/src/imports/window/plugins.qmltypes
index 59e69114e1..1e3577acda 100644
--- a/src/imports/window/plugins.qmltypes
+++ b/src/imports/window/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump QtQuick.Window 2.1 -notrelocatable'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.Window 2.0'
Module {
Component {
@@ -35,11 +36,13 @@ Module {
Property { name: "desktopAvailableWidth"; revision: 1; type: "int"; isReadonly: true }
Property { name: "desktopAvailableHeight"; revision: 1; type: "int"; isReadonly: true }
Property { name: "logicalPixelDensity"; revision: 1; type: "double"; isReadonly: true }
+ Property { name: "pixelDensity"; revision: 2; type: "double"; isReadonly: true }
Property { name: "primaryOrientation"; type: "Qt::ScreenOrientation"; isReadonly: true }
Property { name: "orientation"; type: "Qt::ScreenOrientation"; isReadonly: true }
Signal { name: "nameChanged"; revision: 1 }
Signal { name: "desktopGeometryChanged"; revision: 1 }
Signal { name: "logicalPixelDensityChanged"; revision: 1 }
+ Signal { name: "pixelDensityChanged"; revision: 2 }
Method {
name: "angleBetween"
type: "int"
@@ -51,8 +54,8 @@ Module {
name: "QQuickWindow"
defaultProperty: "data"
prototype: "QWindow"
- exports: ["QtQuick.Window/Window 2.0", "QtQuick.Window/Window 2.1"]
- exportMetaObjectRevisions: [0, 1]
+ exports: ["QtQuick.Window/Window 2.0"]
+ exportMetaObjectRevisions: [0]
Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "color"; type: "QColor" }
Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }
@@ -83,6 +86,13 @@ Module {
Method { name: "releaseResources" }
}
Component {
+ name: "QQuickWindowQmlImpl"
+ defaultProperty: "data"
+ prototype: "QQuickWindow"
+ exports: ["QtQuick.Window/Window 2.1"]
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
name: "QWindow"
prototype: "QObject"
Enum {
@@ -103,14 +113,14 @@ Module {
Property { name: "y"; type: "int" }
Property { name: "width"; type: "int" }
Property { name: "height"; type: "int" }
- Property { name: "minimumWidth"; revision: 1; type: "int" }
- Property { name: "minimumHeight"; revision: 1; type: "int" }
- Property { name: "maximumWidth"; revision: 1; type: "int" }
- Property { name: "maximumHeight"; revision: 1; type: "int" }
+ Property { name: "minimumWidth"; type: "int" }
+ Property { name: "minimumHeight"; type: "int" }
+ Property { name: "maximumWidth"; type: "int" }
+ Property { name: "maximumHeight"; type: "int" }
Property { name: "visible"; type: "bool" }
Property { name: "active"; revision: 1; type: "bool"; isReadonly: true }
Property { name: "visibility"; revision: 1; type: "Visibility" }
- Property { name: "contentOrientation"; revision: 1; type: "Qt::ScreenOrientation" }
+ Property { name: "contentOrientation"; type: "Qt::ScreenOrientation" }
Property { name: "opacity"; revision: 1; type: "double" }
Signal {
name: "screenChanged"
@@ -142,22 +152,18 @@ Module {
}
Signal {
name: "minimumWidthChanged"
- revision: 1
Parameter { name: "arg"; type: "int" }
}
Signal {
name: "minimumHeightChanged"
- revision: 1
Parameter { name: "arg"; type: "int" }
}
Signal {
name: "maximumWidthChanged"
- revision: 1
Parameter { name: "arg"; type: "int" }
}
Signal {
name: "maximumHeightChanged"
- revision: 1
Parameter { name: "arg"; type: "int" }
}
Signal {
@@ -172,7 +178,6 @@ Module {
Signal { name: "activeChanged"; revision: 1 }
Signal {
name: "contentOrientationChanged"
- revision: 1
Parameter { name: "orientation"; type: "Qt::ScreenOrientation" }
}
Signal {
@@ -220,26 +225,23 @@ Module {
}
Method {
name: "setMinimumWidth"
- revision: 1
Parameter { name: "w"; type: "int" }
}
Method {
name: "setMinimumHeight"
- revision: 1
Parameter { name: "h"; type: "int" }
}
Method {
name: "setMaximumWidth"
- revision: 1
Parameter { name: "w"; type: "int" }
}
Method {
name: "setMaximumHeight"
- revision: 1
Parameter { name: "h"; type: "int" }
}
Method {
name: "alert"
+ revision: 1
Parameter { name: "msec"; type: "int" }
}
}
diff --git a/src/imports/xmllistmodel/plugins.qmltypes b/src/imports/xmllistmodel/plugins.qmltypes
index d951d07719..0978237027 100644
--- a/src/imports/xmllistmodel/plugins.qmltypes
+++ b/src/imports/xmllistmodel/plugins.qmltypes
@@ -3,7 +3,8 @@ import QtQuick.tooling 1.1
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
-// This file was auto-generated with the command 'qmlplugindump -notrelocatable QtQuick.XmlListModel 2.0'.
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.XmlListModel 2.0'
Module {
Component {
diff --git a/src/particles/particles.pri b/src/particles/particles.pri
index b391050a58..af71634ec6 100644
--- a/src/particles/particles.pri
+++ b/src/particles/particles.pri
@@ -68,7 +68,12 @@ OTHER_FILES += \
$$PWD/shaders/customparticle.vert \
$$PWD/shaders/customparticle.frag \
$$PWD/shaders/imageparticle.vert \
- $$PWD/shaders/imageparticle.frag
+ $$PWD/shaders/imageparticle.frag \
+ $$PWD/shaders/customparticletemplate_core.vert \
+ $$PWD/shaders/customparticle_core.vert \
+ $$PWD/shaders/customparticle_core.frag \
+ $$PWD/shaders/imageparticle_core.vert \
+ $$PWD/shaders/imageparticle_core.frag
RESOURCES += \
$$PWD/particles.qrc
diff --git a/src/particles/particles.qrc b/src/particles/particles.qrc
index 689a5fb4e9..ad44cf406e 100644
--- a/src/particles/particles.qrc
+++ b/src/particles/particles.qrc
@@ -11,5 +11,10 @@
<file>shaders/customparticletemplate.vert</file>
<file>shaders/imageparticle.frag</file>
<file>shaders/imageparticle.vert</file>
+ <file>shaders/customparticle_core.frag</file>
+ <file>shaders/customparticle_core.vert</file>
+ <file>shaders/customparticletemplate_core.vert</file>
+ <file>shaders/imageparticle_core.frag</file>
+ <file>shaders/imageparticle_core.vert</file>
</qresource>
</RCC>
diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp
index 71d58ae391..a3b41d0eb2 100644
--- a/src/particles/qquickcustomparticle.cpp
+++ b/src/particles/qquickcustomparticle.cpp
@@ -276,11 +276,17 @@ QQuickShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickShaderEffec
QSGShaderSourceBuilder builder;
if (s.sourceCode[Key::FragmentShader].isEmpty()) {
builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.frag"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
s.sourceCode[Key::FragmentShader] = builder.source();
builder.clear();
}
builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticletemplate.vert"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
if (s.sourceCode[Key::VertexShader].isEmpty())
builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.vert"));
s.sourceCode[Key::VertexShader] = builder.source() + s.sourceCode[Key::VertexShader];
diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp
index dfe4524c7c..0bea3a87af 100644
--- a/src/particles/qquickimageparticle.cpp
+++ b/src/particles/qquickimageparticle.cpp
@@ -59,14 +59,8 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_OPENGL_ES_2
-#define SHADER_DEFINES "#version 120\n"
-#else
-#define SHADER_DEFINES ""
-#endif
-
#if defined(Q_OS_BLACKBERRY)
-#define SHADER_PLATFORM_DEFINES "#define Q_OS_BLACKBERRY\n"
+#define SHADER_PLATFORM_DEFINES "Q_OS_BLACKBERRY\n"
#else
#define SHADER_PLATFORM_DEFINES
#endif
@@ -107,15 +101,26 @@ public:
{
QSGShaderSourceBuilder builder;
- builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
- builder.appendSource(QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("TABLE"));
+ builder.addDefinition(QByteArrayLiteral("DEFORM"));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
+
m_vertex_code = builder.source();
builder.clear();
- builder.appendSource(QByteArray(SHADER_DEFINES));
- builder.appendSource(QByteArray("#define TABLE\n#define DEFORM\n#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("TABLE"));
+ builder.addDefinition(QByteArrayLiteral("DEFORM"));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
@@ -174,15 +179,23 @@ public:
{
QSGShaderSourceBuilder builder;
- builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
- builder.appendSource(QByteArray("#define DEFORM\n#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("DEFORM"));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_vertex_code = builder.source();
builder.clear();
- builder.appendSource(QByteArray(SHADER_DEFINES));
- builder.appendSource(QByteArray("#define DEFORM\n#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("DEFORM"));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
@@ -230,15 +243,27 @@ public:
{
QSGShaderSourceBuilder builder;
- builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
- builder.appendSource(QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("SPRITE"));
+ builder.addDefinition(QByteArrayLiteral("TABLE"));
+ builder.addDefinition(QByteArrayLiteral("DEFORM"));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_vertex_code = builder.source();
builder.clear();
- builder.appendSource(QByteArray(SHADER_DEFINES));
- builder.appendSource(QByteArray("#define SPRITE\n#define TABLE\n#define DEFORM\n#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("SPRITE"));
+ builder.addDefinition(QByteArrayLiteral("TABLE"));
+ builder.addDefinition(QByteArrayLiteral("DEFORM"));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
@@ -299,15 +324,21 @@ public:
{
QSGShaderSourceBuilder builder;
- builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
- builder.appendSource(QByteArray("#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_vertex_code = builder.source();
builder.clear();
- builder.appendSource(QByteArray(SHADER_DEFINES));
- builder.appendSource(QByteArray("#define COLOR\n"));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+ builder.addDefinition(QByteArrayLiteral("COLOR"));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
@@ -370,13 +401,19 @@ public:
{
QSGShaderSourceBuilder builder;
- builder.appendSource(QByteArray(SHADER_DEFINES) + QByteArray(SHADER_PLATFORM_DEFINES));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.vert"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_vertex_code = builder.source();
builder.clear();
- builder.appendSource(QByteArray(SHADER_DEFINES));
builder.appendSourceFile(QStringLiteral(":/particles/shaders/imageparticle.frag"));
+ builder.addDefinition(QByteArray(SHADER_PLATFORM_DEFINES));
+#if defined(QT_OPENGL_ES_2)
+ builder.removeVersion();
+#endif
m_fragment_code = builder.source();
Q_ASSERT(!m_vertex_code.isNull());
diff --git a/src/particles/shaders/customparticle.frag b/src/particles/shaders/customparticle.frag
index c1c15ecb0c..64007029f7 100644
--- a/src/particles/shaders/customparticle.frag
+++ b/src/particles/shaders/customparticle.frag
@@ -1,3 +1,5 @@
+#version 120
+
varying highp vec2 qt_TexCoord0;
uniform sampler2D source;
diff --git a/src/particles/shaders/customparticle_core.frag b/src/particles/shaders/customparticle_core.frag
new file mode 100644
index 0000000000..699c834605
--- /dev/null
+++ b/src/particles/shaders/customparticle_core.frag
@@ -0,0 +1,13 @@
+#version 150
+
+in vec2 qt_TexCoord0;
+
+out vec4 fragColor;
+
+uniform sampler2D source;
+uniform float qt_Opacity;
+
+void main()
+{
+ fragColor = texture(source, qt_TexCoord0) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/particles/shaders/customparticle_core.vert b/src/particles/shaders/customparticle_core.vert
new file mode 100644
index 0000000000..b99f73ea53
--- /dev/null
+++ b/src/particles/shaders/customparticle_core.vert
@@ -0,0 +1,4 @@
+void main()
+{
+ defaultMain();
+} \ No newline at end of file
diff --git a/src/particles/shaders/customparticletemplate.vert b/src/particles/shaders/customparticletemplate.vert
index c482c4207b..eef8458a85 100644
--- a/src/particles/shaders/customparticletemplate.vert
+++ b/src/particles/shaders/customparticletemplate.vert
@@ -1,3 +1,5 @@
+#version 120
+
attribute highp vec2 qt_ParticlePos;
attribute highp vec2 qt_ParticleTex;
attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
diff --git a/src/particles/shaders/customparticletemplate_core.vert b/src/particles/shaders/customparticletemplate_core.vert
new file mode 100644
index 0000000000..15d38e797c
--- /dev/null
+++ b/src/particles/shaders/customparticletemplate_core.vert
@@ -0,0 +1,28 @@
+#version 150 core
+
+in vec2 qt_ParticlePos;
+in vec2 qt_ParticleTex;
+in vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize
+in vec4 qt_ParticleVec; // x,y = constant velocity, z,w = acceleration
+in float qt_ParticleR;
+
+out vec2 qt_TexCoord0;
+
+uniform mat4 qt_Matrix;
+uniform float qt_Timestamp;
+
+void defaultMain()
+{
+ qt_TexCoord0 = qt_ParticleTex;
+ float size = qt_ParticleData.z;
+ float endSize = qt_ParticleData.w;
+ float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y;
+ float currentSize = mix(size, endSize, t * t);
+ if (t < 0. || t > 1.)
+ currentSize = 0.;
+ vec2 pos = qt_ParticlePos
+ - currentSize / 2. + currentSize * qt_ParticleTex // adjust size
+ + qt_ParticleVec.xy * t * qt_ParticleData.y // apply velocity vector..
+ + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.);
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+}
diff --git a/src/particles/shaders/imageparticle.frag b/src/particles/shaders/imageparticle.frag
index 699b90babf..92795a5381 100644
--- a/src/particles/shaders/imageparticle.frag
+++ b/src/particles/shaders/imageparticle.frag
@@ -1,3 +1,5 @@
+#version 120
+
uniform sampler2D _qt_texture;
uniform lowp float qt_Opacity;
diff --git a/src/particles/shaders/imageparticle.vert b/src/particles/shaders/imageparticle.vert
index 9e607a7477..377f831686 100644
--- a/src/particles/shaders/imageparticle.vert
+++ b/src/particles/shaders/imageparticle.vert
@@ -1,3 +1,5 @@
+#version 120
+
#if defined(DEFORM)
attribute highp vec4 vPosTex;
#else
diff --git a/src/particles/shaders/imageparticle_core.frag b/src/particles/shaders/imageparticle_core.frag
new file mode 100644
index 0000000000..3ac8c8d34e
--- /dev/null
+++ b/src/particles/shaders/imageparticle_core.frag
@@ -0,0 +1,44 @@
+#version 150 core
+
+#if defined(SPRITE)
+in vec4 fTexS;
+#elif defined(DEFORM)
+in vec2 fTex;
+#endif
+
+#if defined(COLOR)
+in vec4 fColor;
+#else
+in float fFade;
+#endif
+
+#if defined(TABLE)
+in vec2 tt;
+uniform sampler2D colortable;
+#endif
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float qt_Opacity;
+
+void main()
+{
+#if defined(SPRITE)
+ fragColor = mix(texture(_qt_texture, fTexS.xy), texture(_qt_texture, fTexS.zw), tt.y)
+ * fColor
+ * texture(colortable, tt)
+ * qt_Opacity;
+#elif defined(TABLE)
+ fragColor = texture(_qt_texture, fTex)
+ * fColor
+ * texture(colortable, tt)
+ * qt_Opacity;
+#elif defined(DEFORM)
+ fragColor = texture(_qt_texture, fTex) * fColor * qt_Opacity;
+#elif defined(COLOR)
+ fragColor = texture(_qt_texture, gl_PointCoord) * fColor * qt_Opacity;
+#else
+ fragColor = texture(_qt_texture, gl_PointCoord) * fFade * qt_Opacity;
+#endif
+} \ No newline at end of file
diff --git a/src/particles/shaders/imageparticle_core.vert b/src/particles/shaders/imageparticle_core.vert
new file mode 100644
index 0000000000..ed9a918eb3
--- /dev/null
+++ b/src/particles/shaders/imageparticle_core.vert
@@ -0,0 +1,145 @@
+#version 150 core
+
+#if defined(DEFORM)
+in vec4 vPosTex;
+#else
+in vec2 vPos;
+#endif
+
+in vec4 vData; // x = time, y = lifeSpan, z = size, w = endSize
+in vec4 vVec; // x,y = constant velocity, z,w = acceleration
+uniform float entry;
+
+#if defined(COLOR)
+in vec4 vColor;
+#endif
+
+#if defined(DEFORM)
+in vec4 vDeformVec; // x,y x unit vector; z,w = y unit vector
+in vec3 vRotation; // x = radians of rotation, y = rotation velocity, z = bool autoRotate
+#endif
+
+#if defined(SPRITE)
+in vec3 vAnimData; // w,h(premultiplied of anim), interpolation progress
+in vec4 vAnimPos; // x,y, x,y (two frames for interpolation)
+#endif
+
+uniform mat4 qt_Matrix;
+uniform float timestamp;
+
+#if defined(TABLE)
+out vec2 tt;//y is progress if Sprite mode
+uniform float sizetable[64];
+uniform float opacitytable[64];
+#endif
+
+#if defined(SPRITE)
+out vec4 fTexS;
+#elif defined(DEFORM)
+out vec2 fTex;
+#endif
+
+#if defined(COLOR)
+out vec4 fColor;
+#else
+out float fFade;
+#endif
+
+
+void main()
+{
+ float t = (timestamp - vData.x) / vData.y;
+ if (t < 0. || t > 1.) {
+#if defined(DEFORM)
+ gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);
+#else
+ gl_PointSize = 0.;
+#endif
+ } else {
+#if defined(SPRITE)
+ tt.y = vAnimData.z;
+
+ // Calculate frame location in texture
+ fTexS.xy = vAnimPos.xy + vPosTex.zw * vAnimData.xy;
+
+ // Next frame is also passed, for interpolation
+ fTexS.zw = vAnimPos.zw + vPosTex.zw * vAnimData.xy;
+
+#elif defined(DEFORM)
+ fTex = vPosTex.zw;
+#endif
+ float currentSize = mix(vData.z, vData.w, t * t);
+#if defined (Q_OS_BLACKBERRY)
+ float fade = 1.;
+#else
+ float fade = 1.;
+#endif
+ float fadeIn = min(t * 10., 1.);
+ float fadeOut = 1. - clamp((t - 0.75) * 4.,0., 1.);
+
+#if defined(TABLE)
+ currentSize = currentSize * sizetable[int(floor(t*64.))];
+ fade = fade * opacitytable[int(floor(t*64.))];
+#endif
+
+ if (entry == 1.)
+ fade = fade * fadeIn * fadeOut;
+ else if (entry == 2.)
+ currentSize = currentSize * fadeIn * fadeOut;
+
+ if (currentSize <= 0.) {
+#if defined(DEFORM)
+ gl_Position = qt_Matrix * vec4(vPosTex.x, vPosTex.y, 0., 1.);
+#else
+ gl_PointSize = 0.;
+#endif
+ } else {
+ if (currentSize < 3.) // Sizes too small look jittery as they move
+ currentSize = 3.;
+
+ vec2 pos;
+#if defined(DEFORM)
+ float rotation = vRotation.x + vRotation.y * t * vData.y;
+ if (vRotation.z == 1.0) {
+ vec2 curVel = vVec.zw * t * vData.y + vVec.xy;
+ if (length(curVel) > 0.)
+ rotation += atan(curVel.y, curVel.x);
+ }
+ vec2 trigCalcs = vec2(cos(rotation), sin(rotation));
+ vec4 deform = vDeformVec * currentSize * (vPosTex.zzww - 0.5);
+ vec4 rotatedDeform = deform.xxzz * trigCalcs.xyxy;
+ rotatedDeform = rotatedDeform + (deform.yyww * trigCalcs.yxyx * vec4(-1.,1.,-1.,1.));
+ /* The readable version:
+ vec2 xDeform = vDeformVec.xy * currentSize * (vTex.x-0.5);
+ vec2 yDeform = vDeformVec.zw * currentSize * (vTex.y-0.5);
+ vec2 xRotatedDeform;
+ xRotatedDeform.x = trigCalcs.x*xDeform.x - trigCalcs.y*xDeform.y;
+ xRotatedDeform.y = trigCalcs.y*xDeform.x + trigCalcs.x*xDeform.y;
+ vec2 yRotatedDeform;
+ yRotatedDeform.x = trigCalcs.x*yDeform.x - trigCalcs.y*yDeform.y;
+ yRotatedDeform.y = trigCalcs.y*yDeform.x + trigCalcs.x*yDeform.y;
+ */
+ pos = vPosTex.xy
+ + rotatedDeform.xy
+ + rotatedDeform.zw
+ + vVec.xy * t * vData.y // apply velocity
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.); // apply acceleration
+#else
+ pos = vPos
+ + vVec.xy * t * vData.y // apply velocity vector..
+ + 0.5 * vVec.zw * pow(t * vData.y, 2.);
+ gl_PointSize = currentSize;
+#endif
+ gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1);
+
+#if defined(COLOR)
+ fColor = vColor * fade;
+#else
+ fFade = fade;
+#endif
+#if defined(TABLE)
+ tt.x = t;
+#endif
+ }
+ }
+} \ No newline at end of file
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index c2f2feb6bf..c16dd5daea 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -1211,6 +1211,7 @@ JSCodeGen::JSCodeGen(QQmlEnginePrivate *enginePrivate, const QString &fileName,
{
_module = jsModule;
_module->setFileName(fileName);
+ _fileNameIsUrl = true;
}
void JSCodeGen::beginContextScope(const JSCodeGen::ObjectIdMapping &objectIds, QQmlPropertyCache *contextObject)
@@ -1236,7 +1237,11 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<AST::N
Q_ASSERT(node != qmlRoot);
AST::FunctionDeclaration *function = AST::cast<AST::FunctionDeclaration*>(node);
- scan.enterEnvironment(node, function ? FunctionCode : QmlBinding);
+ if (function)
+ scan.enterQmlFunction(function);
+ else
+ scan.enterEnvironment(node, QmlBinding);
+
scan(function ? function->body : node);
scan.leaveEnvironment();
}
@@ -1351,7 +1356,6 @@ V4IR::Expr *JSCodeGen::member(V4IR::Expr *base, const QString *name)
V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col)
{
- V4IR::Expr *result = 0;
// Implement QML lookup semantics in the current file context.
//
// Note: We do not check if properties of the qml scope object or context object
@@ -1366,53 +1370,49 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
// Look for IDs first.
foreach (const IdMapping &mapping, _idObjects)
if (name == mapping.name) {
- result = _block->QML_CONTEXT_MEMBER(_block->NAME(V4IR::Name::builtin_qml_id_scope, line, col),
- _function->newString(mapping.name), mapping.idIndex);
- break;
+ _function->idObjectDependencies.insert(mapping.idIndex);
+ return _block->QML_CONTEXT_MEMBER(_block->NAME(V4IR::Name::builtin_qml_id_scope, line, col),
+ _function->newString(mapping.name), mapping.idIndex);
}
- if (!result) {
+ {
QQmlTypeNameCache::Result r = imports->query(name);
if (r.isValid()) {
- if (r.scriptIndex != -1) {
- result = subscript(_block->NAME(V4IR::Name::builtin_qml_imported_scripts_object, line, col), _block->CONST(V4IR::NumberType, r.scriptIndex));
- } else {
+ if (r.scriptIndex != -1)
+ return subscript(_block->NAME(V4IR::Name::builtin_qml_imported_scripts_object, line, col), _block->CONST(V4IR::NumberType, r.scriptIndex));
+ else
return 0; // TODO: We can't do fast lookup for these yet.
- }
}
}
- if (!result && _scopeObject) {
+ if (_scopeObject) {
bool propertyExistsButForceNameLookup = false;
QQmlPropertyData *pd = lookupQmlCompliantProperty(_scopeObject, name, &propertyExistsButForceNameLookup);
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
+ if (!pd->isConstant())
+ _function->scopeObjectDependencies.insert(pd);
int base = _block->newTemp();
move(_block->TEMP(base), _block->NAME(V4IR::Name::builtin_qml_scope_object, line, col));
- result = _block->QML_QOBJECT_PROPERTY(_block->TEMP(base),
- _function->newString(name), pd);
+ return _block->QML_QOBJECT_PROPERTY(_block->TEMP(base), _function->newString(name), pd);
}
}
- if (!result && _contextObject) {
+ if (_contextObject) {
bool propertyExistsButForceNameLookup = false;
QQmlPropertyData *pd = lookupQmlCompliantProperty(_contextObject, name, &propertyExistsButForceNameLookup);
if (propertyExistsButForceNameLookup)
return 0;
if (pd) {
+ if (!pd->isConstant())
+ _function->contextObjectDependencies.insert(pd);
int base = _block->newTemp();
move(_block->TEMP(base), _block->NAME(V4IR::Name::builtin_qml_context_object, line, col));
- result = _block->QML_QOBJECT_PROPERTY(_block->TEMP(base),
- _function->newString(name), pd);
+ return _block->QML_QOBJECT_PROPERTY(_block->TEMP(base), _function->newString(name), pd);
}
}
- if (result) {
- _function->hasQmlDependencies = true;
- return result;
- }
-
// fall back to name lookup at run-time.
return 0;
}
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 640dad9c99..893abc9659 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -418,6 +418,7 @@ Codegen::Codegen(bool strict)
, _labelledStatement(0)
, _scopeAndFinally(0)
, _strictMode(strict)
+ , _fileNameIsUrl(false)
, hasError(false)
{
}
@@ -1182,7 +1183,7 @@ bool Codegen::visit(BinaryExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
return false;
V4IR::Expr* right = *expression(ast->right);
- if (! (left->asTemp() || left->asName() || left->asSubscript() || left->asMember())) {
+ if (!left->isLValue()) {
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
return false;
}
@@ -2291,11 +2292,11 @@ bool Codegen::visit(ForStatement *ast)
V4IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
V4IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- enterLoop(ast, forcond, forend, forstep);
-
statement(ast->initialiser);
_block->JUMP(forcond);
+ enterLoop(ast, forcond, forend, forstep);
+
_block = forcond;
if (ast->condition)
condition(ast->condition, forbody, forend);
@@ -2431,11 +2432,11 @@ bool Codegen::visit(LocalForStatement *ast)
V4IR::BasicBlock *forstep = _function->newBasicBlock(forcond, exceptionHandler());
V4IR::BasicBlock *forend = _function->newBasicBlock(groupStartBlock(), exceptionHandler());
- enterLoop(ast, forcond, forend, forstep);
-
variableDeclarationList(ast->declarations);
_block->JUMP(forcond);
+ enterLoop(ast, forcond, forend, forstep);
+
_block = forcond;
if (ast->condition)
condition(ast->condition, forbody, forend);
@@ -2850,7 +2851,7 @@ void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail)
hasError = true;
QQmlError error;
- error.setUrl(QUrl::fromLocalFile(_module->fileName));
+ error.setUrl(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName));
error.setDescription(detail);
error.setLine(loc.startLine);
error.setColumn(loc.startColumn);
@@ -2864,7 +2865,7 @@ void Codegen::throwReferenceError(const SourceLocation &loc, const QString &deta
hasError = true;
QQmlError error;
- error.setUrl(QUrl::fromLocalFile(_module->fileName));
+ error.setUrl(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName));
error.setDescription(detail);
error.setLine(loc.startLine);
error.setColumn(loc.startColumn);
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index b20db26467..de22e8904b 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -460,6 +460,7 @@ protected:
QStack<V4IR::BasicBlock *> _exceptionHandlers;
bool _strictMode;
+ bool _fileNameIsUrl;
bool hasError;
QList<QQmlError> _errors;
@@ -476,6 +477,9 @@ protected:
void enterQmlScope(AST::Node *ast, const QString &name)
{ enterFunction(ast, name, /*formals*/0, /*body*/0, /*expr*/0, /*isExpression*/false); }
+ void enterQmlFunction(AST::FunctionDeclaration *ast)
+ { enterFunction(ast, false, false); }
+
protected:
using Visitor::visit;
using Visitor::endVisit;
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index b38c394bdc..cb17b86702 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -171,14 +171,10 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total
for (int i = 0; i < f->locals.size(); ++i)
registerString(*f->locals.at(i));
- if (f->hasQmlDependencies) {
- QQmlJS::V4IR::QmlDependenciesCollector depCollector;
-
- QSet<int> idObjectDeps;
- QSet<QQmlPropertyData*> contextPropertyDeps;
- QSet<QQmlPropertyData*> scopePropertyDeps;
-
- depCollector.run(f, &idObjectDeps, &contextPropertyDeps, &scopePropertyDeps);
+ if (f->hasQmlDependencies()) {
+ QSet<int> idObjectDeps = f->idObjectDependencies;
+ QSet<QQmlPropertyData*> contextPropertyDeps = f->contextObjectDependencies;
+ QSet<QQmlPropertyData*> scopePropertyDeps = f->scopeObjectDependencies;
if (!idObjectDeps.isEmpty())
qmlIdObjectDependenciesPerFunction.insert(f, idObjectDeps);
@@ -206,7 +202,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total
int qmlIdDepsCount = 0;
int qmlPropertyDepsCount = 0;
- if (f->hasQmlDependencies) {
+ if (f->hasQmlDependencies()) {
IdDependencyHash::ConstIterator idIt = qmlIdObjectDependenciesPerFunction.find(f);
if (idIt != qmlIdObjectDependenciesPerFunction.constEnd())
qmlIdDepsCount += idIt->count();
@@ -361,7 +357,7 @@ int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QQmlJS::V4
QSet<QQmlPropertyData*> qmlContextPropertyDeps;
QSet<QQmlPropertyData*> qmlScopePropertyDeps;
- if (irFunction->hasQmlDependencies) {
+ if (irFunction->hasQmlDependencies()) {
qmlIdObjectDeps = qmlIdObjectDependenciesPerFunction.value(irFunction);
qmlContextPropertyDeps = qmlContextPropertyDependenciesPerFunction.value(irFunction);
qmlScopePropertyDeps = qmlScopePropertyDependenciesPerFunction.value(irFunction);
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 9aaab2f105..9baf7f89ca 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -286,6 +286,7 @@ union Instr
int propertyIndex;
Param base;
Param result;
+ bool captureRequired;
};
struct instr_storeProperty {
MOTH_INSTR_HEADER
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index e49216b103..9d470c417d 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -99,72 +99,6 @@ QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int fu
}
namespace {
-class ConvertTemps: protected V4IR::StmtVisitor, protected V4IR::ExprVisitor
-{
- int _nextFreeStackSlot;
- QHash<V4IR::Temp, int> _stackSlotForTemp;
-
- void renumber(V4IR::Temp *t)
- {
- if (t->kind != V4IR::Temp::VirtualRegister)
- return;
-
- int stackSlot = _stackSlotForTemp.value(*t, -1);
- if (stackSlot == -1) {
- stackSlot = _nextFreeStackSlot++;
- _stackSlotForTemp[*t] = stackSlot;
- }
-
- t->kind = V4IR::Temp::StackSlot;
- t->index = stackSlot;
- }
-
-public:
- ConvertTemps()
- : _nextFreeStackSlot(0)
- {}
-
- void toStackSlots(V4IR::Function *function)
- {
- _stackSlotForTemp.reserve(function->tempCount);
-
- foreach (V4IR::BasicBlock *bb, function->basicBlocks)
- foreach (V4IR::Stmt *s, bb->statements)
- s->accept(this);
-
- function->tempCount = _nextFreeStackSlot;
- }
-
-protected:
- virtual void visitConst(V4IR::Const *) {}
- virtual void visitString(V4IR::String *) {}
- virtual void visitRegExp(V4IR::RegExp *) {}
- virtual void visitName(V4IR::Name *) {}
- virtual void visitTemp(V4IR::Temp *e) { renumber(e); }
- virtual void visitClosure(V4IR::Closure *) {}
- virtual void visitConvert(V4IR::Convert *e) { e->expr->accept(this); }
- virtual void visitUnop(V4IR::Unop *e) { e->expr->accept(this); }
- virtual void visitBinop(V4IR::Binop *e) { e->left->accept(this); e->right->accept(this); }
- virtual void visitCall(V4IR::Call *e) {
- e->base->accept(this);
- for (V4IR::ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
- virtual void visitNew(V4IR::New *e) {
- e->base->accept(this);
- for (V4IR::ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
- virtual void visitSubscript(V4IR::Subscript *e) { e->base->accept(this); e->index->accept(this); }
- virtual void visitMember(V4IR::Member *e) { e->base->accept(this); }
- virtual void visitExp(V4IR::Exp *s) { s->expr->accept(this); }
- virtual void visitMove(V4IR::Move *s) { s->target->accept(this); s->source->accept(this); }
- virtual void visitJump(V4IR::Jump *) {}
- virtual void visitCJump(V4IR::CJump *s) { s->cond->accept(this); }
- virtual void visitRet(V4IR::Ret *s) { s->expr->accept(this); }
- virtual void visitPhi(V4IR::Phi *) { Q_UNREACHABLE(); }
-};
-
inline bool isPregOrConst(V4IR::Expr *e)
{
if (V4IR::Temp *t = e->asTemp())
@@ -625,7 +559,6 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
InstructionSelection::InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, Compiler::JSUnitGenerator *jsGenerator)
: EvalInstructionSelection(execAllocator, module, jsGenerator)
, _block(0)
- , _function(0)
, _as(0)
{
compilationUnit = new CompilationUnit;
@@ -1061,9 +994,10 @@ void InstructionSelection::getProperty(V4IR::Expr *base, const QString &name, V4
}
}
-void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, V4IR::Temp *target)
+void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target)
{
- generateFunctionCall(target, __qmljs_get_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex));
+ generateFunctionCall(target, __qmljs_get_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
+ Assembler::TrustedImm32(captureRequired));
}
void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBase,
@@ -1105,13 +1039,13 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR:
_as->and32(Assembler::TrustedImm32(QV4::Managed::SimpleArray), Assembler::ReturnValueRegister);
Assembler::Jump notSimple = _as->branch32(Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm32(0));
- Assembler::Jump fallback;
+ Assembler::Jump fallback, fallback2;
if (tindex->kind == V4IR::Temp::PhysicalRegister) {
if (tindex->type == V4IR::SInt32Type) {
_as->move((Assembler::RegisterID) tindex->index, Assembler::ScratchRegister);
} else {
// double, convert and check if it's a int
- _as->truncateDoubleToUint32((Assembler::FPRegisterID) tindex->index, Assembler::ScratchRegister);
+ fallback2 = _as->branchTruncateDoubleToUint32((Assembler::FPRegisterID) tindex->index, Assembler::ScratchRegister);
_as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr0);
fallback = _as->branchDouble(Assembler::DoubleNotEqual, Assembler::FPGpr0, (Assembler::FPRegisterID) tindex->index);
}
@@ -1128,7 +1062,7 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR:
_as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ReturnValueRegister);
_as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
_as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
- _as->truncateDoubleToUint32(Assembler::FPGpr0, Assembler::ScratchRegister);
+ fallback2 = _as->branchTruncateDoubleToUint32(Assembler::FPGpr0, Assembler::ScratchRegister);
_as->convertInt32ToDouble(Assembler::ScratchRegister, Assembler::FPGpr1);
fallback = _as->branchDouble(Assembler::DoubleNotEqualOrUnordered, Assembler::FPGpr0, Assembler::FPGpr1);
@@ -1161,6 +1095,8 @@ void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR:
outOfRange.link(_as);
if (fallback.isSet())
fallback.link(_as);
+ if (fallback2.isSet())
+ fallback2.link(_as);
notSimple.link(_as);
notManaged.link(_as);
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index f84c981cd1..e3b41857ea 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -1496,7 +1496,7 @@ protected:
virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target);
virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, V4IR::Temp *target);
+ virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target);
virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target);
virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex);
virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
@@ -1651,7 +1651,6 @@ private:
}
V4IR::BasicBlock *_block;
- V4IR::Function* _function;
QSet<V4IR::Jump *> _removableJumps;
Assembler* _as;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 44b4d666ef..6db8f11a9e 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -152,83 +152,12 @@ inline bool isBoolType(V4IR::Expr *e)
} // anonymous namespace
-// TODO: extend to optimize out temp-to-temp moves, where the lifetime of one temp ends at that statement.
-// To handle that, add a hint when such a move will occur, and add a stmt for the hint.
-// Then when asked for a register, check if the active statement is the terminating statement, and if so, apply the hint.
-// This generalises the hint usage for Phi removal too, when the phi is passed in there as the current statement.
-class QQmlJS::Moth::StackSlotAllocator
-{
- QHash<V4IR::Temp, int> _slotForTemp;
- QHash<V4IR::Temp, int> _hints;
- QVector<int> _activeSlots;
-
- QHash<V4IR::Temp, V4IR::LifeTimeInterval> _intervals;
-
-public:
- StackSlotAllocator(const QVector<V4IR::LifeTimeInterval> &ranges, int maxTempCount)
- : _activeSlots(maxTempCount)
- {
- _intervals.reserve(ranges.size());
- foreach (const V4IR::LifeTimeInterval &r, ranges)
- _intervals[r.temp()] = r;
- }
-
- void addHint(const V4IR::Temp &hintedSlotOfTemp, const V4IR::Temp &newTemp)
- {
- if (hintedSlotOfTemp.kind != V4IR::Temp::VirtualRegister
- || newTemp.kind != V4IR::Temp::VirtualRegister)
- return;
-
- if (_slotForTemp.contains(newTemp) || _hints.contains(newTemp))
- return;
-
- int hintedSlot = _slotForTemp.value(hintedSlotOfTemp, -1);
- Q_ASSERT(hintedSlot >= 0);
- _hints[newTemp] = hintedSlot;
- }
-
- int stackSlotFor(V4IR::Temp *t, V4IR::Stmt *currentStmt) {
- Q_ASSERT(t->kind == V4IR::Temp::VirtualRegister);
- Q_ASSERT(t->scope == 0);
- int idx = _slotForTemp.value(*t, -1);
- if (idx == -1)
- idx = allocateSlot(t, currentStmt);
- Q_ASSERT(idx >= 0);
- return idx;
- }
-
-private:
- int allocateSlot(V4IR::Temp *t, V4IR::Stmt *currentStmt) {
- Q_ASSERT(currentStmt->id > 0);
-
- const V4IR::LifeTimeInterval &interval = _intervals[*t];
- int idx = _hints.value(*t, -1);
- if (idx != -1 && _activeSlots[idx] == currentStmt->id) {
- _slotForTemp[*t] = idx;
- _activeSlots[idx] = interval.end();
- return idx;
- }
-
- for (int i = 0, ei = _activeSlots.size(); i != ei; ++i) {
- if (_activeSlots[i] < currentStmt->id) {
- _slotForTemp[*t] = i;
- _activeSlots[i] = interval.end();
- return i;
- }
- }
-
- return -1;
- }
-};
-
InstructionSelection::InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
: EvalInstructionSelection(execAllocator, module, jsGenerator)
- , _function(0)
, _block(0)
, _codeStart(0)
, _codeNext(0)
, _codeEnd(0)
- , _stackSlotAllocator(0)
, _currentStatement(0)
{
compilationUnit = new CompilationUnit;
@@ -263,13 +192,12 @@ void InstructionSelection::run(int functionIndex)
V4IR::Optimizer opt(_function);
opt.run();
- StackSlotAllocator *stackSlotAllocator = 0;
if (opt.isInSSA()) {
- //stackSlotAllocator = new StackSlotAllocator(opt.lifeRanges(), _function->tempCount);
opt.convertOutOfSSA();
+ opt.showMeTheCode(_function);
}
+ ConvertTemps().toStackSlots(_function);
- qSwap(_stackSlotAllocator, stackSlotAllocator);
QSet<V4IR::Jump *> removableJumps = opt.calculateOptionalJumps();
qSwap(_removableJumps, removableJumps);
@@ -324,8 +252,6 @@ void InstructionSelection::run(int functionIndex)
qSwap(_currentStatement, cs);
qSwap(_removableJumps, removableJumps);
- qSwap(_stackSlotAllocator, stackSlotAllocator);
- delete stackSlotAllocator;
qSwap(_function, function);
qSwap(block, _block);
qSwap(nextBlock, _nextBlock);
@@ -395,9 +321,6 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
{
- if (_stackSlotAllocator)
- _stackSlotAllocator->addHint(*source, *target);
-
// FIXME: do something more useful with this info
if (target->type & V4IR::NumberType)
unop(V4IR::OpUPlus, source, target);
@@ -585,12 +508,13 @@ void InstructionSelection::setQObjectProperty(V4IR::Expr *source, V4IR::Expr *ta
addInstruction(store);
}
-void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, V4IR::Temp *target)
+void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target)
{
Instruction::LoadQObjectProperty load;
load.base = getParam(base);
load.propertyIndex = propertyIndex;
load.result = getResultParam(target);
+ load.captureRequired = captureRequired;
addInstruction(load);
}
@@ -615,9 +539,6 @@ void InstructionSelection::setElement(V4IR::Expr *source, V4IR::Expr *targetBase
void InstructionSelection::copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
{
- if (_stackSlotAllocator)
- _stackSlotAllocator->addHint(*sourceTemp, *targetTemp);
-
Instruction::Move move;
move.source = getParam(sourceTemp);
move.result = getResultParam(targetTemp);
@@ -635,9 +556,6 @@ void InstructionSelection::swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *target
void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
{
- if (_stackSlotAllocator)
- _stackSlotAllocator->addHint(*sourceTemp, *targetTemp);
-
switch (oper) {
case V4IR::OpIfTrue:
Q_ASSERT(!"unreachable"); break;
@@ -751,9 +669,6 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
}
}
- if (_stackSlotAllocator && target && leftSource->asTemp())
- _stackSlotAllocator->addHint(*leftSource->asTemp(), *target);
-
if (oper == V4IR::OpAdd) {
Instruction::Add add;
add.lhs = getParam(leftSource);
@@ -1249,11 +1164,10 @@ Param InstructionSelection::getParam(V4IR::Expr *e) {
case V4IR::Temp::ScopedFormal: return Param::createArgument(t->index, t->scope);
case V4IR::Temp::Local: return Param::createLocal(t->index);
case V4IR::Temp::ScopedLocal: return Param::createScopedLocal(t->index, t->scope);
- case V4IR::Temp::VirtualRegister:
- return Param::createTemp(_stackSlotAllocator ?
- _stackSlotAllocator->stackSlotFor(t, _currentStatement) : t->index);
+ case V4IR::Temp::StackSlot:
+ return Param::createTemp(t->index);
default:
- Q_UNIMPLEMENTED();
+ Q_UNREACHABLE();
return Param();
}
} else {
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 0bf7444329..ffb8ff4539 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -54,8 +54,6 @@ QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace Moth {
-class StackSlotAllocator;
-
struct CompilationUnit : public QV4::CompiledData::CompilationUnit
{
virtual ~CompilationUnit();
@@ -65,7 +63,6 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit
};
-
class Q_QML_EXPORT InstructionSelection:
public V4IR::IRDecoder,
public EvalInstructionSelection
@@ -128,7 +125,7 @@ protected:
virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target);
virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, V4IR::Temp *target);
+ virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target);
virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target);
virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex);
virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
@@ -171,7 +168,6 @@ private:
void patchJumpAddresses();
QByteArray squeezeCode() const;
- V4IR::Function *_function;
V4IR::BasicBlock *_block;
V4IR::BasicBlock *_nextBlock;
@@ -182,7 +178,6 @@ private:
uchar *_codeNext;
uchar *_codeEnd;
- StackSlotAllocator *_stackSlotAllocator;
QSet<V4IR::Jump *> _removableJumps;
V4IR::Stmt *_currentStatement;
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 3f9e666c98..45b1e9f3b0 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -151,7 +151,12 @@ void IRDecoder::visitMove(V4IR::Move *s)
return;
}
} else if (m->type == V4IR::Member::MemberOfQObject) {
- getQObjectProperty(m->base, m->property->coreIndex, t);
+ bool captureRequired = true;
+ if (_function) {
+ captureRequired = !_function->contextObjectDependencies.contains(m->property)
+ && !_function->scopeObjectDependencies.contains(m->property);
+ }
+ getQObjectProperty(m->base, m->property->coreIndex, captureRequired, t);
return;
} else if (m->base->asTemp() || m->base->asConst()) {
getProperty(m->base, *m->name, t);
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 5fba560d27..23ef7cc69e 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -100,6 +100,7 @@ namespace V4IR {
class Q_QML_EXPORT IRDecoder: protected V4IR::StmtVisitor
{
public:
+ IRDecoder() : _function(0) {}
virtual ~IRDecoder() = 0;
virtual void visitPhi(V4IR::Phi *) {}
@@ -152,7 +153,7 @@ public: // to implement by subclasses:
virtual void setActivationProperty(V4IR::Expr *source, const QString &targetName) = 0;
virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target) = 0;
virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target) = 0;
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, V4IR::Temp *targetTemp) = 0;
+ virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *targetTemp) = 0;
virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName) = 0;
virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex) = 0;
virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target) = 0;
@@ -164,6 +165,8 @@ public: // to implement by subclasses:
protected:
virtual void callBuiltin(V4IR::Call *c, V4IR::Temp *result);
+
+ V4IR::Function *_function; // subclass needs to set
};
} // namespace IR
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index 5084de8ec9..38ea682d3b 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -95,6 +95,71 @@ inline QV4::Primitive convertToValue(V4IR::Const *c)
return QV4::Primitive::undefinedValue();
}
+class ConvertTemps: protected V4IR::StmtVisitor, protected V4IR::ExprVisitor
+{
+ int _nextFreeStackSlot;
+ QHash<V4IR::Temp, int> _stackSlotForTemp;
+
+ void renumber(V4IR::Temp *t)
+ {
+ if (t->kind != V4IR::Temp::VirtualRegister)
+ return;
+
+ int stackSlot = _stackSlotForTemp.value(*t, -1);
+ if (stackSlot == -1) {
+ stackSlot = _nextFreeStackSlot++;
+ _stackSlotForTemp[*t] = stackSlot;
+ }
+
+ t->kind = V4IR::Temp::StackSlot;
+ t->index = stackSlot;
+ }
+
+public:
+ ConvertTemps()
+ : _nextFreeStackSlot(0)
+ {}
+
+ void toStackSlots(V4IR::Function *function)
+ {
+ _stackSlotForTemp.reserve(function->tempCount);
+
+ foreach (V4IR::BasicBlock *bb, function->basicBlocks)
+ foreach (V4IR::Stmt *s, bb->statements)
+ s->accept(this);
+
+ function->tempCount = _nextFreeStackSlot;
+ }
+
+protected:
+ virtual void visitConst(V4IR::Const *) {}
+ virtual void visitString(V4IR::String *) {}
+ virtual void visitRegExp(V4IR::RegExp *) {}
+ virtual void visitName(V4IR::Name *) {}
+ virtual void visitTemp(V4IR::Temp *e) { renumber(e); }
+ virtual void visitClosure(V4IR::Closure *) {}
+ virtual void visitConvert(V4IR::Convert *e) { e->expr->accept(this); }
+ virtual void visitUnop(V4IR::Unop *e) { e->expr->accept(this); }
+ virtual void visitBinop(V4IR::Binop *e) { e->left->accept(this); e->right->accept(this); }
+ virtual void visitCall(V4IR::Call *e) {
+ e->base->accept(this);
+ for (V4IR::ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+ virtual void visitNew(V4IR::New *e) {
+ e->base->accept(this);
+ for (V4IR::ExprList *it = e->args; it; it = it->next)
+ it->expr->accept(this);
+ }
+ virtual void visitSubscript(V4IR::Subscript *e) { e->base->accept(this); e->index->accept(this); }
+ virtual void visitMember(V4IR::Member *e) { e->base->accept(this); }
+ virtual void visitExp(V4IR::Exp *s) { s->expr->accept(this); }
+ virtual void visitMove(V4IR::Move *s) { s->target->accept(this); s->source->accept(this); }
+ virtual void visitJump(V4IR::Jump *) {}
+ virtual void visitCJump(V4IR::CJump *s) { s->cond->accept(this); }
+ virtual void visitRet(V4IR::Ret *s) { s->expr->accept(this); }
+ virtual void visitPhi(V4IR::Phi *) { Q_UNREACHABLE(); }
+};
} // namespace QQmlJS
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index f8189b673d..75261b2469 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -1042,31 +1042,6 @@ void CloneExpr::visitMember(Member *e)
Q_ASSERT(!"Unimplemented!");
}
-void QmlDependenciesCollector::visitMember(Member *e) {
- e->base->accept(this);
- if (e->type == Member::MemberOfQmlContext) {
- V4IR::Name *base = e->base->asName();
- Q_ASSERT(base);
- if (base->builtin == V4IR::Name::builtin_qml_id_scope)
- _usedIdObjects.insert(e->memberIndex);
- } else if (e->type == Member::MemberOfQObject
- && !e->property->isFunction()) { // only non-functions have notifyIndex
-
- if (Name *base = e->base->asName()) {
- if (base->builtin == Name::builtin_qml_context_object)
- _usedContextProperties.insert(e->property);
- else if (base->builtin == Name::builtin_qml_scope_object)
- _usedScopeProperties.insert(e->property);
- }
- }
-}
-
-void QmlDependenciesCollector::visitPhi(Phi *s) {
- s->targetTemp->accept(this);
- foreach (Expr *e, s->d->incoming)
- e->accept(this);
-}
-
} // end of namespace IR
} // end of namespace QQmlJS
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index a7bed6419b..9a1bd87a1d 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -558,7 +558,7 @@ struct Member: Expr {
}
virtual void accept(ExprVisitor *v) { v->visitMember(this); }
- virtual bool isLValue() { return true; }
+ virtual bool isLValue() { return type != MemberOfQmlContext; }
virtual Member *asMember() { return this; }
virtual void dump(QTextStream &out) const;
@@ -739,13 +739,19 @@ struct Function {
uint isNamedExpression : 1;
uint hasTry: 1;
uint hasWith: 1;
- uint hasQmlDependencies : 1;
- uint unused : 24;
+ uint unused : 25;
// Location of declaration in source code (-1 if not specified)
int line;
int column;
+ // Qml extension:
+ QSet<int> idObjectDependencies;
+ QSet<QQmlPropertyData*> contextObjectDependencies;
+ QSet<QQmlPropertyData*> scopeObjectDependencies;
+
+ bool hasQmlDependencies() const { return !idObjectDependencies.isEmpty() || !contextObjectDependencies.isEmpty() || !scopeObjectDependencies.isEmpty(); }
+
template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
Function(Module *module, Function *outer, const QString &name)
@@ -761,7 +767,6 @@ struct Function {
, isNamedExpression(false)
, hasTry(false)
, hasWith(false)
- , hasQmlDependencies(false)
, unused(0)
, line(-1)
, column(-1)
@@ -957,76 +962,6 @@ private:
V4IR::Expr *cloned;
};
-struct QmlDependenciesCollector : public V4IR::StmtVisitor, V4IR::ExprVisitor
-{
- void run(Function *function, QSet<int> *idObjectDependencies, QSet<QQmlPropertyData*> *contextPropertyDependencies, QSet<QQmlPropertyData*> *scopePropertyDependencies)
- {
- QSet<int> idProperties;
- QSet<QQmlPropertyData*> contextProperties;
- QSet<QQmlPropertyData*> scopeProperties;
- qSwap(_usedIdObjects, idProperties);
- qSwap(_usedContextProperties, contextProperties);
- qSwap(_usedScopeProperties, scopeProperties);
- for (int i = 0; i < function->basicBlocks.count(); ++i) {
- BasicBlock *bb = function->basicBlocks.at(i);
- for (int j = 0; j < bb->statements.count(); ++j) {
- Stmt *s = bb->statements.at(j);
- s->accept(this);
- }
- }
- qSwap(_usedScopeProperties, scopeProperties);
- qSwap(_usedContextProperties, contextProperties);
- qSwap(_usedIdObjects, idProperties);
-
- *idObjectDependencies = idProperties;
- *contextPropertyDependencies = contextProperties;
- *scopePropertyDependencies = scopeProperties;
- }
-
-protected:
- QSet<int> _usedIdObjects;
- QSet<QQmlPropertyData*> _usedContextProperties;
- QSet<QQmlPropertyData*> _usedScopeProperties;
-
- virtual void visitConst(Const *) {}
- virtual void visitString(String *) {}
- virtual void visitRegExp(RegExp *) {}
- virtual void visitName(Name *) {}
- virtual void visitTemp(Temp *) {}
- virtual void visitClosure(Closure *) {}
- virtual void visitConvert(Convert *e) { e->expr->accept(this); }
- virtual void visitUnop(Unop *e) { e->expr->accept(this); }
- virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
-
- virtual void visitCall(Call *e) {
- e->base->accept(this);
- for (ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
- virtual void visitNew(New *e) {
- e->base->accept(this);
- for (ExprList *it = e->args; it; it = it->next)
- it->expr->accept(this);
- }
- virtual void visitSubscript(Subscript *e) {
- e->base->accept(this);
- e->index->accept(this);
- }
-
- virtual void visitMember(Member *e);
-
- virtual void visitExp(Exp *s) {s->expr->accept(this);}
- virtual void visitMove(Move *s) {
- s->source->accept(this);
- s->target->accept(this);
- }
-
- virtual void visitJump(Jump *) {}
- virtual void visitCJump(CJump *s) { s->cond->accept(this); }
- virtual void visitRet(Ret *s) { s->expr->accept(this); }
- virtual void visitPhi(Phi *s);
-};
-
} // end of namespace IR
} // end of namespace QQmlJS
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index f746902814..a6e66d2722 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv4regalloc_p.h"
+#include <private/qv4value_p.h>
#include <algorithm>
@@ -427,7 +428,7 @@ protected: // IRDecoder
addCall();
}
- virtual void getQObjectProperty(V4IR::Expr *base, int /*propertyIndex*/, V4IR::Temp *target)
+ virtual void getQObjectProperty(V4IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, V4IR::Temp *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
@@ -644,7 +645,9 @@ namespace {
class ResolutionPhase: protected StmtVisitor, protected ExprVisitor {
QVector<LifeTimeInterval> _intervals;
Function *_function;
+#if !defined(QT_NO_DEBUG)
RegAllocInfo *_info;
+#endif
const QHash<V4IR::Temp, int> &_assignedSpillSlots;
QHash<V4IR::Temp, LifeTimeInterval> _intervalForTemp;
const QVector<int> &_intRegs;
@@ -663,11 +666,16 @@ public:
const QVector<int> &intRegs, const QVector<int> &fpRegs)
: _intervals(intervals)
, _function(function)
+#if !defined(QT_NO_DEBUG)
, _info(info)
+#endif
, _assignedSpillSlots(assignedSpillSlots)
, _intRegs(intRegs)
, _fpRegs(fpRegs)
{
+#if defined(QT_NO_DEBUG)
+ Q_UNUSED(info)
+#endif
}
void run() {
@@ -886,8 +894,28 @@ private:
#if !defined(QT_NO_DEBUG)
if (_info->def(it.temp()) != successorStart && !it.isSplitFromInterval()) {
const int successorEnd = successor->statements.last()->id;
- foreach (const Use &use, _info->uses(it.temp()))
- Q_ASSERT(use.pos < static_cast<unsigned>(successorStart) || use.pos > static_cast<unsigned>(successorEnd));
+ const int idx = successor->in.indexOf(predecessor);
+ foreach (const Use &use, _info->uses(it.temp())) {
+ if (use.pos == static_cast<unsigned>(successorStart)) {
+ // only check the current edge, not all other possible ones. This is
+ // important for phi nodes: they have uses that are only valid when
+ // coming in over a specific edge.
+ foreach (Stmt *s, successor->statements) {
+ if (Phi *phi = s->asPhi()) {
+ Q_ASSERT(it.temp().index != phi->targetTemp->index);
+ Q_ASSERT(phi->d->incoming[idx]->asTemp() == 0
+ || it.temp().index != phi->d->incoming[idx]->asTemp()->index);
+ } else {
+ // TODO: check that the first non-phi statement does not use
+ // the temp.
+ break;
+ }
+ }
+ } else {
+ Q_ASSERT(use.pos < static_cast<unsigned>(successorStart) ||
+ use.pos > static_cast<unsigned>(successorEnd));
+ }
+ }
}
#endif
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 8f17fb1aff..6b1169d30a 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -224,26 +224,65 @@ class DominatorTree {
QHash<BasicBlock *, BasicBlock *> samedom;
QHash<BasicBlock *, QSet<BasicBlock *> > bucket;
- void DFS(BasicBlock *p, BasicBlock *n) {
- if (dfnum[n] == 0) {
- dfnum[n] = N;
- vertex[N] = n;
- parent[n] = p;
- ++N;
- foreach (BasicBlock *w, n->out)
- DFS(n, w);
+ struct DFSTodo {
+ BasicBlock *node, *parent;
+
+ DFSTodo():node(0),parent(0){}
+ DFSTodo(BasicBlock *node, BasicBlock *parent):node(node),parent(parent){}
+ };
+
+ void DFS(BasicBlock *node) {
+ QVector<DFSTodo> worklist;
+ worklist.reserve(vertex.capacity());
+ DFSTodo todo(node, 0);
+
+ while (true) {
+ BasicBlock *n = todo.node;
+
+ if (dfnum[n] == 0) {
+ dfnum[n] = N;
+ vertex[N] = n;
+ parent[n] = todo.parent;
+ ++N;
+ for (int i = n->out.size() - 1; i > 0; --i)
+ worklist.append(DFSTodo(n->out[i], n));
+
+ if (n->out.size() > 0) {
+ todo.node = n->out.first();
+ todo.parent = n;
+ continue;
+ }
+ }
+
+ if (worklist.isEmpty())
+ break;
+
+ todo = worklist.last();
+ worklist.removeLast();
}
}
BasicBlock *ancestorWithLowestSemi(BasicBlock *v) {
- BasicBlock *a = ancestor[v];
- if (ancestor[a]) {
- BasicBlock *b = ancestorWithLowestSemi(a);
- ancestor[v] = ancestor[a];
- if (dfnum[semi[b]] < dfnum[semi[best[v]]])
- best[v] = b;
+ QVector<BasicBlock *> worklist;
+ worklist.reserve(vertex.capacity());
+ for (BasicBlock *it = v; it; it = ancestor[it])
+ worklist.append(it);
+
+ if (worklist.size() < 2)
+ return best[v];
+
+ BasicBlock *b = 0;
+ BasicBlock *last = worklist.last();
+ for (int it = worklist.size() - 2; it >= 0; --it) {
+ BasicBlock *bbIt = worklist[it];
+ ancestor[bbIt] = last;
+ BasicBlock *&best_it = best[bbIt];
+ if (b && dfnum[semi[b]] < dfnum[semi[best_it]])
+ best_it = b;
+ else
+ b = best_it;
}
- return best[v];
+ return b;
}
void link(BasicBlock *p, BasicBlock *n) {
@@ -262,8 +301,8 @@ class DominatorTree {
samedom[n] = 0;
}
- DFS(0, nodes.first());
- Q_ASSERT(N == nodes.size()); // fails with unreachable nodes...
+ DFS(nodes.first());
+ Q_ASSERT(N == nodes.size()); // fails with unreachable nodes, but those should have been removed before.
for (int i = N - 1; i > 0; --i) {
BasicBlock *n = vertex[i];
@@ -284,9 +323,9 @@ class DominatorTree {
link(p, n);
foreach (BasicBlock *v, bucket[p]) {
BasicBlock *y = ancestorWithLowestSemi(v);
- Q_ASSERT(semi[y] == p);
- if (semi[y] == semi[v])
- idom[v] = p;
+ BasicBlock *semi_v = semi[v];
+ if (semi[y] == semi_v)
+ idom[v] = semi_v;
else
samedom[v] = y;
}
@@ -322,52 +361,88 @@ class DominatorTree {
return false;
}
- void computeDF(BasicBlock *n) {
- if (DF.contains(n))
- return; // TODO: verify this!
+ struct NodeProgress {
+ QSet<BasicBlock *> children;
+ QSet<BasicBlock *> todo;
+ };
+
+ void computeDF(const QVector<BasicBlock *> &nodes) {
+ QHash<BasicBlock *, NodeProgress> nodeStatus;
+ nodeStatus.reserve(nodes.size());
+ QVector<BasicBlock *> worklist;
+ worklist.reserve(nodes.size() * 2);
+ for (int i = 0, ei = nodes.size(); i != ei; ++i) {
+ BasicBlock *node = nodes[i];
+ worklist.append(node);
+ NodeProgress &np = nodeStatus[node];
+ np.children = children[node];
+ np.todo = children[node];
+ }
+
+ while (!worklist.isEmpty()) {
+ BasicBlock *node = worklist.last();
- QSet<BasicBlock *> S;
- foreach (BasicBlock *y, n->out)
- if (idom[y] != n)
- S.insert(y);
+ if (DF.contains(node)) {
+ worklist.removeLast();
+ continue;
+ }
- /*
- * foreach child c of n in the dominator tree
- * computeDF[c]
- * foreach element w of DF[c]
- * if n does not dominate w or if n = w
- * S.insert(w)
- * DF[n] = S;
- */
- foreach (BasicBlock *c, children[n]) {
- computeDF(c);
- foreach (BasicBlock *w, DF[c])
- if (!dominates(n, w) || n == w)
- S.insert(w);
+ NodeProgress &np = nodeStatus[node];
+ QSet<BasicBlock *>::iterator it = np.todo.begin();
+ while (it != np.todo.end()) {
+ if (DF.contains(*it)) {
+ it = np.todo.erase(it);
+ } else {
+ worklist.append(*it);
+ break;
+ }
+ }
+
+ if (np.todo.isEmpty()) {
+ QSet<BasicBlock *> S;
+ foreach (BasicBlock *y, node->out)
+ if (idom[y] != node)
+ if (!S.contains(y))
+ S.insert(y);
+ foreach (BasicBlock *child, np.children)
+ foreach (BasicBlock *w, DF[child])
+ if (!dominates(node, w) || node == w)
+ if (!S.contains(w))
+ S.insert(w);
+ DF.insert(node, S);
+ worklist.removeLast();
+ }
}
- DF[n] = S;
-#ifdef SHOW_SSA
- qout << "\tDF[" << n->index << "]: {";
- QList<BasicBlock *> SList = S.values();
- for (int i = 0; i < SList.size(); ++i) {
- if (i > 0)
- qout << ", ";
- qout << SList[i]->index;
+#if defined(SHOW_SSA)
+ qout << "Dominator Frontiers:" << endl;
+ foreach (BasicBlock *n, nodes) {
+ qout << "\tDF[" << n->index << "]: {";
+ QList<BasicBlock *> SList = DF[n].values();
+ for (int i = 0; i < SList.size(); ++i) {
+ if (i > 0)
+ qout << ", ";
+ qout << SList[i]->index;
+ }
+ qout << "}" << endl;
}
- qout << "}" << endl;
#endif // SHOW_SSA
-#ifndef QT_NO_DEBUG
- foreach (BasicBlock *fBlock, S) {
- Q_ASSERT(!dominates(n, fBlock) || fBlock == n);
- bool hasDominatedSucc = false;
- foreach (BasicBlock *succ, fBlock->in)
- if (dominates(n, succ))
- hasDominatedSucc = true;
- if (!hasDominatedSucc) {
- qout << fBlock->index << " in DF[" << n->index << "] has no dominated predecessors" << endl;
+#if !defined(QT_NO_DEBUG) && defined(CAN_TAKE_LOSTS_OF_TIME)
+ foreach (BasicBlock *n, nodes) {
+ foreach (BasicBlock *fBlock, DF[n]) {
+ Q_ASSERT(!dominates(n, fBlock) || fBlock == n);
+ bool hasDominatedSucc = false;
+ foreach (BasicBlock *succ, fBlock->in) {
+ if (dominates(n, succ)) {
+ hasDominatedSucc = true;
+ break;
+ }
+ }
+ if (!hasDominatedSucc) {
+ qout << fBlock->index << " in DF[" << n->index << "] has no dominated predecessors" << endl;
+ }
+ Q_ASSERT(hasDominatedSucc);
}
- Q_ASSERT(hasDominatedSucc);
}
#endif // !QT_NO_DEBUG
}
@@ -382,14 +457,13 @@ public:
calculateIDoms(nodes);
// compute children of n
- foreach (BasicBlock *n, nodes)
- children[idom[n]].insert(n);
+ foreach (BasicBlock *n, nodes) {
+ QSet<BasicBlock *> &c = children[idom[n]];
+ if (!c.contains(n))
+ c.insert(n);
+ }
-#ifdef SHOW_SSA
- qout << "Dominator Frontiers:" << endl;
-#endif // SHOW_SSA
- foreach (BasicBlock *n, nodes)
- computeDF(n);
+ computeDF(nodes);
}
QSet<BasicBlock *> operator[](BasicBlock *n) const {
@@ -1977,33 +2051,59 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
}
#endif
-void cleanupBasicBlocks(Function *function)
+void cleanupBasicBlocks(Function *function, bool renumber)
{
-// showMeTheCode(function);
+ showMeTheCode(function);
- // remove all basic blocks that have no incoming edges, but skip the entry block
- QVector<BasicBlock *> W = function->basicBlocks;
- W.removeFirst();
+ // Algorithm: this is the iterative version of a depth-first search for all blocks that are
+ // reachable through outgoing edges, starting with the start block and all exception handler
+ // blocks.
+ QSet<BasicBlock *> postponed, done;
QSet<BasicBlock *> toRemove;
+ toRemove.reserve(function->basicBlocks.size());
+ done.reserve(function->basicBlocks.size());
+ postponed.reserve(8);
+ for (int i = 0, ei = function->basicBlocks.size(); i != ei; ++i) {
+ BasicBlock *bb = function->basicBlocks[i];
+ if (i == 0 || bb->isExceptionHandler)
+ postponed.insert(bb);
+ else
+ toRemove.insert(bb);
+ }
- while (!W.isEmpty()) {
- BasicBlock *bb = W.first();
- W.removeFirst();
- if (toRemove.contains(bb))
- continue;
- if (bb->in.isEmpty() && !bb->isExceptionHandler) {
- foreach (BasicBlock *outBB, bb->out) {
- int idx = outBB->in.indexOf(bb);
- if (idx != -1) {
- outBB->in.remove(idx);
- W.append(outBB);
- }
+ while (!postponed.isEmpty()) {
+ QSet<BasicBlock *>::iterator it = postponed.begin();
+ BasicBlock *bb = *it;
+ postponed.erase(it);
+ done.insert(bb);
+
+ foreach (BasicBlock *outBB, bb->out) {
+ if (!done.contains(outBB)) {
+ postponed.insert(outBB);
+ toRemove.remove(outBB);
}
- toRemove.insert(bb);
}
}
foreach (BasicBlock *bb, toRemove) {
+ foreach (BasicBlock *outBB, bb->out) {
+ if (toRemove.contains(outBB))
+ continue; // We do not need to unlink from blocks that are scheduled to be removed.
+ // Actually, it is potentially dangerous: if that block was already
+ // destroyed, this could result in a use-after-free.
+
+ int idx = outBB->in.indexOf(bb);
+ if (idx != -1) {
+ outBB->in.remove(idx);
+ foreach (Stmt *s, outBB->statements) {
+ if (Phi *phi = s->asPhi())
+ phi->d->incoming.remove(idx);
+ else
+ break;
+ }
+ }
+ }
+
foreach (Stmt *s, bb->statements)
s->destroyData();
int idx = function->basicBlocks.indexOf(bb);
@@ -2012,9 +2112,11 @@ void cleanupBasicBlocks(Function *function)
delete bb;
}
- // re-number all basic blocks:
- for (int i = 0; i < function->basicBlocks.size(); ++i)
- function->basicBlocks[i]->index = i;
+ if (renumber)
+ for (int i = 0; i < function->basicBlocks.size(); ++i)
+ function->basicBlocks[i]->index = i;
+
+ showMeTheCode(function);
}
inline Const *isConstPhi(Phi *phi)
@@ -2867,7 +2969,7 @@ void Optimizer::run()
function->basicBlocks[i]->index = i;
// showMeTheCode(function);
- cleanupBasicBlocks(function);
+ cleanupBasicBlocks(function, true);
function->removeSharedExpressions();
@@ -2914,6 +3016,13 @@ void Optimizer::run()
// mergeBasicBlocks(function);
// showMeTheCode(function);
+ // Basic-block cycles that are unreachable (i.e. for loops in a then-part where the
+ // condition is calculated to be always false) are not yet removed. This will choke the
+ // block scheduling, so remove those now.
+// qout << "Cleaning up unreachable basic blocks..." << endl;
+ cleanupBasicBlocks(function, false);
+// showMeTheCode(function);
+
// qout << "Doing block scheduling..." << endl;
startEndLoops = scheduleBlocks(function, df);
// showMeTheCode(function);
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
index 3b6bafdac2..400bb18edd 100644
--- a/src/qml/debugger/qv4debugservice.cpp
+++ b/src/qml/debugger/qv4debugservice.cpp
@@ -439,8 +439,8 @@ public:
continue;
QJsonObject scope;
- scope["index"] = i;
- scope["type"] = type;
+ scope[QLatin1String("index")] = i;
+ scope[QLatin1String("type")] = type;
scopes.push_back(scope);
}
frame[QLatin1String("scopes")] = scopes;
@@ -619,7 +619,7 @@ public:
addRunning();
QJsonObject body;
body.insert(QStringLiteral("V8Version"),
- QStringLiteral("this is not V8, this is V4 in Qt %1").arg(QT_VERSION_STR));
+ QStringLiteral("this is not V8, this is V4 in Qt %1").arg(QLatin1String(QT_VERSION_STR)));
addBody(body);
}
};
diff --git a/src/qml/jsruntime/qv4alloca_p.h b/src/qml/jsruntime/qv4alloca_p.h
index e4580da3d8..f507d174e1 100644
--- a/src/qml/jsruntime/qv4alloca_p.h
+++ b/src/qml/jsruntime/qv4alloca_p.h
@@ -45,10 +45,12 @@
#include <qglobal.h>
#if defined(Q_OS_WIN)
-#include <malloc.h>
-#define alloca _alloca
+# include <malloc.h>
+# ifndef __GNUC__
+# define alloca _alloca
+# endif
#else
-#include <alloca.h>
+# include <alloca.h>
#endif
#endif
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 5422bff800..a0f0345b8b 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -572,6 +572,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
--instance->arrayOffset;
--instance->arrayData;
++instance->arrayDataLen;
+ ++instance->arrayAlloc;
if (instance->arrayAttributes) {
--instance->arrayAttributes;
*instance->arrayAttributes = Attr_Data;
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 18b0de3077..97247ad368 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -579,6 +579,13 @@ ReturnedValue ExecutionContext::throwRangeError(const ValueRef value)
return throwError(error);
}
+ReturnedValue ExecutionContext::throwRangeError(const QString &message)
+{
+ Scope scope(this);
+ ScopedObject error(scope, engine->newRangeErrorObject(message));
+ return throwError(error);
+}
+
ReturnedValue ExecutionContext::throwURIError(const ValueRef msg)
{
Scope scope(this);
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 9a7b9a61b2..ccb5cf98f8 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -136,6 +136,7 @@ struct Q_QML_EXPORT ExecutionContext
ReturnedValue throwReferenceError(const ValueRef value);
ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int line, int column);
ReturnedValue throwRangeError(const ValueRef value);
+ ReturnedValue throwRangeError(const QString &message);
ReturnedValue throwURIError(const ValueRef msg);
ReturnedValue throwUnimplemented(const QString &message);
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 0ba37fa547..95b4100651 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -181,11 +181,11 @@ void Debugger::resume(Speed speed)
if (!m_returnedValue.isUndefined())
m_returnedValue = Primitive::undefinedValue();
- clearTemporaryBreakPoint();
+ clearTemporaryBreakPoints();
if (speed == StepOver)
setTemporaryBreakPointOnNextLine();
if (speed == StepOut)
- m_temporaryBreakPoint.function = getFunction();
+ m_temporaryBreakPoints = TemporaryBreakPoint(getFunction(), m_engine->current);
m_stepping = speed;
m_runningCondition.wakeAll();
@@ -491,7 +491,7 @@ void Debugger::maybeBreakAtInstruction(const uchar *code, bool breakPointHit)
}
if (m_stopForStepping) {
- clearTemporaryBreakPoint();
+ clearTemporaryBreakPoints();
m_stopForStepping = false;
m_pauseRequested = false;
pauseAndWait(Step);
@@ -499,7 +499,7 @@ void Debugger::maybeBreakAtInstruction(const uchar *code, bool breakPointHit)
m_pauseRequested = false;
pauseAndWait(PauseRequest);
} else if (breakPointHit) {
- if (m_stepping == StepOver)
+ if (m_stepping == StepOver && m_temporaryBreakPoints.context == m_engine->current)
pauseAndWait(Step);
else if (reallyHitTheBreakPoint(state.fileName, state.lineNumber))
pauseAndWait(BreakPoint);
@@ -526,8 +526,9 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if (m_stepping == StepOut && temporaryBreakPointInFunction()) {
- clearTemporaryBreakPoint();
+ if ((m_stepping == StepOut || m_stepping == StepOver)
+ && temporaryBreakPointInFunction(m_engine->current)) {
+ clearTemporaryBreakPoints();
m_stepping = NotStepping;
m_stopForStepping = true;
m_pauseRequested = true;
@@ -544,7 +545,7 @@ void Debugger::aboutToThrow()
return;
QMutexLocker locker(&m_lock);
- clearTemporaryBreakPoint();
+ clearTemporaryBreakPoints();
pauseAndWait(Throwing);
}
@@ -589,28 +590,38 @@ void Debugger::setTemporaryBreakPointOnNextLine()
if (!function)
return;
- qptrdiff offset = function->programCounterForLine(state.lineNumber + 1);
- if (offset < 0)
+ QList<qptrdiff> pcs = function->programCountersForAllLines();
+ if (pcs.isEmpty())
return;
- if (hasBreakOnInstruction(function, offset))
- return;
+ m_temporaryBreakPoints = TemporaryBreakPoint(function, m_engine->current);
+ m_temporaryBreakPoints.codeOffsets.reserve(pcs.size());
+ for (QList<qptrdiff>::const_iterator i = pcs.begin(), ei = pcs.end(); i != ei; ++i) {
+ // note: we do set a breakpoint on the current line, because there could be a loop where
+ // a step-over would be jump back to the first instruction making up the current line.
+ qptrdiff offset = *i;
+
+ if (hasBreakOnInstruction(function, offset))
+ continue; // do not set a temporary breakpoint if there already is a breakpoint set by the user
- setBreakOnInstruction(function, offset, true);
- m_temporaryBreakPoint = TemporaryBreakPoint(function, offset);
+ setBreakOnInstruction(function, offset, true);
+ m_temporaryBreakPoints.codeOffsets.append(offset);
+ }
}
-void Debugger::clearTemporaryBreakPoint()
+void Debugger::clearTemporaryBreakPoints()
{
- if (m_temporaryBreakPoint.function && m_temporaryBreakPoint.codeOffset) {
- setBreakOnInstruction(m_temporaryBreakPoint.function, m_temporaryBreakPoint.codeOffset, false);
- m_temporaryBreakPoint = TemporaryBreakPoint();
+ if (m_temporaryBreakPoints.function) {
+ foreach (quintptr offset, m_temporaryBreakPoints.codeOffsets)
+ setBreakOnInstruction(m_temporaryBreakPoints.function, offset, false);
+ m_temporaryBreakPoints = TemporaryBreakPoint();
}
}
-bool Debugger::temporaryBreakPointInFunction() const
+bool Debugger::temporaryBreakPointInFunction(ExecutionContext *context) const
{
- return m_temporaryBreakPoint.function == getFunction();
+ return m_temporaryBreakPoints.function == getFunction()
+ && m_temporaryBreakPoints.context == context;
}
void Debugger::applyPendingBreakPoints()
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index b6f39d86ba..98b549995e 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -181,9 +181,9 @@ private:
// requires lock to be held
void setTemporaryBreakPointOnNextLine();
// requires lock to be held
- void clearTemporaryBreakPoint();
+ void clearTemporaryBreakPoints();
// requires lock to be held
- bool temporaryBreakPointInFunction() const;
+ bool temporaryBreakPointInFunction(ExecutionContext *context) const;
void applyPendingBreakPoints();
static void setBreakOnInstruction(Function *function, qptrdiff codeOffset, bool onoff);
@@ -220,11 +220,14 @@ private:
struct TemporaryBreakPoint {
Function *function;
- qptrdiff codeOffset;
- TemporaryBreakPoint(Function *function = 0, qptrdiff codeOffset = 0)
- : function(function), codeOffset(codeOffset)
+ QVector<qptrdiff> codeOffsets;
+ ExecutionContext *context;
+ TemporaryBreakPoint(): function(0), context(0) {}
+ TemporaryBreakPoint(Function *function, ExecutionContext *context)
+ : function(function)
+ , context(context)
{}
- } m_temporaryBreakPoint;
+ } m_temporaryBreakPoints;
bool m_breakOnThrow;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 7af313307e..84be89d31a 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -72,6 +72,10 @@
#include "qv4isel_moth_p.h"
+#if USE(PTHREADS)
+# include <pthread.h>
+#endif
+
QT_BEGIN_NAMESPACE
using namespace QV4;
@@ -83,6 +87,42 @@ static ReturnedValue throwTypeError(CallContext *ctx)
return ctx->throwTypeError();
}
+quintptr getStackLimit()
+{
+ quintptr stackLimit;
+#if USE(PTHREADS) && !OS(QNX)
+# if OS(DARWIN)
+ pthread_t thread_self = pthread_self();
+ void *stackTop = pthread_get_stackaddr_np(thread_self);
+ stackLimit = reinterpret_cast<quintptr>(stackTop);
+ stackLimit -= pthread_get_stacksize_np(thread_self);
+# else
+ void* stackBottom = 0;
+ pthread_attr_t attr;
+ pthread_getattr_np(pthread_self(), &attr);
+ size_t stackSize = 0;
+ pthread_attr_getstack(&attr, &stackBottom, &stackSize);
+ pthread_attr_destroy(&attr);
+
+ stackLimit = reinterpret_cast<quintptr>(stackBottom);
+# endif
+// This is wrong. StackLimit is the currently committed stack size, not the real end.
+// only way to get that limit is apparently by using VirtualQuery (Yuck)
+//#elif OS(WINDOWS)
+// PNT_TIB tib = (PNT_TIB)NtCurrentTeb();
+// stackLimit = static_cast<quintptr>(tib->StackLimit);
+#else
+ int dummy;
+ // this is inexact, as part of the stack is used when being called here,
+ // but let's simply default to 1MB from where the stack is right now
+ stackLimit = reinterpret_cast<qintptr>(&dummy) - 1024*1024;
+#endif
+
+ // 256k slack
+ return stackLimit + 256*1024;
+}
+
+
ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
: memoryManager(new QV4::MemoryManager)
, executableAllocator(new QV4::ExecutableAllocator)
@@ -118,11 +158,17 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
memoryManager->setExecutionEngine(this);
- // reserve 8MB for the JS stack
- *jsStack = WTF::PageAllocation::allocate(8*1024*1024, WTF::OSAllocator::JSVMStackPages, true);
+ // reserve space for the JS stack
+ // we allow it to grow to 2 times JSStackLimit, as we can overshoot due to garbage collection
+ // and ScopedValues allocated outside of JIT'ed methods.
+ *jsStack = WTF::PageAllocation::allocate(2*JSStackLimit, WTF::OSAllocator::JSVMStackPages, true);
jsStackBase = (SafeValue *)jsStack->base();
jsStackTop = jsStackBase;
+ // set up stack limits
+ jsStackLimit = jsStackBase + JSStackLimit/sizeof(SafeValue);
+ cStackLimit = getStackLimit();
+
Scope scope(this);
identifierTable = new IdentifierTable(this);
@@ -867,4 +913,19 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError(ExecutionContext *context)
return error;
}
+bool ExecutionEngine::recheckCStackLimits()
+{
+ int dummy;
+#ifdef Q_OS_WIN
+ // ### this is only required on windows, where we currently use heuristics to get the stack limit
+ if (cStackLimit - reinterpret_cast<quintptr>(&dummy) > 128*1024)
+ // we're more then 128k away from our stack limit, assume the thread has changed, and
+ // call getStackLimit
+#endif
+ // this can happen after a thread change
+ cStackLimit = getStackLimit();
+
+ return (reinterpret_cast<quintptr>(&dummy) >= cStackLimit);
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 2df148a4a8..b4972904ee 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -113,6 +113,12 @@ class RegExpCache;
struct QmlExtensions;
struct Exception;
+#define CHECK_STACK_LIMITS(v4) \
+ if ((v4->jsStackTop <= v4->jsStackLimit) && (reinterpret_cast<quintptr>(&v4) >= v4->cStackLimit || v4->recheckCStackLimits())) {} \
+ else \
+ return v4->current->throwRangeError(QStringLiteral("Maximum call stack size exceeded."))
+
+
struct Q_QML_EXPORT ExecutionEngine
{
MemoryManager *memoryManager;
@@ -123,11 +129,15 @@ struct Q_QML_EXPORT ExecutionEngine
ExecutionContext *current;
GlobalContext *rootContext;
+ SafeValue *jsStackTop;
+ SafeValue *jsStackLimit;
+ quintptr cStackLimit;
+
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
+ enum { JSStackLimit = 4*1024*1024 };
WTF::PageAllocation *jsStack;
SafeValue *jsStackBase;
- SafeValue *jsStackTop;
SafeValue *stackPush(uint nValues) {
SafeValue *ptr = jsStackTop;
@@ -329,6 +339,8 @@ struct Q_QML_EXPORT ExecutionEngine
QmlExtensions *qmlExtensions();
+ bool recheckCStackLimits();
+
// Exception handling
SafeValue exceptionValue;
quint32 hasException;
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 291d4d37d4..ebe214ad72 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -103,7 +103,7 @@ struct LineNumberMappingHelper
while (n > 0) {
half = n >> 1;
middle = begin + half;
- if (table[middle * 2 + field] < value) {
+ if (table[middle * 2 + field] < static_cast<quint32>(value)) {
begin = middle + 1;
n -= half + 1;
} else {
@@ -147,19 +147,22 @@ int Function::lineNumberForProgramCounter(qptrdiff offset) const
return helper.table[pos * 2 + 1];
}
-qptrdiff Function::programCounterForLine(quint32 line) const
+QList<qptrdiff> Function::programCountersForAllLines() const
{
- // Access the second field, the line number
- LineNumberMappingHelper<1, quint32> helper;
- helper.table = compiledFunction->lineNumberMapping();
- const int count = static_cast<int>(compiledFunction->nLineNumberMappingEntries);
+ // Only store 1 breakpoint per line...
+ QHash<quint32, qptrdiff> offsetsPerLine;
+ const quint32 *mapping = compiledFunction->lineNumberMapping();
+
+ // ... and make it the first instruction by walking backwards over the line mapping table
+ // and inserting all entries keyed on line.
+ for (quint32 i = compiledFunction->nLineNumberMappingEntries; i > 0; ) {
+ --i; // the loop is written this way, because starting at endIndex-1 and checking for i>=0 will never end: i>=0 is always true for unsigned.
+ quint32 offset = mapping[i * 2];
+ quint32 line = mapping[i * 2 + 1];
+ offsetsPerLine.insert(line, offset);
+ }
- int pos = helper.upperBound(0, count, line);
- if (pos != 0 && count > 0)
- --pos;
- if (pos == count)
- return -1;
- return helper.table[pos * 2];
+ return offsetsPerLine.values();
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 8a8f6a5d79..5d284f1b2b 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -112,7 +112,7 @@ struct Function {
void mark(ExecutionEngine *e);
int lineNumberForProgramCounter(qptrdiff offset) const;
- qptrdiff programCounterForLine(quint32 line) const;
+ QList<qptrdiff> programCountersForAllLines() const;
};
}
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 7841f7c331..aa1cb89a44 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -438,6 +438,7 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
ExecutionEngine *v4 = that->internalClass->engine;
if (v4->hasException)
return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
Scope scope(v4);
Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
@@ -468,6 +469,7 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
ExecutionEngine *v4 = f->internalClass->engine;
if (v4->hasException)
return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
ExecutionContext *context = v4->current;
Scope scope(context);
@@ -523,6 +525,7 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
ExecutionEngine *v4 = that->internalClass->engine;
if (v4->hasException)
return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
Scope scope(v4);
Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
@@ -566,6 +569,7 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
ExecutionEngine *v4 = that->internalClass->engine;
if (v4->hasException)
return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
@@ -617,6 +621,7 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
ExecutionEngine *v4 = f->internalClass->engine;
if (v4->hasException)
return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
ExecutionContext *context = v4->current;
@@ -636,6 +641,8 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
ExecutionEngine *v4 = f->internalClass->engine;
if (v4->hasException)
return Encode::undefined();
+ CHECK_STACK_LIMITS(v4);
+
ExecutionContext *context = v4->current;
Scope scope(v4);
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index 4f4309769a..cb799a473c 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -69,10 +69,10 @@ static inline int primeForNumBits(int numBits)
}
PropertyHashData::PropertyHashData(int numBits)
- : size(0)
+ : refCount(1)
+ , size(0)
, numBits(numBits)
{
- refCount.store(1);
alloc = primeForNumBits(numBits);
entries = (PropertyHash::Entry *)malloc(alloc*sizeof(PropertyHash::Entry));
memset(entries, 0, alloc*sizeof(PropertyHash::Entry));
@@ -97,8 +97,8 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize)
dd->entries[idx] = e;
}
dd->size = classSize;
- assert(d->refCount.load() > 1);
- d->refCount.deref();
+ Q_ASSERT(d->refCount > 1);
+ --d->refCount;
d = dd;
}
@@ -113,7 +113,7 @@ void PropertyHash::addEntry(const PropertyHash::Entry &entry, int classSize)
uint PropertyHash::lookup(const Identifier *identifier) const
{
- assert(d->entries);
+ Q_ASSERT(d->entries);
uint idx = identifier->hashValue % d->alloc;
while (1) {
@@ -149,9 +149,9 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
if (index)
*index = idx;
- assert(idx != UINT_MAX);
+ Q_ASSERT(idx != UINT_MAX);
- if (data == propertyData[idx])
+ if (data == propertyData.at(idx))
return this;
@@ -162,7 +162,7 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
// create a new class and add it to the tree
InternalClass *newClass = engine->newClass(*this);
- newClass->propertyData[idx] = data;
+ newClass->propertyData.set(idx, data);
transitions.insert(t, newClass);
return newClass;
@@ -189,7 +189,7 @@ InternalClass *InternalClass::changePrototype(Object *proto)
newClass->prototype = proto;
} else {
newClass = engine->emptyClass->changePrototype(proto);
- for (int i = 0; i < nameMap.size(); ++i)
+ for (uint i = 0; i < size; ++i)
newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
}
@@ -228,9 +228,9 @@ InternalClass *InternalClass::addMember(String *string, PropertyAttributes data,
// store a string in the nameMap that's guaranteed to get
// marked properly during GC.
String *name = engine->newIdentifier(string->toQString());
- newClass->nameMap.append(name);
+ newClass->nameMap.add(size, name);
- newClass->propertyData.append(data);
+ newClass->propertyData.add(size, data);
++newClass->size;
transitions.insert(t, newClass);
return newClass;
@@ -238,8 +238,8 @@ InternalClass *InternalClass::addMember(String *string, PropertyAttributes data,
void InternalClass::removeMember(Object *object, Identifier *id)
{
- int propIdx = propertyTable.lookup(id);
- assert(propIdx < static_cast<int>(size));
+ uint propIdx = propertyTable.lookup(id);
+ Q_ASSERT(propIdx < size);
Transition t = { { id } , -1 };
QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
@@ -251,7 +251,7 @@ void InternalClass::removeMember(Object *object, Identifier *id)
// create a new class and add it to the tree
object->internalClass = engine->emptyClass->changePrototype(prototype);
- for (int i = 0; i < nameMap.size(); ++i) {
+ for (uint i = 0; i < size; ++i) {
if (i == propIdx)
continue;
object->internalClass = object->internalClass->addMember(nameMap.at(i), propertyData.at(i));
@@ -284,7 +284,7 @@ InternalClass *InternalClass::sealed()
m_sealed = engine->emptyClass;
m_sealed = m_sealed->changePrototype(prototype);
- for (int i = 0; i < nameMap.size(); ++i) {
+ for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
attrs.setConfigurable(false);
m_sealed = m_sealed->addMember(nameMap.at(i), attrs);
@@ -301,7 +301,7 @@ InternalClass *InternalClass::frozen()
m_frozen = engine->emptyClass;
m_frozen = m_frozen->changePrototype(prototype);
- for (int i = 0; i < nameMap.size(); ++i) {
+ for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
attrs.setWritable(false);
attrs.setConfigurable(false);
@@ -319,12 +319,9 @@ void InternalClass::destroy()
return;
engine = 0;
- // Free the memory of the hashes/vectors by calling clear(), which
- // re-assigns them to the shared null instance. Therefore Internalclass
- // doesn't need a destructor to be called.
propertyTable.~PropertyHash();
- nameMap.clear();
- propertyData.clear();
+ nameMap.~SharedInternalClassData<String *>();
+ propertyData.~SharedInternalClassData<PropertyAttributes>();
if (m_sealed)
m_sealed->destroy();
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 659789b344..9586637b32 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -82,7 +82,7 @@ struct PropertyHashData
free(entries);
}
- QBasicAtomicInt refCount;
+ int refCount;
int alloc;
int size;
int numBits;
@@ -97,15 +97,102 @@ inline PropertyHash::PropertyHash()
inline PropertyHash::PropertyHash(const PropertyHash &other)
{
d = other.d;
- d->refCount.ref();
+ ++d->refCount;
}
inline PropertyHash::~PropertyHash()
{
- if (!d->refCount.deref())
+ if (!--d->refCount)
delete d;
}
+
+template <typename T>
+struct SharedInternalClassData {
+ struct Private {
+ Private(int alloc)
+ : refcount(1),
+ alloc(alloc),
+ size(0)
+ { data = new T [alloc]; }
+ ~Private() { delete [] data; }
+
+ int refcount;
+ uint alloc;
+ uint size;
+ T *data;
+ };
+ Private *d;
+
+ inline SharedInternalClassData() {
+ d = new Private(8);
+ }
+
+ inline SharedInternalClassData(const SharedInternalClassData &other)
+ : d(other.d)
+ {
+ ++d->refcount;
+ }
+ inline ~SharedInternalClassData() {
+ if (!--d->refcount)
+ delete d;
+ }
+
+ void add(uint pos, T value) {
+ if (pos < d->size) {
+ Q_ASSERT(d->refcount > 1);
+ // need to detach
+ Private *dd = new Private(pos + 8);
+ memcpy(dd->data, d->data, pos*sizeof(T));
+ dd->size = pos + 1;
+ dd->data[pos] = value;
+ if (!--d->refcount)
+ delete d;
+ d = dd;
+ return;
+ }
+ Q_ASSERT(pos == d->size);
+ if (pos == d->alloc) {
+ T *n = new T[d->alloc * 2];
+ memcpy(n, d->data, d->alloc*sizeof(T));
+ delete [] d->data;
+ d->data = n;
+ d->alloc *= 2;
+ }
+ d->data[pos] = value;
+ ++d->size;
+ }
+
+ void set(uint pos, T value) {
+ Q_ASSERT(pos < d->size);
+ if (d->refcount > 1) {
+ // need to detach
+ Private *dd = new Private(d->alloc);
+ memcpy(dd->data, d->data, d->size*sizeof(T));
+ dd->size = d->size;
+ if (!--d->refcount)
+ delete d;
+ d = dd;
+ }
+ d->data[pos] = value;
+ }
+
+ T *constData() const {
+ return d->data;
+ }
+ T at(uint i) const {
+ Q_ASSERT(i < d->size);
+ return d->data[i];
+ }
+ T operator[] (uint i) {
+ Q_ASSERT(i < d->size);
+ return d->data[i];
+ }
+
+private:
+ SharedInternalClassData &operator=(const SharedInternalClassData &other);
+};
+
struct InternalClassTransition
{
union {
@@ -124,9 +211,8 @@ struct InternalClass {
ExecutionEngine *engine;
Object *prototype;
PropertyHash propertyTable; // id to valueIndex
- QVector<String *> nameMap;
-
- QVector<PropertyAttributes> propertyData;
+ SharedInternalClassData<String *> nameMap;
+ SharedInternalClassData<PropertyAttributes> propertyData;
typedef InternalClassTransition Transition;
QHash<Transition, InternalClass *> transitions; // id to next class, positive means add, negative delete
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 099b5a5480..cca7d2b26a 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -918,7 +918,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name,
if (isArrayObject() && name->equals(ctx->engine->id_length)) {
assert(ArrayObject::LengthPropertyIndex == internalClass->find(ctx->engine->id_length));
Property *lp = memberData + ArrayObject::LengthPropertyIndex;
- cattrs = internalClass->propertyData.data() + ArrayObject::LengthPropertyIndex;
+ cattrs = internalClass->propertyData.constData() + ArrayObject::LengthPropertyIndex;
if (attrs.isEmpty() || p.isSubset(attrs, *lp, *cattrs))
return true;
if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
@@ -947,7 +947,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, const StringRef name,
{
uint member = internalClass->find(name.getPointer());
current = (member < UINT_MAX) ? memberData + member : 0;
- cattrs = internalClass->propertyData.data() + member;
+ cattrs = internalClass->propertyData.constData() + member;
}
if (!current) {
@@ -1133,7 +1133,7 @@ ReturnedValue Object::arrayIndexOf(const ValueRef v, uint fromIndex, uint endInd
Scope scope(engine());
ScopedValue value(scope);
- if (o->protoHasArray() || o->arrayAttributes) {
+ if (!(flags & SimpleArray) || o->protoHasArray() || o->arrayAttributes) {
// lets be safe and slow
for (uint i = fromIndex; i < endIndex; ++i) {
bool exists;
@@ -1319,19 +1319,17 @@ void Object::arrayReserve(uint n)
off = arrayOffset;
}
arrayAlloc = qMax(n, 2*arrayAlloc);
- Property *newArrayData = new Property[arrayAlloc];
+ Property *newArrayData = new Property[arrayAlloc + off];
if (arrayData) {
- memcpy(newArrayData, arrayData, sizeof(Property)*arrayDataLen);
+ memcpy(newArrayData + off, arrayData, sizeof(Property)*arrayDataLen);
delete [] (arrayData - off);
}
- arrayData = newArrayData;
+ arrayData = newArrayData + off;
if (sparseArray) {
for (uint i = arrayFreeList; i < arrayAlloc; ++i) {
arrayData[i].value = Primitive::emptyValue();
arrayData[i].value = Primitive::fromInt32(i + 1);
}
- } else {
- arrayOffset = 0;
}
if (arrayAttributes) {
@@ -1354,7 +1352,9 @@ void Object::ensureArrayAttributes()
return;
flags &= ~SimpleArray;
- arrayAttributes = new PropertyAttributes[arrayAlloc];
+ uint off = sparseArray ? 0 : arrayOffset;
+ arrayAttributes = new PropertyAttributes[arrayAlloc + off];
+ arrayAttributes += off;
for (uint i = 0; i < arrayDataLen; ++i)
arrayAttributes[i] = Attr_Data;
for (uint i = arrayDataLen; i < arrayAlloc; ++i)
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 578c7310f2..f1b0e0bdc4 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -334,7 +334,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
return getProperty(ctx, result);
}
-ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, QQmlPropertyData *property)
+ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
{
QV4::Scope scope(ctx);
@@ -371,17 +371,19 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, QQmlPropertyDat
QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->engine->v8Engine, m_object, *property, nptr));
- if (property->accessors->notifier) {
- if (n)
- ep->captureProperty(n);
- } else {
- ep->captureProperty(m_object, property->coreIndex, property->notifyIndex);
+ if (captureRequired) {
+ if (property->accessors->notifier) {
+ if (n)
+ ep->captureProperty(n);
+ } else {
+ ep->captureProperty(m_object, property->coreIndex, property->notifyIndex);
+ }
}
return rv.asReturnedValue();
}
- if (ep && !property->isConstant())
+ if (captureRequired && ep && !property->isConstant())
ep->captureProperty(m_object, property->coreIndex, property->notifyIndex);
if (property->isVarProperty()) {
@@ -614,7 +616,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
}
}
-ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, int propertyIndex)
+ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, int propertyIndex, bool captureRequired)
{
if (QQmlData::wasDeleted(m_object))
return QV4::Encode::null();
@@ -626,7 +628,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, int propertyInd
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return getProperty(ctx, property);
+ return getProperty(ctx, property, captureRequired);
}
void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const ValueRef value)
@@ -644,6 +646,15 @@ void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const
return setProperty(m_object, ctx, property, value);
}
+bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
+{
+ QV4::QObjectWrapper *qobjectWrapper = a->as<QV4::QObjectWrapper>();
+ if (QV4::QmlTypeWrapper *qmlTypeWrapper = b->asObject()->as<QV4::QmlTypeWrapper>())
+ return qmlTypeWrapper->toVariant().value<QObject*>() == qobjectWrapper->object();
+
+ return false;
+}
+
ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QQmlData *ddata, QObject *object)
{
QQmlEngine *qmlEngine = engine->v8Engine->engine();
@@ -1537,6 +1548,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
QV4::Scope scope(QV8Engine::getV4(engine));
+ bool queryEngine = false;
if (callType == qMetaTypeId<QJSValue>()) {
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(v4, value));
@@ -1566,6 +1578,8 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
qobjectPtr = 0;
if (QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
+ else if (QV4::QmlTypeWrapper *qmlTypeWrapper = value->as<QV4::QmlTypeWrapper>())
+ queryEngine = qmlTypeWrapper->isSingleton();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, -1));
@@ -1608,6 +1622,10 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
} else if (callType == QMetaType::Void) {
*qvariantPtr = QVariant();
} else {
+ queryEngine = true;
+ }
+
+ if (queryEngine) {
qvariantPtr = new (&allocData) QVariant();
type = -1;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index f6c333f401..a73c96d098 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -94,11 +94,14 @@ struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
using Object::get;
- ReturnedValue getProperty(ExecutionContext *ctx, int propertyIndex);
+ ReturnedValue getProperty(ExecutionContext *ctx, int propertyIndex, bool captureRequired);
void setProperty(ExecutionContext *ctx, int propertyIndex, const ValueRef value);
+protected:
+ static bool isEqualTo(Managed *that, Managed *o);
+
private:
- ReturnedValue getProperty(ExecutionContext *ctx, QQmlPropertyData *property);
+ ReturnedValue getProperty(ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
static void setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const ValueRef value);
static ReturnedValue create(ExecutionEngine *engine, QQmlData *ddata, QObject *object);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 75af118090..a8cabcb374 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -533,6 +533,8 @@ void __qmljs_set_property(ExecutionContext *ctx, const ValueRef object, const St
{
Scope scope(ctx);
ScopedObject o(scope, object->toObject(ctx));
+ if (!o)
+ return;
o->put(name, value);
}
@@ -720,8 +722,8 @@ Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y)
if (x->isNumber())
return y->isNumber() && x->asDouble() == y->asDouble();
- if (x->isString())
- return y->isString() && x->stringValue()->isEqualTo(y->stringValue());
+ if (x->isManaged())
+ return y->isManaged() && x->managed()->isEqualTo(y->managed());
return false;
}
@@ -1247,7 +1249,7 @@ ReturnedValue __qmljs_get_scope_object(NoThrowContext *ctx)
return QObjectWrapper::wrap(ctx->engine, c->getScopeObject());
}
-ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex)
+ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired)
{
Scope scope(ctx);
QV4::Scoped<QObjectWrapper> wrapper(scope, object);
@@ -1255,7 +1257,7 @@ ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef
ctx->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- return wrapper->getProperty(ctx, propertyIndex);
+ return wrapper->getProperty(ctx, propertyIndex, captureRequired);
}
void __qmljs_set_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value)
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index b2d2d211eb..b5567693e5 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -174,7 +174,7 @@ QV4::ReturnedValue __qmljs_get_id_object(NoThrowContext *ctx, int id);
QV4::ReturnedValue __qmljs_get_imported_scripts(NoThrowContext *ctx);
QV4::ReturnedValue __qmljs_get_context_object(NoThrowContext *ctx);
QV4::ReturnedValue __qmljs_get_scope_object(NoThrowContext *ctx);
-QV4::ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex);
+QV4::ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired);
void __qmljs_set_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value);
// For each
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 26cb0d940c..25791cff61 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -89,6 +89,8 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml)
ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
{
ExecutionEngine *engine = that->engine();
+ CHECK_STACK_LIMITS(engine);
+
Scope scope(engine);
QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
Q_ASSERT(This->function);
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index ec6b0f5ad1..3ee89d5b53 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -57,9 +57,9 @@ bool ArrayElementLessThan::operator()(const Property &p1, const Property &p2) co
{
Scope scope(m_context);
- if (p1.value.isUndefined())
+ if (p1.value.isUndefined() || p1.value.isEmpty())
return false;
- if (p2.value.isUndefined())
+ if (p2.value.isUndefined() || p2.value.isEmpty())
return true;
ScopedObject o(scope, m_comparefn);
if (o) {
@@ -71,7 +71,7 @@ bool ArrayElementLessThan::operator()(const Property &p1, const Property &p2) co
callData->args[1] = p2.value;
result = __qmljs_call_value(m_context, m_comparefn, callData);
- return result->toNumber() <= 0;
+ return result->toNumber() < 0;
}
ScopedString p1s(scope, p1.value.toString(m_context));
ScopedString p2s(scope, p2.value.toString(m_context));
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index eef901d74a..0e43d03987 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -234,7 +234,10 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (t == o)
return true;
- Q_ASSERT(t->type == Type_String && o->type == Type_String);
+ if (o->type != Type_String)
+ return false;
+
+ Q_ASSERT(t->type == Type_String);
String *that = static_cast<String *>(t);
String *other = static_cast<String *>(o);
if (that->hashValue() != other->hashValue())
diff --git a/src/qml/jsruntime/qv4value_def_p.h b/src/qml/jsruntime/qv4value_def_p.h
index 48b50951f9..cf351c125a 100644
--- a/src/qml/jsruntime/qv4value_def_p.h
+++ b/src/qml/jsruntime/qv4value_def_p.h
@@ -243,7 +243,7 @@ struct Q_QML_EXPORT Value
void setDouble(double d) { dbl = d; }
bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
#endif
- bool isString() const;
+ inline bool isString() const;
inline bool isObject() const;
inline bool isInt32() {
if (tag == _Integer_Type)
@@ -286,15 +286,15 @@ struct Q_QML_EXPORT Value
return val;
}
- static Value fromManaged(Managed *o);
+ static inline Value fromManaged(Managed *o);
int toUInt16() const;
- int toInt32() const;
- unsigned int toUInt32() const;
+ inline int toInt32() const;
+ inline unsigned int toUInt32() const;
- bool toBoolean() const;
+ inline bool toBoolean() const;
double toInteger() const;
- double toNumber() const;
+ inline double toNumber() const;
double toNumberImpl() const;
QString toQStringNoThrow() const;
QString toQString() const;
@@ -309,20 +309,20 @@ struct Q_QML_EXPORT Value
return b;
}
- String *asString() const;
- Managed *asManaged() const;
- Object *asObject() const;
- FunctionObject *asFunctionObject() const;
- NumberObject *asNumberObject() const;
- StringObject *asStringObject() const;
- DateObject *asDateObject() const;
- ArrayObject *asArrayObject() const;
- ErrorObject *asErrorObject() const;
+ inline String *asString() const;
+ inline Managed *asManaged() const;
+ inline Object *asObject() const;
+ inline FunctionObject *asFunctionObject() const;
+ inline NumberObject *asNumberObject() const;
+ inline StringObject *asStringObject() const;
+ inline DateObject *asDateObject() const;
+ inline ArrayObject *asArrayObject() const;
+ inline ErrorObject *asErrorObject() const;
template<typename T> inline T *as() const;
- uint asArrayIndex() const;
- uint asArrayLength(bool *ok) const;
+ inline uint asArrayIndex() const;
+ inline uint asArrayLength(bool *ok) const;
inline ExecutionEngine *engine() const;
@@ -354,13 +354,13 @@ inline String *Value::asString() const
struct Q_QML_EXPORT Primitive : public Value
{
- static Primitive emptyValue();
- static Primitive fromBoolean(bool b);
- static Primitive fromInt32(int i);
- static Primitive undefinedValue();
- static Primitive nullValue();
- static Primitive fromDouble(double d);
- static Primitive fromUInt32(uint i);
+ inline static Primitive emptyValue();
+ static inline Primitive fromBoolean(bool b);
+ static inline Primitive fromInt32(int i);
+ inline static Primitive undefinedValue();
+ static inline Primitive nullValue();
+ static inline Primitive fromDouble(double d);
+ static inline Primitive fromUInt32(uint i);
static double toInteger(double fromNumber);
static int toInt32(double value);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 68f791c87d..72db469ee6 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -317,7 +317,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
MOTH_END_INSTR(StoreQObjectProperty)
MOTH_BEGIN_INSTR(LoadQObjectProperty)
- STOREVALUE(instr.result, __qmljs_get_qobject_property(context, VALUEPTR(instr.base), instr.propertyIndex));
+ STOREVALUE(instr.result, __qmljs_get_qobject_property(context, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
MOTH_BEGIN_INSTR(Push)
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 3bba6f8e83..f969f5c644 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -126,7 +126,7 @@ HEADERS += \
$$PWD/qqmlplatform_p.h \
$$PWD/qqmlbinding_p.h \
$$PWD/qqmlextensionplugin_p.h \
- $$PWD/qqmlabstracturlinterceptor.h \
+ $$PWD/qqmlabstracturlinterceptor_p.h \
$$PWD/qqmlapplicationengine_p.h \
$$PWD/qqmlapplicationengine.h \
$$PWD/qqmllistwrapper_p.h \
diff --git a/src/qml/qml/qqmlabstracturlinterceptor.cpp b/src/qml/qml/qqmlabstracturlinterceptor.cpp
index 127dad86ce..321698ad8e 100644
--- a/src/qml/qml/qqmlabstracturlinterceptor.cpp
+++ b/src/qml/qml/qqmlabstracturlinterceptor.cpp
@@ -44,6 +44,9 @@
\inmodule QtQml
\brief allows you to control QML file loading.
+ \note This class is not currently public API, due to the risk of being affected
+ by planned engine changes in upcoming releases.
+
QQmlAbstractUrlInterceptor is an interface which can be used to alter URLs
before they are used by the QML engine. This is primarily useful for altering
file urls into other file urls, such as selecting different graphical assets
diff --git a/src/qml/qml/qqmlabstracturlinterceptor.h b/src/qml/qml/qqmlabstracturlinterceptor_p.h
index 4bcaa89b4a..471c837eed 100644
--- a/src/qml/qml/qqmlabstracturlinterceptor.h
+++ b/src/qml/qml/qqmlabstracturlinterceptor_p.h
@@ -43,11 +43,11 @@
#define QQMLABSTRACTURLINTERCEPTOR_H
#include <QtCore/qurl.h>
-#include <QtQml/qtqmlglobal.h>
+#include <private/qtqmlglobal_p.h>
QT_BEGIN_NAMESPACE
-class Q_QML_EXPORT QQmlAbstractUrlInterceptor
+class Q_QML_PRIVATE_EXPORT QQmlAbstractUrlInterceptor
{
Q_FLAGS(InterceptionPoint)
public:
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 3f13f8a140..b4ace17738 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -77,7 +77,7 @@ void QQmlApplicationEnginePrivate::init()
QCoreApplication::installTranslator(qtTranslator);
translators << qtTranslator;
#endif
- q->setUrlInterceptor(new QQmlFileSelector(q));
+ new QQmlFileSelector(q,q);
QCoreApplication::instance()->setProperty("__qml_using_qqmlapplicationengine", QVariant(true));
}
diff --git a/src/qml/qml/qqmlcompiler.cpp b/src/qml/qml/qqmlcompiler.cpp
index fdbbed0bf8..7b33849e67 100644
--- a/src/qml/qml/qqmlcompiler.cpp
+++ b/src/qml/qml/qqmlcompiler.cpp
@@ -61,7 +61,7 @@
#include "qqmlscriptstring.h"
#include "qqmlglobal_p.h"
#include "qqmlbinding_p.h"
-#include "qqmlabstracturlinterceptor.h"
+#include "qqmlabstracturlinterceptor_p.h"
#include "qqmlcodegenerator_p.h"
#include <QDebug>
@@ -3682,6 +3682,11 @@ bool QQmlCompiler::completeComponentBuild()
jsCodeGen.beginObjectScope(scopeObject->metatype);
cd->runtimeFunctionIndices = jsCodeGen.generateJSCodeForFunctionsAndBindings(cd->functionsToCompile, expressionNames);
+ QList<QQmlError> errors = jsCodeGen.errors();
+ if (!errors.isEmpty()) {
+ exceptions << errors;
+ return false;
+ }
foreach (const QQmlCompilerTypes::ComponentCompileState::CompiledMetaMethod &cmm, cd->compiledMetaMethods) {
typedef QQmlVMEMetaData VMD;
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 78e6650d02..7731935b75 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -48,7 +48,7 @@
#include "qqmlengine_p.h"
#include "qqmlengine.h"
#include "qqmlinfo.h"
-#include "qqmlabstracturlinterceptor.h"
+#include "qqmlabstracturlinterceptor_p.h"
#include <qjsengine.h>
#include <QtCore/qvarlengtharray.h>
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index f7b36b51bb..81ccec3571 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -66,7 +66,7 @@
#include <private/qv4debugservice_p.h>
#include <private/qdebugmessageservice_p.h>
#include "qqmlincubator.h"
-#include "qqmlabstracturlinterceptor.h"
+#include "qqmlabstracturlinterceptor_p.h"
#include <private/qv8profilerservice_p.h>
#include <private/qqmlboundsignal_p.h>
diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp
index 5810e269eb..7f2007ec00 100644
--- a/src/qml/qml/qqmlfileselector.cpp
+++ b/src/qml/qml/qqmlfileselector.cpp
@@ -40,26 +40,30 @@
****************************************************************************/
#include <QtCore/QFileSelector>
+#include <qobjectdefs.h>
#include "qqmlfileselector.h"
#include "qqmlfileselector_p.h"
+#include "qqmlabstracturlinterceptor_p.h"
+#include <QDebug>
QT_BEGIN_NAMESPACE
+typedef QHash<QQmlAbstractUrlInterceptor*, QQmlFileSelector*> interceptorSelectorMap;
+Q_GLOBAL_STATIC(interceptorSelectorMap, interceptorInstances);
/*!
\class QQmlFileSelector
\since 5.2
\inmodule QtQml
- \brief A convenience class for applying a QFileSelector to QML file loading
+ \brief A class for applying a QFileSelector to QML file loading
- QQmlFileSelector is a QQmlAbstractUrlInterceptor which will automatically apply a QFileSelector to
+ QQmlFileSelector will automatically apply a QFileSelector to
qml file and asset paths.
It is used as follows:
\code
QQmlEngine engine;
- QQmlFileSelector selector;
- engine.setUrlInterceptor(&selector);
+ QQmlFileSelector* selector = new QQmlFileSelector(&engine);
\endcode
Then you can swap out files like so:
@@ -86,15 +90,34 @@ QT_BEGIN_NAMESPACE
Your platform may also provide additional selectors for you to use. As specified by QFileSelector,
directories used for selection must start with a '+' character, so you will not accidentally
trigger this feature unless you have directories with such names inside your project.
+
+ If a new QQmlFileSelector is set on the engine, the old one will be replaced. Use
+ \l QQmlFileSelector::get to query or use the existing instance.
*/
/*!
Creates a new QQmlFileSelector, which includes its own QFileSelector.
+ \a engine is the QQmlEngine you wish to apply file selectors too. It will
+ also take ownership of the QQmlFileSelector.
*/
-QQmlFileSelector::QQmlFileSelector(QObject* parent)
+QQmlFileSelector::QQmlFileSelector(QQmlEngine* engine, QObject* parent)
: QObject(*(new QQmlFileSelectorPrivate), parent)
{
+ Q_D(QQmlFileSelector);
+ d->engine = engine;
+ interceptorInstances()->insert(d->myInstance, this);
+ d->engine->setUrlInterceptor(d->myInstance);
+}
+
+QQmlFileSelector::~QQmlFileSelector()
+{
+ Q_D(QQmlFileSelector);
+ if (d->engine && QQmlFileSelector::get(d->engine) == this) {
+ d->engine->setUrlInterceptor(0);
+ d->engine = 0;
+ }
+ interceptorInstances()->remove(d->myInstance);
}
QQmlFileSelectorPrivate::QQmlFileSelectorPrivate()
@@ -102,6 +125,7 @@ QQmlFileSelectorPrivate::QQmlFileSelectorPrivate()
Q_Q(QQmlFileSelector);
ownSelector = true;
selector = new QFileSelector(q);
+ myInstance = new QQmlFileSelectorInterceptor(this);
}
/*!
@@ -127,9 +151,42 @@ void QQmlFileSelector::setSelector(QFileSelector *selector)
}
}
-QUrl QQmlFileSelector::intercept(const QUrl &path, DataType type)
+/*!
+ Adds extra selectors to the current QFileSelector being used. Use this when
+ extra selectors are all you need to avoid having to create your own
+ QFileSelector instance.
+*/
+void QQmlFileSelector::setExtraSelectors(QStringList &strings)
{
Q_D(QQmlFileSelector);
+ d->selector->setExtraSelectors(strings);
+}
+
+/*!
+ Gets the QQmlFileSelector currently active on the target engine.
+*/
+QQmlFileSelector* QQmlFileSelector::get(QQmlEngine* engine)
+{
+ //Since I think we still can't use dynamic_cast inside Qt...
+ QQmlAbstractUrlInterceptor* current = engine->urlInterceptor();
+ if (current && interceptorInstances()->contains(current))
+ return interceptorInstances()->value(current);
+ return 0;
+}
+
+/*!
+ \internal
+*/
+QQmlFileSelectorInterceptor::QQmlFileSelectorInterceptor(QQmlFileSelectorPrivate* pd)
+ : d(pd)
+{
+}
+
+/*!
+ \internal
+*/
+QUrl QQmlFileSelectorInterceptor::intercept(const QUrl &path, DataType type)
+{
if ( type == QQmlAbstractUrlInterceptor::QmldirFile ) //Don't intercept qmldir files, to prevent double interception
return path;
return d->selector->select(path);
diff --git a/src/qml/qml/qqmlfileselector.h b/src/qml/qml/qqmlfileselector.h
index 2be221e0e4..ec9bbc77db 100644
--- a/src/qml/qml/qqmlfileselector.h
+++ b/src/qml/qml/qqmlfileselector.h
@@ -44,23 +44,23 @@
#include <QtCore/QObject>
#include <QtCore/QUrl>
-#include <QtQml/QQmlAbstractUrlInterceptor>
+#include <QtQml/QQmlEngine>
#include <QtQml/qtqmlglobal.h>
QT_BEGIN_NAMESPACE
class QFileSelector;
class QQmlFileSelectorPrivate;
-class Q_QML_EXPORT QQmlFileSelector : public QObject, public QQmlAbstractUrlInterceptor
+class Q_QML_EXPORT QQmlFileSelector : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQmlFileSelector)
public:
- QQmlFileSelector(QObject* parent=0);
+ QQmlFileSelector(QQmlEngine* engine, QObject* parent=0);
+ ~QQmlFileSelector();
void setSelector(QFileSelector *selector);
-
-protected:
- virtual QUrl intercept(const QUrl &path, DataType type);
+ void setExtraSelectors(QStringList &strings);
+ static QQmlFileSelector* get(QQmlEngine*);
private:
Q_DISABLE_COPY(QQmlFileSelector)
diff --git a/src/qml/qml/qqmlfileselector_p.h b/src/qml/qml/qqmlfileselector_p.h
index 60d6072c8c..fe3679e08d 100644
--- a/src/qml/qml/qqmlfileselector_p.h
+++ b/src/qml/qml/qqmlfileselector_p.h
@@ -54,19 +54,33 @@
//
#include "qqmlfileselector.h"
+#include "qqmlabstracturlinterceptor_p.h"
+#include <QSet>
#include <private/qobject_p.h>
#include <private/qtqmlglobal_p.h>
QT_BEGIN_NAMESPACE
class QFileSelector;
+class QQmlFileSelectorInterceptor;
class Q_QML_PRIVATE_EXPORT QQmlFileSelectorPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQmlFileSelector)
public:
QQmlFileSelectorPrivate();
QFileSelector* selector;
+ QPointer<QQmlEngine> engine;
bool ownSelector;
+ QQmlFileSelectorInterceptor* myInstance;
+};
+
+class Q_QML_PRIVATE_EXPORT QQmlFileSelectorInterceptor : public QQmlAbstractUrlInterceptor
+{
+public:
+ QQmlFileSelectorInterceptor(QQmlFileSelectorPrivate* pd);
+ QQmlFileSelectorPrivate* d;
+protected:
+ virtual QUrl intercept(const QUrl &path, DataType type);
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index f33fd97c16..30b5abb383 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1023,7 +1023,8 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba
dir.chop(1);
QStringList paths = database->fileImportPath;
- std::sort(paths.begin(), paths.end(), I::greaterThan); // Ensure subdirs preceed their parents.
+ if (!paths.isEmpty())
+ std::sort(paths.begin(), paths.end(), I::greaterThan); // Ensure subdirs preceed their parents.
QString stableRelativePath = dir;
foreach(const QString &path, paths) {
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 85d2fe41d9..895a2a9cd6 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "qqmltypeloader_p.h"
-#include "qqmlabstracturlinterceptor.h"
+#include "qqmlabstracturlinterceptor_p.h"
#include "qqmlcontextwrapper_p.h"
#include "qqmlexpression_p.h"
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index b93cf2942d..c9a5edc39e 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -59,7 +59,6 @@
#include <QtQml/qqmlerror.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlfile.h>
-#include <QtQml/qqmlabstracturlinterceptor.h>
#include <private/qhashedstring_p.h>
#include <private/qqmlscript_p.h>
@@ -68,6 +67,7 @@
#include <private/qqmldirparser_p.h>
#include <private/qqmlbundle_p.h>
#include <private/qflagpointer_p.h>
+#include <private/qqmlabstracturlinterceptor_p.h>
#include <private/qv4value_p.h>
#include <private/qv4script_p.h>
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index f309d69136..258442bc1d 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -69,6 +69,11 @@ QmlTypeWrapper::~QmlTypeWrapper()
typeNamespace->release();
}
+bool QmlTypeWrapper::isSingleton() const
+{
+ return type && type->isSingleton();
+}
+
QVariant QmlTypeWrapper::toVariant() const
{
if (type && type->isSingleton()) {
@@ -281,4 +286,15 @@ void QmlTypeWrapper::destroy(Managed *that)
static_cast<QmlTypeWrapper *>(that)->~QmlTypeWrapper();
}
+bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
+{
+ QV4::QmlTypeWrapper *qmlTypeWrapperA = a->asObject()->as<QV4::QmlTypeWrapper>();
+ if (QV4::QmlTypeWrapper *qmlTypeWrapperB = b->asObject()->as<QV4::QmlTypeWrapper>())
+ return qmlTypeWrapperA->toVariant() == qmlTypeWrapperB->toVariant();
+ else if (QV4::QObjectWrapper *qobjectWrapper = b->as<QV4::QObjectWrapper>())
+ return qmlTypeWrapperA->toVariant().value<QObject*>() == qobjectWrapper->object();
+
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 9078c184c6..ee462d6479 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -76,6 +76,8 @@ private:
public:
enum TypeNameMode { IncludeEnums, ExcludeEnums };
+ bool isSingleton() const;
+
QVariant toVariant() const;
static ReturnedValue create(QV8Engine *, QObject *, QQmlType *, TypeNameMode = IncludeEnums);
@@ -87,6 +89,9 @@ public:
static PropertyAttributes query(const Managed *, StringRef name);
static void destroy(Managed *that);
+protected:
+ static bool isEqualTo(Managed *that, Managed *o);
+
private:
QV8Engine *v8;
TypeNameMode mode;
diff --git a/src/quick/doc/src/concepts/statesanimations/animations.qdoc b/src/quick/doc/src/concepts/statesanimations/animations.qdoc
index 1a324b1983..07f1048bf2 100644
--- a/src/quick/doc/src/concepts/statesanimations/animations.qdoc
+++ b/src/quick/doc/src/concepts/statesanimations/animations.qdoc
@@ -32,7 +32,7 @@
\brief the animation system in Qt Quick
\section1 Animation and Transitions Types
-\generatelist{related}
+
\list
\li \l {Transition} - Animates transitions during state changes
\li \l {SequentialAnimation} - Runs animations sequentially
@@ -47,15 +47,6 @@
Types that animate properties based on data types
\annotatedlist qtquick-animation-properties
-\list
-\li \l {PropertyAnimation} - Animates property changes
-\li \l {NumberAnimation} - Animates properties of type qreal
-\li \l {Vector3dAnimation} - Animates properties of type QVector3d
-\li \l {ColorAnimation} - Animates color changes
-\li \l {RotationAnimation} - Animates rotations
-\li \l {ParentAnimation} - Animates parent changes
-\li \l {AnchorAnimation} - Animates anchor changes
-\endlist
Animations are created by applying animation types to property
values. Animation types will interpolate property values to create smooth
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 908e0c91a4..2a9e0f2ac2 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -1660,7 +1660,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
QV8Engine *engine = ctx->engine->v8Engine;
- if (ctx->callData->argc == 6) {
+ if (ctx->callData->argc == 3) {
qreal x = ctx->callData->args[0].toNumber();
qreal y = ctx->callData->args[1].toNumber();
qreal angle = DEGREES(ctx->callData->args[2].toNumber());
@@ -2981,7 +2981,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
} else if (arg->isObject()) {
if (QV4::Referenced<QV4::QObjectWrapper> qobjectWrapper = arg->asRef<QV4::QObjectWrapper>()) {
if (QQuickImage *imageItem = qobject_cast<QQuickImage*>(qobjectWrapper->object())) {
- pixmap.take(r->context->createPixmap(imageItem->source()));
+ pixmap = r->context->createPixmap(imageItem->source());
} else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
QImage img = canvas->toImage();
if (!img.isNull())
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index d0ebbcfcdb..3996512f9d 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -145,7 +145,13 @@ OTHER_FILES += \
$$PWD/shaders/shadereffect.vert \
$$PWD/shaders/shadereffect.frag \
$$PWD/shaders/shadereffectfallback.vert \
- $$PWD/shaders/shadereffectfallback.frag
+ $$PWD/shaders/shadereffectfallback.frag \
+ $$PWD/shaders/sprite_core.vert \
+ $$PWD/shaders/sprite_core.frag \
+ $$PWD/shaders/shadereffect_core.vert \
+ $$PWD/shaders/shadereffect_core.frag \
+ $$PWD/shaders/shadereffectfallback_core.vert \
+ $$PWD/shaders/shadereffectfallback_core.frag
RESOURCES += \
$$PWD/items.qrc
diff --git a/src/quick/items/items.qrc b/src/quick/items/items.qrc
index 837cffb65a..671d8acdbb 100644
--- a/src/quick/items/items.qrc
+++ b/src/quick/items/items.qrc
@@ -6,5 +6,11 @@
<file>shaders/shadereffect.frag</file>
<file>shaders/shadereffectfallback.frag</file>
<file>shaders/shadereffectfallback.vert</file>
+ <file>shaders/shadereffect_core.frag</file>
+ <file>shaders/shadereffect_core.vert</file>
+ <file>shaders/shadereffectfallback_core.frag</file>
+ <file>shaders/shadereffectfallback_core.vert</file>
+ <file>shaders/sprite_core.frag</file>
+ <file>shaders/sprite_core.vert</file>
</qresource>
</RCC>
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 55ba25c63f..c11bf904be 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -3827,7 +3827,12 @@ void QQuickItem::setBaselineOffset(qreal offset)
void QQuickItem::update()
{
Q_D(QQuickItem);
- Q_ASSERT(flags() & ItemHasContents);
+ if (!(flags() & ItemHasContents)) {
+#ifndef QT_NO_DEBUG
+ qWarning() << metaObject()->className() << ": Update called for a item without content";
+#endif
+ return;
+ }
d->dirty(QQuickItemPrivate::Content);
}
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index e32f31308e..48c0f8e084 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
/*!
\qmltype Screen
\instantiates QQuickScreenAttached
- \inqmlmodule QtQuick.Window 2
+ \inqmlmodule QtQuick.Window
\ingroup qtquick-visual-utility
\brief The Screen attached object provides information about the Screen an Item or Window is displayed on.
@@ -80,26 +80,26 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \qmlattachedproperty String QtQuick.Window::Screen::name
+ \qmlattachedproperty string Screen::name
\readonly
\since 5.1
The name of the screen.
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::width
+ \qmlattachedproperty int Screen::width
\readonly
This contains the width of the screen in pixels.
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::height
+ \qmlattachedproperty int Screen::height
\readonly
This contains the height of the screen in pixels.
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::desktopAvailableWidth
+ \qmlattachedproperty int Screen::desktopAvailableWidth
\readonly
\since 5.1
@@ -113,7 +113,7 @@ QT_BEGIN_NAMESPACE
\endqml
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::desktopAvailableHeight
+ \qmlattachedproperty int Screen::desktopAvailableHeight
\readonly
\since 5.1
@@ -127,23 +127,30 @@ QT_BEGIN_NAMESPACE
\endqml
*/
/*!
- \qmlattachedproperty real QtQuick.Window::Screen::logicalPixelDensity
+ \qmlattachedproperty real Screen::logicalPixelDensity
\readonly
\since 5.1
+ \deprecated
- The number of logical pixels per millimeter. Logical pixels are the
- usual units in QML; on some systems they may be different than physical
- pixels.
+ The number of logical pixels per millimeter. This is the effective pixel
+ density provided by the platform to use in image scaling calculations.
+
+ Due to inconsistencies in how logical pixel density is handled across
+ the various platforms Qt supports, it is recommended to
+ use physical pixels instead (via the \c pixelDensity property) for
+ portability.
+
+ \sa pixelDensity
*/
/*!
- \qmlattachedproperty real QtQuick.Window::Screen::pixelDensity
+ \qmlattachedproperty real Screen::pixelDensity
\readonly
\since 5.2
The number of physical pixels per millimeter.
*/
/*!
- \qmlattachedproperty Qt::ScreenOrientation QtQuick.Window::Screen::primaryOrientation
+ \qmlattachedproperty Qt::ScreenOrientation Screen::primaryOrientation
\readonly
This contains the primary orientation of the screen. If the
@@ -160,7 +167,7 @@ QT_BEGIN_NAMESPACE
automatically, so again you will see the primaryOrientation change.
*/
/*!
- \qmlattachedproperty Qt::ScreenOrientation QtQuick.Window::Screen::orientation
+ \qmlattachedproperty Qt::ScreenOrientation Screen::orientation
\readonly
This contains the current orientation of the screen, from the accelerometer
@@ -174,7 +181,7 @@ QT_BEGIN_NAMESPACE
\l Item.transform to rotate your content.
*/
/*!
- \qmlattachedmethod int QtQuick.Window::Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
+ \qmlattachedmethod int Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
Returns the rotation angle, in degrees, between the two specified angles.
*/
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 28a5df789f..41a1781394 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -865,7 +865,7 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
/*!
\qmltype Window
\instantiates QQuickWindow
- \inqmlmodule QtQuick.Window 2
+ \inqmlmodule QtQuick.Window
\ingroup qtquick-visual
\brief Creates a new top-level window
@@ -2114,7 +2114,7 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent
}
/*!
- \qmlproperty list<Object> QtQuick.Window::Window::data
+ \qmlproperty list<Object> Window::data
\default
The data property allows you to freely mix visual children, resources
@@ -2631,7 +2631,7 @@ QOpenGLContext *QQuickWindow::openglContext() const
/*!
\qmltype CloseEvent
\instantiates QQuickCloseEvent
- \inqmlmodule QtQuick.Window 2
+ \inqmlmodule QtQuick.Window
\ingroup qtquick-visual
\brief Notification that a \l Window is about to be closed
\since 5.1
@@ -2644,7 +2644,7 @@ QOpenGLContext *QQuickWindow::openglContext() const
*/
/*!
- \qmlproperty bool QtQuick.Window::CloseEvent::accepted
+ \qmlproperty bool CloseEvent::accepted
This property indicates whether the application will allow the user to
close the window. It is true by default.
@@ -2659,7 +2659,7 @@ QOpenGLContext *QQuickWindow::openglContext() const
*/
/*!
- \qmlsignal QtQuick.Window::closing(CloseEvent close)
+ \qmlsignal closing(CloseEvent close)
\since 5.1
This signal is emitted when the user tries to close the window.
@@ -3019,7 +3019,7 @@ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, Create
}
/*!
- \qmlproperty color QtQuick.Window::Window::color
+ \qmlproperty color Window::color
The background color for the window.
@@ -3148,7 +3148,7 @@ void QQuickWindow::resetOpenGLState()
}
/*!
- \qmlproperty string QtQuick.Window::Window::title
+ \qmlproperty string Window::title
The window's title in the windowing system.
@@ -3159,7 +3159,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Qt::WindowModality QtQuick.Window::Window::modality
+ \qmlproperty Qt::WindowModality Window::modality
The modality of the window.
@@ -3169,7 +3169,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Qt::WindowFlags QtQuick.Window::Window::flags
+ \qmlproperty Qt::WindowFlags Window::flags
The window flags of the window.
@@ -3182,10 +3182,10 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty int QtQuick.Window::Window::x
- \qmlproperty int QtQuick.Window::Window::y
- \qmlproperty int QtQuick.Window::Window::width
- \qmlproperty int QtQuick.Window::Window::height
+ \qmlproperty int Window::x
+ \qmlproperty int Window::y
+ \qmlproperty int Window::width
+ \qmlproperty int Window::height
Defines the window's position and size.
@@ -3200,8 +3200,8 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty int QtQuick.Window::Window::minimumWidth
- \qmlproperty int QtQuick.Window::Window::minimumHeight
+ \qmlproperty int Window::minimumWidth
+ \qmlproperty int Window::minimumHeight
\since 5.1
Defines the window's minimum size.
@@ -3211,8 +3211,8 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty int QtQuick.Window::Window::maximumWidth
- \qmlproperty int QtQuick.Window::Window::maximumHeight
+ \qmlproperty int Window::maximumWidth
+ \qmlproperty int Window::maximumHeight
\since 5.1
Defines the window's maximum size.
@@ -3222,7 +3222,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty bool QtQuick.Window::Window::visible
+ \qmlproperty bool Window::visible
Whether the window is visible on the screen.
@@ -3232,7 +3232,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty QWindow::Visibility QtQuick.Window::Window::visibility
+ \qmlproperty QWindow::Visibility Window::visibility
The screen-occupation state of the window.
@@ -3252,7 +3252,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Qt::ScreenOrientation QtQuick.Window::Window::contentOrientation
+ \qmlproperty Qt::ScreenOrientation Window::contentOrientation
This is a hint to the window manager in case it needs to display
additional content like popups, dialogs, status bars, or similar
@@ -3273,7 +3273,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty real QtQuick.Window::Window::opacity
+ \qmlproperty real Window::opacity
The opacity of the window.
@@ -3290,7 +3290,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Item QtQuick.Window::Window::activeFocusItem
+ \qmlproperty Item Window::activeFocusItem
\since 5.1
The item which currently has active focus or \c null if there is
@@ -3298,7 +3298,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty QtQuick.Window::Window::active
+ \qmlproperty Window::active
\since 5.1
The active status of the window.
diff --git a/src/quick/items/shaders/shadereffect_core.frag b/src/quick/items/shaders/shadereffect_core.frag
new file mode 100644
index 0000000000..2163753edc
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 qt_TexCoord0;
+
+out vec4 fragColor;
+
+uniform sampler2D source;
+uniform float qt_Opacity;
+
+void main()
+{
+ fragColor = texture(source, qt_TexCoord0) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffect_core.vert b/src/quick/items/shaders/shadereffect_core.vert
new file mode 100644
index 0000000000..2ed2d47b5f
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect_core.vert
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec4 qt_Vertex;
+in vec2 qt_MultiTexCoord0;
+
+out vec2 qt_TexCoord0;
+
+uniform mat4 qt_Matrix;
+
+void main()
+{
+ qt_TexCoord0 = qt_MultiTexCoord0;
+ gl_Position = qt_Matrix * qt_Vertex;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback_core.frag b/src/quick/items/shaders/shadereffectfallback_core.frag
new file mode 100644
index 0000000000..4abf124737
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback_core.frag
@@ -0,0 +1,8 @@
+#version 150 core
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(1., 0., 1., 1.);
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback_core.vert b/src/quick/items/shaders/shadereffectfallback_core.vert
new file mode 100644
index 0000000000..b1ca84cc6d
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 v;
+
+uniform mat4 qt_Matrix;
+
+void main()
+{
+ gl_Position = qt_Matrix * v;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/sprite_core.frag b/src/quick/items/shaders/sprite_core.frag
new file mode 100644
index 0000000000..c1087a8754
--- /dev/null
+++ b/src/quick/items/shaders/sprite_core.frag
@@ -0,0 +1,16 @@
+#version 150 core
+
+in vec4 fTexS;
+in float progress;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float qt_Opacity;
+
+void main()
+{
+ fragColor = mix(texture(_qt_texture, fTexS.xy),
+ texture(_qt_texture, fTexS.zw),
+ progress) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/sprite_core.vert b/src/quick/items/shaders/sprite_core.vert
new file mode 100644
index 0000000000..5027bf03fc
--- /dev/null
+++ b/src/quick/items/shaders/sprite_core.vert
@@ -0,0 +1,24 @@
+#version 150 core
+
+in vec2 vPos;
+in vec2 vTex;
+
+out vec4 fTexS;
+out float progress;
+
+uniform vec3 animData; // w,h(premultiplied of anim), interpolation progress
+uniform vec4 animPos; // x,y, x,y (two frames for interpolation)
+uniform mat4 qt_Matrix;
+
+void main()
+{
+ progress = animData.z;
+
+ // Calculate frame location in texture
+ fTexS.xy = animPos.xy + vTex.xy * animData.xy;
+
+ // Next frame is also passed, for interpolation
+ fTexS.zw = animPos.zw + vTex.xy * animData.xy;
+
+ gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 940b8dd02b..79b5de72c0 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -46,6 +46,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOpenGLVertexArrayObject>
#include <private/qqmlprofilerservice_p.h>
@@ -57,7 +58,7 @@
QT_BEGIN_NAMESPACE
-extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input);
+extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat::OpenGLContextProfile profile);
namespace QSGBatchRenderer
{
@@ -113,6 +114,7 @@ struct QMatrix4x4_Accessor
int flagBits;
static bool isTranslate(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits <= 0x1; }
+ static bool isScale(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits <= 0x2; }
static bool is2DSafe(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits < 0x8; }
};
@@ -131,10 +133,12 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
#endif
QSGMaterialShader *s = material->createShader();
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QSurfaceFormat::OpenGLContextProfile profile = ctx->format().profile();
QOpenGLShaderProgram *p = s->program();
p->addShaderFromSourceCode(QOpenGLShader::Vertex,
- qsgShaderRewriter_insertZAttributes(s->vertexShader()));
+ qsgShaderRewriter_insertZAttributes(s->vertexShader(), profile));
p->addShaderFromSourceCode(QOpenGLShader::Fragment,
s->fragmentShader());
@@ -533,6 +537,38 @@ int qsg_positionAttribute(QSGGeometry *g) {
return -1;
}
+
+void Rect::map(const QMatrix4x4 &matrix)
+{
+ const float *m = matrix.constData();
+ if (QMatrix4x4_Accessor::isScale(matrix)) {
+ tl.x = tl.x * m[0] + m[12];
+ tl.y = tl.y * m[5] + m[13];
+ br.x = br.x * m[0] + m[12];
+ br.y = br.y * m[5] + m[13];
+ if (tl.x > br.x)
+ qSwap(tl.x, br.x);
+ if (tl.y > br.y)
+ qSwap(tl.y, br.y);
+ } else {
+ Pt mtl = tl;
+ Pt mtr = { br.x, tl.y };
+ Pt mbl = { tl.x, br.y };
+ Pt mbr = br;
+
+ mtl.map(matrix);
+ mtr.map(matrix);
+ mbl.map(matrix);
+ mbr.map(matrix);
+
+ set(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
+ (*this) |= mtl;
+ (*this) |= mtr;
+ (*this) |= mbl;
+ (*this) |= mbr;
+ }
+}
+
void Element::computeBounds()
{
Q_ASSERT(!boundsComputed);
@@ -728,6 +764,7 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_zRange(0)
, m_currentMaterial(0)
, m_currentShader(0)
+ , m_vao(0)
{
setNodeUpdater(new Updater(this));
@@ -768,6 +805,13 @@ Renderer::Renderer(QSGRenderContext *ctx)
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"));
}
+
+ // If rendering with an OpenGL Core profile context, we need to create a VAO
+ // to hold our vertex specification state.
+ if (context()->openglContext()->format().profile() == QSurfaceFormat::CoreProfile) {
+ m_vao = new QOpenGLVertexArrayObject(this);
+ m_vao->create();
+ }
}
static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs)
@@ -1528,6 +1572,13 @@ void Renderer::prepareAlphaBatches()
ej->batch = batch;
next->nextInBatch = ej;
next = ej;
+ } else {
+ /* When we come across a compatible element which hits an overlap, we
+ * need to stop the batch right away. We cannot add more elements
+ * to the current batch as they will be rendered before the batch that the
+ * current 'ej' will be added to.
+ */
+ break;
}
} else {
overlapBounds |= ej->bounds;
@@ -2178,6 +2229,17 @@ void Renderer::deleteRemovedElements()
m_elementsToDelete.reset();
}
+void Renderer::preprocess()
+{
+ // Bind our VAO. It's important that we do this here as the
+ // QSGRenderer::preprocess() call may well do work that requires
+ // a bound VAO.
+ if (m_vao)
+ m_vao->bind();
+
+ QSGRenderer::preprocess();
+}
+
void Renderer::render()
{
if (Q_UNLIKELY(debug_dump)) {
@@ -2285,6 +2347,9 @@ void Renderer::render()
renderBatches();
m_rebuild = 0;
+
+ if (m_vao)
+ m_vao->release();
}
void Renderer::prepareRenderNode(RenderNodeElement *e)
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 6d95f83d7a..95e111552d 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -50,6 +50,8 @@
QT_BEGIN_NAMESPACE
+class QOpenGLVertexArrayObject;
+
namespace QSGBatchRenderer
{
@@ -119,14 +121,7 @@ struct Rect {
Q_ASSERT(tl.y <= br.y);
}
- void map(const QMatrix4x4 &m) {
- tl.map(m);
- br.map(m);
- if (br.x < tl.x)
- qSwap(br.x, tl.x);
- if (br.y < tl.y)
- qSwap(br.y, tl.y);
- }
+ void map(const QMatrix4x4 &m);
void set(float left, float top, float right, float bottom) {
tl.set(left, top);
@@ -405,6 +400,7 @@ public:
protected:
void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
+ void preprocess() Q_DECL_OVERRIDE;
void render();
private:
@@ -488,6 +484,9 @@ private:
QSGMaterialShader *m_currentProgram;
ShaderManager::Shader *m_currentShader;
const QSGClipNode *m_currentClip;
+
+ // For minimal OpenGL core profile support
+ QOpenGLVertexArrayObject *m_vao;
};
Batch *Renderer::newBatch()
diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
index eade198cd0..909def2c19 100644
--- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
+++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <QtCore>
+#include <QtGui/QSurfaceFormat>
// Duct Tape tokenizer for the purpose of parsing and rewriting
// shader source code
@@ -173,7 +174,7 @@ Tokenizer::Token Tokenizer::next()
using namespace QSGShaderRewriter;
-QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
+QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat::OpenGLContextProfile profile)
{
Tokenizer tok;
tok.initialize(input);
@@ -182,15 +183,33 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
Tokenizer::Token t = tok.next();
// First find "void main() { ... "
+ const char* voidPos = input;
while (t != Tokenizer::Token_EOF) {
if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
if (qstrncmp("main", tok.identifier, 4) == 0)
break;
}
+ voidPos = tok.pos - 4;
lt = t;
t = tok.next();
}
+ QByteArray result;
+ result.reserve(1024);
+ result += QByteArray::fromRawData(input, voidPos - input);
+ switch (profile) {
+ case QSurfaceFormat::NoProfile:
+ case QSurfaceFormat::CompatibilityProfile:
+ result += QByteArrayLiteral("attribute highp float _qt_order;\n");
+ result += QByteArrayLiteral("uniform highp float _qt_zRange;\n");
+ break;
+
+ case QSurfaceFormat::CoreProfile:
+ result += QByteArrayLiteral("in float _qt_order;\n");
+ result += QByteArrayLiteral("uniform float _qt_zRange;\n");
+ break;
+ }
+
// Find first brace '{'
while (t != Tokenizer::Token_EOF && t != Tokenizer::Token_OpenBrace) t = tok.next();
int braceDepth = 1;
@@ -202,12 +221,8 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
case Tokenizer::Token_CloseBrace:
braceDepth--;
if (braceDepth == 0) {
- QByteArray result;
- result.reserve(1024);
- result += "attribute highp float _qt_order;\n";
- result += "uniform highp float _qt_zRange;\n";
- result += QByteArray::fromRawData(input, tok.pos - 1 - input);
- result += " gl_Position.z = gl_Position.z * _qt_zRange + _qt_order;\n";
+ result += QByteArray::fromRawData(voidPos, tok.pos - 1 - voidPos);
+ result += QByteArrayLiteral(" gl_Position.z = gl_Position.z * _qt_zRange + _qt_order;\n");
result += QByteArray(tok.pos - 1);
return result;
}
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 8585caa22d..58c843a286 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -60,7 +60,7 @@ static QElapsedTimer qsg_render_timer;
QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture;
-QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font)
+QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
: m_manager(man)
, m_pendingGlyphs(64)
{
@@ -74,6 +74,8 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCach
m_referenceFont = font;
m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution));
Q_ASSERT(m_referenceFont.isValid());
+
+ m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile);
}
QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index f9e59f9c7f..f2d7dc07ca 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -66,6 +66,7 @@ class QImage;
class TextureReference;
class QSGDistanceFieldGlyphCacheManager;
class QSGDistanceFieldGlyphNode;
+class QOpenGLContext;
class Q_QUICK_PRIVATE_EXPORT QSGRectangleNode : public QSGGeometryNode
{
@@ -149,7 +150,7 @@ public:
class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache
{
public:
- QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font);
+ QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
virtual ~QSGDistanceFieldGlyphCache();
struct Metrics {
@@ -246,6 +247,8 @@ protected:
GlyphData &glyphData(glyph_t glyph);
+ inline bool isCoreProfile() const { return m_coreProfile; }
+
private:
QSGDistanceFieldGlyphCacheManager *m_manager;
@@ -253,6 +256,7 @@ private:
int m_glyphCount;
bool m_doubleGlyphResolution;
+ bool m_coreProfile;
QList<Texture> m_textures;
QHash<glyph_t, GlyphData> m_glyphsData;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 1f219e735f..fa095b8165 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -391,12 +391,13 @@ QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRaw
cache = new QSGSharedDistanceFieldGlyphCache(keyName,
sharedGraphicsCache,
m_distanceFieldCacheManager,
+ openglContext(),
font);
}
}
}
if (!cache)
- cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, font);
+ cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
m_distanceFieldCacheManager->insertCache(font, cache);
}
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 25ff98bc67..c5c4e18e37 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -48,16 +48,23 @@
#include <qopenglfunctions.h>
#include <qmath.h>
+#if !defined(QT_OPENGL_ES_2)
+#include <QtGui/qopenglfunctions_3_2_core.h>
+#endif
+
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlUseGlyphCacheWorkaround, QML_USE_GLYPHCACHE_WORKAROUND)
-QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font)
- : QSGDistanceFieldGlyphCache(man, font)
+QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
+ : QSGDistanceFieldGlyphCache(man, c, font)
, m_maxTextureSize(0)
, m_maxTextureCount(3)
, m_blitProgram(0)
, m_fboGuard(0)
+#if !defined(QT_OPENGL_ES_2)
+ , m_funcs(0)
+#endif
{
m_blitVertexCoordinateArray[0] = -1.0f;
m_blitVertexCoordinateArray[1] = -1.0f;
@@ -177,17 +184,22 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
}
}
+#if !defined(QT_OPENGL_ES_2)
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLenum format = GL_ALPHA;
+#endif
if (useTextureUploadWorkaround()) {
for (int i = 0; i < glyph.height(); ++i) {
glTexSubImage2D(GL_TEXTURE_2D, 0,
c.x, c.y + i, glyph.width(),1,
- GL_ALPHA, GL_UNSIGNED_BYTE,
+ format, GL_UNSIGNED_BYTE,
glyph.scanLine(i));
}
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0,
c.x, c.y, glyph.width(), glyph.height(),
- GL_ALPHA, GL_UNSIGNED_BYTE,
+ format, GL_UNSIGNED_BYTE,
glyph.constBits());
}
}
@@ -230,8 +242,14 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#if !defined(QT_OPENGL_ES_2)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA;
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLint internalFormat = GL_ALPHA;
+ const GLenum format = GL_ALPHA;
#endif
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, 0);
texInfo->size = QSize(width, height);
@@ -267,22 +285,74 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
updateTexture(oldTexture, texInfo->texture, texInfo->size);
+#if !defined(QT_OPENGL_ES_2)
+ if (isCoreProfile() && !useTextureResizeWorkaround()) {
+ // For an OpenGL Core Profile we can use http://www.opengl.org/wiki/Framebuffer#Blitting
+ // to efficiently copy the contents of the old texture to the new texture
+ // TODO: Use ARB_copy_image if available of if we have >=4.3 context
+ if (!m_funcs) {
+ m_funcs = ctx->versionFunctions<QOpenGLFunctions_3_2_Core>();
+ Q_ASSERT(m_funcs);
+ m_funcs->initializeOpenGLFunctions();
+ }
+
+ // Create a framebuffer object to which we can attach our old and new textures (to
+ // the first two color buffer attachment points)
+ if (!m_fboGuard) {
+ GLuint fbo;
+ m_funcs->glGenFramebuffers(1, &fbo);
+ m_fboGuard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
+ }
+
+ // Bind the FBO to both the GL_READ_FRAMEBUFFER? and GL_DRAW_FRAMEBUFFER targets
+ m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_fboGuard->id());
+
+ // Bind the old texture to GL_COLOR_ATTACHMENT0
+ m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, oldTexture, 0);
+
+ // Bind the new texture to GL_COLOR_ATTACHMENT1
+ m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
+ GL_TEXTURE_2D, texInfo->texture, 0);
+
+ // Set the source and destination buffers
+ m_funcs->glReadBuffer(GL_COLOR_ATTACHMENT0);
+ m_funcs->glDrawBuffer(GL_COLOR_ATTACHMENT1);
+
+ // Do the blit
+ m_funcs->glBlitFramebuffer(0, 0, oldWidth, oldHeight,
+ 0, 0, oldWidth, oldHeight,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ // Reset the default framebuffer
+ m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return;
+ } else if (useTextureResizeWorkaround()) {
+#else
if (useTextureResizeWorkaround()) {
+#endif
GLint alignment = 4; // default value
glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+#if !defined(QT_OPENGL_ES_2)
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLenum format = GL_ALPHA;
+#endif
+
if (useTextureUploadWorkaround()) {
for (int i = 0; i < texInfo->image.height(); ++i) {
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, i, oldWidth, 1,
- GL_ALPHA, GL_UNSIGNED_BYTE,
+ format, GL_UNSIGNED_BYTE,
texInfo->image.scanLine(i));
}
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, oldWidth, oldHeight,
- GL_ALPHA, GL_UNSIGNED_BYTE,
+ format, GL_UNSIGNED_BYTE,
texInfo->image.constBits());
}
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index 3fee6c9ef3..a5833af5fb 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -51,10 +51,14 @@
QT_BEGIN_NAMESPACE
class QOpenGLSharedResourceGuard;
+#if !defined(QT_OPENGL_ES_2)
+class QOpenGLFunctions_3_2_Core;
+#endif
+
class Q_QUICK_PRIVATE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
{
public:
- QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font);
+ QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
virtual ~QSGDefaultDistanceFieldGlyphCache();
void requestGlyphs(const QSet<glyph_t> &glyphs);
@@ -133,6 +137,9 @@ private:
GLfloat m_blitTextureCoordinateArray[8];
QOpenGLSharedResourceGuard *m_fboGuard;
+#if !defined(QT_OPENGL_ES_2)
+ QOpenGLFunctions_3_2_Core *m_funcs;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 06a112b0a4..aa0d7b5a6c 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -242,6 +242,7 @@ void QSGGuiThreadRenderLoop::hide(QQuickWindow *window)
if (m_windows.size() == 0) {
if (!cd->persistentSceneGraph) {
rc->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
if (!cd->persistentGLContext) {
delete gl;
gl = 0;
@@ -255,6 +256,7 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
hide(window);
if (m_windows.size() == 0) {
rc->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete gl;
gl = 0;
}
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
index 20e1210b68..cc0218aefd 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
@@ -199,8 +199,9 @@ namespace {
QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
QPlatformSharedGraphicsCache *sharedGraphicsCache,
QSGDistanceFieldGlyphCacheManager *man,
+ QOpenGLContext *c,
const QRawFont &font)
- : QSGDistanceFieldGlyphCache(man, font)
+ : QSGDistanceFieldGlyphCache(man, c, font)
, m_cacheId(cacheId)
, m_sharedGraphicsCache(sharedGraphicsCache)
, m_isInSceneGraphUpdate(false)
@@ -227,7 +228,6 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
this, SLOT(reportItemsInvalidated(QByteArray,QVector<quint32>)),
Qt::DirectConnection);
- QOpenGLContext *c = QOpenGLContext::currentContext();
Q_ASSERT(c);
QQuickWindow *window = static_cast<QQuickWindow *>(c->surface());
Q_ASSERT(window != 0);
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
index a8d70be732..d72d2a740f 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
@@ -55,6 +55,7 @@ public:
explicit QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
QPlatformSharedGraphicsCache *sharedGraphicsCache,
QSGDistanceFieldGlyphCacheManager *man,
+ QOpenGLContext *c,
const QRawFont &font);
~QSGSharedDistanceFieldGlyphCache();
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index db3f34883f..0c46747e53 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -108,27 +108,14 @@ QT_BEGIN_NAMESPACE
// #define QSG_RENDER_LOOP_DEBUG
-// #define QSG_RENDER_LOOP_DEBUG_FULL
-#ifdef QSG_RENDER_LOOP_DEBUG
-#define QSG_RENDER_LOOP_DEBUG_BASIC
-#endif
-
-#ifdef QSG_RENDER_LOOP_DEBUG_FULL
-#define QSG_RENDER_LOOP_DEBUG_BASIC
-#endif
-
-#if defined (QSG_RENDER_LOOP_DEBUG_FULL)
-QElapsedTimer qsgrl_timer;
-# define RLDEBUG1(x) qDebug("(%6d) %s : %4d - %s", (int) qsgrl_timer.elapsed(), __FILE__, __LINE__, x);
-# define RLDEBUG(x) qDebug("(%6d) %s : %4d - %s", (int) qsgrl_timer.elapsed(), __FILE__, __LINE__, x);
-#elif defined (QSG_RENDER_LOOP_DEBUG_BASIC)
+#if defined (QSG_RENDER_LOOP_DEBUG)
QElapsedTimer qsgrl_timer;
-# define RLDEBUG1(x) qDebug("(%6d) %s : %4d - %s", (int) qsgrl_timer.elapsed(), __FILE__, __LINE__, x);
-# define RLDEBUG(x)
+# define QSG_RT_DEBUG(MSG) qDebug("(%6d) line=%4d - win=%10p): Render: %s", (int) qsgrl_timer.elapsed(), __LINE__, window, MSG);
+# define QSG_GUI_DEBUG(WIN, MSG) qDebug("(%6d) line=%4d - win=%10p): Gui: %s", (int) qsgrl_timer.elapsed(), __LINE__, WIN, MSG);
#else
-# define RLDEBUG1(x)
-# define RLDEBUG(x)
+# define QSG_RT_DEBUG(MSG)
+# define QSG_GUI_DEBUG(WIN,MSG)
#endif
@@ -331,7 +318,7 @@ public:
public slots:
void sceneGraphChanged() {
- RLDEBUG(" Render: sceneGraphChanged()");
+ QSG_RT_DEBUG("sceneGraphChanged()");
syncResultedInChanges = true;
}
@@ -373,7 +360,7 @@ bool QSGRenderThread::event(QEvent *e)
switch ((int) e->type()) {
case WM_Expose: {
- RLDEBUG1(" Render: WM_Expose");
+ QSG_RT_DEBUG("WM_Expose");
WMExposeEvent *se = static_cast<WMExposeEvent *>(e);
pendingUpdate |= RepaintRequest;
@@ -382,7 +369,7 @@ bool QSGRenderThread::event(QEvent *e)
windowSize = se->size;
if (window) {
- RLDEBUG1(" Render: - window already added...");
+ QSG_RT_DEBUG(" - window already added...");
return true;
}
@@ -390,19 +377,22 @@ bool QSGRenderThread::event(QEvent *e)
return true; }
case WM_Obscure: {
- RLDEBUG1(" Render: WM_Obscure");
+ QSG_RT_DEBUG("WM_Obscure");
Q_ASSERT(!window || window == static_cast<WMWindowEvent *>(e)->window);
+ mutex.lock();
if (window) {
- RLDEBUG1(" Render: - removed one...");
+ QSG_RT_DEBUG(" - removed one...");
window = 0;
}
+ waitCondition.wakeOne();
+ mutex.unlock();
return true; }
case WM_RequestSync:
- RLDEBUG(" Render: WM_RequestSync");
+ QSG_RT_DEBUG("WM_RequestSync");
if (sleeping)
stopEventProcessing = true;
if (window)
@@ -410,17 +400,17 @@ bool QSGRenderThread::event(QEvent *e)
return true;
case WM_TryRelease: {
- RLDEBUG1(" Render: WM_TryRelease");
+ QSG_RT_DEBUG("WM_TryRelease");
mutex.lock();
if (!window) {
WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e);
- RLDEBUG1(" Render: - setting exit flag and invalidating GL");
+ QSG_RT_DEBUG(" - setting exit flag and invalidating GL");
invalidateOpenGL(wme->window, wme->inDestructor);
active = gl;
if (sleeping)
stopEventProcessing = true;
} else {
- RLDEBUG1(" Render: - not releasing anything because we have active windows...");
+ QSG_RT_DEBUG(" - not releasing anything because we have active windows...");
}
waitCondition.wakeOne();
mutex.unlock();
@@ -428,24 +418,24 @@ bool QSGRenderThread::event(QEvent *e)
}
case WM_Grab: {
- RLDEBUG1(" Render: WM_Grab");
+ QSG_RT_DEBUG("WM_Grab");
WMGrabEvent *ce = static_cast<WMGrabEvent *>(e);
Q_ASSERT(ce->window == window);
mutex.lock();
if (window) {
gl->makeCurrent(window);
- RLDEBUG1(" Render: - syncing scene graph");
+ QSG_RT_DEBUG(" - syncing scene graph");
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->syncSceneGraph();
- RLDEBUG1(" Render: - rendering scene graph");
+ QSG_RT_DEBUG(" - rendering scene graph");
QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize);
- RLDEBUG1(" Render: - grabbing result...");
+ QSG_RT_DEBUG(" - grabbing result...");
*ce->image = qt_gl_read_framebuffer(windowSize, false, false);
}
- RLDEBUG1(" Render: - waking gui to handle grab result");
+ QSG_RT_DEBUG(" - waking gui to handle grab result");
waitCondition.wakeOne();
mutex.unlock();
return true;
@@ -465,7 +455,7 @@ bool QSGRenderThread::event(QEvent *e)
void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor)
{
- RLDEBUG1(" Render: invalidateOpenGL()");
+ QSG_RT_DEBUG("invalidateOpenGL()");
if (!gl)
return;
@@ -486,7 +476,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor)
QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window);
dd->cleanupNodesOnShutdown();
} else {
- RLDEBUG1(" Render: - persistent SG, avoiding cleanup");
+ QSG_RT_DEBUG(" - persistent SG, avoiding cleanup");
return;
}
@@ -494,14 +484,14 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor)
QCoreApplication::processEvents();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
gl->doneCurrent();
- RLDEBUG1(" Render: - invalidated scenegraph..");
+ QSG_RT_DEBUG(" - invalidated scenegraph..");
if (wipeGL) {
delete gl;
gl = 0;
- RLDEBUG1(" Render: - invalidated OpenGL");
+ QSG_RT_DEBUG(" - invalidated OpenGL");
} else {
- RLDEBUG1(" Render: - persistent GL, avoiding cleanup");
+ QSG_RT_DEBUG(" - persistent GL, avoiding cleanup");
}
}
@@ -511,7 +501,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor)
*/
void QSGRenderThread::sync()
{
- RLDEBUG(" Render: sync()");
+ QSG_RT_DEBUG("sync()");
mutex.lock();
Q_ASSERT_X(wm->m_locked, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked...");
@@ -522,7 +512,7 @@ void QSGRenderThread::sync()
bool hadRenderer = d->renderer != 0;
d->syncSceneGraph();
if (!hadRenderer && d->renderer) {
- RLDEBUG(" Render: - renderer was created, hooking up changed signal");
+ QSG_RT_DEBUG(" - renderer was created, hooking up changed signal");
syncResultedInChanges = true;
connect(d->renderer, SIGNAL(sceneGraphChanged()), this, SLOT(sceneGraphChanged()), Qt::DirectConnection);
}
@@ -532,10 +522,10 @@ void QSGRenderThread::sync()
// and the delete is a safe operation.
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
} else {
- RLDEBUG(" Render: - window has bad size, waiting...");
+ QSG_RT_DEBUG(" - window has bad size, waiting...");
}
- RLDEBUG(" Render: - window has bad size, waiting...");
+ QSG_RT_DEBUG(" - window has bad size, waiting...");
waitCondition.wakeOne();
mutex.unlock();
}
@@ -553,7 +543,7 @@ void QSGRenderThread::syncAndRender()
QElapsedTimer waitTimer;
waitTimer.start();
- RLDEBUG(" Render: syncAndRender()");
+ QSG_RT_DEBUG("syncAndRender()");
syncResultedInChanges = false;
@@ -562,12 +552,12 @@ void QSGRenderThread::syncAndRender()
pendingUpdate = 0;
if (syncRequested) {
- RLDEBUG(" Render: - update pending, doing sync");
+ QSG_RT_DEBUG(" - update pending, doing sync");
sync();
}
if (!syncResultedInChanges && !(repaintRequested)) {
- RLDEBUG(" Render: - no changes, rendering aborted");
+ QSG_RT_DEBUG(" - no changes, rendering aborted");
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
if (waitTime > 0)
msleep(waitTime);
@@ -578,7 +568,7 @@ void QSGRenderThread::syncAndRender()
if (profileFrames)
syncTime = threadTimer.nsecsElapsed();
#endif
- RLDEBUG(" Render: - rendering starting");
+ QSG_RT_DEBUG(" - rendering starting");
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
@@ -598,10 +588,10 @@ void QSGRenderThread::syncAndRender()
gl->swapBuffers(window);
d->fireFrameSwapped();
} else {
- RLDEBUG(" Render: - Window not yet ready, skipping render...");
+ QSG_RT_DEBUG(" - Window not yet ready, skipping render...");
}
- RLDEBUG(" Render: - rendering done");
+ QSG_RT_DEBUG(" - rendering done");
#ifndef QSG_NO_RENDER_TIMING
if (qsg_render_timing)
@@ -633,30 +623,30 @@ void QSGRenderThread::postEvent(QEvent *e)
void QSGRenderThread::processEvents()
{
- RLDEBUG(" Render: processEvents()");
+ QSG_RT_DEBUG("processEvents()");
while (eventQueue.hasMoreEvents()) {
QEvent *e = eventQueue.takeEvent(false);
event(e);
delete e;
}
- RLDEBUG(" Render: - done with processEvents()");
+ QSG_RT_DEBUG(" - done with processEvents()");
}
void QSGRenderThread::processEventsAndWaitForMore()
{
- RLDEBUG(" Render: processEventsAndWaitForMore()");
+ QSG_RT_DEBUG("processEventsAndWaitForMore()");
stopEventProcessing = false;
while (!stopEventProcessing) {
QEvent *e = eventQueue.takeEvent(true);
event(e);
delete e;
}
- RLDEBUG(" Render: - done with processEventsAndWaitForMore()");
+ QSG_RT_DEBUG(" - done with processEventsAndWaitForMore()");
}
void QSGRenderThread::run()
{
- RLDEBUG1(" Render: run()");
+ QSG_RT_DEBUG("run()");
animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0);
animatorDriver->install();
QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming());
@@ -675,7 +665,7 @@ void QSGRenderThread::run()
QCoreApplication::processEvents();
if (active && (pendingUpdate == 0 || !window)) {
- RLDEBUG(" Render: enter event loop (going to sleep)");
+ QSG_RT_DEBUG("enter event loop (going to sleep)");
sleeping = true;
processEventsAndWaitForMore();
sleeping = false;
@@ -684,7 +674,7 @@ void QSGRenderThread::run()
Q_ASSERT_X(!gl, "QSGRenderThread::run()", "The OpenGL context should be cleaned up before exiting the render thread...");
- RLDEBUG1(" Render: run() completed...");
+ QSG_RT_DEBUG("run() completed...");
delete animatorDriver;
animatorDriver = 0;
@@ -709,7 +699,7 @@ QSGThreadedRenderLoop::QSGThreadedRenderLoop()
connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped()));
m_animation_driver->install();
- RLDEBUG1("GUI: QSGThreadedRenderLoop() created");
+ QSG_GUI_DEBUG((void *) 0, "QSGThreadedRenderLoop() created");
}
QSGRenderContext *QSGThreadedRenderLoop::createRenderContext(QSGContext *sg) const
@@ -720,7 +710,7 @@ QSGRenderContext *QSGThreadedRenderLoop::createRenderContext(QSGContext *sg) con
void QSGThreadedRenderLoop::maybePostPolishRequest(Window *w)
{
if (w->timerId == 0) {
- RLDEBUG("GUI: - posting update");
+ QSG_GUI_DEBUG(w->window, " - posting update");
w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer);
}
}
@@ -752,7 +742,7 @@ bool QSGThreadedRenderLoop::interleaveIncubation() const
void QSGThreadedRenderLoop::animationStarted()
{
- RLDEBUG("GUI: animationStarted()");
+ QSG_GUI_DEBUG((void *) 0, "animationStarted()");
startOrStopAnimationTimer();
for (int i=0; i<m_windows.size(); ++i)
@@ -761,7 +751,7 @@ void QSGThreadedRenderLoop::animationStarted()
void QSGThreadedRenderLoop::animationStopped()
{
- RLDEBUG("GUI: animationStopped()");
+ QSG_GUI_DEBUG((void *) 0, "animationStopped()");
startOrStopAnimationTimer();
}
@@ -798,13 +788,27 @@ void QSGThreadedRenderLoop::startOrStopAnimationTimer()
void QSGThreadedRenderLoop::show(QQuickWindow *window)
{
- RLDEBUG1("GUI: show()");
-
- if (windowFor(m_windows, window)) {
- RLDEBUG1("GUI: - already showing");
+ QSG_GUI_DEBUG(window, "show()");
+
+ if (Window *w = windowFor(m_windows, window)) {
+ /* Safeguard ourselves against misbehaving platform plugins.
+ *
+ * When being shown, the window should not be exposed as the
+ * platform plugin is only told to show after we send the show
+ * event. If we are already shown at this time and we don't have
+ * an active rendering thread we don't trust the plugin to send
+ * us another expose event, so make this explicit call to
+ * handleExposure.
+ *
+ * REF: QTCREATORBUG-10699
+ */
+ if (window->isExposed() && (!w->thread || !w->thread->window))
+ handleExposure(w);
return;
}
+ QSG_GUI_DEBUG(window, " - now tracking new window");
+
Window win;
win.window = window;
win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context);
@@ -823,7 +827,7 @@ void QSGThreadedRenderLoop::show(QQuickWindow *window)
void QSGThreadedRenderLoop::hide(QQuickWindow *window)
{
- RLDEBUG1("GUI: hide()");
+ QSG_GUI_DEBUG(window, "hide()");
if (window->isExposed())
handleObscurity(windowFor(m_windows, window));
@@ -839,7 +843,7 @@ void QSGThreadedRenderLoop::hide(QQuickWindow *window)
*/
void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window)
{
- RLDEBUG1("GUI: windowDestroyed()");
+ QSG_GUI_DEBUG(window, "windowDestroyed()");
if (window->isVisible())
hide(window);
@@ -857,13 +861,13 @@ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window)
}
}
- RLDEBUG1("GUI: - done with windowDestroyed()");
+ QSG_GUI_DEBUG(window, " - done with windowDestroyed()");
}
void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window)
{
- RLDEBUG1("GUI: exposureChanged()");
+ QSG_GUI_DEBUG(window, "exposureChanged()");
Window *w = windowFor(m_windows, window);
if (!w)
return;
@@ -882,7 +886,7 @@ void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window)
*/
void QSGThreadedRenderLoop::handleExposure(Window *w)
{
- RLDEBUG1("GUI: handleExposure");
+ QSG_GUI_DEBUG(w->window, "handleExposure");
// Because we are going to bind a GL context to it, make sure it
// is created.
@@ -892,7 +896,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w)
// Start render thread if it is not running
if (!w->thread->isRunning()) {
- RLDEBUG1("GUI: - starting render thread...");
+ QSG_GUI_DEBUG(w->window, " - starting render thread...");
if (!w->thread->gl) {
w->thread->gl = new QOpenGLContext();
@@ -907,7 +911,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w)
}
w->thread->gl->moveToThread(w->thread);
- RLDEBUG1("GUI: - OpenGL context created...");
+ QSG_GUI_DEBUG(w->window, " - OpenGL context created...");
}
QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController;
@@ -922,7 +926,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w)
w->thread->start();
} else {
- RLDEBUG1("GUI: - render thread already running");
+ QSG_GUI_DEBUG(w->window, " - render thread already running");
}
w->thread->postEvent(new WMExposeEvent(w->window));
@@ -940,9 +944,13 @@ void QSGThreadedRenderLoop::handleExposure(Window *w)
*/
void QSGThreadedRenderLoop::handleObscurity(Window *w)
{
- RLDEBUG1("GUI: handleObscurity");
- if (w->thread->isRunning())
+ QSG_GUI_DEBUG(w->window, "handleObscurity");
+ if (w->thread->isRunning()) {
+ w->thread->mutex.lock();
w->thread->postEvent(new WMWindowEvent(w->window, WM_Obscure));
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ w->thread->mutex.unlock();
+ }
startOrStopAnimationTimer();
}
@@ -965,7 +973,7 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w)
"QQuickItem::update()",
"Function can only be called from GUI thread or during QQuickItem::updatePaintNode()");
- RLDEBUG("GUI: maybeUpdate...");
+ QSG_GUI_DEBUG(w->window, "maybeUpdate...");
if (!w || !w->thread->isRunning()) {
return;
}
@@ -973,7 +981,7 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w)
// Call this function from the Gui thread later as startTimer cannot be
// called from the render thread.
if (QThread::currentThread() == w->thread) {
- RLDEBUG("GUI: - on render thread, will update later..");
+ QSG_GUI_DEBUG(w->window, " - on render thread, will update later..");
w->updateDuringSync = true;
return;
}
@@ -993,12 +1001,12 @@ void QSGThreadedRenderLoop::update(QQuickWindow *window)
return;
if (w->thread == QThread::currentThread()) {
- RLDEBUG(" Render: QQuickWindow::update called on render thread");
+ QSG_RT_DEBUG("QQuickWindow::update called on render thread");
w->thread->requestRepaint();
return;
}
- RLDEBUG("GUI: update called");
+ QSG_GUI_DEBUG(w->window, "update called");
w->thread->postEvent(new QEvent(WM_RequestRepaint));
maybeUpdate(w);
}
@@ -1011,7 +1019,7 @@ void QSGThreadedRenderLoop::update(QQuickWindow *window)
*/
void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestructor)
{
- RLDEBUG1("GUI: releaseResources requested...");
+ QSG_GUI_DEBUG(window, "releaseResources requested...");
Window *w = windowFor(m_windows, window);
if (!w)
@@ -1019,7 +1027,7 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru
w->thread->mutex.lock();
if (w->thread->isRunning() && w->thread->active) {
- RLDEBUG1("GUI: - posting release request to render thread");
+ QSG_GUI_DEBUG(w->window, " - posting release request to render thread");
w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor));
w->thread->waitCondition.wait(&w->thread->mutex);
}
@@ -1030,10 +1038,10 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru
void QSGThreadedRenderLoop::polishAndSync(Window *w)
{
- RLDEBUG("GUI: polishAndSync()");
+ QSG_GUI_DEBUG(w->window, "polishAndSync()");
- if (!w->window->isExposed() || !w->window->isVisible()) {
- RLDEBUG("GUI: - not exposed, aborting...");
+ if (!w->window->isExposed() || !w->window->isVisible() || w->window->size().isEmpty()) {
+ QSG_GUI_DEBUG(w->window, " - not exposed, aborting...");
killTimer(w->timerId);
w->timerId = 0;
return;
@@ -1060,12 +1068,12 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
w->updateDuringSync = false;
- RLDEBUG("GUI: - lock for sync...");
+ QSG_GUI_DEBUG(w->window, " - lock for sync...");
w->thread->mutex.lock();
m_locked = true;
w->thread->postEvent(new QEvent(WM_RequestSync));
- RLDEBUG("GUI: - wait for sync...");
+ QSG_GUI_DEBUG(w->window, " - wait for sync...");
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
waitTime = timer.nsecsElapsed();
@@ -1073,7 +1081,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
w->thread->waitCondition.wait(&w->thread->mutex);
m_locked = false;
w->thread->mutex.unlock();
- RLDEBUG("GUI: - unlocked after sync...");
+ QSG_GUI_DEBUG(w->window, " - unlocked after sync...");
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
@@ -1084,9 +1092,9 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w)
w->timerId = 0;
if (m_animation_timer == 0 && m_animation_driver->isRunning()) {
- RLDEBUG("GUI: - animations advancing");
+ QSG_GUI_DEBUG(w->window, " - animations advancing");
m_animation_driver->advance();
- RLDEBUG("GUI: - animations done");
+ QSG_GUI_DEBUG(w->window, " - animations done");
// We need to trigger another sync to keep animations running...
maybePostPolishRequest(w);
emit timeToIncubate();
@@ -1121,11 +1129,11 @@ bool QSGThreadedRenderLoop::event(QEvent *e)
case QEvent::Timer: {
QTimerEvent *te = static_cast<QTimerEvent *>(e);
if (te->timerId() == m_animation_timer) {
- RLDEBUG("GUI: QEvent::Timer -> non-visual animation");
+ QSG_GUI_DEBUG((void *) 0, "QEvent::Timer -> non-visual animation");
m_animation_driver->advance();
emit timeToIncubate();
} else {
- RLDEBUG("GUI: QEvent::Timer -> Polish & Sync");
+ QSG_GUI_DEBUG((void *) 0, "QEvent::Timer -> Polish & Sync");
Window *w = 0;
for (int i=0; i<m_windows.size(); ++i) {
if (m_windows.at(i).timerId == te->timerId()) {
@@ -1160,7 +1168,7 @@ bool QSGThreadedRenderLoop::event(QEvent *e)
QImage QSGThreadedRenderLoop::grab(QQuickWindow *window)
{
- RLDEBUG("GUI: grab");
+ QSG_GUI_DEBUG(window, "grab");
Window *w = windowFor(m_windows, window);
Q_ASSERT(w);
@@ -1171,19 +1179,19 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window)
if (!window->handle())
window->create();
- RLDEBUG1("GUI: - polishing items...");
+ QSG_GUI_DEBUG(w->window, " - polishing items...");
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->polishItems();
QImage result;
w->thread->mutex.lock();
- RLDEBUG1("GUI: - locking, posting grab event");
+ QSG_GUI_DEBUG(w->window, " - locking, posting grab event");
w->thread->postEvent(new WMGrabEvent(window, &result));
w->thread->waitCondition.wait(&w->thread->mutex);
- RLDEBUG1("GUI: - locking, grab done, unlocking");
+ QSG_GUI_DEBUG(w->window, " - locking, grab done, unlocking");
w->thread->mutex.unlock();
- RLDEBUG1("Gui: - grab complete");
+ QSG_GUI_DEBUG(w->window, " - grab complete");
return result;
}
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index bcd4f390b4..0c128d5cae 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -248,6 +248,7 @@ void QSGWindowsRenderLoop::hide(QQuickWindow *window)
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;
@@ -264,6 +265,7 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window)
// If this is the last tracked window, clean up SG and GL.
if (m_windows.size() == 0) {
QQuickWindowPrivate::get(window)->context->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete m_gl;
m_gl = 0;
}
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index aebc2ece9c..6f64c881a8 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -126,5 +126,37 @@ OTHER_FILES += \
$$PWD/shaders/textmask.vert \
$$PWD/shaders/texture.frag \
$$PWD/shaders/vertexcolor.frag \
- $$PWD/shaders/vertexcolor.vert
+ $$PWD/shaders/vertexcolor.vert \
+ $$PWD/shaders/24bittextmask_core.frag \
+ $$PWD/shaders/8bittextmask_core.frag \
+ $$PWD/shaders/distancefieldoutlinetext_core.frag \
+ $$PWD/shaders/distancefieldshiftedtext_core.frag \
+ $$PWD/shaders/distancefieldshiftedtext_core.vert \
+ $$PWD/shaders/distancefieldtext_core.frag \
+ $$PWD/shaders/distancefieldtext_core.vert \
+ $$PWD/shaders/flatcolor_core.frag \
+ $$PWD/shaders/flatcolor_core.vert \
+ $$PWD/shaders/hiqsubpixeldistancefieldtext_core.frag \
+ $$PWD/shaders/hiqsubpixeldistancefieldtext_core.vert \
+ $$PWD/shaders/loqsubpixeldistancefieldtext_core.frag \
+ $$PWD/shaders/loqsubpixeldistancefieldtext_core.vert \
+ $$PWD/shaders/opaquetexture_core.frag \
+ $$PWD/shaders/opaquetexture_core.vert \
+ $$PWD/shaders/outlinedtext_core.frag \
+ $$PWD/shaders/outlinedtext_core.vert \
+ $$PWD/shaders/rendernode_core.frag \
+ $$PWD/shaders/rendernode_core.vert \
+ $$PWD/shaders/smoothcolor_core.frag \
+ $$PWD/shaders/smoothcolor_core.vert \
+ $$PWD/shaders/smoothtexture_core.frag \
+ $$PWD/shaders/smoothtexture_core.vert \
+ $$PWD/shaders/stencilclip_core.frag \
+ $$PWD/shaders/stencilclip_core.vert \
+ $$PWD/shaders/styledtext_core.frag \
+ $$PWD/shaders/styledtext_core.vert \
+ $$PWD/shaders/textmask_core.frag \
+ $$PWD/shaders/textmask_core.vert \
+ $$PWD/shaders/texture_core.frag \
+ $$PWD/shaders/vertexcolor_core.frag \
+ $$PWD/shaders/vertexcolor_core.vert
diff --git a/src/quick/scenegraph/scenegraph.qrc b/src/quick/scenegraph/scenegraph.qrc
index 5299ec6d9f..2be8b246d3 100644
--- a/src/quick/scenegraph/scenegraph.qrc
+++ b/src/quick/scenegraph/scenegraph.qrc
@@ -32,5 +32,37 @@
<file>shaders/rendernode.frag</file>
<file>shaders/stencilclip.frag</file>
<file>shaders/stencilclip.vert</file>
+ <file>shaders/8bittextmask_core.frag</file>
+ <file>shaders/24bittextmask_core.frag</file>
+ <file>shaders/distancefieldoutlinetext_core.frag</file>
+ <file>shaders/distancefieldshiftedtext_core.frag</file>
+ <file>shaders/distancefieldshiftedtext_core.vert</file>
+ <file>shaders/distancefieldtext_core.frag</file>
+ <file>shaders/distancefieldtext_core.vert</file>
+ <file>shaders/flatcolor_core.frag</file>
+ <file>shaders/flatcolor_core.vert</file>
+ <file>shaders/hiqsubpixeldistancefieldtext_core.frag</file>
+ <file>shaders/hiqsubpixeldistancefieldtext_core.vert</file>
+ <file>shaders/loqsubpixeldistancefieldtext_core.frag</file>
+ <file>shaders/loqsubpixeldistancefieldtext_core.vert</file>
+ <file>shaders/opaquetexture_core.frag</file>
+ <file>shaders/opaquetexture_core.vert</file>
+ <file>shaders/outlinedtext_core.frag</file>
+ <file>shaders/outlinedtext_core.vert</file>
+ <file>shaders/rendernode_core.frag</file>
+ <file>shaders/rendernode_core.vert</file>
+ <file>shaders/smoothcolor_core.frag</file>
+ <file>shaders/smoothcolor_core.vert</file>
+ <file>shaders/smoothtexture_core.frag</file>
+ <file>shaders/smoothtexture_core.vert</file>
+ <file>shaders/stencilclip_core.frag</file>
+ <file>shaders/stencilclip_core.vert</file>
+ <file>shaders/styledtext_core.frag</file>
+ <file>shaders/styledtext_core.vert</file>
+ <file>shaders/textmask_core.frag</file>
+ <file>shaders/textmask_core.vert</file>
+ <file>shaders/texture_core.frag</file>
+ <file>shaders/vertexcolor_core.frag</file>
+ <file>shaders/vertexcolor_core.vert</file>
</qresource>
</RCC>
diff --git a/src/quick/scenegraph/shaders/24bittextmask.frag b/src/quick/scenegraph/shaders/24bittextmask.frag
index ac62e7b642..5c21e202f9 100644
--- a/src/quick/scenegraph/shaders/24bittextmask.frag
+++ b/src/quick/scenegraph/shaders/24bittextmask.frag
@@ -1,10 +1,10 @@
varying highp vec2 sampleCoord;
-uniform lowp sampler2D texture;
+uniform lowp sampler2D _qt_texture;
uniform lowp float color; // just the alpha, really...
void main()
{
- lowp vec4 glyph = texture2D(texture, sampleCoord);
+ lowp vec4 glyph = texture2D(_qt_texture, sampleCoord);
gl_FragColor = vec4(glyph.rgb * color, glyph.a);
} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/24bittextmask_core.frag b/src/quick/scenegraph/shaders/24bittextmask_core.frag
new file mode 100644
index 0000000000..29d1f23017
--- /dev/null
+++ b/src/quick/scenegraph/shaders/24bittextmask_core.frag
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float color; // just the alpha, really...
+
+void main()
+{
+ vec4 glyph = texture(_qt_texture, sampleCoord);
+ fragColor = vec4(glyph.rgb * color, glyph.a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/8bittextmask.frag b/src/quick/scenegraph/shaders/8bittextmask.frag
index f2f06e8e07..44ffb279cb 100644
--- a/src/quick/scenegraph/shaders/8bittextmask.frag
+++ b/src/quick/scenegraph/shaders/8bittextmask.frag
@@ -1,9 +1,9 @@
varying highp vec2 sampleCoord;
-uniform lowp sampler2D texture;
+uniform lowp sampler2D _qt_texture;
uniform lowp vec4 color;
void main()
{
- gl_FragColor = color * texture2D(texture, sampleCoord).a;
+ gl_FragColor = color * texture2D(_qt_texture, sampleCoord).a;
} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/8bittextmask_core.frag b/src/quick/scenegraph/shaders/8bittextmask_core.frag
new file mode 100644
index 0000000000..2d67a4676a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/8bittextmask_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+
+void main()
+{
+ fragColor = color * texture(_qt_texture, sampleCoord).r;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag b/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag
new file mode 100644
index 0000000000..80fa05ca3c
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag
@@ -0,0 +1,20 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+uniform float alphaMin;
+uniform float alphaMax;
+uniform float outlineAlphaMax0;
+uniform float outlineAlphaMax1;
+
+void main()
+{
+ float d = texture(_qt_texture, sampleCoord).r;
+ fragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d))
+ * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag
new file mode 100644
index 0000000000..3f66965e78
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag
@@ -0,0 +1,20 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 shiftedSampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ float a = smoothstep(alphaMin, alphaMax, texture(_qt_texture, sampleCoord).r);
+ vec4 shifted = styleColor * smoothstep(alphaMin, alphaMax,
+ texture(_qt_texture, shiftedSampleCoord).r);
+ fragColor = mix(shifted, color, a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert
new file mode 100644
index 0000000000..b7a3ecc667
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 shiftedSampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ shiftedSampleCoord = (tCoord - shift) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext_core.frag b/src/quick/scenegraph/shaders/distancefieldtext_core.frag
new file mode 100644
index 0000000000..9c64a60d3d
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext_core.frag
@@ -0,0 +1,16 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ fragColor = color * smoothstep(alphaMin, alphaMax,
+ texture(_qt_texture, sampleCoord).r);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext_core.vert b/src/quick/scenegraph/shaders/distancefieldtext_core.vert
new file mode 100644
index 0000000000..7fc693d139
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/flatcolor_core.frag b/src/quick/scenegraph/shaders/flatcolor_core.frag
new file mode 100644
index 0000000000..23a957ad7b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+out vec4 fragColor;
+
+uniform vec4 color;
+
+void main()
+{
+ fragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/flatcolor_core.vert b/src/quick/scenegraph/shaders/flatcolor_core.vert
new file mode 100644
index 0000000000..e33c591b95
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 vCoord;
+
+uniform mat4 matrix;
+
+void main()
+{
+ gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag
new file mode 100644
index 0000000000..cf6ba2b8d9
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag
@@ -0,0 +1,32 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec3 sampleFarLeft;
+in vec3 sampleNearLeft;
+in vec3 sampleNearRight;
+in vec3 sampleFarRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ vec4 n;
+ n.x = textureProj(_qt_texture, sampleFarLeft).r;
+ n.y = textureProj(_qt_texture, sampleNearLeft).r;
+ float c = texture(_qt_texture, sampleCoord).r;
+ n.z = textureProj(_qt_texture, sampleNearRight).r;
+ n.w = textureProj(_qt_texture, sampleFarRight).r;
+
+ vec2 d = min(abs(n.yw - n.xz) * 2., 0.67);
+ vec2 lo = mix(vec2(alphaMin), vec2(0.5), d);
+ vec2 hi = mix(vec2(alphaMax), vec2(0.5), d);
+ n = smoothstep(lo.xxyy, hi.xxyy, n);
+ c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c);
+
+ fragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert
new file mode 100644
index 0000000000..936f74725b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert
@@ -0,0 +1,36 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec3 sampleFarLeft;
+out vec3 sampleNearLeft;
+out vec3 sampleNearRight;
+out vec3 sampleFarRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform float fontScale;
+uniform vec4 vecDelta;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+
+ // Calculate neighbor pixel position in item space.
+ vec3 wDelta = gl_Position.w * vecDelta.xyw;
+ vec3 farLeft = vCoord.xyw - 0.667 * wDelta;
+ vec3 nearLeft = vCoord.xyw - 0.333 * wDelta;
+ vec3 nearRight = vCoord.xyw + 0.333 * wDelta;
+ vec3 farRight = vCoord.xyw + 0.667 * wDelta;
+
+ // Calculate neighbor texture coordinate.
+ vec2 scale = textureScale / fontScale;
+ vec2 base = sampleCoord - scale * vCoord.xy;
+ sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z);
+ sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+ sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+ sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag
new file mode 100644
index 0000000000..2dd588d307
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag
@@ -0,0 +1,21 @@
+#version 150 core
+
+in vec3 sampleNearLeft;
+in vec3 sampleNearRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ vec2 n;
+ n.x = textureProj(_qt_texture, sampleNearLeft).r;
+ n.y = textureProj(_qt_texture, sampleNearRight).r;
+ n = smoothstep(alphaMin, alphaMax, n);
+ float c = 0.5 * (n.x + n.y);
+ fragColor = vec4(n.x, c, n.y, c) * color.w;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert
new file mode 100644
index 0000000000..b887a70001
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert
@@ -0,0 +1,29 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec3 sampleNearLeft;
+out vec3 sampleNearRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform float fontScale;
+uniform vec4 vecDelta;
+
+void main()
+{
+ vec2 sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+
+ // Calculate neighbor pixel position in item space.
+ vec3 wDelta = gl_Position.w * vecDelta.xyw;
+ vec3 nearLeft = vCoord.xyw - 0.25 * wDelta;
+ vec3 nearRight = vCoord.xyw + 0.25 * wDelta;
+
+ // Calculate neighbor texture coordinate.
+ vec2 scale = textureScale / fontScale;
+ vec2 base = sampleCoord - scale * vCoord.xy;
+ sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+ sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture_core.frag b/src/quick/scenegraph/shaders/opaquetexture_core.frag
new file mode 100644
index 0000000000..5f30e68677
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture_core.frag
@@ -0,0 +1,12 @@
+#version 150 core
+
+in vec2 qt_TexCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+
+void main()
+{
+ fragColor = texture(qt_Texture, qt_TexCoord);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture_core.vert b/src/quick/scenegraph/shaders/opaquetexture_core.vert
new file mode 100644
index 0000000000..419b1a825c
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture_core.vert
@@ -0,0 +1,14 @@
+#version 150 core
+
+uniform mat4 qt_Matrix;
+
+in vec4 qt_VertexPosition;
+in vec2 qt_VertexTexCoord;
+
+out vec2 qt_TexCoord;
+
+void main()
+{
+ qt_TexCoord = qt_VertexTexCoord;
+ gl_Position = qt_Matrix * qt_VertexPosition;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext_core.frag b/src/quick/scenegraph/shaders/outlinedtext_core.frag
new file mode 100644
index 0000000000..e19c8937f9
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext_core.frag
@@ -0,0 +1,25 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 sCoordUp;
+in vec2 sCoordDown;
+in vec2 sCoordLeft;
+in vec2 sCoordRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+
+void main()
+{
+ float glyph = texture(_qt_texture, sampleCoord).r;
+ float outline = clamp(clamp(texture(_qt_texture, sCoordUp).r +
+ texture(_qt_texture, sCoordDown).r +
+ texture(_qt_texture, sCoordLeft).r +
+ texture(_qt_texture, sCoordRight).r,
+ 0.0, 1.0) - glyph,
+ 0.0, 1.0);
+ fragColor = outline * styleColor + glyph * color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext_core.vert b/src/quick/scenegraph/shaders/outlinedtext_core.vert
new file mode 100644
index 0000000000..4aa13101fd
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext_core.vert
@@ -0,0 +1,24 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 sCoordUp;
+out vec2 sCoordDown;
+out vec2 sCoordLeft;
+out vec2 sCoordRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ sCoordUp = (tCoord - vec2(0.0, -1.0)) * textureScale;
+ sCoordDown = (tCoord - vec2(0.0, 1.0)) * textureScale;
+ sCoordLeft = (tCoord - vec2(-1.0, 0.0)) * textureScale;
+ sCoordRight = (tCoord - vec2(1.0, 0.0)) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode_core.frag b/src/quick/scenegraph/shaders/rendernode_core.frag
new file mode 100644
index 0000000000..7c187265df
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode_core.frag
@@ -0,0 +1,12 @@
+#version 150 core
+
+uniform sampler2D tex;
+
+in vec2 t;
+
+out vec4 color;
+
+void main()
+{
+ fragColor = texture(tex, t);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode_core.vert b/src/quick/scenegraph/shaders/rendernode_core.vert
new file mode 100644
index 0000000000..a76d519a5a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode_core.vert
@@ -0,0 +1,12 @@
+#version 150 core
+
+in vec4 av;
+in vec2 at;
+
+out vec2 t;
+
+void main()
+{
+ gl_Position = av;
+ t = at;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor_core.frag b/src/quick/scenegraph/shaders/smoothcolor_core.frag
new file mode 100644
index 0000000000..84533c2b40
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor_core.vert b/src/quick/scenegraph/shaders/smoothcolor_core.vert
new file mode 100644
index 0000000000..1eed751ccd
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor_core.vert
@@ -0,0 +1,47 @@
+#version 150 core
+
+in vec4 vertex;
+in vec4 vertexColor;
+in vec2 vertexOffset;
+
+out vec4 color;
+
+uniform vec2 pixelSize;
+uniform mat4 matrix;
+uniform float opacity;
+
+void main()
+{
+ vec4 pos = matrix * vertex;
+ gl_Position = pos;
+
+ if (vertexOffset.x != 0.) {
+ vec4 delta = matrix[0] * vertexOffset.x;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ }
+
+ if (vertexOffset.y != 0.) {
+ vec4 delta = matrix[1] * vertexOffset.y;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ }
+
+ color = vertexColor * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture_core.frag b/src/quick/scenegraph/shaders/smoothtexture_core.frag
new file mode 100644
index 0000000000..8a9aefd4c8
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 texCoord;
+in float vertexOpacity;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+
+void main()
+{
+ fragColor = texture(qt_Texture, texCoord) * vertexOpacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture_core.vert b/src/quick/scenegraph/shaders/smoothtexture_core.vert
new file mode 100644
index 0000000000..a2489a39c5
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture_core.vert
@@ -0,0 +1,54 @@
+#version 150 core
+
+in vec4 vertex;
+in vec2 multiTexCoord;
+in vec2 vertexOffset;
+in vec2 texCoordOffset;
+
+out vec2 texCoord;
+out float vertexOpacity;
+
+uniform vec2 pixelSize;
+uniform mat4 qt_Matrix;
+uniform float opacity;
+
+void main()
+{
+ vec4 pos = qt_Matrix * vertex;
+ gl_Position = pos;
+ texCoord = multiTexCoord;
+
+ if (vertexOffset.x != 0.) {
+ vec4 delta = qt_Matrix[0] * vertexOffset.x;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ texCoord.x += scale * texCoordOffset.x;
+ }
+
+ if (vertexOffset.y != 0.) {
+ vec4 delta = qt_Matrix[1] * vertexOffset.y;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ texCoord.y += scale * texCoordOffset.y;
+ }
+
+ bool onEdge = any(notEqual(vertexOffset, vec2(0.)));
+ bool outerEdge = all(equal(texCoordOffset, vec2(0.)));
+ vertexOpacity = onEdge && outerEdge ? 0. : opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip_core.frag b/src/quick/scenegraph/shaders/stencilclip_core.frag
new file mode 100644
index 0000000000..4d05de4ca9
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip_core.frag
@@ -0,0 +1,8 @@
+#version 150 core
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(0.81, 0.83, 0.12, 1.0); // Trolltech green ftw!
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip_core.vert b/src/quick/scenegraph/shaders/stencilclip_core.vert
new file mode 100644
index 0000000000..37e240c735
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 vCoord;
+
+uniform mat4 matrix;
+
+void main()
+{
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext_core.frag b/src/quick/scenegraph/shaders/styledtext_core.frag
new file mode 100644
index 0000000000..50f64c64a2
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext_core.frag
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 shiftedSampleCoord;
+
+out vec4 color;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+
+void main()
+{
+ float glyph = texture(_qt_texture, sampleCoord).a;
+ float style = clamp(texture(_qt_texture, shiftedSampleCoord).r - glyph,
+ 0.0, 1.0);
+ fragColor = style * styleColor + glyph * color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext_core.vert b/src/quick/scenegraph/shaders/styledtext_core.vert
new file mode 100644
index 0000000000..b7a3ecc667
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext_core.vert
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 shiftedSampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ shiftedSampleCoord = (tCoord - shift) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/textmask_core.frag b/src/quick/scenegraph/shaders/textmask_core.frag
new file mode 100644
index 0000000000..17dda53c97
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask_core.frag
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+
+void main()
+{
+ vec4 glyph = texture(_qt_texture, sampleCoord);
+ fragColor = vec4(glyph.rgb * color.a, glyph.a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/textmask_core.vert b/src/quick/scenegraph/shaders/textmask_core.vert
new file mode 100644
index 0000000000..619248dccb
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/texture_core.frag b/src/quick/scenegraph/shaders/texture_core.frag
new file mode 100644
index 0000000000..d9bdf6a238
--- /dev/null
+++ b/src/quick/scenegraph/shaders/texture_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 qt_TexCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+uniform float opacity;
+
+void main()
+{
+ fragColor = texture(qt_Texture, qt_TexCoord) * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor_core.frag b/src/quick/scenegraph/shaders/vertexcolor_core.frag
new file mode 100644
index 0000000000..84533c2b40
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor_core.vert b/src/quick/scenegraph/shaders/vertexcolor_core.vert
new file mode 100644
index 0000000000..219b840913
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vertexCoord;
+in vec4 vertexColor;
+
+out vec4 color;
+
+uniform mat4 matrix;
+uniform float opacity;
+
+void main()
+{
+ gl_Position = matrix * vertexCoord;
+ color = vertexColor * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 2bc106a025..8678d106ff 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -149,6 +149,11 @@ Atlas::Atlas(const QSize &size)
|| strstr(ext, "GL_EXT_texture_format_BGRA8888")
|| strstr(ext, "GL_IMG_texture_format_BGRA8888")) {
m_internalFormat = m_externalFormat = GL_BGRA;
+#ifdef Q_OS_IOS
+ } else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {
+ m_internalFormat = GL_RGBA;
+ m_externalFormat = GL_BGRA;
+#endif
} else {
m_internalFormat = m_externalFormat = GL_RGBA;
}
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
index c7dd1a9799..1a1963dbca 100644
--- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
@@ -41,6 +41,7 @@
#include "qsgshadersourcebuilder_p.h"
+#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglshaderprogram.h>
#include <QtCore/qdebug.h>
@@ -48,6 +49,162 @@
QT_BEGIN_NAMESPACE
+namespace QSGShaderParser {
+
+struct Tokenizer {
+
+ enum Token {
+ Token_Invalid,
+ Token_Void,
+ Token_OpenBrace,
+ Token_CloseBrace,
+ Token_SemiColon,
+ Token_Identifier,
+ Token_Macro,
+ Token_Version,
+ Token_Extension,
+ Token_SingleLineComment,
+ Token_MultiLineCommentStart,
+ Token_MultiLineCommentEnd,
+ Token_NewLine,
+ Token_Unspecified,
+ Token_EOF
+ };
+
+ static const char *NAMES[];
+
+ void initialize(const char *input);
+ Token next();
+
+ const char *stream;
+ const char *pos;
+ const char *identifier;
+};
+
+const char *Tokenizer::NAMES[] = {
+ "Invalid",
+ "Void",
+ "OpenBrace",
+ "CloseBrace",
+ "SemiColon",
+ "Identifier",
+ "Macro",
+ "Version",
+ "Extension",
+ "SingleLineComment",
+ "MultiLineCommentStart",
+ "MultiLineCommentEnd",
+ "NewLine",
+ "Unspecified",
+ "EOF"
+};
+
+void Tokenizer::initialize(const char *input)
+{
+ stream = input;
+ pos = input;
+ identifier = input;
+}
+
+Tokenizer::Token Tokenizer::next()
+{
+ while (*pos != 0) {
+ char c = *pos++;
+ switch (c) {
+ case '/':
+ if (*pos == '/') {
+ // '//' comment
+ return Token_SingleLineComment;
+ } else if (*pos == '*') {
+ // /* */ comment
+ return Token_MultiLineCommentStart;
+ }
+ break;
+
+ case '*':
+ if (*pos == '/')
+ return Token_MultiLineCommentEnd;
+
+ case '\n':
+ return Token_NewLine;
+
+ case '\r':
+ if (*pos == '\n')
+ return Token_NewLine;
+
+ case '#': {
+ if (*pos == 'v' && pos[1] == 'e' && pos[2] == 'r' && pos[3] == 's'
+ && pos[4] == 'i' && pos[5] == 'o' && pos[6] == 'n') {
+ return Token_Version;
+ } else if (*pos == 'e' && pos[1] == 'x' && pos[2] == 't' && pos[3] == 'e'
+ && pos[4] == 'n' && pos[5] == 's' && pos[6] == 'i'&& pos[7] == 'o'
+ && pos[8] == 'n') {
+ return Token_Extension;
+ } else {
+ while (*pos != 0) {
+ if (*pos == '\n') {
+ ++pos;
+ break;
+ } else if (*pos == '\\') {
+ ++pos;
+ while (*pos != 0 && (*pos == ' ' || *pos == '\t'))
+ ++pos;
+ if (*pos != 0 && (*pos == '\n' || (*pos == '\r' && pos[1] == '\n')))
+ pos+=2;
+ } else {
+ ++pos;
+ }
+ }
+ }
+ break;
+ }
+
+ case ';':
+ return Token_SemiColon;
+
+ case 0:
+ return Token_EOF;
+
+ case '{':
+ return Token_OpenBrace;
+
+ case '}':
+ return Token_CloseBrace;
+
+ case ' ':
+ break;
+
+ case 'v': {
+ if (*pos == 'o' && pos[1] == 'i' && pos[2] == 'd') {
+ pos += 3;
+ return Token_Void;
+ }
+ // Fall-thru
+ }
+ default:
+ // Identifier...
+ if ((c >= 'a' && c <= 'z' ) || (c >= 'A' && c <= 'Z' ) || c == '_') {
+ identifier = pos - 1;
+ while (*pos != 0 && ((*pos >= 'a' && *pos <= 'z')
+ || (*pos >= 'A' && *pos <= 'Z')
+ || *pos == '_'
+ || (*pos >= '0' && *pos <= '9'))) {
+ ++pos;
+ }
+ return Token_Identifier;
+ } else {
+ return Token_Unspecified;
+ }
+ }
+ }
+
+ return Token_Invalid;
+}
+
+} // namespace QSGShaderParser
+
+using namespace QSGShaderParser;
+
QSGShaderSourceBuilder::QSGShaderSourceBuilder()
{
}
@@ -87,7 +244,7 @@ void QSGShaderSourceBuilder::appendSource(const QByteArray &source)
void QSGShaderSourceBuilder::appendSourceFile(const QString &fileName)
{
const QString resolvedFileName = resolveShaderPath(fileName);
- QFile f(fileName);
+ QFile f(resolvedFileName);
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Failed to find shader" << resolvedFileName;
return;
@@ -95,12 +252,152 @@ void QSGShaderSourceBuilder::appendSourceFile(const QString &fileName)
m_source += f.readAll();
}
+void QSGShaderSourceBuilder::addDefinition(const QByteArray &definition)
+{
+ if (definition.isEmpty())
+ return;
+
+ Tokenizer tok;
+ const char *input = m_source.constData();
+ tok.initialize(input);
+
+ // First find #version, #extension's and "void main() { ... "
+ const char *versionPos = 0;
+ const char *extensionPos = 0;
+ bool inSingleLineComment = false;
+ bool inMultiLineComment = false;
+ bool foundVersionStart = false;
+ bool foundExtensionStart = false;
+
+ Tokenizer::Token lt = Tokenizer::Token_Unspecified;
+ Tokenizer::Token t = tok.next();
+ while (t != Tokenizer::Token_EOF) {
+ // Handle comment blocks
+ if (t == Tokenizer::Token_MultiLineCommentStart )
+ inMultiLineComment = true;
+ if (t == Tokenizer::Token_MultiLineCommentEnd)
+ inMultiLineComment = false;
+ if (t == Tokenizer::Token_SingleLineComment)
+ inSingleLineComment = true;
+ if (t == Tokenizer::Token_NewLine && inSingleLineComment && !inMultiLineComment)
+ inSingleLineComment = false;
+
+ // Have we found #version, #extension or void main()?
+ if (t == Tokenizer::Token_Version && !inSingleLineComment && !inMultiLineComment)
+ foundVersionStart = true;
+
+ if (t == Tokenizer::Token_Extension && !inSingleLineComment && !inMultiLineComment)
+ foundExtensionStart = true;
+
+ if (foundVersionStart && t == Tokenizer::Token_NewLine) {
+ versionPos = tok.pos;
+ foundVersionStart = false;
+ } else if (foundExtensionStart && t == Tokenizer::Token_NewLine) {
+ extensionPos = tok.pos;
+ foundExtensionStart = false;
+ } else if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
+ if (qstrncmp("main", tok.identifier, 4) == 0)
+ break;
+ }
+
+ // Scan to next token
+ lt = t;
+ t = tok.next();
+ }
+
+ // Determine where to insert the definition.
+ // If we found #extension directives, insert after last one,
+ // else, if we found #version insert after #version
+ // otherwise, insert at beginning.
+ const char *insertionPos = extensionPos ? extensionPos : (versionPos ? versionPos : input);
+
+ // Construct a new shader string, inserting the definition
+ QByteArray newSource;
+ newSource.reserve(m_source.size() + definition.size() + 9);
+ newSource += QByteArray::fromRawData(input, insertionPos - input);
+ newSource += QByteArrayLiteral("#define ") + definition + QByteArrayLiteral("\n");
+ newSource += QByteArray::fromRawData(insertionPos, m_source.size() - (insertionPos - input));
+
+ m_source = newSource;
+}
+
+void QSGShaderSourceBuilder::removeVersion()
+{
+ Tokenizer tok;
+ const char *input = m_source.constData();
+ tok.initialize(input);
+
+ // First find #version beginning and end (if present)
+ const char *versionStartPos = 0;
+ const char *versionEndPos = 0;
+ bool inSingleLineComment = false;
+ bool inMultiLineComment = false;
+ bool foundVersionStart = false;
+
+ Tokenizer::Token lt = Tokenizer::Token_Unspecified;
+ Tokenizer::Token t = tok.next();
+ while (t != Tokenizer::Token_EOF) {
+ // Handle comment blocks
+ if (t == Tokenizer::Token_MultiLineCommentStart )
+ inMultiLineComment = true;
+ if (t == Tokenizer::Token_MultiLineCommentEnd)
+ inMultiLineComment = false;
+ if (t == Tokenizer::Token_SingleLineComment)
+ inSingleLineComment = true;
+ if (t == Tokenizer::Token_NewLine && inSingleLineComment && !inMultiLineComment)
+ inSingleLineComment = false;
+
+ // Have we found #version, #extension or void main()?
+ if (t == Tokenizer::Token_Version && !inSingleLineComment && !inMultiLineComment) {
+ versionStartPos = tok.pos - 1;
+ foundVersionStart = true;
+ } else if (foundVersionStart && t == Tokenizer::Token_NewLine) {
+ versionEndPos = tok.pos;
+ break;
+ } else if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
+ if (qstrncmp("main", tok.identifier, 4) == 0)
+ break;
+ }
+
+ // Scan to next token
+ lt = t;
+ t = tok.next();
+ }
+
+ if (versionStartPos == 0)
+ return;
+
+ // Construct a new shader string, inserting the definition
+ QByteArray newSource;
+ newSource.reserve(m_source.size() - (versionEndPos - versionStartPos));
+ newSource += QByteArray::fromRawData(input, versionStartPos - input);
+ newSource += QByteArray::fromRawData(versionEndPos, m_source.size() - (versionEndPos - versionStartPos));
+
+ m_source = newSource;
+}
+
QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const
{
- // For now, just return the path unaltered.
- // TODO: Resolve to more specific filename based upon OpenGL profile and
- // version, platform, GPU type etc
- return path;
+ if (contextProfile() != QSurfaceFormat::CoreProfile) {
+ return path;
+ } else {
+ int idx = path.lastIndexOf(QStringLiteral("."));
+ QString resolvedPath;
+ if (idx != -1)
+ resolvedPath = path.left(idx)
+ + QStringLiteral("_core")
+ + path.right(path.length() - idx);
+ return resolvedPath;
+ }
+}
+
+QSurfaceFormat::OpenGLContextProfile QSGShaderSourceBuilder::contextProfile() const
+{
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QSurfaceFormat::OpenGLContextProfile profile = QSurfaceFormat::NoProfile;
+ Q_ASSERT(context);
+ profile = context->format().profile();
+ return profile;
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
index 8def250d4f..63f2d78767 100644
--- a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
@@ -44,6 +44,7 @@
#include <private/qtquickglobal_p.h>
+#include <QtGui/qsurfaceformat.h>
#include <QtCore/qbytearray.h>
QT_BEGIN_NAMESPACE
@@ -64,11 +65,15 @@ public:
void appendSource(const QByteArray &source);
void appendSourceFile(const QString &fileName);
+ void addDefinition(const QByteArray &definition);
+ void removeVersion();
protected:
virtual QString resolveShaderPath(const QString &path) const;
private:
+ QSurfaceFormat::OpenGLContextProfile contextProfile() const;
+
QByteArray m_source;
};
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index b079100a37..51b3bafaf7 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -682,16 +682,21 @@ void QSGPlainTexture::bind()
GLenum externalFormat = GL_RGBA;
GLenum internalFormat = GL_RGBA;
- const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
- if (strstr(extensions, "GL_EXT_bgra")) {
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) {
externalFormat = GL_BGRA;
#ifdef QT_OPENGL_ES
internalFormat = GL_BGRA;
#endif
- } else if (strstr(extensions, "GL_EXT_texture_format_BGRA8888")
- || strstr(extensions, "GL_IMG_texture_format_BGRA8888")) {
+ } else if (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
+ || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888"))) {
externalFormat = GL_BGRA;
internalFormat = GL_BGRA;
+#ifdef Q_OS_IOS
+ } else if (context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+#endif
} else {
qsg_swizzleBGRAToRGBA(&tmp);
}
@@ -711,8 +716,7 @@ void QSGPlainTexture::bind()
if (m_has_mipmaps) {
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ context->functions()->glGenerateMipmap(GL_TEXTURE_2D);
m_mipmaps_generated = true;
}
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 342cf2eaff..f743acc249 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -1648,7 +1648,8 @@ QQuickAnimationGroup::QQuickAnimationGroup(QQuickAnimationGroupPrivate &dd, QObj
void QQuickAnimationGroupPrivate::append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a)
{
- if (QQuickAnimationGroup *q = qmlobject_cast<QQuickAnimationGroup *>(list->object))
+ QQuickAnimationGroup *q = qmlobject_cast<QQuickAnimationGroup *>(list->object);
+ if (q && a)
a->setGroup(q);
}
diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp
index efaa5ba56c..36aae36459 100644
--- a/src/quick/util/qquickspringanimation.cpp
+++ b/src/quick/util/qquickspringanimation.cpp
@@ -308,7 +308,8 @@ void QSpringAnimation::updateCurrentTime(int time)
QQmlPropertyPrivate::DontRemoveBinding);
if (stopped && old_to == to) { // do not stop if we got restarted
- stopTime = animationTemplate->elapsed.elapsed();
+ if (animationTemplate)
+ stopTime = animationTemplate->elapsed.elapsed();
stop();
}
}
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
index 9318372e2c..2fee7cfc92 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
+++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
@@ -48,7 +48,6 @@
#include <QtCore/QString>
#include <QtTest/QtTest>
-const char *ENABLE_DEBUG= "-enable-debugger";
const char *NORMALMODE = "-qmljsdebugger=port:3777,3787,block";
const char *QMLFILE = "test.qml";
@@ -183,7 +182,7 @@ void tst_QDebugMessageService::init()
m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml", this);
m_client = new QQmlDebugMsgClient(m_connection);
- m_process->start(QStringList() << QLatin1String(ENABLE_DEBUG) << QLatin1String(NORMALMODE) << QQmlDataTest::instance()->testFile(QMLFILE));
+ m_process->start(QStringList() << QLatin1String(NORMALMODE) << QQmlDataTest::instance()->testFile(QMLFILE));
QVERIFY2(m_process->waitForSessionStart(),
"Could not launch application, or did not get 'Waiting for connection'.");
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index fb6b4eee65..2cf6ee958a 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -1454,9 +1454,9 @@ void tst_QQmlDebugJS::getScripts()
QVERIFY(init());
+ client->setBreakpoint(QLatin1String(SCRIPTREGEXP), QString(TEST_QMLFILE), 48, -1, true);
client->connect();
- client->interrupt();
- QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(interruptRequested())));
+ QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(stopped())));
client->scripts();
QVERIFY(QQmlDebugTest::waitForSignal(client, SIGNAL(scriptsResult())));
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
index 231e37c6fb..efb130d789 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
@@ -110,7 +110,7 @@ void tst_QQmlEngineDebugInspectorIntegration::init()
// ### Still using qmlscene because of QTBUG-33376
m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath)
+ "/qmlscene", this);
- m_process->start(QStringList() << QLatin1String("-enable-debugger") << argument << testFile("qtquick2.qml"));
+ m_process->start(QStringList() << argument << testFile("qtquick2.qml"));
QVERIFY2(m_process->waitForSessionStart(),
"Could not launch application, or did not get 'Waiting for connection'.");
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
index 2eeb4ce5b2..6a9ecdfa73 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
@@ -91,7 +91,7 @@ void tst_QQmlInspector::startQmlsceneProcess(const char * /* qmlFile */)
// ### This should be using qml instead of qmlscene, but can't because of QTBUG-33376 (same as the XFAIL testcase)
m_process = new QQmlDebugProcess(QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene", this);
- m_process->start(QStringList() << QLatin1String("-enable-debugger") << argument << testFile("qtquick2.qml"));
+ m_process->start(QStringList() << argument << testFile("qtquick2.qml"));
QVERIFY2(m_process->waitForSessionStart(),
"Could not launch application, or did not get 'Waiting for connection'.");
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 902e525dd6..f2b82db630 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -300,8 +300,6 @@ void tst_QQmlProfilerService::connect(bool block, const QString &testFile)
// ### Still using qmlscene due to QTBUG-33377
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
QStringList arguments;
- arguments << QLatin1String("-enable-debugger");
-
if (block)
arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block");
else
@@ -450,8 +448,9 @@ void tst_QQmlProfilerService::scenegraphData()
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(true);
- QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
- QVERIFY(m_process->output().indexOf(QLatin1String("tick")) != -1);
+
+ while (!m_process->output().contains(QLatin1String("tick")))
+ QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
diff --git a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
index f0485fb68a..a461519c75 100644
--- a/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
+++ b/tests/auto/qml/debugger/qv8profilerservice/tst_qv8profilerservice.cpp
@@ -206,7 +206,6 @@ bool tst_QV8ProfilerService::connect(bool block, const QString &testFile,
{
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qml";
QStringList arguments;
- arguments << QLatin1String("-enable-debugger");
if (block)
arguments << QString("-qmljsdebugger=port:" STR_PORT_FROM "," STR_PORT_TO ",block");
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 2b8da26dc9..e73edc812a 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -2206,7 +2206,7 @@ void tst_QJSValue::strictlyEquals()
{
QJSValue var1 = eng.toScriptValue(QVariant(QPoint(1, 2)));
QJSValue var2 = eng.toScriptValue(QVariant(QPoint(1, 2)));
- QVERIFY(!var1.strictlyEquals(var2));
+ QVERIFY(var1.strictlyEquals(var2));
}
{
QJSValue var1 = eng.toScriptValue(QVariant(QPoint(1, 2)));
diff --git a/tests/auto/qml/qqmlecmascript/data/idAsLValue.qml b/tests/auto/qml/qqmlecmascript/data/idAsLValue.qml
new file mode 100644
index 0000000000..1035f844b4
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/idAsLValue.qml
@@ -0,0 +1,7 @@
+import QtQml 2.0
+QtObject {
+ id: root
+ Component.onCompleted: {
+ root = "hello"
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/misctypetest.qml b/tests/auto/qml/qqmlecmascript/data/misctypetest.qml
new file mode 100644
index 0000000000..60ff53a2b4
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/misctypetest.qml
@@ -0,0 +1,28 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Item {
+ MiscTypeTest {
+ id: mtt
+ }
+
+ function test_invalid_url_equal()
+ {
+ return mtt.invalidUrl() == mtt.invalidUrl();
+ }
+
+ function test_invalid_url_refequal()
+ {
+ return mtt.invalidUrl() === mtt.invalidUrl();
+ }
+
+ function test_valid_url_equal()
+ {
+ return mtt.validUrl() == mtt.validUrl();
+ }
+
+ function test_valid_url_refequal()
+ {
+ return mtt.validUrl() === mtt.validUrl();
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug34792.qml b/tests/auto/qml/qqmlecmascript/data/qtbug34792.qml
new file mode 100644
index 0000000000..37c551b587
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug34792.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.1
+Rectangle {
+ function foo()
+ {
+ for (var i = 0; i < 1; i++)
+ {
+ if (i >= 0)
+ break
+
+ return
+ }
+
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_33754.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_33754.qml
new file mode 100644
index 0000000000..705334fbfa
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_33754.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+
+Item {
+ property int a: 0
+ property int b: 0
+
+ Component.onCompleted: {
+ for (var i = ((a > b) ? b : a); i < ((a > b) ? a : b); i++)
+ {
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_34493.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_34493.qml
new file mode 100644
index 0000000000..7e7d350aae
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_34493.qml
@@ -0,0 +1,19 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyQmlObject {
+ function doIt() {
+ d.hello("World")
+ }
+
+ property QtObject subobject: QtObject {
+ id: d
+ function hello(input) {
+ var temp = "Hello " + input;
+ var input = temp + "!";
+ prop = input
+ }
+ }
+
+ property string prop
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.indexes.qml b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.indexes.qml
index 962e8dd474..a3f306f717 100644
--- a/tests/auto/qml/qqmlecmascript/data/sequenceConversion.indexes.qml
+++ b/tests/auto/qml/qqmlecmascript/data/sequenceConversion.indexes.qml
@@ -72,4 +72,17 @@ Item {
if (!verifyExpected(msco.intListProperty, 4))
success = false;
}
+
+ function indexOf() {
+ if (msco.qstringListProperty.length != 4)
+ success = false;
+ if (msco.qstringListProperty.indexOf("first") != 0)
+ success = false;
+ if (msco.qstringListProperty.indexOf("second") != 1)
+ success = false;
+ if (msco.qstringListProperty.indexOf("third") != 2)
+ success = false;
+ if (msco.qstringListProperty.indexOf("fourth") != 3)
+ success = false;
+ }
}
diff --git a/tests/auto/qml/qqmlecmascript/data/setPropertyOnNull.qml b/tests/auto/qml/qqmlecmascript/data/setPropertyOnNull.qml
new file mode 100644
index 0000000000..a3288f47d7
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/setPropertyOnNull.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.2
+
+QtObject {
+ Component.onCompleted: null.bug = 0
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/setPropertyOnUndefined.qml b/tests/auto/qml/qqmlecmascript/data/setPropertyOnUndefined.qml
new file mode 100644
index 0000000000..6655c47e5f
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/setPropertyOnUndefined.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.2
+
+QtObject {
+ Component.onCompleted: undefined.bug = 0
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/singletonTest.qml b/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
new file mode 100644
index 0000000000..6d296cd613
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Canonical Limited 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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Test 1.0
+
+Item {
+ property bool qobjectTest: MyInheritedQmlObjectSingleton.isItYouQObject(MyInheritedQmlObjectSingleton)
+ property bool myQmlObjectTest: MyInheritedQmlObjectSingleton.isItYouMyQmlObject(MyInheritedQmlObjectSingleton)
+ property bool myInheritedQmlObjectTest: MyInheritedQmlObjectSingleton.isItYouMyInheritedQmlObject(MyInheritedQmlObjectSingleton)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml b/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
new file mode 100644
index 0000000000..ec457589de
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Canonical Limited 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$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Test 1.0
+
+Item {
+ property bool myInheritedQmlObjectTest1: false
+ property bool myInheritedQmlObjectTest2: false
+ property bool myInheritedQmlObjectTest3: false
+ property bool myQmlObjectTest1: false
+ property bool myQmlObjectTest2: false
+ property bool myQmlObjectTest3: false
+ property bool qobjectTest1: false
+ property bool qobjectTest2: false
+ property bool qobjectTest3: false
+ property bool singletonEqualToItself: true
+
+ Component.onCompleted: {
+ MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty = MyInheritedQmlObjectSingleton;
+ myInheritedQmlObjectTest1 = MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty == MyInheritedQmlObjectSingleton;
+ myInheritedQmlObjectTest2 = MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty == MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty;
+ myInheritedQmlObjectTest3 = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton.myInheritedQmlObjectProperty;
+
+ MyInheritedQmlObjectSingleton.myQmlObjectProperty = MyInheritedQmlObjectSingleton;
+ myQmlObjectTest1 = MyInheritedQmlObjectSingleton.myQmlObjectProperty == MyInheritedQmlObjectSingleton;
+ myQmlObjectTest2 = MyInheritedQmlObjectSingleton.myQmlObjectProperty == MyInheritedQmlObjectSingleton.myQmlObjectProperty;
+ myQmlObjectTest3 = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton.myQmlObjectProperty;
+
+ MyInheritedQmlObjectSingleton.qobjectProperty = MyInheritedQmlObjectSingleton;
+ qobjectTest1 = MyInheritedQmlObjectSingleton.qobjectProperty == MyInheritedQmlObjectSingleton;
+ qobjectTest2 = MyInheritedQmlObjectSingleton.qobjectProperty == MyInheritedQmlObjectSingleton.qobjectProperty;
+ qobjectTest3 = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton.qobjectProperty;
+
+ singletonEqualToItself = MyInheritedQmlObjectSingleton == MyInheritedQmlObjectSingleton;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/updateCall.qml b/tests/auto/qml/qqmlecmascript/data/updateCall.qml
new file mode 100644
index 0000000000..341a360d25
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/updateCall.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.1
+
+Rectangle {
+ MouseArea {
+ anchors.fill: parent;
+ Component.onCompleted: {
+ update();
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index a09bd9f3c6..41fa3672bd 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -235,6 +235,21 @@ public:
}
};
+class MiscTypeTestClass : public QObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE QUrl invalidUrl()
+ {
+ return QUrl();
+ }
+
+ Q_INVOKABLE QUrl validUrl()
+ {
+ return QUrl("http://wwww.qt-project.org");
+ }
+};
+
class MyStringClass : public QObject
{
Q_OBJECT
@@ -257,10 +272,34 @@ public:
}
};
+static MyInheritedQmlObject *theSingletonObject = 0;
+
+static QObject *inheritedQmlObject_provider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
+{
+ theSingletonObject = new MyInheritedQmlObject();
+ return theSingletonObject;
+}
+
+bool MyInheritedQmlObject::isItYouQObject(QObject *o)
+{
+ return o && o == theSingletonObject;
+}
+
+bool MyInheritedQmlObject::isItYouMyQmlObject(MyQmlObject *o)
+{
+ return o && o == theSingletonObject;
+}
+
+bool MyInheritedQmlObject::isItYouMyInheritedQmlObject(MyInheritedQmlObject *o)
+{
+ return o && o == theSingletonObject;
+}
+
void registerTypes()
{
qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias");
qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObject");
+ qmlRegisterSingletonType<MyInheritedQmlObject>("Test", 1, 0, "MyInheritedQmlObjectSingleton", inheritedQmlObject_provider);
qmlRegisterType<MyDeferredObject>("Qt.test", 1,0, "MyDeferredObject");
qmlRegisterType<MyVeryDeferredObject>("Qt.test", 1,0, "MyVeryDeferredObject");
qmlRegisterType<MyQmlContainer>("Qt.test", 1,0, "MyQmlContainer");
@@ -329,6 +368,7 @@ void registerTypes()
qmlRegisterType<MyDateClass>("Qt.test", 1, 0, "MyDateClass");
qmlRegisterType<MyStringClass>("Qt.test", 1, 0, "MyStringClass");
+ qmlRegisterType<MiscTypeTestClass>("Qt.test", 1, 0, "MiscTypeTest");
qmlRegisterSingletonType<testImportOrderApi>("Qt.test.importOrderApi",1,0,"Data",testImportOrder_api);
qmlRegisterSingletonType<testImportOrderApi>("NamespaceAndType",1,0,"NamespaceAndType",testImportOrder_api);
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index 52a619637c..556cc32fd3 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -291,6 +291,34 @@ Q_DECLARE_METATYPE(QQmlListProperty<MyQmlObject>)
QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES)
+class MyInheritedQmlObject : public MyQmlObject
+{
+ Q_OBJECT
+ Q_PROPERTY(MyInheritedQmlObject *myInheritedQmlObjectProperty READ myInheritedQmlObject WRITE setMyInheritedQmlObject)
+ Q_PROPERTY(MyQmlObject *myQmlObjectProperty READ myQmlObject WRITE setMyQmlObject)
+ Q_PROPERTY(QObject *qobjectProperty READ qobject WRITE setQObject)
+public:
+ MyInheritedQmlObject() : m_myInheritedQmlObject(0), m_myQmlObject(0), m_qobject(0) {}
+
+ MyInheritedQmlObject *myInheritedQmlObject() const { return m_myInheritedQmlObject; }
+ void setMyInheritedQmlObject(MyInheritedQmlObject * o) { m_myInheritedQmlObject = o; }
+
+ MyQmlObject *myQmlObject() const { return m_myQmlObject; }
+ void setMyQmlObject(MyQmlObject * o) { m_myQmlObject = o; }
+
+ QObject *qobject() const { return m_qobject; }
+ void setQObject(QObject * o) { m_qobject = o; }
+
+ Q_INVOKABLE bool isItYouQObject(QObject *o);
+ Q_INVOKABLE bool isItYouMyQmlObject(MyQmlObject *o);
+ Q_INVOKABLE bool isItYouMyInheritedQmlObject(MyInheritedQmlObject *o);
+private:
+ MyInheritedQmlObject *m_myInheritedQmlObject;
+ MyQmlObject *m_myQmlObject;
+ QObject *m_qobject;
+};
+QML_DECLARE_TYPE(MyInheritedQmlObject)
+
class MyQmlContainer : public QObject
{
Q_OBJECT
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index f4641145ab..6b19c13109 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -304,10 +304,21 @@ private slots:
void propertyOverride();
void concatenatedStringPropertyAccess();
void jsOwnedObjectsDeletedOnEngineDestroy();
+ void updateCall();
void numberParsing();
void stringParsing();
+ void push_and_shift();
void qtbug_32801();
void thisObject();
+ void qtbug_33754();
+ void qtbug_34493();
+ void singletonFromQMLToCpp();
+ void singletonFromQMLAndBackAndCompare();
+ void setPropertyOnInvalid();
+ void miscTypeTest();
+ void stackLimits();
+ void idsAsLValues();
+ void qtbug_34792();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -5422,6 +5433,8 @@ void tst_qqmlecmascript::sequenceConversionIndexes()
QTest::ignoreMessage(QtWarningMsg, qPrintable(w3));
QMetaObject::invokeMethod(object, "indexedAccess");
QVERIFY(object->property("success").toBool());
+ QMetaObject::invokeMethod(object, "indexOf");
+ QVERIFY(object->property("success").toBool());
delete object;
}
@@ -7272,6 +7285,17 @@ void tst_qqmlecmascript::jsOwnedObjectsDeletedOnEngineDestroy()
delete object;
}
+void tst_qqmlecmascript::updateCall()
+{
+ // update is a slot on QQuickItem. Even though it's not
+ // documented it can be called from within QML. Make sure
+ // we don't crash when calling it.
+ QString file("updateCall.qml");
+ QQmlComponent component(&engine, testFileUrl(file));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+}
+
void tst_qqmlecmascript::numberParsing()
{
for (int i = 1; i < 8; ++i) {
@@ -7300,6 +7324,18 @@ void tst_qqmlecmascript::stringParsing()
}
}
+void tst_qqmlecmascript::push_and_shift()
+{
+ QJSEngine e;
+ const QString program =
+ "var array = []; "
+ "for (var i = 0; i < 10000; i++) {"
+ " array.push(5); array.unshift(5); array.push(5);"
+ "}"
+ "array.length;";
+ QVERIFY(e.evaluate(program).toNumber() == 30000);
+}
+
void tst_qqmlecmascript::qtbug_32801()
{
QQmlComponent component(&engine, testFileUrl("qtbug_32801.qml"));
@@ -7321,6 +7357,140 @@ void tst_qqmlecmascript::thisObject()
delete object;
}
+void tst_qqmlecmascript::qtbug_33754()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug_33754.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj != 0);
+}
+
+void tst_qqmlecmascript::qtbug_34493()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug_34493.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ if (component.errors().size())
+ qDebug() << component.errors();
+ QVERIFY(component.errors().isEmpty());
+ QVERIFY(obj != 0);
+ QVERIFY(QMetaObject::invokeMethod(obj.data(), "doIt"));
+ QTRY_VERIFY(obj->property("prop").toString() == QLatin1String("Hello World!"));
+}
+
+// Check that a Singleton can be passed from QML to C++
+// as its type*, it's parent type* and as QObject*
+void tst_qqmlecmascript::singletonFromQMLToCpp()
+{
+ QQmlComponent component(&engine, testFile("singletonTest.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ if (component.errors().size())
+ qDebug() << component.errors();
+ QVERIFY(component.errors().isEmpty());
+ QVERIFY(obj != 0);
+
+ QCOMPARE(obj->property("qobjectTest"), QVariant(true));
+ QCOMPARE(obj->property("myQmlObjectTest"), QVariant(true));
+ QCOMPARE(obj->property("myInheritedQmlObjectTest"), QVariant(true));
+}
+
+// Check that a Singleton can be passed from QML to C++
+// as its type*, it's parent type* and as QObject*
+// and correctly compares to itself
+void tst_qqmlecmascript::singletonFromQMLAndBackAndCompare()
+{
+ QQmlComponent component(&engine, testFile("singletonTest2.qml"));
+ QScopedPointer<QObject> o(component.create());
+ if (component.errors().size())
+ qDebug() << component.errors();
+ QVERIFY(component.errors().isEmpty());
+ QVERIFY(o != 0);
+
+ QCOMPARE(o->property("myInheritedQmlObjectTest1"), QVariant(true));
+ QCOMPARE(o->property("myInheritedQmlObjectTest2"), QVariant(true));
+ QCOMPARE(o->property("myInheritedQmlObjectTest3"), QVariant(true));
+
+ QCOMPARE(o->property("myQmlObjectTest1"), QVariant(true));
+ QCOMPARE(o->property("myQmlObjectTest2"), QVariant(true));
+ QCOMPARE(o->property("myQmlObjectTest3"), QVariant(true));
+
+ QCOMPARE(o->property("qobjectTest1"), QVariant(true));
+ QCOMPARE(o->property("qobjectTest2"), QVariant(true));
+ QCOMPARE(o->property("qobjectTest3"), QVariant(true));
+
+ QCOMPARE(o->property("singletonEqualToItself"), QVariant(true));
+}
+
+void tst_qqmlecmascript::setPropertyOnInvalid()
+{
+ {
+ QQmlComponent component(&engine, testFileUrl("setPropertyOnNull.qml"));
+ QString warning = component.url().toString() + ":4: TypeError: Type error";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ QObject *object = component.create();
+ QVERIFY(object);
+ delete object;
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("setPropertyOnUndefined.qml"));
+ QString warning = component.url().toString() + ":4: TypeError: Type error";
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
+ QObject *object = component.create();
+ QVERIFY(object);
+ delete object;
+ }
+}
+
+void tst_qqmlecmascript::miscTypeTest()
+{
+ QQmlComponent component(&engine, testFileUrl("misctypetest.qml"));
+
+ QObject *object = component.create();
+ if (object == 0)
+ qDebug() << component.errorString();
+ QVERIFY(object != 0);
+
+ QVariant q;
+ QMetaObject::invokeMethod(object, "test_invalid_url_equal", Q_RETURN_ARG(QVariant, q));
+ QVERIFY(q.toBool() == true);
+ QMetaObject::invokeMethod(object, "test_invalid_url_strictequal", Q_RETURN_ARG(QVariant, q));
+ QVERIFY(q.toBool() == true);
+ QMetaObject::invokeMethod(object, "test_valid_url_equal", Q_RETURN_ARG(QVariant, q));
+ QVERIFY(q.toBool() == true);
+ QMetaObject::invokeMethod(object, "test_valid_url_strictequal", Q_RETURN_ARG(QVariant, q));
+ QVERIFY(q.toBool() == true);
+
+ delete object;
+}
+
+void tst_qqmlecmascript::stackLimits()
+{
+ QJSEngine engine;
+ engine.evaluate(QStringLiteral("function foo() {foo();} try {foo()} catch(e) { }"));
+}
+
+void tst_qqmlecmascript::idsAsLValues()
+{
+ QString err = QString(QLatin1String("%1:5 left-hand side of assignment operator is not an lvalue\n")).arg(testFileUrl("idAsLValue.qml").toString());
+ QQmlComponent component(&engine, testFileUrl("idAsLValue.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(!object);
+ QCOMPARE(component.errorString(), err);
+}
+
+void tst_qqmlecmascript::qtbug_34792()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug34792.qml"));
+
+ QObject *object = component.create();
+ if (object == 0)
+ qDebug() << component.errorString();
+ QVERIFY(object != 0);
+ delete object;
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 004514d39c..382bfe4b73 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -54,7 +54,7 @@
#include <QQmlExpression>
#include <QQmlIncubationController>
#include <private/qqmlengine_p.h>
-#include <QQmlAbstractUrlInterceptor>
+#include <private/qqmlabstracturlinterceptor_p.h>
class tst_qqmlengine : public QQmlDataTest
{
diff --git a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
index a583fd0c4c..a9c1c11549 100644
--- a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
+++ b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
@@ -43,6 +43,7 @@
#include <QQmlEngine>
#include <QQmlComponent>
#include <QQmlFileSelector>
+#include <QQmlApplicationEngine>
#include <QFileSelector>
#include <QQmlContext>
#include <qqmlinfo.h>
@@ -56,17 +57,30 @@ public:
private slots:
void basicTest();
+ void applicationEngineTest();
};
void tst_qqmlfileselector::basicTest()
{
QQmlEngine engine;
- QFileSelector selector;
+ QQmlFileSelector selector(&engine);
selector.setExtraSelectors(QStringList() << "basic");
- QQmlFileSelector qmlSelector;
- qmlSelector.setSelector(&selector);
- engine.setUrlInterceptor(&qmlSelector);
+
+ QQmlComponent component(&engine, testFileUrl("basicTest.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("value").toString(), QString("selected"));
+
+ delete object;
+}
+
+void tst_qqmlfileselector::applicationEngineTest()
+{
+ QQmlApplicationEngine engine;
+ QQmlFileSelector* selector = QQmlFileSelector::get(&engine);
+ QVERIFY(selector != 0);
+ selector->setExtraSelectors(QStringList() << "basic");
QQmlComponent component(&engine, testFileUrl("basicTest.qml"));
QObject *object = component.create();
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index f889036961..621061ab6a 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -3511,12 +3511,9 @@ void tst_qqmllanguage::compositeSingletonJavaScriptPragma()
// Reads values from a Singleton accessed through selectors.
void tst_qqmllanguage::compositeSingletonSelectors()
{
- QFileSelector selector;
- selector.setExtraSelectors(QStringList() << "basicSelector");
- QQmlFileSelector qmlSelector;
- qmlSelector.setSelector(&selector);
QQmlEngine e2;
- e2.setUrlInterceptor(&qmlSelector);
+ QQmlFileSelector qmlSelector(&e2);
+ qmlSelector.setExtraSelectors(QStringList() << "basicSelector");
QQmlComponent component(&e2, testFile("singletonTest1.qml"));
VERIFY_ERRORS(0);
QObject *o = component.create();
diff --git a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
index fa3b190826..f1b48df437 100644
--- a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
+++ b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
@@ -98,6 +98,7 @@ public:
void verifyReceiverCount()
{
+ //Note: QTBUG-34829 means we can't call this from within disconnectNotify or it can lock
QCOMPARE(receivers(SIGNAL(qmlObjectPropChanged())), qmlObjectPropConnections);
QCOMPARE(receivers(SIGNAL(cppObjectPropChanged())), cppObjectPropConnections);
QCOMPARE(receivers(SIGNAL(unboundPropChanged())), unboundPropConnections);
@@ -134,7 +135,6 @@ protected:
if (signal.name() == "scriptBindingPropChanged") scriptBindingPropConnections--;
if (signal.name() == "boundSignal") boundSignalConnections--;
if (signal.name() == "unusedSignal") unusedSignalConnections--;
- verifyReceiverCount();
//qDebug() << Q_FUNC_INFO << this << signal.methodSignature();
}
@@ -205,6 +205,7 @@ void tst_qqmlnotifier::createObjects()
exportedClass = qobject_cast<ExportedClass *>(
root->findChild<ExportedClass*>("exportedClass"));
QVERIFY(exportedClass != 0);
+ exportedClass->verifyReceiverCount();
}
void tst_qqmlnotifier::cleanupTestCase()
diff --git a/tests/auto/quick/nodes/tst_nodestest.cpp b/tests/auto/quick/nodes/tst_nodestest.cpp
index 9910729807..d07fd7177d 100644
--- a/tests/auto/quick/nodes/tst_nodestest.cpp
+++ b/tests/auto/quick/nodes/tst_nodestest.cpp
@@ -48,6 +48,8 @@
#include <QtQuick/qsgnode.h>
#include <QtQuick/private/qsgbatchrenderer_p.h>
#include <QtQuick/private/qsgnodeupdater_p.h>
+#include <QtQuick/private/qsgrenderloop_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
#include <QtQuick/qsgsimplerectnode.h>
@@ -75,16 +77,22 @@ private Q_SLOTS:
private:
QOffscreenSurface *surface;
QOpenGLContext *context;
+ QSGRenderContext *renderContext;
};
void NodesTest::initTestCase()
{
+ QSGRenderLoop *renderLoop = QSGRenderLoop::instance();
+
surface = new QOffscreenSurface;
surface->create();
context = new QOpenGLContext();
context->create();
context->makeCurrent(surface);
+
+ renderContext = renderLoop->createRenderContext(renderLoop->sceneGraphContext());
+ renderContext->initialize(context);
}
void NodesTest::cleanupTestCase()
@@ -97,8 +105,8 @@ void NodesTest::cleanupTestCase()
class DummyRenderer : public QSGBatchRenderer::Renderer
{
public:
- DummyRenderer(QSGRootNode *root)
- : QSGBatchRenderer::Renderer(new QSGRenderContext(0))
+ DummyRenderer(QSGRootNode *root, QSGRenderContext *renderContext)
+ : QSGBatchRenderer::Renderer(renderContext)
, changedNode(0)
, changedState(0)
, renderCount(0)
@@ -138,7 +146,7 @@ void NodesTest::propegate()
QSGNode child; child.setFlag(QSGNode::OwnedByParent, false);
root.appendChildNode(&child);
- DummyRenderer renderer(&root);
+ DummyRenderer renderer(&root, renderContext);
child.markDirty(QSGNode::DirtyGeometry);
@@ -158,8 +166,8 @@ void NodesTest::propegateWithMultipleRoots()
child2.appendChildNode(&root3);
root3.appendChildNode(&child4);
- DummyRenderer ren1(&root1);
- DummyRenderer ren2(&root3);
+ DummyRenderer ren1(&root1, renderContext);
+ DummyRenderer ren2(&root3, renderContext);
child4.markDirty(QSGNode::DirtyGeometry);
@@ -195,7 +203,7 @@ void NodesTest::opacityPropegation()
QSGSimpleRectNode *geometry = new QSGSimpleRectNode;
geometry->setRect(0, 0, 100, 100);
- DummyRenderer renderer(&root);
+ DummyRenderer renderer(&root, renderContext);
root.appendChildNode(a);
a->appendChildNode(b);
diff --git a/tests/auto/quick/qquickanimations/data/parallelAnimationNullChildBug.qml b/tests/auto/quick/qquickanimations/data/parallelAnimationNullChildBug.qml
new file mode 100644
index 0000000000..8da3e8e1af
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/parallelAnimationNullChildBug.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.2
+
+Item {
+ id: root
+ Component.onCompleted: Qt.createQmlObject("import QtQuick 2.2; ParallelAnimation{animations: [null]}", root)
+}
diff --git a/tests/auto/quick/qquickanimations/data/sequentialAnimationNullChildBug.qml b/tests/auto/quick/qquickanimations/data/sequentialAnimationNullChildBug.qml
new file mode 100644
index 0000000000..7a5c6063c4
--- /dev/null
+++ b/tests/auto/quick/qquickanimations/data/sequentialAnimationNullChildBug.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.2
+
+Item {
+ id: root
+ Component.onCompleted: Qt.createQmlObject("import QtQuick 2.2; SequentialAnimation{animations: [null]}", root)
+}
diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
index 94726aa5fe..c6f4779819 100644
--- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
+++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp
@@ -110,6 +110,7 @@ private slots:
void anchorBug();
void pathAnimationInOutBackBug();
void scriptActionBug();
+ void groupAnimationNullChildBug();
};
#define QTIMED_COMPARE(lhs, rhs) do { \
@@ -1450,6 +1451,31 @@ void tst_qquickanimations::scriptActionBug()
QCOMPARE(obj->property("actionTriggered").toBool(), true);
}
+//QTBUG-34851
+void tst_qquickanimations::groupAnimationNullChildBug()
+{
+ {
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, testFileUrl("sequentialAnimationNullChildBug.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(root);
+
+ delete root;
+ }
+
+ {
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, testFileUrl("parallelAnimationNullChildBug.qml"));
+ QQuickItem *root = qobject_cast<QQuickItem*>(c.create());
+ QVERIFY(root);
+
+ delete root;
+ }
+}
+
+
QTEST_MAIN(tst_qquickanimations)
#include "tst_qquickanimations.moc"
diff --git a/tests/auto/quick/qquickspringanimation/data/inTransition.qml b/tests/auto/quick/qquickspringanimation/data/inTransition.qml
new file mode 100644
index 0000000000..68d3125e40
--- /dev/null
+++ b/tests/auto/quick/qquickspringanimation/data/inTransition.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 250
+ height: 250
+
+ ListView {
+ anchors.fill: parent
+ model: ListModel {
+ ListElement { text: "A" }
+ ListElement { text: "B" }
+ }
+
+ populate: Transition {
+ SpringAnimation { properties: "x"; from: 0; to: 100; spring: 4; damping: 0.3 }
+ }
+
+ delegate: Text {
+ text: "Test"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp b/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
index 78d114c904..137b5c08e4 100644
--- a/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
+++ b/tests/auto/quick/qquickspringanimation/tst_qquickspringanimation.cpp
@@ -41,6 +41,7 @@
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
+#include <QtQuick/qquickview.h>
#include <private/qquickspringanimation_p.h>
#include <private/qqmlvaluetype_p.h>
#include "../../shared/util.h"
@@ -55,6 +56,7 @@ private slots:
void defaultValues();
void values();
void disabled();
+ void inTransition();
private:
QQmlEngine engine;
@@ -128,6 +130,14 @@ void tst_qquickspringanimation::disabled()
delete obj;
}
+void tst_qquickspringanimation::inTransition()
+{
+ QQuickView view(testFileUrl("inTransition.qml"));
+ view.show();
+ // this used to crash after ~1 sec, once the spring animation was done
+ QTest::qWait(2000);
+}
+
QTEST_MAIN(tst_qquickspringanimation)
#include "tst_qquickspringanimation.moc"
diff --git a/tests/auto/quick/scenegraph/data/render_StackingOrder.qml b/tests/auto/quick/scenegraph/data/render_StackingOrder.qml
new file mode 100644
index 0000000000..ab335004c2
--- /dev/null
+++ b/tests/auto/quick/scenegraph/data/render_StackingOrder.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 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:LGPL$
+** 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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+
+/*
+ This test verifies that items that go from being batched because
+ of no overlap will be split into multiple batches because of an
+ overlap and that no rendering errors occur as a result of this.
+
+ #samples: 3
+ PixelPos R G B Error-tolerance
+ #final: 10 10 1.0 0.0 0.0 0.05
+ #final: 10 110 0.0 1.0 0.0 0.05
+ #final: 10 120 0.0 0.0 1.0 0.05
+*/
+
+RenderTestBase {
+ Item {
+ opacity: 0.99; // Just to trigger alpha batches
+ Rectangle { color: "#ff0000"; x: 10; y: 10; width: 20; height: 20; }
+ Image { source: "logo-small.jpg"; x: 10; y: 50; width: 50; height: 51; }
+ Rectangle { color: "#00ff00"; x: 10; y: 100; width: 50; height: 50; }
+ Rectangle { color: "#0000ff"; x: 10; y: 120; width: 10; height: 10; }
+ }
+ onEnterFinalStage: finalStageComplete = true;
+}
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 755cec460d..3b79f01f12 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -323,6 +323,7 @@ void tst_SceneGraph::render_data()
<< "data/render_MovingOverlap.qml"
<< "data/render_BreakOpacityBatch.qml"
<< "data/render_OutOfFloatRange.qml"
+ << "data/render_StackingOrder.qml"
;
QRegExp sampleCount("#samples: *(\\d+)");
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index f3743e970d..ddcd259ae0 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -267,7 +267,6 @@ void printUsage()
printf("\t-- ........................... Arguments after this one are ignored by the launcher, but may be used within the QML application.\n");
printf("\tDebugging options:\n");
printf("\t-verbose ..................... Print information about what qml is doing, like specific file urls being loaded.\n");
- printf("\t-enable-debugger ............. Allow the QML debugger to connect to the application (also requires debugger arguments).\n");
printf("\t-translation [file] .......... Load the given file as the translations file.\n");
printf("\t-dummy-data [directory] ...... Load QML files from the given directory as context properties.\n");
printf("\t-slow-animations ............. Run all animations in slow motion.\n");
@@ -278,15 +277,9 @@ void printUsage()
//Called before application initialization, removes arguments it uses
void getAppFlags(int &argc, char **argv)
{
- for (int i=0; i<argc; i++) {
- if (!strcmp(argv[i], "-enable-debugger")) { // Normally done via a define in the include, so expects to be before application (and must be before engine)
- static QQmlDebuggingEnabler qmlEnableDebuggingHelper(true);
- for (int j=i; j<argc-1; j++)
- argv[j] = argv[j+1];
- argc --;
- }
#ifdef QT_GUI_LIB
- else if (!strcmp(argv[i], "-apptype")) { // Must be done before application, as it selects application
+ for (int i=0; i<argc; i++) {
+ if (!strcmp(argv[i], "-apptype")) { // Must be done before application, as it selects application
applicationType = QmlApplicationTypeUnknown;
if (i+1 < argc) {
if (!strcmp(argv[i+1], "core"))
@@ -311,8 +304,8 @@ void getAppFlags(int &argc, char **argv)
argv[j] = argv[j+2];
argc -= 2;
}
-#endif // QT_GUI_LIB
}
+#endif // QT_GUI_LIB
}
bool getFileSansBangLine(const QString &path, QByteArray &output)
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
index 0642696b4e..fe90916980 100644
--- a/tools/qml/qml.pro
+++ b/tools/qml/qml.pro
@@ -12,4 +12,6 @@ mac {
ICON = qml.icns
}
+DEFINES += QT_QML_DEBUG_NO_WARNING
+
load(qt_tool)
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index 755ab452ee..08b88142bb 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QSet>
@@ -68,12 +69,13 @@ QStringList g_qmlImportPaths;
void printUsage(const QString &appName)
{
std::cerr << qPrintable(QString::fromLatin1(
- "Usage: %1 -rootPath qmldir -importPath importPath \n"
- "Example: %1 -rootPath qmldir -importPath importPath").arg(
+ "Usage: %1 -rootPath path/to/app/qml/directory -importPath path/to/qt/qml/directory \n"
+ " %1 -qmlFiles file1 file2 -importPath path/to/qt/qml/directory \n"
+ "Example: %1 -rootPath . -importPath /home/user/dev/qt-install/qml \n").arg(
appName));
}
-QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, const QByteArray &code, const QString &path)
+QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, const QString &code, const QString &path)
{
QVariantList imports;
@@ -87,8 +89,13 @@ QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, con
if (!importNode->fileName.isEmpty()) {
QString name = importNode->fileName.toString();
import[QStringLiteral("name")] = name;
- import[QStringLiteral("type")] = QStringLiteral("directory");
- import[QStringLiteral("path")] = path + QLatin1Char('/') + name;
+ if (name.endsWith(QStringLiteral(".js"))) {
+ import[QStringLiteral("type")] = QStringLiteral("javascript");
+ } else {
+ import[QStringLiteral("type")] = QStringLiteral("directory");
+ }
+
+ import[QStringLiteral("path")] = QDir::cleanPath(path + QLatin1Char('/') + name);
} else {
// Walk the id chain ("Foo" -> "Bar" -> etc)
QString name;
@@ -111,51 +118,6 @@ QVariantList findImportsInAst(QQmlJS::AST::UiHeaderItemList *headerItemList, con
return imports;
}
-// Scan a single qml file for import statements
-QVariantList findQmlImportsInFile(const QString &qmlFilePath)
-{
- QFile qmlFile(qmlFilePath);
- if (!qmlFile.open(QIODevice::ReadOnly)) {
- std::cerr << "Cannot open input file " << qPrintable(QDir::toNativeSeparators(qmlFile.fileName()))
- << ':' << qPrintable(qmlFile.errorString()) << std::endl;
- return QVariantList();
- }
- QByteArray code = qmlFile.readAll();
-
- QQmlJS::Engine engine;
- QQmlJS::Lexer lexer(&engine);
- lexer.setCode(QString::fromUtf8(code), /*line = */ 1);
- QQmlJS::Parser parser(&engine);
-
- if (!parser.parse() || !parser.diagnosticMessages().isEmpty()) {
- // Extract errors from the parser
- foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
- std::cerr << qPrintable(QDir::toNativeSeparators(qmlFile.fileName())) << ':'
- << m.loc.startLine << ':' << qPrintable(m.message) << std::endl;
- }
- return QVariantList();
- }
-
- return findImportsInAst(parser.ast()->headers, code, QFileInfo(qmlFilePath).absolutePath());
-}
-
-// Scan all qml files in directory for import statements
-QVariantList findQmlImportsInDirectory(const QString &qmlDir)
-{
- QVariantList ret;
- if (qmlDir.isEmpty())
- return ret;
-
- QStringList qmlFileNames = QDir(qmlDir).entryList(QStringList(QStringLiteral("*.qml")));
- foreach (const QString &qmlFileName, qmlFileNames) {
- QString qmlFilePath = qmlDir + QLatin1Char('/') + qmlFileName;
- QVariantList imports = findQmlImportsInFile(qmlFilePath);
- ret.append(imports);
-
- }
- return ret;
-}
-
// Read the qmldir file, extract a list of plugins by
// parsing the "plugin" and "classname" lines.
QVariantMap pluginsForModulePath(const QString &modulePath) {
@@ -221,21 +183,51 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
foreach (QVariant importVariant, imports) {
QVariantMap import = qvariant_cast<QVariantMap>(importVariant);
if (import[QStringLiteral("type")] == QStringLiteral("module")) {
- import[QStringLiteral("path")] = resolveImportPath(import[QStringLiteral("name")].toString(), import[QStringLiteral("version")].toString());
- QVariantMap plugininfo = pluginsForModulePath(import[QStringLiteral("path")].toString());
- QString plugins = plugininfo[QStringLiteral("plugins")].toString();
- QString classnames = plugininfo[QStringLiteral("classnames")].toString();
- if (!plugins.isEmpty()) {
+ QString path = resolveImportPath(import.value(QStringLiteral("name")).toString(), import.value(QStringLiteral("version")).toString());
+ if (!path.isEmpty())
+ import[QStringLiteral("path")] = path;
+ QVariantMap plugininfo = pluginsForModulePath(import.value(QStringLiteral("path")).toString());
+ QString plugins = plugininfo.value(QStringLiteral("plugins")).toString();
+ QString classnames = plugininfo.value(QStringLiteral("classnames")).toString();
+ if (!plugins.isEmpty())
import[QStringLiteral("plugin")] = plugins;
+ if (!classnames.isEmpty())
import[QStringLiteral("classname")] = classnames;
- }
}
- if (!import[QStringLiteral("path")].isNull())
- done.append(import);
+ done.append(import);
}
return done;
}
+// Scan a single qml file for import statements
+QVariantList findQmlImportsInFile(const QString &qmlFilePath)
+{
+ QFile qmlFile(qmlFilePath);
+ if (!qmlFile.open(QIODevice::ReadOnly)) {
+ std::cerr << "Cannot open input file " << QDir::toNativeSeparators(qmlFile.fileName()).toStdString()
+ << ':' << qmlFile.errorString().toStdString() << std::endl;
+ return QVariantList();
+ }
+ QString code = QString::fromUtf8(qmlFile.readAll());
+
+ QQmlJS::Engine engine;
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(code, /*line = */ 1);
+ QQmlJS::Parser parser(&engine);
+
+ if (!parser.parse() || !parser.diagnosticMessages().isEmpty()) {
+ // Extract errors from the parser
+ foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
+ std::cerr << QDir::toNativeSeparators(qmlFile.fileName()).toStdString() << ':'
+ << m.loc.startLine << ':' << m.message.toStdString() << std::endl;
+ }
+ return QVariantList();
+ }
+
+ return findPathsForModuleImports(
+ findImportsInAst(parser.ast()->headers, code, QFileInfo(qmlFilePath).absolutePath()));
+}
+
// Merge two lists of imports, discard duplicates.
QVariantList mergeImports(const QVariantList &a, const QVariantList &b)
{
@@ -247,12 +239,72 @@ QVariantList mergeImports(const QVariantList &a, const QVariantList &b)
return merged;
}
-// find Qml Imports Recursively
-QVariantList findQmlImportsRecursively(const QStringList &qmlDirs)
+// Scan all qml files in directory for import statements
+QVariantList findQmlImportsInDirectory(const QString &qmlDir)
{
QVariantList ret;
+ if (qmlDir.isEmpty())
+ return ret;
+
+ QDirIterator iterator(qmlDir, QDirIterator::Subdirectories);
+ while (iterator.hasNext()) {
+ iterator.next();
+ QString path = iterator.filePath();
+ if (!path.endsWith(QStringLiteral(".qml")))
+ continue;
+
+ // skip obvious build output directories
+ if (path.contains(QStringLiteral("Debug-iphoneos")) || path.contains(QStringLiteral("Release-iphoneos")) ||
+ path.contains(QStringLiteral("Debug-iphonesimulator")) || path.contains(QStringLiteral("Release-iphonesimulator"))
+#ifdef Q_OS_WIN
+ || path.contains(QStringLiteral("/release/")) || path.contains(QStringLiteral("/debug/"))
+#endif
+ ){
+ continue;
+ }
+
+ QVariantList imports = findQmlImportsInFile(path);
+ ret = mergeImports(ret, imports);
+ }
+ return ret;
+}
+
+QSet<QString> importModulePaths(QVariantList imports) {
+ QSet<QString> ret;
+ foreach (const QVariant &importVariant, imports) {
+ QVariantMap import = qvariant_cast<QVariantMap>(importVariant);
+ QString path = import.value(QStringLiteral("path")).toString();
+ QString type = import.value(QStringLiteral("type")).toString();
+ if (type == QStringLiteral("module") && !path.isEmpty())
+ ret.insert(QDir(path).canonicalPath());
+ }
+ return ret;
+}
- QSet<QString> toVisit = qmlDirs.toSet();
+// Find Qml Imports Recursively from a root set of qml files.
+// The directories in qmlDirs are searched recursively.
+// The files in qmlFiles parsed directly.
+QVariantList findQmlImportsRecursively(const QStringList &qmlDirs, const QStringList &qmlFiles)
+{
+ QVariantList ret;
+
+ // scan all app root qml directories for imports
+ foreach (const QString &qmlDir, qmlDirs) {
+ QVariantList imports = findQmlImportsInDirectory(qmlDir);
+ ret = mergeImports(ret, imports);
+ }
+
+ // scan app qml files for imports
+ foreach (const QString &qmlFile, qmlFiles) {
+ QVariantList imports = findQmlImportsInFile(qmlFile);
+ ret = mergeImports(ret, imports);
+ }
+
+
+ // get the paths to theimports found in the app qml
+ QSet<QString> toVisit = importModulePaths(ret);
+
+ // recursivly scan for import dependencies.
QSet<QString> visited;
while (!toVisit.isEmpty()) {
QString qmlDir = *toVisit.begin();
@@ -260,20 +312,12 @@ QVariantList findQmlImportsRecursively(const QStringList &qmlDirs)
visited.insert(qmlDir);
QVariantList imports = findQmlImportsInDirectory(qmlDir);
- imports = findPathsForModuleImports(imports);
-
- // schedule recursive visit of imports
- foreach (const QVariant &importVariant, imports) {
- QVariantMap import = qvariant_cast<QVariantMap>(importVariant);
- QString path = import[QStringLiteral("path")].toString();
- if (!path.isEmpty() && !visited.contains(path)) {
- toVisit.insert(path);
- }
- }
-
ret = mergeImports(ret, imports);
- }
+ QSet<QString> candidatePaths = importModulePaths(ret);
+ candidatePaths.subtract(visited);
+ toVisit.unite(candidatePaths);
+ }
return ret;
}
@@ -288,46 +332,46 @@ int main(int argc, char *argv[])
}
QStringList qmlRootPaths;
+ QStringList qmlFiles;
QStringList qmlImportPaths;
int i = 1;
while (i < args.count()) {
const QString &arg = args.at(i);
++i;
+ QStringList *argReceiver = 0;
if (!arg.startsWith(QLatin1Char('-'))) {
qmlRootPaths += arg;
} else if (arg == QLatin1String("-rootPath")) {
if (i >= args.count())
std::cerr << "-rootPath requires an argument\n";
-
- while (i < args.count()) {
- const QString arg = args.at(i);
- if (arg.startsWith(QLatin1Char('-')))
- break;
- ++i;
- qmlRootPaths += arg;
- }
+ argReceiver = &qmlRootPaths;
+ } else if (arg == QLatin1String("-qmlFiles")) {
+ if (i >= args.count())
+ std::cerr << "-qmlFiles requires an argument\n";
+ argReceiver = &qmlFiles;
} else if (arg == QLatin1String("-importPath")) {
if (i >= args.count())
std::cerr << "-importPath requires an argument\n";
-
- while (i < args.count()) {
- const QString arg = args.at(i);
- if (arg.startsWith(QLatin1Char('-')))
- break;
- ++i;
- qmlImportPaths += arg;
- }
+ argReceiver = &qmlImportPaths;
} else {
std::cerr << "Invalid argument: \"" << qPrintable(arg) << "\"\n";
return 1;
}
+
+ while (i < args.count()) {
+ const QString arg = args.at(i);
+ if (arg.startsWith(QLatin1Char('-')))
+ break;
+ ++i;
+ *argReceiver += arg;
+ }
}
g_qmlImportPaths = qmlImportPaths;
// Find the imports!
- QVariantList imports = findQmlImportsRecursively(qmlRootPaths);
+ QVariantList imports = findQmlImportsRecursively(qmlRootPaths, qmlFiles);
// Convert to JSON
QByteArray json = QJsonDocument(QJsonArray::fromVariantList(imports)).toJson();