aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-05-24 11:08:09 +0200
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2016-05-24 11:33:42 +0200
commit9ff09fb283cd130fb717769b44f54bfbb28efd8a (patch)
tree711f70b4b494bd996d54bdab5c44f3c89b37a6d1
parent592b5b49b6c0043fae5db7721689813ebd226032 (diff)
parentec2b2a5f5d804095b6b2b8575b1cd1b75a8335ff (diff)
Merge remote-tracking branch 'origin/dev' into wip/scenegraphng
Conflicts: src/quick/items/qquickopenglshadereffectnode.cpp src/quick/items/qquickshadereffect.cpp src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h src/quick/scenegraph/qsgdefaultglyphnode_p.h Change-Id: I3d6874b4e4231a89d2836c04fe8e7f2ef2d698c4
-rw-r--r--examples/qml/qmlextensionplugins/plugin.cpp2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro11
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h2
-rw-r--r--examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp10
-rw-r--r--examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h2
-rw-r--r--examples/quick/imageprovider/imageprovider.cpp5
-rw-r--r--examples/quick/imageresponseprovider/imageresponseprovider.cpp5
-rw-r--r--src/3rdparty/masm/wtf/Compiler.h3
-rw-r--r--src/3rdparty/masm/wtf/MathExtras.h7
-rw-r--r--src/imports/folderlistmodel/plugin.cpp2
-rw-r--r--src/imports/layouts/plugin.cpp2
-rw-r--r--src/imports/localstorage/plugin.cpp2
-rw-r--r--src/imports/models/plugin.cpp2
-rw-r--r--src/imports/particles/plugin.cpp2
-rw-r--r--src/imports/qtquick2/plugin.cpp2
-rw-r--r--src/imports/settings/plugin.cpp2
-rw-r--r--src/imports/statemachine/plugin.cpp2
-rw-r--r--src/imports/testlib/main.cpp2
-rw-r--r--src/imports/window/plugin.cpp2
-rw-r--r--src/imports/xmllistmodel/plugin.cpp2
-rw-r--r--src/particles/qquickcustomparticle.cpp2
-rw-r--r--src/particles/qquickparticleemitter_p.h5
-rw-r--r--src/particles/qquickparticlesystem.cpp7
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp19
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp14
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp78
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp46
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp43
-rw-r--r--src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h2
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp310
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h20
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp180
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h6
-rw-r--r--src/qml/compiler/qv4compileddata.cpp10
-rw-r--r--src/qml/compiler/qv4compileddata_p.h47
-rw-r--r--src/qml/compiler/qv4ssa_p.h2
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp16
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h223
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc12
-rw-r--r--src/qml/doc/src/cppintegration/extending-tutorial.qdoc26
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc2
-rw-r--r--src/qml/jit/qv4targetplatform_p.h3
-rw-r--r--src/qml/jsapi/qjsengine.cpp8
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp8
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp10
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp2
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp10
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp16
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp7
-rw-r--r--src/qml/jsruntime/qv4object.cpp5
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp41
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h24
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp14
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp3
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp350
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h343
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4string.cpp120
-rw-r--r--src/qml/jsruntime/qv4string_p.h4
-rw-r--r--src/qml/parser/qqmljsparser_p.h2
-rw-r--r--src/qml/qml/ftw/qhashedstring.cpp4
-rw-r--r--src/qml/qml/qqmlbinding.cpp2
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp10
-rw-r--r--src/qml/qml/qqmlcompiler_p.h2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmlengine_p.h2
-rw-r--r--src/qml/qml/qqmlerror.cpp7
-rw-r--r--src/qml/qml/qqmlextensioninterface.h2
-rw-r--r--src/qml/qml/qqmlfile.cpp2
-rw-r--r--src/qml/qml/qqmlimport.cpp162
-rw-r--r--src/qml/qml/qqmlimport_p.h3
-rw-r--r--src/qml/qml/qqmlincubator.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp18
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp25
-rw-r--r--src/qml/qml/qqmlproperty.cpp16
-rw-r--r--src/qml/qml/qqmltypeloader.cpp37
-rw-r--r--src/qml/qml/qqmltypeloader_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp32
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h1
-rw-r--r--src/qml/qml/qqmlvme_p.h2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp414
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h71
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp82
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h14
-rw-r--r--src/qml/qml/v8/qv8engine.cpp3
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp39
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h1
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h2
-rw-r--r--src/qml/util/qqmladaptormodel.cpp4
-rw-r--r--src/qmltest/quicktest.cpp2
-rw-r--r--src/quick/designer/qqmldesignermetaobject.cpp48
-rw-r--r--src/quick/designer/qqmldesignermetaobject_p.h2
-rw-r--r--src/quick/designer/qquickdesignersupport.cpp20
-rw-r--r--src/quick/doc/snippets/qml/externaldrag.qml76
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp142
-rw-r--r--src/quick/items/qquickanchors.cpp522
-rw-r--r--src/quick/items/qquickanchors_p.h9
-rw-r--r--src/quick/items/qquickanchors_p_p.h137
-rw-r--r--src/quick/items/qquickanimatedimage.cpp24
-rw-r--r--src/quick/items/qquickanimatedimage_p_p.h2
-rw-r--r--src/quick/items/qquickdrag.cpp59
-rw-r--r--src/quick/items/qquickdrag_p.h6
-rw-r--r--src/quick/items/qquickflickable.cpp8
-rw-r--r--src/quick/items/qquickflickable_p.h3
-rw-r--r--src/quick/items/qquickimage.cpp4
-rw-r--r--src/quick/items/qquickimagebase.cpp2
-rw-r--r--src/quick/items/qquickitem.cpp49
-rw-r--r--src/quick/items/qquickitem_p.h5
-rw-r--r--src/quick/items/qquickitemgrabresult.cpp1
-rw-r--r--src/quick/items/qquickitemsmodule.cpp1
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp1
-rw-r--r--src/quick/items/qquickopenglshadereffectnode.cpp4
-rw-r--r--src/quick/items/qquickopenglshadereffectnode_p.h1
-rw-r--r--src/quick/items/qquickpainteditem.cpp7
-rw-r--r--src/quick/items/qquickpainteditem.h1
-rw-r--r--src/quick/items/qquickpathview.cpp57
-rw-r--r--src/quick/items/qquickpathview_p.h7
-rw-r--r--src/quick/items/qquickpathview_p_p.h4
-rw-r--r--src/quick/items/qquickrectangle.cpp1
-rw-r--r--src/quick/items/qquickscalegrid.cpp45
-rw-r--r--src/quick/items/qquickscalegrid_p_p.h2
-rw-r--r--src/quick/items/qquicktext_p.h10
-rw-r--r--src/quick/items/qquicktextcontrol.cpp27
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h2
-rw-r--r--src/quick/items/qquicktextedit.cpp3
-rw-r--r--src/quick/items/qquicktextinput.cpp73
-rw-r--r--src/quick/items/qquicktextinput_p.h8
-rw-r--r--src/quick/items/qquicktextinput_p_p.h12
-rw-r--r--src/quick/items/qquickwindow.cpp39
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp18
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h6
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp11
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture_p.h2
-rw-r--r--src/quick/scenegraph/util/qsgshadersourcebuilder.cpp6
-rw-r--r--src/quick/util/qquickanimation.cpp2
-rw-r--r--src/quick/util/qquickglobal.cpp22
-rw-r--r--src/quick/util/qquickpath_p.h2
-rw-r--r--src/quick/util/qquickpixmapcache.cpp12
-rw-r--r--src/quick/util/qquicksmoothedanimation.cpp3
-rw-r--r--src/quick/util/qquickstategroup.cpp21
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml10
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml8
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml8
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml10
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp4
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp15
-rw-r--r--tests/auto/qml/qml.pro3
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qtbug_52340.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/sequenceSort.qml26
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp12
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp26
-rw-r--r--tests/auto/qml/qqmlextensionplugin/qqmlextensionplugin.pro5
-rw-r--r--tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp119
-rw-r--r--tests/auto/qml/qqmlimport/tst_qqmlimport.cpp39
-rw-r--r--tests/auto/qml/qqmllanguage/BLACKLIST2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/child.qml3
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/child2.qml3
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/child21.qml3
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp71
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.pro12
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/qmldir1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp71
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.pro13
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/qmldir1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp70
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.pro12
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/qmldir1
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro5
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp54
-rw-r--r--tests/auto/qml/qqmlqt/data/qtObjectContents.qml10
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp46
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/plugin.h2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/trim_cache.qml8
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp30
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp21
-rw-r--r--tests/auto/quick/qquickanchors/tst_qquickanchors.cpp33
-rw-r--r--tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp29
-rw-r--r--tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml22
-rw-r--r--tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro1
-rw-r--r--tests/auto/quick/qquickdrag/tst_qquickdrag.cpp46
-rw-r--r--tests/auto/quick/qquickpathview/data/movementDirection.qml43
-rw-r--r--tests/auto/quick/qquickpathview/tst_qquickpathview.cpp68
-rw-r--r--tests/auto/quick/qquickstates/tst_qquickstates.cpp4
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp8
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp2
-rw-r--r--tests/auto/quick/quick.pro1
-rw-r--r--tests/benchmarks/qml/creation/tst_creation.cpp35
-rw-r--r--tests/manual/highdpi/imageprovider.cpp5
-rw-r--r--tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h2
-rw-r--r--tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h2
-rw-r--r--tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h2
-rw-r--r--tests/manual/qmltypememory/TestPlugin/plugin.cpp2
-rw-r--r--tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps2.qml22
-rw-r--r--tools/qmlimportscanner/main.cpp46
-rw-r--r--tools/qmlplugindump/Info.plist6
-rw-r--r--tools/qmlplugindump/main.cpp2
221 files changed, 3761 insertions, 2032 deletions
diff --git a/examples/qml/qmlextensionplugins/plugin.cpp b/examples/qml/qmlextensionplugins/plugin.cpp
index 56057b7f06..e04cfa57d8 100644
--- a/examples/qml/qmlextensionplugins/plugin.cpp
+++ b/examples/qml/qmlextensionplugins/plugin.cpp
@@ -141,7 +141,7 @@ MinuteTimer *TimeModel::timer=0;
class QExampleQmlPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro
index c55db00d27..4d0e807417 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/app.pro
@@ -1,10 +1,15 @@
TARGET = chapter6-plugins
QT += qml quick
-# Avoid going to debug/release subdirectory
-# so that our application will see the
-# import path for the Charts module.
+# Ensure that the application will see the import path for the Charts module:
+# * On Windows, do not build into a debug/release subdirectory.
+# * On OS X, add the plugin files into the bundle.
win32: DESTDIR = ./
+osx {
+ charts.files = $$OUT_PWD/Charts
+ charts.path = Contents/PlugIns
+ QMAKE_BUNDLE_DATA += charts
+}
SOURCES += main.cpp
RESOURCES += app.qrc
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h
index 3c0f84fe34..2a9c2446bd 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/import/chartsplugin.h
@@ -46,7 +46,7 @@
class ChartsPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri);
diff --git a/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp b/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp
index b20ae35f92..d165513861 100644
--- a/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp
+++ b/examples/qml/tutorials/extending-qml/chapter6-plugins/main.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -37,17 +37,21 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-//![0]
#include <QtQuick/QQuickView>
#include <QGuiApplication>
+#include <QQmlEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
+//![0]
QQuickView view;
+#ifdef Q_OS_OSX
+ view.engine()->addImportPath(app.applicationDirPath() + "/../PlugIns");
+#endif
+//![0]
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:///app.qml"));
view.show();
return app.exec();
}
-//![0]
diff --git a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h
index 3a2ddae871..d3a1f4ba91 100644
--- a/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h
+++ b/examples/quick/customitems/painteditem/TextBalloonPlugin/plugin.h
@@ -55,7 +55,7 @@
class TextBalloonPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
{
diff --git a/examples/quick/imageprovider/imageprovider.cpp b/examples/quick/imageprovider/imageprovider.cpp
index f402ce0ce8..1e4f53e736 100644
--- a/examples/quick/imageprovider/imageprovider.cpp
+++ b/examples/quick/imageprovider/imageprovider.cpp
@@ -87,7 +87,7 @@ public:
class ImageProviderExtensionPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
{
@@ -103,7 +103,4 @@ public:
};
-#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
-
-
#include "imageprovider.moc"
diff --git a/examples/quick/imageresponseprovider/imageresponseprovider.cpp b/examples/quick/imageresponseprovider/imageresponseprovider.cpp
index bdec29114b..a888c823a6 100644
--- a/examples/quick/imageresponseprovider/imageresponseprovider.cpp
+++ b/examples/quick/imageresponseprovider/imageresponseprovider.cpp
@@ -102,7 +102,7 @@ private:
class ImageProviderExtensionPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
{
@@ -117,7 +117,4 @@ public:
};
-
-#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
-
#include "imageresponseprovider.moc"
diff --git a/src/3rdparty/masm/wtf/Compiler.h b/src/3rdparty/masm/wtf/Compiler.h
index b886f37151..fc3b5c5c08 100644
--- a/src/3rdparty/masm/wtf/Compiler.h
+++ b/src/3rdparty/masm/wtf/Compiler.h
@@ -74,12 +74,15 @@
/* COMPILER(MSVC) - Microsoft Visual C++ */
/* COMPILER(MSVC7_OR_LOWER) - Microsoft Visual C++ 2003 or lower*/
/* COMPILER(MSVC9_OR_LOWER) - Microsoft Visual C++ 2008 or lower*/
+/* COMPILER(MSVC12_OR_LOWER) - Microsoft Visual C++ 2013 or lower*/
#if defined(_MSC_VER)
#define WTF_COMPILER_MSVC 1
#if _MSC_VER < 1400
#define WTF_COMPILER_MSVC7_OR_LOWER 1
#elif _MSC_VER < 1600
#define WTF_COMPILER_MSVC9_OR_LOWER 1
+#elif _MSC_VER < 1800
+#define WTF_COMPILER_MSVC12_OR_LOWER 1
#endif
/* Specific compiler features */
diff --git a/src/3rdparty/masm/wtf/MathExtras.h b/src/3rdparty/masm/wtf/MathExtras.h
index 9a85291ae2..9ded0ab736 100644
--- a/src/3rdparty/masm/wtf/MathExtras.h
+++ b/src/3rdparty/masm/wtf/MathExtras.h
@@ -173,11 +173,15 @@ inline float log2f(float num)
inline long long abs(long long num) { return _abs64(num); }
#endif
+#if COMPILER(MSVC12_OR_LOWER)
+
inline double nextafter(double x, double y) { return _nextafter(x, y); }
inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; }
inline double copysign(double x, double y) { return _copysign(x, y); }
+#endif // COMPILER(MSVC12_OR_LOWER)
+
// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
inline double wtf_atan2(double x, double y)
{
@@ -211,6 +215,8 @@ inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); }
#define fmod(x, y) wtf_fmod(x, y)
#define pow(x, y) wtf_pow(x, y)
+#if COMPILER(MSVC12_OR_LOWER)
+
// MSVC's math functions do not bring lrint.
inline long int lrint(double flt)
{
@@ -233,6 +239,7 @@ inline long int lrint(double flt)
return static_cast<long int>(intgr);
}
+#endif // COMPILER(MSVC12_OR_LOWER)
#endif // COMPILER(MSVC)
inline double deg2rad(double d) { return d * piDouble / 180.0; }
diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp
index 38de232dc0..affde1c3aa 100644
--- a/src/imports/folderlistmodel/plugin.cpp
+++ b/src/imports/folderlistmodel/plugin.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
class QmlFolderListModelPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QmlFolderListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
diff --git a/src/imports/layouts/plugin.cpp b/src/imports/layouts/plugin.cpp
index 64d687cf3b..da5f264ab5 100644
--- a/src/imports/layouts/plugin.cpp
+++ b/src/imports/layouts/plugin.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
class QtQuickLayoutsPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QtQuickLayoutsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent)
{
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 8780dcc757..3fd36f3f0d 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -754,7 +754,7 @@ static QObject *module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine)
class QQmlLocalStoragePlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QQmlLocalStoragePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent)
diff --git a/src/imports/models/plugin.cpp b/src/imports/models/plugin.cpp
index 046d69cbc5..dbb62cd25d 100644
--- a/src/imports/models/plugin.cpp
+++ b/src/imports/models/plugin.cpp
@@ -75,7 +75,7 @@ QT_BEGIN_NAMESPACE
class QtQmlModelsPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QtQmlModelsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
void registerTypes(const char *uri) Q_DECL_OVERRIDE
diff --git a/src/imports/particles/plugin.cpp b/src/imports/particles/plugin.cpp
index 22eea16d4c..28ce0f7796 100644
--- a/src/imports/particles/plugin.cpp
+++ b/src/imports/particles/plugin.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QtQuick2ParticlesPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
void registerTypes(const char *uri) Q_DECL_OVERRIDE
diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp
index 1e3ff255f8..e56027c1bb 100644
--- a/src/imports/qtquick2/plugin.cpp
+++ b/src/imports/qtquick2/plugin.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
class QtQuick2Plugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QtQuick2Plugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
void registerTypes(const char *uri) Q_DECL_OVERRIDE
diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp
index ce498774d2..c422296446 100644
--- a/src/imports/settings/plugin.cpp
+++ b/src/imports/settings/plugin.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
class QmlSettingsPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QmlSettingsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp
index c061607f40..ae32f6446a 100644
--- a/src/imports/statemachine/plugin.cpp
+++ b/src/imports/statemachine/plugin.cpp
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
class QtQmlStateMachinePlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtQml.StateMachine/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QtQmlStateMachinePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp
index 1632d7ba64..4e2bd919e9 100644
--- a/src/imports/testlib/main.cpp
+++ b/src/imports/testlib/main.cpp
@@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
class QTestQmlModule : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QTestQmlModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp
index b85ccc6dc7..200f6f7b08 100644
--- a/src/imports/window/plugin.cpp
+++ b/src/imports/window/plugin.cpp
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
class QtQuick2WindowPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QtQuick2WindowPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
void registerTypes(const char *uri) Q_DECL_OVERRIDE
diff --git a/src/imports/xmllistmodel/plugin.cpp b/src/imports/xmllistmodel/plugin.cpp
index ca676c36b0..af7625c96a 100644
--- a/src/imports/xmllistmodel/plugin.cpp
+++ b/src/imports/xmllistmodel/plugin.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
class QmlXmlListModelPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
QmlXmlListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp
index 38c0b855e8..a89b0d6a3b 100644
--- a/src/particles/qquickcustomparticle.cpp
+++ b/src/particles/qquickcustomparticle.cpp
@@ -291,8 +291,6 @@ QQuickOpenGLShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickOpenG
builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.vert"));
s.sourceCode[Key::VertexShader] = builder.source() + s.sourceCode[Key::VertexShader];
- s.className = metaObject()->className();
-
material->setProgramSource(s);
material->attributes = m_common.attributes;
foreach (QQuickOpenGLShaderEffectNode* node, m_nodes)
diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h
index 9b114ad46b..dd55fdc7a6 100644
--- a/src/particles/qquickparticleemitter_p.h
+++ b/src/particles/qquickparticleemitter_p.h
@@ -322,6 +322,8 @@ public:
return m_startTime;
}
+ void reclaculateGroupId() const;
+
protected:
qreal m_particlesPerSecond;
int m_particleDuration;
@@ -359,9 +361,6 @@ protected:
bool isEmitConnected();
-private: // methods
- void reclaculateGroupId() const;
-
private: // data
QString m_group;
mutable bool m_groupIdNeedRecalculation;
diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp
index 17d9e49d63..b60180b2ed 100644
--- a/src/particles/qquickparticlesystem.cpp
+++ b/src/particles/qquickparticlesystem.cpp
@@ -597,6 +597,13 @@ void QQuickParticleSystem::initGroups()
groupIds.clear();
nextFreeGroupId = 0;
+ for (auto e : qAsConst(m_emitters)) {
+ e->reclaculateGroupId();
+ }
+ foreach (QQuickParticlePainter *p, m_painters) {
+ p->recalculateGroupIds();
+ }
+
QQuickParticleGroupData *pd = new QQuickParticleGroupData(QString(), this); // Default group
Q_ASSERT(pd->index == 0);
Q_UNUSED(pd);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index a9996da7f4..e08436b7a3 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -683,11 +683,13 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
QQmlContext *context = qmlContext(object);
if (object && context) {
- QString parentProperty = propertyName;
- if (propertyName.indexOf(QLatin1Char('.')) != -1)
- parentProperty = propertyName.left(propertyName.indexOf(QLatin1Char('.')));
+ QStringRef parentPropertyRef(&propertyName);
+ const int idx = parentPropertyRef.indexOf(QLatin1Char('.'));
+ if (idx != -1)
+ parentPropertyRef = parentPropertyRef.left(idx);
- if (object->property(parentProperty.toLatin1()).isValid()) {
+ const QByteArray parentProperty = parentPropertyRef.toLatin1();
+ if (object->property(parentProperty).isValid()) {
QQmlProperty property(object, propertyName);
QQmlPropertyPrivate::removeBinding(property);
if (property.isResettable()) {
@@ -700,7 +702,7 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope
// overwrite with default value
if (QQmlType *objType = QQmlMetaType::qmlType(object->metaObject())) {
if (QObject *emptyObject = objType->create()) {
- if (emptyObject->property(parentProperty.toLatin1()).isValid()) {
+ if (emptyObject->property(parentProperty).isValid()) {
QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read();
if (defaultValue.isValid()) {
setBinding(objectId, propertyName, defaultValue, true);
@@ -764,9 +766,14 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
- int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle());
QV4::Scope scope(v4);
+
+ int lineNumber = 0;
+ QV4::ScopedFunctionObject oldMethod(scope, vmeMetaObject->vmeMethod(prop->coreIndex));
+ if (oldMethod && oldMethod->d()->function) {
+ lineNumber = oldMethod->d()->function->compiledFunction->location.line;
+ }
QV4::ScopedValue v(scope, QQmlJavaScriptExpression::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
vmeMetaObject->setVmeMethod(prop->coreIndex, v);
return true;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
index 075f56226d..99f5b760ba 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp
@@ -704,7 +704,7 @@ bool NativeDebugger::reallyHitTheBreakPoint(const QV4::Function *function, int l
const BreakPoint &bp = m_service->m_breakHandler->m_breakPoints.at(i);
if (bp.lineNumber == lineNumber) {
const QString fileName = function->sourceFile();
- const QString base = fileName.mid(fileName.lastIndexOf('/') + 1);
+ const QStringRef base = fileName.midRef(fileName.lastIndexOf('/') + 1);
if (bp.fileName.endsWith(base)) {
if (bp.condition.isEmpty() || checkCondition(bp.condition)) {
BreakPoint &mbp = m_service->m_breakHandler->m_breakPoints[i];
diff --git a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
index cc0118f0c2..3145601612 100644
--- a/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
+++ b/src/plugins/qmltooling/qmldbg_native/qqmlnativedebugconnector.cpp
@@ -49,6 +49,7 @@
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qpointer.h>
+#include <QtCore/qvector.h>
//#define TRACE_PROTOCOL(s) qDebug() << s
#define TRACE_PROTOCOL(s)
@@ -182,24 +183,21 @@ QQmlNativeDebugConnector::QQmlNativeDebugConnector()
: m_blockingMode(false)
{
const QString args = commandLineArguments();
- const QStringList lstjsDebugArguments = args.split(QLatin1Char(','));
+ const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','));
QStringList services;
- QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend();
- QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin();
- for (; argsIt != argsItEnd; ++argsIt) {
- const QString strArgument = *argsIt;
+ for (const QStringRef &strArgument : lstjsDebugArguments) {
if (strArgument == QLatin1String("block")) {
m_blockingMode = true;
} else if (strArgument == QLatin1String("native")) {
// Ignore. This is used to signal that this connector
// should be loaded and that has already happened.
} else if (strArgument.startsWith(QLatin1String("services:"))) {
- services.append(strArgument.mid(9));
+ services.append(strArgument.mid(9).toString());
} else if (!services.isEmpty()) {
- services.append(strArgument);
+ services.append(strArgument.toString());
} else {
qWarning("QML Debugger: Invalid argument \"%s\" detected. Ignoring the same.",
- qUtf8Printable(strArgument));
+ strArgument.toUtf8().constData());
}
}
setServices(services);
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index 688ced26ec..a193ddea0b 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -58,71 +58,81 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QVector<QQmlProfilerData>)),
- this, SLOT(receiveData(QVector<QQmlProfilerData>)));
+ connect(engine->profiler,
+ SIGNAL(dataReady(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)),
+ this,
+ SLOT(receiveData(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)));
}
// convert to QByteArrays that can be sent to the debug client
// use of QDataStream can skew results
// (see tst_qqmldebugtrace::trace() benchmark)
-static void qQmlProfilerDataToByteArrays(const QQmlProfilerData *d, QList<QByteArray> &messages)
+static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
+ const QQmlProfiler::LocationHash &locations,
+ QList<QByteArray> &messages)
{
QQmlDebugPacket ds;
- Q_ASSERT_X(((d->messageType | d->detailType) & (1 << 31)) == 0, Q_FUNC_INFO,
- "You can use at most 31 message types and 31 detail types.");
- for (uint decodedMessageType = 0; (d->messageType >> decodedMessageType) != 0;
+ Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO,
+ "You can use at most 31 message types.");
+ for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0;
++decodedMessageType) {
- if ((d->messageType & (1 << decodedMessageType)) == 0)
+ if ((d.messageType & (1 << decodedMessageType)) == 0)
continue;
- for (uint decodedDetailType = 0; (d->detailType >> decodedDetailType) != 0;
- ++decodedDetailType) {
- if ((d->detailType & (1 << decodedDetailType)) == 0)
- continue;
+ //### using QDataStream is relatively expensive
+ ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
- //### using QDataStream is relatively expensive
- ds << d->time << decodedMessageType << decodedDetailType;
+ QQmlProfiler::Location l = locations.value(d.locationId);
- switch (decodedMessageType) {
- case QQmlProfilerDefinitions::RangeStart:
- case QQmlProfilerDefinitions::RangeEnd:
- break;
- case QQmlProfilerDefinitions::RangeData:
- ds << (d->detailString.isEmpty() ? d->detailUrl.toString() : d->detailString);
- break;
- case QQmlProfilerDefinitions::RangeLocation:
- ds << (d->detailUrl.isEmpty() ? d->detailString : d->detailUrl.toString()) << d->x
- << d->y;
- break;
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
- break;
- }
- messages.append(ds.squeezedData());
- ds.clear();
+ switch (decodedMessageType) {
+ case QQmlProfilerDefinitions::RangeStart:
+ case QQmlProfilerDefinitions::RangeEnd:
+ break;
+ case QQmlProfilerDefinitions::RangeData:
+ ds << (l.location.sourceFile.isEmpty() ? l.url.toString() : l.location.sourceFile);
+ break;
+ case QQmlProfilerDefinitions::RangeLocation:
+ ds << (l.url.isEmpty() ? l.location.sourceFile : l.url.toString())
+ << static_cast<qint32>(l.location.line) << static_cast<qint32>(l.location.column);
+ break;
+ default:
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
+ break;
}
+ messages.append(ds.squeezedData());
+ ds.clear();
}
}
qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
while (next != data.length()) {
- if (data[next].time > until || messages.length() > s_numMessagesPerBatch)
- return data[next].time;
- qQmlProfilerDataToByteArrays(&(data[next++]), messages);
+ const QQmlProfilerData &nextData = data.at(next);
+ if (nextData.time > until || messages.length() > s_numMessagesPerBatch)
+ return nextData.time;
+ qQmlProfilerDataToByteArrays(nextData, locations, messages);
+ ++next;
}
next = 0;
data.clear();
+ locations.clear();
return -1;
}
-void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data)
+void QQmlProfilerAdapter::receiveData(const QVector<QQmlProfilerData> &new_data,
+ const QQmlProfiler::LocationHash &new_locations)
{
if (data.isEmpty())
data = new_data;
else
data.append(new_data);
+
+ if (locations.isEmpty())
+ locations = new_locations;
+ else
+ locations.unite(new_locations);
+
service->dataReady(this);
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index 2d93efba1b..7e13b6c479 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -63,10 +63,12 @@ public:
qint64 sendMessages(qint64 until, QList<QByteArray> &messages) Q_DECL_OVERRIDE;
public slots:
- void receiveData(const QVector<QQmlProfilerData> &new_data);
+ void receiveData(const QVector<QQmlProfilerData> &new_data,
+ const QQmlProfiler::LocationHash &locations);
private:
QVector<QQmlProfilerData> data;
+ QQmlProfiler::LocationHash locations;
int next;
};
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index b50eef5545..68a71a5524 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -61,29 +61,35 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
- connect(engine->profiler, SIGNAL(dataReady(QVector<QV4::Profiling::FunctionCallProperties>,
+ connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
+ QVector<QV4::Profiling::FunctionCallProperties>,
QVector<QV4::Profiling::MemoryAllocationProperties>)),
- this, SLOT(receiveData(QVector<QV4::Profiling::FunctionCallProperties>,
+ this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash,
+ QVector<QV4::Profiling::FunctionCallProperties>,
QVector<QV4::Profiling::MemoryAllocationProperties>)));
}
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages,
QQmlDebugPacket &d)
{
- while (m_memoryData.length() > m_memoryPos && m_memoryData[m_memoryPos].timestamp <= until) {
- QV4::Profiling::MemoryAllocationProperties &props = m_memoryData[m_memoryPos];
+ // Make it const, so that we cannot accidentally detach it.
+ const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData = m_memoryData;
+
+ while (memoryData.length() > m_memoryPos && memoryData[m_memoryPos].timestamp <= until) {
+ const QV4::Profiling::MemoryAllocationProperties &props = memoryData[m_memoryPos];
d << props.timestamp << MemoryAllocation << props.type << props.size;
++m_memoryPos;
messages.append(d.squeezedData());
d.clear();
}
- return m_memoryData.length() == m_memoryPos ? -1 : m_memoryData[m_memoryPos].timestamp;
+ return memoryData.length() == m_memoryPos ? -1 : memoryData[m_memoryPos].timestamp;
}
qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
qint64 callNext, QQmlDebugPacket &d)
{
if (callNext == -1) {
+ m_functionLocations.clear();
m_functionCallData.clear();
m_functionCallPos = 0;
}
@@ -102,10 +108,15 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
{
QQmlDebugPacket d;
+
+ // Make it const, so that we cannot accidentally detach it.
+ const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData;
+ const QV4::Profiling::FunctionLocationHash &functionLocations = m_functionLocations;
+
while (true) {
while (!m_stack.isEmpty() &&
- (m_functionCallPos == m_functionCallData.length() ||
- m_stack.top() <= m_functionCallData[m_functionCallPos].start)) {
+ (m_functionCallPos == functionCallData.length() ||
+ m_stack.top() <= functionCallData[m_functionCallPos].start)) {
if (m_stack.top() > until || messages.length() > s_numMessagesPerBatch)
return finalizeMessages(until, messages, m_stack.top(), d);
@@ -114,39 +125,46 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
messages.append(d.squeezedData());
d.clear();
}
- while (m_functionCallPos != m_functionCallData.length() &&
- (m_stack.empty() || m_functionCallData[m_functionCallPos].start < m_stack.top())) {
+ while (m_functionCallPos != functionCallData.length() &&
+ (m_stack.empty() || functionCallData[m_functionCallPos].start < m_stack.top())) {
const QV4::Profiling::FunctionCallProperties &props =
- m_functionCallData[m_functionCallPos];
+ functionCallData[m_functionCallPos];
if (props.start > until || messages.length() > s_numMessagesPerBatch)
return finalizeMessages(until, messages, props.start, d);
appendMemoryEvents(props.start, messages, d);
+ auto location = functionLocations.constFind(props.id);
+ Q_ASSERT(location != functionLocations.constEnd());
d << props.start << RangeStart << Javascript;
messages.push_back(d.squeezedData());
d.clear();
- d << props.start << RangeLocation << Javascript << props.file << props.line
- << props.column;
+ d << props.start << RangeLocation << Javascript << location->file << location->line
+ << location->column;
messages.push_back(d.squeezedData());
d.clear();
- d << props.start << RangeData << Javascript << props.name;
+ d << props.start << RangeData << Javascript << location->name;
messages.push_back(d.squeezedData());
d.clear();
m_stack.push(props.end);
++m_functionCallPos;
}
- if (m_stack.empty() && m_functionCallPos == m_functionCallData.length())
+ if (m_stack.empty() && m_functionCallPos == functionCallData.length())
return finalizeMessages(until, messages, -1, d);
}
}
void QV4ProfilerAdapter::receiveData(
+ const QV4::Profiling::FunctionLocationHash &locations,
const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData,
const QVector<QV4::Profiling::MemoryAllocationProperties> &memoryData)
{
// In rare cases it could be that another flush or stop event is processed while data from
// the previous one is still pending. In that case we just append the data.
+ if (m_functionLocations.isEmpty())
+ m_functionLocations = locations;
+ else
+ m_functionLocations.unite(locations);
if (m_functionCallData.isEmpty())
m_functionCallData = functionCallData;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index f2985af98b..968825c346 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -74,7 +74,8 @@ signals:
void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
public slots:
- void receiveData(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ void receiveData(const QV4::Profiling::FunctionLocationHash &,
+ const QVector<QV4::Profiling::FunctionCallProperties> &,
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private slots:
@@ -82,6 +83,7 @@ private slots:
void forwardEnabledWhileWaiting(quint64 features);
private:
+ QV4::Profiling::FunctionLocationHash m_functionLocations;
QVector<QV4::Profiling::FunctionCallProperties> m_functionCallData;
QVector<QV4::Profiling::MemoryAllocationProperties> m_memoryData;
int m_functionCallPos;
diff --git a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
index bc259afaa4..a6d93e85ae 100644
--- a/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
+++ b/src/plugins/qmltooling/qmldbg_server/qqmldebugserver.cpp
@@ -53,6 +53,7 @@
#include <QtCore/QDir>
#include <QtCore/QPluginLoader>
#include <QtCore/QStringList>
+#include <QtCore/QVector>
#include <QtCore/qwaitcondition.h>
QT_BEGIN_NAMESPACE
@@ -345,40 +346,40 @@ void QQmlDebugServerImpl::parseArguments()
QString fileName;
QStringList services;
- const QStringList lstjsDebugArguments = args.split(QLatin1Char(','));
- QStringList::const_iterator argsItEnd = lstjsDebugArguments.cend();
- QStringList::const_iterator argsIt = lstjsDebugArguments.cbegin();
- for (; argsIt != argsItEnd; ++argsIt) {
- const QString strArgument = *argsIt;
+ const auto lstjsDebugArguments = args.splitRef(QLatin1Char(','));
+ for (auto argsIt = lstjsDebugArguments.begin(), argsItEnd = lstjsDebugArguments.end(); argsIt != argsItEnd; ++argsIt) {
+ const QStringRef &strArgument = *argsIt;
if (strArgument.startsWith(QLatin1String("port:"))) {
- portFrom = strArgument.midRef(5).toInt(&ok);
+ portFrom = strArgument.mid(5).toInt(&ok);
portTo = portFrom;
- QStringList::const_iterator argsNext = argsIt + 1;
+ const auto argsNext = argsIt + 1;
if (argsNext == argsItEnd)
break;
- const QString nextArgument = *argsNext;
-
- // Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly
- // shared copy of the passed string. That copy isn't properly detached when the library
- // is unloaded if the original string lives in the library's .rodata
- if (ok && nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) {
- portTo = nextArgument.toInt(&ok);
- ++argsIt;
+ if (ok) {
+ const QString nextArgument = argsNext->toString();
+
+ // Don't use QStringLiteral here. QRegExp has a global cache and will save an implicitly
+ // shared copy of the passed string. That copy isn't properly detached when the library
+ // is unloaded if the original string lives in the library's .rodata
+ if (nextArgument.contains(QRegExp(QLatin1String("^\\s*\\d+\\s*$")))) {
+ portTo = nextArgument.toInt(&ok);
+ ++argsIt;
+ }
}
} else if (strArgument.startsWith(QLatin1String("host:"))) {
- hostAddress = strArgument.mid(5);
+ hostAddress = strArgument.mid(5).toString();
} else if (strArgument == QLatin1String("block")) {
block = true;
} else if (strArgument.startsWith(QLatin1String("file:"))) {
- fileName = strArgument.mid(5);
+ fileName = strArgument.mid(5).toString();
ok = !fileName.isEmpty();
} else if (strArgument.startsWith(QLatin1String("services:"))) {
- services.append(strArgument.mid(9));
+ services.append(strArgument.mid(9).toString());
} else if (!services.isEmpty()) {
- services.append(strArgument);
+ services.append(strArgument.toString());
} else {
const QString message = tr("QML Debugger: Invalid argument \"%1\" detected."
- " Ignoring the same.").arg(strArgument);
+ " Ignoring the same.").arg(strArgument.toString());
qWarning("%s", qPrintable(message));
}
}
@@ -423,7 +424,7 @@ void QQmlDebugServerImpl::parseArguments()
//: Please preserve the line breaks and formatting
<< tr("Sends qDebug() and similar messages over the QML debug\n"
"\t\t connection. QtCreator uses this for showing debug\n"
- "\t\t messages in the JavaScript console.") << '\n'
+ "\t\t messages in the debugger console.") << '\n'
<< tr("Other services offered by qmltooling plugins that implement "
"QQmlDebugServiceFactory and which can be found in the standard plugin "
"paths will also be available and can be specified. If no \"services\" "
diff --git a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
index 668ce2558d..85ff9b182f 100644
--- a/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
+++ b/src/plugins/qmltooling/shared/qqmlconfigurabledebugservice.h
@@ -72,7 +72,7 @@ protected:
{
QMutexLocker lock(&m_configMutex);
m_waitingForConfiguration = false;
- foreach (QJSEngine *engine, m_waitingEngines)
+ for (QJSEngine *engine : qAsConst(m_waitingEngines))
emit Base::attachedToEngine(engine);
m_waitingEngines.clear();
}
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index d4757bed39..a1713dd809 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -80,8 +80,10 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQm
location.column = loc.startColumn;
idIndex = id;
- indexOfDefaultProperty = -1;
+ indexOfDefaultPropertyOrAlias = -1;
+ defaultPropertyIsAlias = false;
properties = pool->New<PoolList<Property> >();
+ aliases = pool->New<PoolList<Alias> >();
qmlSignals = pool->New<PoolList<Signal> >();
bindings = pool->New<PoolList<Binding> >();
functions = pool->New<PoolList<Function> >();
@@ -145,15 +147,42 @@ QString Object::appendProperty(Property *prop, const QString &propertyName, bool
const int index = target->properties->append(prop);
if (isDefaultProperty) {
- if (target->indexOfDefaultProperty != -1) {
+ if (target->indexOfDefaultPropertyOrAlias != -1) {
*errorLocation = defaultToken;
return tr("Duplicate default property");
}
- target->indexOfDefaultProperty = index;
+ target->indexOfDefaultPropertyOrAlias = index;
}
return QString(); // no error
}
+QString Object::appendAlias(Alias *alias, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation)
+{
+ Object *target = declarationsOverride;
+ if (!target)
+ target = this;
+
+ for (Alias *p = target->aliases->first; p; p = p->next)
+ if (p->nameIndex == alias->nameIndex)
+ return tr("Duplicate alias name");
+
+ if (aliasName.constData()->isUpper())
+ return tr("Alias names cannot begin with an upper case letter");
+
+ const int index = target->aliases->append(alias);
+
+ if (isDefaultProperty) {
+ if (target->indexOfDefaultPropertyOrAlias != -1) {
+ *errorLocation = defaultToken;
+ return tr("Duplicate default property");
+ }
+ target->indexOfDefaultPropertyOrAlias = index;
+ target->defaultPropertyIsAlias = true;
+ }
+
+ return QString(); // no error
+}
+
void Object::appendFunction(QmlIR::Function *f)
{
Object *target = declarationsOverride;
@@ -190,7 +219,7 @@ Binding *Object::findBinding(quint32 nameIndex) const
void Object::insertSorted(Binding *b)
{
- Binding *insertionPoint = bindings->findSortedInsertionPoint<QV4::CompiledData::Location, QV4::CompiledData::Binding, &QV4::CompiledData::Binding::valueLocation>(b);
+ Binding *insertionPoint = bindings->findSortedInsertionPoint<quint32, Binding, &Binding::offset>(b);
bindings->insertAfter(insertionPoint, b);
}
@@ -249,8 +278,8 @@ void Document::collectTypeReferences()
void Document::removeScriptPragmas(QString &script)
{
- const QString pragma(QLatin1String("pragma"));
- const QString library(QLatin1String("library"));
+ const QLatin1String pragma("pragma");
+ const QLatin1String library("library");
QQmlJS::Lexer l(0);
l.setCode(script, 0);
@@ -268,7 +297,7 @@ void Document::removeScriptPragmas(QString &script)
if (token != QQmlJSGrammar::T_PRAGMA ||
l.tokenStartLine() != startLine ||
- script.mid(l.tokenOffset(), l.tokenLength()) != pragma)
+ script.midRef(l.tokenOffset(), l.tokenLength()) != pragma)
return;
token = l.lex();
@@ -277,7 +306,7 @@ void Document::removeScriptPragmas(QString &script)
l.tokenStartLine() != startLine)
return;
- QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength());
+ const QStringRef pragmaValue = script.midRef(l.tokenOffset(), l.tokenLength());
int endOffset = l.tokenLength() + l.tokenOffset();
token = l.lex();
@@ -806,130 +835,86 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
}
} else {
const QStringRef &memberType = node->memberType;
- const QStringRef &name = node->name;
-
- bool typeFound = false;
- QV4::CompiledData::Property::Type type;
-
if (memberType == QLatin1String("alias")) {
- type = QV4::CompiledData::Property::Alias;
- typeFound = true;
- }
+ return appendAlias(node);
+ } else {
+ const QStringRef &name = node->name;
- for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
- const TypeNameToType *t = propTypeNameToTypes + ii;
- if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
- type = t->type;
- typeFound = true;
+ bool typeFound = false;
+ QV4::CompiledData::Property::Type type;
+
+ for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
+ const TypeNameToType *t = propTypeNameToTypes + ii;
+ if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
+ type = t->type;
+ typeFound = true;
+ }
}
- }
- if (!typeFound && memberType.at(0).isUpper()) {
- const QStringRef &typeModifier = node->typeModifier;
+ if (!typeFound && memberType.at(0).isUpper()) {
+ const QStringRef &typeModifier = node->typeModifier;
- if (typeModifier.isEmpty()) {
- type = QV4::CompiledData::Property::Custom;
- } else if (typeModifier == QLatin1String("list")) {
- type = QV4::CompiledData::Property::CustomList;
- } else {
- recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
+ if (typeModifier.isEmpty()) {
+ type = QV4::CompiledData::Property::Custom;
+ } else if (typeModifier == QLatin1String("list")) {
+ type = QV4::CompiledData::Property::CustomList;
+ } else {
+ recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier"));
+ return false;
+ }
+ typeFound = true;
+ } else if (!node->typeModifier.isNull()) {
+ recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Unexpected property type modifier"));
return false;
}
- typeFound = true;
- } else if (!node->typeModifier.isNull()) {
- recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Unexpected property type modifier"));
- return false;
- }
-
- if (!typeFound) {
- recordError(node->typeToken, QCoreApplication::translate("QQmlParser","Expected property type"));
- return false;
- }
-
- Property *property = New<Property>();
- property->flags = 0;
- if (node->isReadonlyMember)
- property->flags |= QV4::CompiledData::Property::IsReadOnly;
- property->type = type;
- if (type >= QV4::CompiledData::Property::Custom)
- property->customTypeNameIndex = registerString(memberType.toString());
- else
- property->customTypeNameIndex = emptyStringIndex;
- const QString propName = name.toString();
- property->nameIndex = registerString(propName);
-
- QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
- property->location.line = loc.startLine;
- property->location.column = loc.startColumn;
-
- property->aliasPropertyValueIndex = emptyStringIndex;
-
- if (type == QV4::CompiledData::Property::Alias) {
- if (!node->statement && !node->binding)
- COMPILE_EXCEPTION(loc, tr("No property alias location"));
+ if (!typeFound) {
+ recordError(node->typeToken, QCoreApplication::translate("QQmlParser","Expected property type"));
+ return false;
+ }
- QQmlJS::AST::SourceLocation rhsLoc;
- if (node->binding)
- rhsLoc = node->binding->firstSourceLocation();
- else if (node->statement)
- rhsLoc = node->statement->firstSourceLocation();
+ Property *property = New<Property>();
+ property->flags = 0;
+ if (node->isReadonlyMember)
+ property->flags |= QV4::CompiledData::Property::IsReadOnly;
+ property->type = type;
+ if (type >= QV4::CompiledData::Property::Custom)
+ property->customTypeNameIndex = registerString(memberType.toString());
else
- rhsLoc = node->semicolonToken;
- property->aliasLocation.line = rhsLoc.startLine;
- property->aliasLocation.column = rhsLoc.startColumn;
-
- QStringList alias;
-
- if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(node->statement)) {
- alias = astNodeToStringList(stmt->expression);
- if (alias.isEmpty()) {
- if (isStatementNodeScript(node->statement)) {
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
- } else {
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location"));
- }
- }
- } else {
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
- }
+ property->customTypeNameIndex = emptyStringIndex;
- if (alias.count() < 1 || alias.count() > 3)
- COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+ const QString propName = name.toString();
+ property->nameIndex = registerString(propName);
- property->aliasIdValueIndex = registerString(alias.first());
+ QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
+ property->location.line = loc.startLine;
+ property->location.column = loc.startColumn;
- QString propertyValue = alias.value(1);
- if (alias.count() == 3) {
- propertyValue += QLatin1Char('.');
- propertyValue += alias.at(2);
- }
- property->aliasPropertyValueIndex = registerString(propertyValue);
- }
- QQmlJS::AST::SourceLocation errorLocation;
- QString error;
+ QQmlJS::AST::SourceLocation errorLocation;
+ QString error;
- if (illegalNames.contains(propName))
- error = tr("Illegal property name");
- else
- error = _object->appendProperty(property, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
+ if (illegalNames.contains(propName))
+ error = tr("Illegal property name");
+ else
+ error = _object->appendProperty(property, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
- if (!error.isEmpty()) {
- if (errorLocation.startLine == 0)
- errorLocation = node->identifierToken;
+ if (!error.isEmpty()) {
+ if (errorLocation.startLine == 0)
+ errorLocation = node->identifierToken;
- recordError(errorLocation, error);
- return false;
- }
+ recordError(errorLocation, error);
+ return false;
+ }
- qSwap(_propertyDeclaration, property);
- if (node->binding) {
- // process QML-like initializers (e.g. property Object o: Object {})
- QQmlJS::AST::Node::accept(node->binding, this);
- } else if (node->statement && type != QV4::CompiledData::Property::Alias) {
- appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
+ qSwap(_propertyDeclaration, property);
+ if (node->binding) {
+ // process QML-like initializers (e.g. property Object o: Object {})
+ QQmlJS::AST::Node::accept(node->binding, this);
+ } else if (node->statement) {
+ appendBinding(node->identifierToken, node->identifierToken, _propertyDeclaration->nameIndex, node->statement);
+ }
+ qSwap(_propertyDeclaration, property);
}
- qSwap(_propertyDeclaration, property);
}
return false;
@@ -1084,6 +1069,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
{
Binding *binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
+ binding->offset = nameLocation.offset;
binding->location.line = nameLocation.startLine;
binding->location.column = nameLocation.startColumn;
binding->flags = 0;
@@ -1103,6 +1089,7 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
Binding *binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
+ binding->offset = nameLocation.offset;
binding->location.line = nameLocation.startLine;
binding->location.column = nameLocation.startColumn;
@@ -1132,6 +1119,79 @@ void IRBuilder::appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLo
}
}
+bool IRBuilder::appendAlias(QQmlJS::AST::UiPublicMember *node)
+{
+ Alias *alias = New<Alias>();
+ alias->flags = 0;
+ if (node->isReadonlyMember)
+ alias->flags |= QV4::CompiledData::Alias::IsReadOnly;
+
+ const QString propName = node->name.toString();
+ alias->nameIndex = registerString(propName);
+
+ QQmlJS::AST::SourceLocation loc = node->firstSourceLocation();
+ alias->location.line = loc.startLine;
+ alias->location.column = loc.startColumn;
+
+ alias->propertyNameIndex = emptyStringIndex;
+
+ if (!node->statement && !node->binding)
+ COMPILE_EXCEPTION(loc, tr("No property alias location"));
+
+ QQmlJS::AST::SourceLocation rhsLoc;
+ if (node->binding)
+ rhsLoc = node->binding->firstSourceLocation();
+ else if (node->statement)
+ rhsLoc = node->statement->firstSourceLocation();
+ else
+ rhsLoc = node->semicolonToken;
+ alias->referenceLocation.line = rhsLoc.startLine;
+ alias->referenceLocation.column = rhsLoc.startColumn;
+
+ QStringList aliasReference;
+
+ if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast<QQmlJS::AST::ExpressionStatement*>(node->statement)) {
+ aliasReference = astNodeToStringList(stmt->expression);
+ if (aliasReference.isEmpty()) {
+ if (isStatementNodeScript(node->statement)) {
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+ } else {
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias location"));
+ }
+ }
+ } else {
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+ }
+
+ if (aliasReference.count() < 1 || aliasReference.count() > 3)
+ COMPILE_EXCEPTION(rhsLoc, tr("Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property>"));
+
+ alias->idIndex = registerString(aliasReference.first());
+
+ QString propertyValue = aliasReference.value(1);
+ if (aliasReference.count() == 3)
+ propertyValue += QLatin1Char('.') + aliasReference.at(2);
+ alias->propertyNameIndex = registerString(propertyValue);
+
+ QQmlJS::AST::SourceLocation errorLocation;
+ QString error;
+
+ if (illegalNames.contains(propName))
+ error = tr("Illegal property name");
+ else
+ error = _object->appendAlias(alias, propName, node->isDefaultMember, node->defaultToken, &errorLocation);
+
+ if (!error.isEmpty()) {
+ if (errorLocation.startLine == 0)
+ errorLocation = node->identifierToken;
+
+ recordError(errorLocation, error);
+ return false;
+ }
+
+ return false;
+}
+
Object *IRBuilder::bindingsTarget() const
{
if (_propertyDeclaration && _object->declarationsOverride)
@@ -1201,8 +1261,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O
if (import->qualifierIndex != emptyStringIndex
&& stringAt(import->qualifierIndex) == currentName) {
qualifiedIdElement = qualifiedIdElement->next;
- currentName += QLatin1Char('.');
- currentName += qualifiedIdElement->name;
+ currentName += QLatin1Char('.') + qualifiedIdElement->name;
if (!qualifiedIdElement->name.unicode()->isUpper())
COMPILE_EXCEPTION(qualifiedIdElement->firstSourceLocation(), tr("Expected type name"));
@@ -1228,6 +1287,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O
if (!binding) {
binding = New<Binding>();
binding->propertyNameIndex = propertyNameIndex;
+ binding->offset = qualifiedIdElement->identifierToken.offset;
binding->location.line = qualifiedIdElement->identifierToken.startLine;
binding->location.column = qualifiedIdElement->identifierToken.startColumn;
binding->valueLocation.line = qualifiedIdElement->next->identifierToken.startLine;
@@ -1313,7 +1373,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
int objectsSize = 0;
foreach (Object *o, output.objects) {
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
- objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
+ objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
int signalTableSize = 0;
for (const Signal *s = o->firstSignal(); s; s = s->next)
@@ -1358,7 +1418,8 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr);
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
- objectToWrite->indexOfDefaultProperty = o->indexOfDefaultProperty;
+ objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias;
+ objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias;
objectToWrite->idIndex = o->idIndex;
objectToWrite->location = o->location;
objectToWrite->locationOfIdProperty = o->locationOfIdProperty;
@@ -1373,6 +1434,10 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
objectToWrite->offsetToProperties = nextOffset;
nextOffset += objectToWrite->nProperties * sizeof(QV4::CompiledData::Property);
+ objectToWrite->nAliases = o->aliasCount();
+ objectToWrite->offsetToAliases = nextOffset;
+ nextOffset += objectToWrite->nAliases * sizeof(QV4::CompiledData::Alias);
+
objectToWrite->nSignals = o->signalCount();
objectToWrite->offsetToSignals = nextOffset;
nextOffset += objectToWrite->nSignals * sizeof(quint32);
@@ -1392,6 +1457,13 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
propertiesPtr += sizeof(QV4::CompiledData::Property);
}
+ char *aliasesPtr = objectPtr + objectToWrite->offsetToAliases;
+ for (const Alias *a = o->firstAlias(); a; a = a->next) {
+ QV4::CompiledData::Alias *aliasToWrite = reinterpret_cast<QV4::CompiledData::Alias*>(aliasesPtr);
+ *aliasToWrite = *a;
+ aliasesPtr += sizeof(QV4::CompiledData::Alias);
+ }
+
char *bindingPtr = objectPtr + objectToWrite->offsetToBindings;
bindingPtr = writeBindings(bindingPtr, o, &QV4::CompiledData::Binding::isValueBindingNoAlias);
bindingPtr = writeBindings(bindingPtr, o, &QV4::CompiledData::Binding::isSignalHandler);
@@ -1420,7 +1492,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
signalPtr += size;
}
- objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->signalCount(), o->bindingCount());
+ objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
objectPtr += signalTableSize;
}
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 057ed1be9f..c53004a331 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -113,7 +113,7 @@ struct PoolList
T *insertPos = 0;
for (T *it = first; it; it = it->next) {
- if (!(it->*sortMember < item->*sortMember))
+ if (!(it->*sortMember <= item->*sortMember))
break;
insertPos = it;
}
@@ -227,10 +227,19 @@ struct Property : public QV4::CompiledData::Property
struct Binding : public QV4::CompiledData::Binding
{
+ // The offset in the source file where the binding appeared. This is used for sorting to ensure
+ // that assignments to list properties are done in the correct order. We use the offset here instead
+ // of Binding::location as the latter has limited precision.
+ quint32 offset;
// Binding's compiledScriptIndex is index in object's functionsAndExpressions
Binding *next;
};
+struct Alias : public QV4::CompiledData::Alias
+{
+ Alias *next;
+};
+
struct Function
{
QQmlJS::AST::FunctionDeclaration *functionDeclaration;
@@ -266,13 +275,16 @@ struct Q_QML_PRIVATE_EXPORT Object
public:
quint32 inheritedTypeNameIndex;
quint32 idIndex;
- int indexOfDefaultProperty;
+ int indexOfDefaultPropertyOrAlias : 31;
+ int defaultPropertyIsAlias : 1;
QV4::CompiledData::Location location;
QV4::CompiledData::Location locationOfIdProperty;
const Property *firstProperty() const { return properties->first; }
int propertyCount() const { return properties->count; }
+ Alias *firstAlias() const { return aliases->first; }
+ int aliasCount() const { return aliases->count; }
const Signal *firstSignal() const { return qmlSignals->first; }
int signalCount() const { return qmlSignals->count; }
Binding *firstBinding() const { return bindings->first; }
@@ -290,6 +302,7 @@ public:
QString appendSignal(Signal *signal);
QString appendProperty(Property *prop, const QString &propertyName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
+ QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
void appendFunction(QmlIR::Function *f);
QString appendBinding(Binding *b, bool isListBinding);
@@ -305,6 +318,7 @@ private:
friend struct IRLoader;
PoolList<Property> *properties;
+ PoolList<Alias> *aliases;
PoolList<Signal> *qmlSignals;
PoolList<Binding> *bindings;
PoolList<Function> *functions;
@@ -410,6 +424,8 @@ public:
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value);
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false);
+ bool appendAlias(QQmlJS::AST::UiPublicMember *node);
+
Object *bindingsTarget() const;
bool setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST::Statement *value);
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index a71793f2b6..097d072734 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -179,16 +179,16 @@ bool QQmlTypeCompiler::compile()
for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) {
const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex);
- QString qualifier = script.qualifier;
+ QStringRef qualifier(&script.qualifier);
QString enclosingNamespace;
const int lastDotIndex = qualifier.lastIndexOf(QLatin1Char('.'));
if (lastDotIndex != -1) {
- enclosingNamespace = qualifier.left(lastDotIndex);
+ enclosingNamespace = qualifier.left(lastDotIndex).toString();
qualifier = qualifier.mid(lastDotIndex+1);
}
- compiledData->importCache->add(qualifier, scriptIndex, enclosingNamespace);
+ compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
QQmlScriptData *scriptData = script.script->scriptData();
scriptData->addref();
compiledData->scripts << scriptData;
@@ -480,7 +480,7 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
}
}
- bool needVMEMetaObject = obj->propertyCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
+ bool needVMEMetaObject = obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0 || obj->functionCount() != 0;
if (!needVMEMetaObject) {
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type == QV4::CompiledData::Binding::Type_Object && (binding->flags & QV4::CompiledData::Binding::IsOnAssignment)) {
@@ -507,7 +507,7 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
Q_ASSERT(typeRef);
if (typeRef->isFullyDynamicType) {
- if (obj->propertyCount() > 0) {
+ if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
recordError(obj->location, tr("Fully dynamic types cannot declare new properties."));
return false;
}
@@ -586,9 +586,9 @@ bool QQmlPropertyCacheCreator::ensureMetaObject(int objectIndex)
bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Object *obj, QQmlPropertyCache *baseTypeCache)
{
- QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount(),
- obj->functionCount() + obj->propertyCount() + obj->signalCount(),
- obj->signalCount() + obj->propertyCount());
+ QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount() + obj->aliasCount(),
+ obj->functionCount() + obj->propertyCount() + obj->aliasCount() + obj->signalCount(),
+ obj->signalCount() + obj->propertyCount() + obj->aliasCount());
propertyCaches[objectIndex] = cache;
struct TypeData {
@@ -624,7 +624,7 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
QString path = compiler->url().path();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
if (lastSlash > -1) {
- QString nameBase = path.mid(lastSlash + 1, path.length()-lastSlash-5);
+ const QStringRef nameBase = path.midRef(lastSlash + 1, path.length() - lastSlash - 5);
if (!nameBase.isEmpty() && nameBase.at(0).isUpper())
newClassName = nameBase.toUtf8() + "_QMLTYPE_" +
QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1));
@@ -638,30 +638,30 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
cache->_dynamicClassName = newClassName;
- int aliasCount = 0;
int varPropCount = 0;
QmlIR::PropertyResolver resolver(baseTypeCache);
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
- if (p->type == QV4::CompiledData::Property::Alias)
- aliasCount++;
- else if (p->type == QV4::CompiledData::Property::Var)
+ if (p->type == QV4::CompiledData::Property::Var)
varPropCount++;
- // No point doing this for both the alias and non alias cases
bool notInRevision = false;
QQmlPropertyData *d = resolver.property(stringAt(p->nameIndex), &notInRevision);
if (d && d->isFinal())
COMPILE_EXCEPTION(p, tr("Cannot override FINAL property"));
}
+ for (const QmlIR::Alias *a = obj->firstAlias(); a; a = a->next) {
+ bool notInRevision = false;
+ QQmlPropertyData *d = resolver.property(stringAt(a->nameIndex), &notInRevision);
+ if (d && d->isFinal())
+ COMPILE_EXCEPTION(a, tr("Cannot override FINAL property"));
+ }
+
typedef QQmlVMEMetaData VMD;
- QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData)
- + obj->propertyCount() * sizeof(VMD::PropertyData)
- + obj->functionCount() * sizeof(VMD::MethodData)
- + aliasCount * sizeof(VMD::AliasData), 0);
+ vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData) + obj->aliasCount() * sizeof(VMD::AliasData), 0);
int effectivePropertyIndex = cache->propertyIndexCacheStart;
int effectiveMethodIndex = cache->methodIndexCacheStart;
@@ -689,25 +689,25 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
}
}
- // First set up notify signals for properties - first normal, then var, then alias
- enum { NSS_Normal = 0, NSS_Alias = 1 };
- for (int ii = NSS_Normal; ii <= NSS_Alias; ++ii) { // 0 == normal, 1 == var, 2 == alias
+ // Set up notify signals for properties - first normal, then alias
+ for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
- if (ii == NSS_Alias && aliasCount == 0) continue;
+ QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
+ seenSignals.insert(changedSigName);
- for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next) {
- if ((ii == NSS_Normal && p->type == QV4::CompiledData::Property::Alias) ||
- (ii == NSS_Alias && p->type != QV4::CompiledData::Property::Alias))
- continue;
+ cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
+ }
- quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
- QQmlPropertyData::IsVMESignal;
+ for (const QmlIR::Alias *a = obj->firstAlias(); a; a = a->next) {
+ quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
+ QQmlPropertyData::IsVMESignal;
- QString changedSigName = stringAt(p->nameIndex) + QLatin1String("Changed");
- seenSignals.insert(changedSigName);
+ QString changedSigName = stringAt(a->nameIndex) + QLatin1String("Changed");
+ seenSignals.insert(changedSigName);
- cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
- }
+ cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
}
// Dynamic signals
@@ -752,8 +752,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
}
}
- ((QQmlVMEMetaData *)dynamicData.data())->signalCount++;
-
quint32 flags = QQmlPropertyData::IsSignal | QQmlPropertyData::IsFunction |
QQmlPropertyData::IsVMESignal;
if (paramCount)
@@ -795,25 +793,18 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
}
- // Dynamic properties (except var and aliases)
+ // Dynamic properties
int effectiveSignalIndex = cache->signalHandlerIndexCacheStart;
int propertyIdx = 0;
for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) {
-
- if (p->type == QV4::CompiledData::Property::Alias)
- continue;
-
int propertyType = 0;
- int vmePropertyType = 0;
quint32 propertyFlags = 0;
if (p->type == QV4::CompiledData::Property::Var) {
propertyType = QMetaType::QVariant;
- vmePropertyType = QQmlVMEMetaData::VarPropertyType;
propertyFlags = QQmlPropertyData::IsVarProperty;
} else if (p->type < builtinTypeCount) {
propertyType = builtinTypes[p->type].metaType;
- vmePropertyType = propertyType;
if (p->type == QV4::CompiledData::Property::Variant)
propertyFlags |= QQmlPropertyData::IsQVariant;
@@ -836,20 +827,16 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
if (p->type == QV4::CompiledData::Property::Custom) {
propertyType = data->metaTypeId;
- vmePropertyType = QMetaType::QObjectStar;
} else {
propertyType = data->listMetaTypeId;
- vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
}
tdata->release();
} else {
if (p->type == QV4::CompiledData::Property::Custom) {
propertyType = qmltype->typeId();
- vmePropertyType = QMetaType::QObjectStar;
} else {
propertyType = qmltype->qListTypeId();
- vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >();
}
}
@@ -864,38 +851,12 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob
QString propertyName = stringAt(p->nameIndex);
- if (propertyIdx == obj->indexOfDefaultProperty) cache->_defaultPropertyName = propertyName;
+ if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias)
+ cache->_defaultPropertyName = propertyName;
cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
propertyType, effectiveSignalIndex);
effectiveSignalIndex++;
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- (vmd->propertyData() + vmd->propertyCount)->propertyType = vmePropertyType;
- vmd->propertyCount++;
- }
-
- // Alias property count. Actual data is setup in buildDynamicMetaAliases
- ((QQmlVMEMetaData *)dynamicData.data())->aliasCount = aliasCount;
-
- // Dynamic slot data - comes after the property data
- for (const QmlIR::Function *s = obj->firstFunction(); s; s = s->next) {
- QQmlJS::AST::FunctionDeclaration *astFunction = s->functionDeclaration;
- int formalsCount = 0;
- QQmlJS::AST::FormalParameterList *param = astFunction->formals;
- while (param) {
- formalsCount++;
- param = param->next;
- }
-
- VMD::MethodData methodData = { /* runtimeFunctionIndex*/ 0, // ###
- formalsCount,
- /* s->location.start.line */0 }; // ###
-
- VMD *vmd = (QQmlVMEMetaData *)dynamicData.data();
- VMD::MethodData &md = *(vmd->methodData() + vmd->methodCount);
- vmd->methodCount++;
- md = methodData;
}
return true;
@@ -1163,10 +1124,10 @@ struct StaticQtMetaObject : public QObject
{ return &staticQtMetaObject; }
};
-bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject)
+bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject)
{
if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) {
- COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName));
+ COMPILE_EXCEPTION(binding, tr("Invalid property assignment: Enum value \"%1\" cannot start with a lowercase letter").arg(enumName.toString()));
}
binding->type = QV4::CompiledData::Binding::Type_Number;
binding->value.d = (double)enumValue;
@@ -1197,7 +1158,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
QHashedStringRef typeName(string.constData(), dot);
const bool isQtObject = (typeName == QLatin1String("Qt"));
- QString enumValue = string.mid(dot+1);
+ const QStringRef enumValue = string.midRef(dot + 1);
if (isIntProp) {
// Allow enum assignment to ints.
@@ -1318,7 +1279,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases()
const QmlIR::Object *obj = qmlObjects.at(i);
QmlIR::PropertyResolver resolver(propertyCache);
- QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (!binding->isValueBinding())
@@ -1350,7 +1311,7 @@ void QQmlScriptStringScanner::scan()
const QmlIR::Object *obj = qmlObjects.at(i);
QmlIR::PropertyResolver resolver(propertyCache);
- QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type != QV4::CompiledData::Binding::Type_Script)
@@ -1390,7 +1351,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
{
QmlIR::PropertyResolver propertyResolver(propertyCache);
- QQmlPropertyData *defaultProperty = obj->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type != QV4::CompiledData::Binding::Type_Object)
@@ -1497,7 +1458,7 @@ bool QQmlComponentAndAliasResolver::resolve()
if (obj->functionCount() > 0)
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
- if (obj->propertyCount() > 0)
+ if (obj->propertyCount() > 0 || obj->aliasCount() > 0)
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties."));
if (obj->signalCount() > 0)
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals."));
@@ -1568,12 +1529,8 @@ bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
_objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
}
- for (const QmlIR::Property *property = obj->firstProperty(); property; property = property->next) {
- if (property->type == QV4::CompiledData::Property::Alias) {
- _objectsWithAliases.append(objectIndex);
- break;
- }
- }
+ if (obj->aliasCount() > 0)
+ _objectsWithAliases.append(objectIndex);
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type != QV4::CompiledData::Binding::Type_Object
@@ -1604,21 +1561,20 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.count();
int effectiveAliasIndex = 0;
- const QmlIR::Property *p = obj->firstProperty();
- for (int propertyIndex = 0; propertyIndex < obj->propertyCount(); ++propertyIndex, p = p->next) {
- if (p->type != QV4::CompiledData::Property::Alias)
- continue;
-
- const int idIndex = p->aliasIdValueIndex;
+ int aliasIndex = 0;
+ for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next, ++aliasIndex) {
+ const int idIndex = alias->idIndex;
const int targetObjectIndex = _idToObjectIndex.value(idIndex, -1);
if (targetObjectIndex == -1) {
- recordError(p->aliasLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
+ recordError(alias->referenceLocation, tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
return false;
}
- const int targetId = _objectIndexToIdInScope->value(targetObjectIndex, -1);
- Q_ASSERT(targetId != -1);
+ Q_ASSERT(!(alias->flags & QV4::CompiledData::Alias::Resolved));
+ alias->flags |= QV4::CompiledData::Alias::Resolved;
+ Q_ASSERT(_objectIndexToIdInScope->contains(targetObjectIndex));
+ alias->targetObjectId = _objectIndexToIdInScope->value(targetObjectIndex);
- const QString aliasPropertyValue = stringAt(p->aliasPropertyValueIndex);
+ const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
QStringRef property;
QStringRef subProperty;
@@ -1631,9 +1587,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
property = QStringRef(&aliasPropertyValue, 0, aliasPropertyValue.length());
int propIdx = -1;
- int propType = 0;
int notifySignal = -1;
- int flags = 0;
int type = 0;
bool writable = false;
bool resettable = false;
@@ -1650,7 +1604,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
else
type = typeRef->component->metaTypeId;
- flags |= QML_ALIAS_FLAG_PTR;
+ alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
propertyFlags |= QQmlPropertyData::IsQObjectDerived;
} else {
QQmlPropertyCache *targetCache = propertyCaches.at(targetObjectIndex);
@@ -1659,7 +1613,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
QQmlPropertyData *targetProperty = resolver.property(property.toString());
if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
- recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(property.toString()));
+ recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString()));
return false;
}
@@ -1673,16 +1627,14 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
if (!subProperty.isEmpty()) {
const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(type);
if (!valueTypeMetaObject) {
- recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
+ recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
return false;
}
- propType = type;
-
int valueTypeIndex =
valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
if (valueTypeIndex == -1) {
- recordError(p->aliasLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
+ recordError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
return false;
}
Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
@@ -1704,12 +1656,13 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
propertyFlags |= QQmlPropertyData::IsQVariant;
if (targetProperty->isQObject())
- flags |= QML_ALIAS_FLAG_PTR;
+ alias->flags |= QV4::CompiledData::Alias::AliasPointsToPointerObject;
}
}
}
- QQmlVMEMetaData::AliasData aliasData = { targetId, propIdx, propType, flags, notifySignal };
+ alias->encodedMetaPropertyIndex = propIdx;
+ QQmlVMEMetaData::AliasData aliasData = { notifySignal };
typedef QQmlVMEMetaData VMD;
QByteArray &dynamicData = (*vmeMetaObjectData)[objectIndex];
@@ -1719,7 +1672,7 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
Q_ASSERT(dynamicData.isDetached());
- if (!(p->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
+ if (!(alias->flags & QV4::CompiledData::Property::IsReadOnly) && writable)
propertyFlags |= QQmlPropertyData::IsWritable;
else
propertyFlags &= ~QQmlPropertyData::IsWritable;
@@ -1729,8 +1682,11 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
else
propertyFlags &= ~QQmlPropertyData::IsResettable;
- QString propertyName = stringAt(p->nameIndex);
- if (propertyIndex == obj->indexOfDefaultProperty) propertyCache->_defaultPropertyName = propertyName;
+ QString propertyName = stringAt(alias->nameIndex);
+
+ if (obj->defaultPropertyIsAlias && aliasIndex == obj->indexOfDefaultPropertyOrAlias)
+ propertyCache->_defaultPropertyName = propertyName;
+
propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
type, effectiveSignalIndex++);
@@ -1842,7 +1798,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
QString defaultPropertyName;
QQmlPropertyData *defaultProperty = 0;
- if (obj->indexOfDefaultProperty != -1) {
+ if (obj->indexOfDefaultPropertyOrAlias != -1) {
QQmlPropertyCache *cache = propertyCache->parent();
defaultPropertyName = cache->defaultPropertyName();
defaultProperty = cache->defaultProperty();
@@ -2562,7 +2518,7 @@ void QQmlDefaultPropertyMerger::mergeDefaultProperties(int objectIndex)
QmlIR::Object *object = qmlObjects.at(objectIndex);
- QString defaultProperty = object->indexOfDefaultProperty != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName();
+ QString defaultProperty = object->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName();
QmlIR::Binding *bindingsToReinsert = 0;
QmlIR::Binding *tail = 0;
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 240f591f91..273ba01a88 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -196,7 +196,11 @@ public:
bool resolveEnumBindings();
private:
- bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject);
+ bool assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject);
+ bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject)
+ {
+ return assignEnumToBinding(binding, QStringRef(&enumName), enumValue, isQtObject);
+ }
bool tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache,
const QQmlPropertyData *prop,
QmlIR::Binding *binding);
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 4d0361302e..ded2c1a9f8 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -72,6 +72,9 @@ CompilationUnit::CompilationUnit()
CompilationUnit::~CompilationUnit()
{
unlink();
+ if (data && !(data->flags & QV4::CompiledData::Unit::StaticData))
+ free(data);
+ data = 0;
}
QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
@@ -163,9 +166,6 @@ void CompilationUnit::unlink()
if (engine)
engine->compilationUnits.erase(engine->compilationUnits.find(this));
engine = 0;
- if (data && !(data->flags & QV4::CompiledData::Unit::StaticData))
- free(data);
- data = 0;
free(runtimeStrings);
runtimeStrings = 0;
delete [] runtimeLookups;
@@ -221,8 +221,8 @@ QString Binding::valueAsString(const Unit *unit) const
// This code must match that in the qsTr() implementation
const QString &path = unit->stringAt(unit->sourceFileIndex);
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
- QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) :
- QString();
+ QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5)
+ : QStringRef();
QByteArray contextUtf8 = context.toUtf8();
QByteArray comment = unit->stringAt(value.translationData.commentIndex).toUtf8();
QByteArray text = unit->stringAt(stringIndex).toUtf8();
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 8990db075d..3c2d895bff 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -351,22 +351,42 @@ struct Property
enum Type { Var = 0, Variant, Int, Bool, Real, String, Url, Color,
Font, Time, Date, DateTime, Rect, Point, Size,
Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion,
- Alias, Custom, CustomList };
+ Custom, CustomList };
enum Flags {
IsReadOnly = 0x1
};
quint32 nameIndex;
- quint32 type;
+ quint32 type : 31;
+ quint32 flags : 1; // readonly
+ quint32 customTypeNameIndex; // If type >= Custom
+ Location location;
+};
+
+struct Alias {
+ enum Flags {
+ IsReadOnly = 0x1,
+ Resolved = 0x2,
+ AliasPointsToPointerObject = 0x4
+ };
+ quint32 nameIndex : 29;
+ quint32 flags : 3;
union {
- quint32 customTypeNameIndex; // If type >= Custom
- quint32 aliasIdValueIndex; // If type == Alias
+ quint32 idIndex; // string index
+ quint32 targetObjectId; // object id index (in QQmlContextData::idValues)
+ };
+ union {
+ quint32 propertyNameIndex; // string index
+ qint32 encodedMetaPropertyIndex;
};
- quint32 aliasPropertyValueIndex;
- quint32 flags; // readonly
Location location;
- Location aliasLocation; // If type == Alias
+ Location referenceLocation;
+
+ bool isObjectAlias() const {
+ Q_ASSERT(flags & Resolved);
+ return encodedMetaPropertyIndex == -1;
+ }
};
struct Object
@@ -376,11 +396,14 @@ struct Object
// it will be the name of the attached type.
quint32 inheritedTypeNameIndex;
quint32 idIndex;
- qint32 indexOfDefaultProperty; // -1 means no default property declared in this object
+ qint32 indexOfDefaultPropertyOrAlias : 31; // -1 means no default property declared in this object
+ quint32 defaultPropertyIsAlias : 1;
quint32 nFunctions;
quint32 offsetToFunctions;
quint32 nProperties;
quint32 offsetToProperties;
+ quint32 nAliases;
+ quint32 offsetToAliases;
quint32 nSignals;
quint32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
quint32 nBindings;
@@ -392,11 +415,12 @@ struct Object
// Signal[]
// Binding[]
- static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nSignals, int nBindings)
+ static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings)
{
return ( sizeof(Object)
+ nFunctions * sizeof(quint32)
+ nProperties * sizeof(Property)
+ + nAliases * sizeof(Alias)
+ nSignals * sizeof(quint32)
+ nBindings * sizeof(Binding)
+ 0x7
@@ -413,6 +437,11 @@ struct Object
return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
}
+ const Alias *aliasTable() const
+ {
+ return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
+ }
+
const Binding *bindingTable() const
{
return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index 86f812bc41..e608c08591 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -135,7 +135,7 @@ public:
// Validate the new range
if (_end != InvalidPosition) {
Q_ASSERT(!_ranges.isEmpty());
- foreach (const Range &range, _ranges) {
+ for (const Range &range : qAsConst(_ranges)) {
Q_ASSERT(range.start >= 0);
Q_ASSERT(range.end >= 0);
Q_ASSERT(range.start <= range.end);
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index 8d60325a19..629d5cb7b8 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -45,7 +45,9 @@ QT_BEGIN_NAMESPACE
QQmlProfiler::QQmlProfiler() : featuresEnabled(0)
{
static int metatype = qRegisterMetaType<QVector<QQmlProfilerData> >();
+ static int metatype2 = qRegisterMetaType<QQmlProfiler::LocationHash> ();
Q_UNUSED(metatype);
+ Q_UNUSED(metatype2);
m_timer.start();
}
@@ -62,8 +64,18 @@ void QQmlProfiler::stopProfiling()
void QQmlProfiler::reportData()
{
- emit dataReady(m_data);
- m_data.clear();
+ LocationHash resolved;
+ resolved.reserve(m_locations.size());
+ for (auto it = m_locations.constBegin(), end = m_locations.constEnd(); it != end; ++it)
+ resolved.insert(it.key(), it.value());
+
+ // This unrefs all the objects. We have to make sure we do this in the GUI thread. Also, it's
+ // a good idea to release the memory before creating the packets to be sent.
+ m_locations.clear();
+
+ QVector<QQmlProfilerData> data;
+ data.swap(m_data);
+ emit dataReady(data, resolved);
}
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 24001159f3..1380599fb7 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -54,6 +54,8 @@
#include <private/qv4function_p.h>
#include <private/qqmlboundsignal_p.h>
#include <private/qfinitestack_p.h>
+#include <private/qqmlbinding_p.h>
+#include <private/qqmlcompiler_p.h>
#include "qqmlprofilerdefinitions_p.h"
#include "qqmlabstractprofileradapter_p.h"
@@ -77,40 +79,18 @@ QT_BEGIN_NAMESPACE
// independently when converting to QByteArrays. Thus you can only pack
// messages if their data doesn't overlap. It's up to you to figure that
// out.
-struct Q_AUTOTEST_EXPORT QQmlProfilerData
+struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions
{
- QQmlProfilerData() {}
-
- QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url,
- int x = 0, int y = 0) :
- time(time), messageType(messageType), detailType(detailType), detailUrl(url),
- x(x), y(y) {}
-
- QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
- int x = 0, int y = 0) :
- time(time), messageType(messageType), detailType(detailType),detailString(str),
- x(x), y(y) {}
-
- QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str,
- const QUrl &url, int x = 0, int y = 0) :
- time(time), messageType(messageType), detailType(detailType), detailString(str),
- detailUrl(url), x(x), y(y) {}
-
-
- QQmlProfilerData(qint64 time, int messageType, int detailType) :
- time(time), messageType(messageType), detailType(detailType) {}
-
+ QQmlProfilerData(qint64 time = -1, int messageType = -1,
+ RangeType detailType = MaximumRangeType, quintptr locationId = 0) :
+ time(time), locationId(locationId), messageType(messageType), detailType(detailType)
+ {}
qint64 time;
- int messageType; //bit field of QQmlProfilerService::Message
- int detailType;
+ quintptr locationId;
- // RangeData prefers detailString; RangeLocation prefers detailUrl.
- QString detailString; //used by RangeData and possibly by RangeLocation
- QUrl detailUrl; //used by RangeLocation and possibly by RangeData
-
- int x; //used by RangeLocation
- int y; //used by RangeLocation
+ int messageType; //bit field of QQmlProfilerService::Message
+ RangeType detailType;
};
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
@@ -118,58 +98,166 @@ Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
public:
- void startBinding(const QQmlSourceLocation &location)
+
+ class BindingRefCount : public QQmlRefCount {
+ public:
+ BindingRefCount(QQmlBinding *binding):
+ m_binding(binding)
+ {
+ m_binding->ref.ref();
+ }
+
+ BindingRefCount(const BindingRefCount &other) :
+ QQmlRefCount(other), m_binding(other.m_binding)
+ {
+ m_binding->ref.ref();
+ }
+
+ BindingRefCount &operator=(const BindingRefCount &other)
+ {
+ if (this != &other) {
+ QQmlRefCount::operator=(other);
+ other.m_binding->ref.ref();
+ if (!m_binding->ref.deref())
+ delete m_binding;
+ m_binding = other.m_binding;
+ }
+ return *this;
+ }
+
+ ~BindingRefCount()
+ {
+ if (!m_binding->ref.deref())
+ delete m_binding;
+ }
+
+ private:
+ QQmlBinding *m_binding;
+ };
+
+ struct Location {
+ Location(const QQmlSourceLocation &location = QQmlSourceLocation(),
+ const QUrl &url = QUrl()) :
+ location(location), url(url) {}
+ QQmlSourceLocation location;
+ QUrl url;
+ };
+
+ // Unfortunately we have to resolve the locations right away because the QML context might not
+ // be available anymore when we send the data.
+ struct RefLocation : public Location {
+ RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr)
+ {}
+
+ RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) :
+ Location(function->sourceLocation()), locationType(Binding),
+ ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt)
+ {}
+
+ RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj,
+ const QString &type) :
+ Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
+ locationType(Creating), ref(ref)
+ {}
+
+ RefLocation(QQmlBoundSignalExpression *ref) :
+ Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref)
+ {}
+
+ RefLocation(QQmlDataBlob *ref) :
+ Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref)
+ {}
+
+ bool isValid() const
+ {
+ return locationType != MaximumRangeType;
+ }
+
+ RangeType locationType;
+ QQmlRefPointer<QQmlRefCount> ref;
+ };
+
+ typedef QHash<quintptr, Location> LocationHash;
+
+ void startBinding(QQmlBinding *binding, QV4::FunctionObject *function)
{
+ quintptr locationId(id(binding));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
- (1 << RangeStart | 1 << RangeLocation), 1 << Binding,
- location.sourceFile, qmlSourceCoordinate(location.line), qmlSourceCoordinate(location.column)));
+ (1 << RangeStart | 1 << RangeLocation), Binding,
+ locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(binding, function);
}
// Have toByteArrays() construct another RangeData event from the same QString later.
// This is somewhat pointless but important for backwards compatibility.
- void startCompiling(const QUrl &url)
+ void startCompiling(QQmlDataBlob *blob)
{
+ quintptr locationId(id(blob));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
- 1 << Compiling, url, 1, 1));
+ Compiling, locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(blob);
}
- void startHandlingSignal(const QQmlSourceLocation &location)
+ void startHandlingSignal(QQmlBoundSignalExpression *expression)
{
+ quintptr locationId(id(expression));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
- (1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal,
- location.sourceFile, location.line, location.column));
+ (1 << RangeStart | 1 << RangeLocation), HandlingSignal,
+ locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(expression);
}
void startCreating()
{
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, 1 << Creating));
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating));
}
- void startCreating(const QString &typeName, const QUrl &fileName, int line, int column)
+ void startCreating(const QV4::CompiledData::Object *obj)
{
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeStart | 1 << RangeLocation | 1 << RangeData),
- 1 << Creating, typeName, fileName, line, column));
+ Creating, id(obj)));
}
- void updateCreating(const QString &typeName, const QUrl &fileName, int line, int column)
+ void updateCreating(const QV4::CompiledData::Object *obj, QQmlCompiledData *ref,
+ const QUrl &url, const QString &type)
{
+ quintptr locationId(id(obj));
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
(1 << RangeLocation | 1 << RangeData),
- 1 << Creating, typeName, fileName, line, column));
+ Creating, locationId));
+
+ RefLocation &location = m_locations[locationId];
+ if (!location.isValid())
+ location = RefLocation(ref, url, obj, type);
}
template<RangeType Range>
void endRange()
{
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range));
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, Range));
}
QQmlProfiler();
quint64 featuresEnabled;
+ template<typename Object>
+ static quintptr id(const Object *pointer)
+ {
+ return reinterpret_cast<quintptr>(pointer);
+ }
+
public slots:
void startProfiling(quint64 features);
void stopProfiling();
@@ -177,10 +265,11 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QVector<QQmlProfilerData> &);
+ void dataReady(const QVector<QQmlProfilerData> &, const QQmlProfiler::LocationHash &);
protected:
QElapsedTimer m_timer;
+ QHash<quintptr, RefLocation> m_locations;
QVector<QQmlProfilerData> m_data;
};
@@ -194,11 +283,12 @@ struct QQmlProfilerHelper : public QQmlProfilerDefinitions {
};
struct QQmlBindingProfiler : public QQmlProfilerHelper {
- QQmlBindingProfiler(QQmlProfiler *profiler, const QV4::FunctionObject *function) :
+ QQmlBindingProfiler(QQmlProfiler *profiler, QQmlBinding *binding,
+ QV4::FunctionObject *function) :
QQmlProfilerHelper(profiler)
{
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileBinding, profiler,
- startBinding(function->sourceLocation()));
+ startBinding(binding, function));
}
~QQmlBindingProfiler()
@@ -213,7 +303,7 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
QQmlProfilerHelper(profiler)
{
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileHandlingSignal, profiler,
- startHandlingSignal(expression->sourceLocation()));
+ startHandlingSignal(expression));
}
~QQmlHandlingSignalProfiler()
@@ -224,10 +314,10 @@ struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper {
};
struct QQmlCompilingProfiler : public QQmlProfilerHelper {
- QQmlCompilingProfiler(QQmlProfiler *profiler, const QUrl &url) :
+ QQmlCompilingProfiler(QQmlProfiler *profiler, QQmlDataBlob *blob) :
QQmlProfilerHelper(profiler)
{
- Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(url));
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCompiling, profiler, startCompiling(blob));
}
~QQmlCompilingProfiler()
@@ -239,14 +329,6 @@ struct QQmlCompilingProfiler : public QQmlProfilerHelper {
struct QQmlVmeProfiler : public QQmlProfilerDefinitions {
public:
- struct Data {
- Data() : m_line(0), m_column(0) {}
- QUrl m_url;
- int m_line;
- int m_column;
- QString m_typeName;
- };
-
QQmlVmeProfiler() : profiler(0) {}
void init(QQmlProfiler *p, int maxDepth)
@@ -255,30 +337,30 @@ public:
ranges.allocate(maxDepth);
}
- Data pop()
+ const QV4::CompiledData::Object *pop()
{
if (ranges.count() > 0)
return ranges.pop();
else
- return Data();
+ return nullptr;
}
- void push(const Data &data)
+ void push(const QV4::CompiledData::Object *object)
{
if (ranges.capacity() > ranges.count())
- ranges.push(data);
+ ranges.push(object);
}
QQmlProfiler *profiler;
private:
- QFiniteStack<Data> ranges;
+ QFiniteStack<const QV4::CompiledData::Object *> ranges;
};
#define Q_QML_OC_PROFILE(member, Code)\
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
-class QQmlObjectCreationProfiler : public QQmlVmeProfiler::Data {
+class QQmlObjectCreationProfiler {
public:
QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
@@ -291,13 +373,10 @@ public:
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>());
}
- void update(const QString &typeName, const QUrl &url, int line, int column)
+ void update(QQmlCompiledData *ref, const QV4::CompiledData::Object *obj,
+ const QString &typeName, const QUrl &url)
{
- profiler->updateCreating(typeName, url, line, column);
- m_typeName = typeName;
- m_url = url;
- m_line = line;
- m_column = column;
+ profiler->updateCreating(obj, ref, url, typeName);
}
private:
@@ -310,8 +389,7 @@ public:
profiler(parent->profiler)
{
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler, {
- QQmlVmeProfiler::Data data = parent->pop();
- profiler->startCreating(data.m_typeName, data.m_url, data.m_line, data.m_column);
+ profiler->startCreating(parent->pop());
});
}
@@ -326,5 +404,6 @@ private:
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
+Q_DECLARE_METATYPE(QQmlProfiler::LocationHash)
#endif // QQMLPROFILER_P_H
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index e153ca3d8b..0d875bd10f 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -112,7 +112,7 @@ when passed from C++ to QML and vice-versa:
\li QVector2D, QVector3D, QVector4D
\li \l vector2d, \l vector3d, \l vector4d
\row
- \li Enums declared with Q_ENUMS()
+ \li Enums declared with Q_ENUM() or Q_ENUMS()
\li \l enumeration
\endtable
@@ -261,6 +261,9 @@ In particular, QML currently supports:
\li \c {QList<bool>}
\li \c {QList<QString>} and \c{QStringList}
\li \c {QList<QUrl>}
+ \li \c {QVector<int>}
+ \li \c {QVector<qreal>}
+ \li \c {QVector<bool>}
\endlist
These sequence types are implemented directly in terms of the underlying C++
@@ -303,6 +306,9 @@ The default-constructed values for each sequence type are as follows:
\row \li QList<bool> \li boolean value \c {false}
\row \li QList<QString> and QStringList \li empty QString
\row \li QList<QUrl> \li empty QUrl
+\row \li QVector<int> \li integer value 0
+\row \li QVector<qreal> \li real value 0.0
+\row \li QVector<bool> \li boolean value \c {false}
\endtable
If you wish to remove elements from a sequence rather than simply replace
@@ -341,7 +347,7 @@ properties:
\section1 Enumeration Types
To use a custom enumeration as a data type, its class must be registered and
-the enumeration must also be declared with Q_ENUMS() to register it with Qt's
+the enumeration must also be declared with Q_ENUM() to register it with Qt's
meta object system. For example, the \c Message class below has a \c Status
enum:
@@ -349,7 +355,6 @@ enum:
class Message : public QObject
{
Q_OBJECT
- Q_ENUMS(Status)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
public:
enum Status {
@@ -357,6 +362,7 @@ enum:
Loading,
Error
};
+ Q_ENUM(Status)
Status status() const;
signals:
void statusChanged();
diff --git a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
index d862b50fcb..c0cfc3e1aa 100644
--- a/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
+++ b/src/qml/doc/src/cppintegration/extending-tutorial.qdoc
@@ -386,12 +386,26 @@ directory.
\quotefile tutorials/extending-qml/chapter6-plugins/import/import.pro
-In this example, the \c Charts directory is located at the same level as the application
-that uses our new import module. This way, the QML engine will find our module
-as the default search path for QML imports includes the directory of the application
-executable. Alternatively, we could control what directories the \l {QML Import Path}
-{QML import path} contains, useful if there are multiple QML applications using the
-same QML imports.
+When building this example on Windows or Linux, the \c Charts directory will be
+located at the same level as the application that uses our new import module.
+This way, the QML engine will find our module as the default search path for QML
+imports includes the directory of the application executable. On OS X, the
+plugin binary is copied to \c Contents/PlugIns in the the application bundle;
+this path is set in \l {tutorials/extending-qml/chapter6-plugins/app.pro}
+{chapter6-plugins/app.pro}:
+
+\quotefromfile tutorials/extending-qml/chapter6-plugins/app.pro
+\skipto osx
+\printuntil }
+
+To account for this, we also need to add this location as a
+\l {QML Import Path}{QML import path} in \c main.cpp:
+
+\snippet tutorials/extending-qml/chapter6-plugins/main.cpp 0
+\dots
+
+Defining custom import paths is useful also when there are multiple
+applications using the same QML imports.
The \c .pro file also contains additional magic to ensure that the
\l {Module Definition qmldir Files}{module definition qmldir file} is always copied
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index 04d769e4dc..04d0d0ed2e 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -508,7 +508,7 @@ built-in \l {Rectangle::color} property:
Any object that use this type and refer to its \c color property will be
referring to the alias rather than the ordinary \l {Rectangle::color} property.
-Internally, however, the red can correctly set its \c color
+Internally, however, the rectangle can correctly set its \c color
property and refer to the actual defined property rather than the alias.
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 80a18a7f5b..54b17c4f07 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -134,7 +134,8 @@ public:
static int ebxIdx = -1;
if (ebxIdx == -1) {
int calleeSaves = 0;
- foreach (const RegisterInfo &info, getRegisterInfo()) {
+ const auto infos = getRegisterInfo();
+ for (const RegisterInfo &info : infos) {
if (info.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
ebxIdx = calleeSaves;
break;
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 424d5548a1..257dd357fd 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -247,6 +247,11 @@ Q_DECLARE_METATYPE(QList<int>)
QT_BEGIN_NAMESPACE
+static void checkForApplicationInstance()
+{
+ if (!QCoreApplication::instance())
+ qFatal("QJSEngine: Must construct a QCoreApplication before a QJSEngine");
+}
/*!
Constructs a QJSEngine object.
@@ -270,6 +275,8 @@ QJSEngine::QJSEngine(QObject *parent)
: QObject(*new QJSEnginePrivate, parent)
, d(new QV8Engine(this))
{
+ checkForApplicationInstance();
+
QJSEnginePrivate::addToDebugServer(this);
}
@@ -280,6 +287,7 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
: QObject(dd, parent)
, d(new QV8Engine(this))
{
+ checkForApplicationInstance();
}
/*!
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 73aa7047b8..4c4639c94f 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -287,7 +287,13 @@ void SimpleArrayData::push_front(Object *o, const Value *values, uint n)
Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
dd = o->d()->arrayData.cast<Heap::SimpleArrayData>();
}
- dd->offset = (dd->offset - n) % dd->alloc;
+ if (n <= dd->offset) {
+ dd->offset -= n; // there is enough space left in front
+ } else {
+ // we need to wrap around, so:
+ dd->offset = dd->alloc - // start at the back, but subtract:
+ (n - dd->offset); // the number of items we can put in the free space at the start of the allocated array
+ }
dd->len += n;
for (uint i = 0; i < n; ++i)
dd->data(i) = values[i].asReturnedValue();
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 5783e8fa2b..0cd72d6811 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -338,7 +338,7 @@ static inline double currentTime()
static inline double TimeClip(double t)
{
- if (! qIsFinite(t) || fabs(t) > 8.64e15)
+ if (! qt_is_finite(t) || fabs(t) > 8.64e15)
return qt_qnan();
return Primitive::toInteger(t);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 9f1e6b613b..2db04bbfda 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -160,13 +160,9 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
if (i > 0)
trace += QLatin1Char('\n');
const StackFrame &frame = This->d()->stackTrace[i];
- trace += frame.function;
- trace += QLatin1Char('@');
- trace += frame.source;
- if (frame.line >= 0) {
- trace += QLatin1Char(':');
- trace += QString::number(frame.line);
- }
+ trace += frame.function + QLatin1Char('@') + frame.source;
+ if (frame.line >= 0)
+ trace += QLatin1Char(':') + QString::number(frame.line);
}
This->d()->stack = ctx->d()->engine->newString(trace);
}
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index c8d66b1254..626648067f 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -131,7 +131,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const
return 0;
Q_ASSERT(d->entries);
- uint hash = String::createHashValue(str.constData(), str.length());
+ uint hash = String::createHashValue(str.constData(), str.length(), Q_NULLPTR);
uint idx = hash % d->alloc;
while (1) {
if (!d->entries[idx].identifier)
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index 5adb17b4ea..3def6defbf 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -118,7 +118,8 @@ void IdentifierTable::addEntry(Heap::String *str)
Heap::String *IdentifierTable::insertString(const QString &s)
{
- uint hash = String::createHashValue(s.constData(), s.length());
+ uint subtype;
+ uint hash = String::createHashValue(s.constData(), s.length(), &subtype);
uint idx = hash % alloc;
while (Heap::String *e = entries[idx]) {
if (e->stringHash == hash && e->toQString() == s)
@@ -128,6 +129,8 @@ Heap::String *IdentifierTable::insertString(const QString &s)
}
Heap::String *str = engine->newString(s);
+ str->stringHash = hash;
+ str->subtype = subtype;
addEntry(str);
return str;
}
@@ -178,7 +181,8 @@ Identifier *IdentifierTable::identifier(const QString &s)
Identifier *IdentifierTable::identifier(const char *s, int len)
{
- uint hash = String::createHashValue(s, len);
+ uint subtype;
+ uint hash = String::createHashValue(s, len, &subtype);
if (hash == UINT_MAX)
return identifier(QString::fromUtf8(s, len));
@@ -192,6 +196,8 @@ Identifier *IdentifierTable::identifier(const char *s, int len)
}
Heap::String *str = engine->newString(QString::fromLatin1(s, len));
+ str->stringHash = hash;
+ str->subtype = subtype;
addEntry(str);
return str->identifier;
}
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index a5405dad0d..9660a5e76d 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -429,11 +429,13 @@ InternalClass *InternalClass::propertiesFrozen() const
void InternalClass::destroy()
{
- QList<InternalClass *> destroyStack;
- destroyStack.append(this);
+ std::vector<InternalClass *> destroyStack;
+ destroyStack.reserve(64);
+ destroyStack.push_back(this);
- while (!destroyStack.isEmpty()) {
- InternalClass *next = destroyStack.takeLast();
+ while (!destroyStack.empty()) {
+ InternalClass *next = destroyStack.back();
+ destroyStack.pop_back();
if (!next->engine)
continue;
next->engine = 0;
@@ -441,13 +443,13 @@ void InternalClass::destroy()
next->nameMap.~SharedInternalClassData<Identifier *>();
next->propertyData.~SharedInternalClassData<PropertyAttributes>();
if (next->m_sealed)
- destroyStack.append(next->m_sealed);
+ destroyStack.push_back(next->m_sealed);
if (next->m_frozen)
- destroyStack.append(next->m_frozen);
+ destroyStack.push_back(next->m_frozen);
for (size_t i = 0; i < next->transitions.size(); ++i) {
Q_ASSERT(next->transitions.at(i).lookup);
- destroyStack.append(next->transitions.at(i).lookup);
+ destroyStack.push_back(next->transitions.at(i).lookup);
}
next->transitions.~vector<Transition>();
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index a211d46153..0ae7c33dea 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -590,8 +590,7 @@ bool JsonParser::parseString(QString *string)
return false;
}
if (QChar::requiresSurrogates(ch)) {
- *string += QChar(QChar::highSurrogate(ch));
- *string += QChar(QChar::lowSurrogate(ch));
+ *string += QChar(QChar::highSurrogate(ch)) + QChar(QChar::lowSurrogate(ch));
} else {
*string += QChar(ch);
}
@@ -672,8 +671,8 @@ static QString quote(const QString &str)
default:
if (c.unicode() <= 0x1f) {
product += QStringLiteral("\\u00");
- product += c.unicode() > 0xf ? QLatin1Char('1') : QLatin1Char('0');
- product += QLatin1Char("0123456789abcdef"[c.unicode() & 0xf]);
+ product += (c.unicode() > 0xf ? QLatin1Char('1') : QLatin1Char('0')) +
+ QLatin1Char("0123456789abcdef"[c.unicode() & 0xf]);
} else {
product += c;
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 0727f35edd..ff3208485e 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -753,9 +753,8 @@ void Object::internalPut(String *name, const Value &value)
reject:
if (engine()->current->strictMode) {
- QString message = QStringLiteral("Cannot assign to read-only property \"");
- message += name->toQString();
- message += QLatin1Char('\"');
+ QString message = QStringLiteral("Cannot assign to read-only property \"") +
+ name->toQString() + QLatin1Char('\"');
engine()->throwTypeError(message);
}
}
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index c0a4129d9d..72475c5416 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -46,26 +46,32 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Profiling {
-FunctionCallProperties FunctionCall::resolve() const
+FunctionLocation FunctionCall::resolveLocation() const
+{
+ return FunctionLocation(m_function->name()->toQString(),
+ m_function->compilationUnit->fileName(),
+ m_function->compiledFunction->location.line,
+ m_function->compiledFunction->location.column);
+}
+
+FunctionCallProperties FunctionCall::properties() const
{
FunctionCallProperties props = {
m_start,
m_end,
- m_function->name()->toQString(),
- m_function->compilationUnit->fileName(),
- m_function->compiledFunction->location.line,
- m_function->compiledFunction->location.column
+ reinterpret_cast<quintptr>(m_function)
};
return props;
}
-
Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(engine)
{
- static int meta = qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >();
- static int meta2 = qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >();
- Q_UNUSED(meta);
- Q_UNUSED(meta2);
+ static const int metatypes[] = {
+ qRegisterMetaType<QVector<QV4::Profiling::FunctionCallProperties> >(),
+ qRegisterMetaType<QVector<QV4::Profiling::MemoryAllocationProperties> >(),
+ qRegisterMetaType<FunctionLocationHash>()
+ };
+ Q_UNUSED(metatypes);
m_timer.start();
}
@@ -85,13 +91,18 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2)
void Profiler::reportData()
{
std::sort(m_data.begin(), m_data.end());
- QVector<FunctionCallProperties> resolved;
- resolved.reserve(m_data.size());
+ QVector<FunctionCallProperties> properties;
+ FunctionLocationHash locations;
+ properties.reserve(m_data.size());
- foreach (const FunctionCall &call, m_data)
- resolved.append(call.resolve());
+ foreach (const FunctionCall &call, m_data) {
+ properties.append(call.properties());
+ FunctionLocation &location = locations[properties.constLast().id];
+ if (!location.isValid())
+ location = call.resolveLocation();
+ }
- emit dataReady(resolved, m_memory_data);
+ emit dataReady(locations, properties, m_memory_data);
m_data.clear();
m_memory_data.clear();
}
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index 25ef8223bf..bb128b7cf3 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -77,12 +77,28 @@ enum MemoryType {
struct FunctionCallProperties {
qint64 start;
qint64 end;
+ quintptr id;
+};
+
+struct FunctionLocation {
+ FunctionLocation(const QString &name = QString(), const QString &file = QString(),
+ int line = -1, int column = -1) :
+ name(name), file(file), line(line), column(column)
+ {}
+
+ bool isValid()
+ {
+ return !name.isEmpty();
+ }
+
QString name;
QString file;
int line;
int column;
};
+typedef QHash<quintptr, QV4::Profiling::FunctionLocation> FunctionLocationHash;
+
struct MemoryAllocationProperties {
qint64 timestamp;
qint64 size;
@@ -118,7 +134,8 @@ public:
return *this;
}
- FunctionCallProperties resolve() const;
+ FunctionLocation resolveLocation() const;
+ FunctionCallProperties properties() const;
private:
friend bool operator<(const FunctionCall &call1, const FunctionCall &call2);
@@ -173,7 +190,8 @@ public slots:
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
- void dataReady(const QVector<QV4::Profiling::FunctionCallProperties> &,
+ void dataReady(const QV4::Profiling::FunctionLocationHash &,
+ const QVector<QV4::Profiling::FunctionCallProperties> &,
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private:
@@ -218,8 +236,10 @@ public:
Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionLocation, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index fca218d9d0..35fcd00eb7 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1285,6 +1285,8 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
return 10;
} else if (conversionType == QMetaType::QJsonObject) {
return 5;
+ } else if (conversionType == qMetaTypeId<QJSValue>()) {
+ return 0;
} else {
return 10;
}
@@ -1768,17 +1770,13 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) co
QString result;
if (const QMetaObject *metaObject = d()->metaObject()) {
- result += QString::fromUtf8(metaObject->className());
- result += QLatin1String("(0x");
- result += QString::number((quintptr)d()->object.data(),16);
+ result += QString::fromUtf8(metaObject->className()) +
+ QLatin1String("(0x") + QString::number((quintptr)d()->object.data(),16);
if (d()->object) {
QString objectName = d()->object->objectName();
- if (!objectName.isEmpty()) {
- result += QLatin1String(", \"");
- result += objectName;
- result += QLatin1Char('\"');
- }
+ if (!objectName.isEmpty())
+ result += QLatin1String(", \"") + objectName + QLatin1Char('\"');
}
result += QLatin1Char(')');
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 71e2bd1a06..05752dc6dc 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -185,8 +185,7 @@ QRegExp RegExpObject::toQRegExp() const
QString RegExpObject::toString() const
{
- QString result = QLatin1Char('/') + source();
- result += QLatin1Char('/');
+ QString result = QLatin1Char('/') + source() + QLatin1Char('/');
if (global())
result += QLatin1Char('g');
if (value()->ignoreCase)
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index a974909798..b7543692d5 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -984,10 +984,9 @@ ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine
Scope scope(engine);
ScopedFunctionObject o(scope, method_getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex));
if (!o) {
- QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ QString error = QStringLiteral("Property '%1' of scope object is not a function").arg(propertyIndex);
return engine->throwTypeError(error);
}
-
return o->call(callData);
}
@@ -996,7 +995,7 @@ ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engi
Scope scope(engine);
ScopedFunctionObject o(scope, method_getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex));
if (!o) {
- QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow());
+ QString error = QStringLiteral("Property '%1' of context object is not a function").arg(propertyIndex);
return engine->throwTypeError(error);
}
@@ -1623,6 +1622,351 @@ void Runtime::method_convertThisToObject(ExecutionEngine *engine)
}
}
+ReturnedValue Runtime::method_uPlus(const Value &value)
+{
+ TRACE1(value);
+
+ if (value.isNumber())
+ return value.asReturnedValue();
+ if (value.integerCompatible())
+ return Encode(value.int_32());
+
+ double n = value.toNumberImpl();
+ return Encode(n);
+}
+
+ReturnedValue Runtime::method_uMinus(const Value &value)
+{
+ TRACE1(value);
+
+ // +0 != -0, so we need to convert to double when negating 0
+ if (value.isInteger() && value.integerValue())
+ return Encode(-value.integerValue());
+ else {
+ double n = RuntimeHelpers::toNumber(value);
+ return Encode(-n);
+ }
+}
+
+ReturnedValue Runtime::method_complement(const Value &value)
+{
+ TRACE1(value);
+
+ int n = value.toInt32();
+ return Encode((int)~n);
+}
+
+ReturnedValue Runtime::method_uNot(const Value &value)
+{
+ TRACE1(value);
+
+ bool b = value.toBoolean();
+ return Encode(!b);
+}
+
+// binary operators
+ReturnedValue Runtime::method_bitOr(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode(lval | rval);
+}
+
+ReturnedValue Runtime::method_bitXor(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode(lval ^ rval);
+}
+
+ReturnedValue Runtime::method_bitAnd(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32();
+ return Encode(lval & rval);
+}
+
+#ifndef V4_BOOTSTRAP
+ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ if (Q_LIKELY(left.isInteger() && right.isInteger()))
+ return add_int32(left.integerValue(), right.integerValue());
+ if (left.isNumber() && right.isNumber())
+ return Primitive::fromDouble(left.asDouble() + right.asDouble()).asReturnedValue();
+
+ return RuntimeHelpers::addHelper(engine, left, right);
+}
+#endif // V4_BOOTSTRAP
+
+ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ if (Q_LIKELY(left.isInteger() && right.isInteger()))
+ return sub_int32(left.integerValue(), right.integerValue());
+
+ double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
+ double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
+
+ return Primitive::fromDouble(lval - rval).asReturnedValue();
+}
+
+ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ if (Q_LIKELY(left.isInteger() && right.isInteger()))
+ return mul_int32(left.integerValue(), right.integerValue());
+
+ double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
+ double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
+
+ return Primitive::fromDouble(lval * rval).asReturnedValue();
+}
+
+ReturnedValue Runtime::method_div(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ if (Value::integerCompatible(left, right)) {
+ int lval = left.integerValue();
+ int rval = right.integerValue();
+ if (rval != 0 && (lval % rval == 0))
+ return Encode(int(lval / rval));
+ else
+ return Encode(double(lval) / rval);
+ }
+
+ double lval = left.toNumber();
+ double rval = right.toNumber();
+ return Primitive::fromDouble(lval / rval).asReturnedValue();
+}
+
+ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ if (Value::integerCompatible(left, right) && right.integerValue() != 0) {
+ int intRes = left.integerValue() % right.integerValue();
+ if (intRes != 0 || left.integerValue() >= 0)
+ return Encode(intRes);
+ }
+
+ double lval = RuntimeHelpers::toNumber(left);
+ double rval = RuntimeHelpers::toNumber(right);
+#ifdef fmod
+# undef fmod
+#endif
+ return Primitive::fromDouble(std::fmod(lval, rval)).asReturnedValue();
+}
+
+ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ int rval = right.toInt32() & 0x1f;
+ return Encode((int)(lval << rval));
+}
+
+ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ int lval = left.toInt32();
+ unsigned rval = right.toUInt32() & 0x1f;
+ return Encode((int)(lval >> rval));
+}
+
+ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ unsigned lval = left.toUInt32();
+ unsigned rval = right.toUInt32() & 0x1f;
+ uint res = lval >> rval;
+
+ return Encode(res);
+}
+
+ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = method_compareGreaterThan(left, right);
+ return Encode(r);
+}
+
+ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = method_compareLessThan(left, right);
+ return Encode(r);
+}
+
+ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = method_compareGreaterEqual(left, right);
+ return Encode(r);
+}
+
+ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = method_compareLessEqual(left, right);
+ return Encode(r);
+}
+
+Bool Runtime::method_compareEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ if (left.rawValue() == right.rawValue())
+ // NaN != NaN
+ return !left.isNaN();
+
+ if (left.type() == right.type()) {
+ if (!left.isManaged())
+ return false;
+ if (left.isString() == right.isString())
+ return left.cast<Managed>()->isEqualTo(right.cast<Managed>());
+ }
+
+ return RuntimeHelpers::equalHelper(left, right);
+}
+
+ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = method_compareEqual(left, right);
+ return Encode(r);
+}
+
+ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = !method_compareEqual(left, right);
+ return Encode(r);
+}
+
+ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = RuntimeHelpers::strictEqual(left, right);
+ return Encode(r);
+}
+
+ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ bool r = ! RuntimeHelpers::strictEqual(left, right);
+ return Encode(r);
+}
+
+Bool Runtime::method_compareNotEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ return !Runtime::method_compareEqual(left, right);
+}
+
+Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ return RuntimeHelpers::strictEqual(left, right);
+}
+
+Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right)
+{
+ TRACE2(left, right);
+
+ return ! RuntimeHelpers::strictEqual(left, right);
+}
+
+Bool Runtime::method_toBoolean(const Value &value)
+{
+ return value.toBoolean();
+}
+
+ReturnedValue Runtime::method_accessQmlScopeObjectQRealProperty(const Value &context,
+ QQmlAccessors *accessors)
+{
+#ifndef V4_BOOTSTRAP
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ qreal rv = 0;
+ accessors->read(c.d()->qml->scopeObject, &rv);
+ return QV4::Encode(rv);
+#else
+ Q_UNUSED(context);
+ Q_UNUSED(accessors);
+ return QV4::Encode::undefined();
+#endif
+}
+
+ReturnedValue Runtime::method_accessQmlScopeObjectIntProperty(const Value &context,
+ QQmlAccessors *accessors)
+{
+#ifndef V4_BOOTSTRAP
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ int rv = 0;
+ accessors->read(c.d()->qml->scopeObject, &rv);
+ return QV4::Encode(rv);
+#else
+ Q_UNUSED(context);
+ Q_UNUSED(accessors);
+ return QV4::Encode::undefined();
+#endif
+}
+
+ReturnedValue Runtime::method_accessQmlScopeObjectBoolProperty(const Value &context,
+ QQmlAccessors *accessors)
+{
+#ifndef V4_BOOTSTRAP
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ bool rv = false;
+ accessors->read(c.d()->qml->scopeObject, &rv);
+ return QV4::Encode(rv);
+#else
+ Q_UNUSED(context);
+ Q_UNUSED(accessors);
+ return QV4::Encode::undefined();
+#endif
+}
+
+ReturnedValue Runtime::method_accessQmlScopeObjectQStringProperty(ExecutionEngine *engine,
+ const Value &context,
+ QQmlAccessors *accessors)
+{
+#ifndef V4_BOOTSTRAP
+ const QmlContext &c = static_cast<const QmlContext &>(context);
+ QString rv;
+ accessors->read(c.d()->qml->scopeObject, &rv);
+ return QV4::Encode(engine->newString(rv));
+#else
+ Q_UNUSED(engine);
+ Q_UNUSED(context);
+ Q_UNUSED(accessors);
+ return QV4::Encode::undefined();
+#endif
+}
+
#endif // V4_BOOTSTRAP
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index ffae55995f..807fbe2f0e 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -140,349 +140,6 @@ inline double RuntimeHelpers::toNumber(const Value &value)
{
return value.toNumber();
}
-
-inline ReturnedValue Runtime::method_uPlus(const Value &value)
-{
- TRACE1(value);
-
- if (value.isNumber())
- return value.asReturnedValue();
- if (value.integerCompatible())
- return Encode(value.int_32());
-
- double n = value.toNumberImpl();
- return Encode(n);
-}
-
-inline ReturnedValue Runtime::method_uMinus(const Value &value)
-{
- TRACE1(value);
-
- // +0 != -0, so we need to convert to double when negating 0
- if (value.isInteger() && value.integerValue())
- return Encode(-value.integerValue());
- else {
- double n = RuntimeHelpers::toNumber(value);
- return Encode(-n);
- }
-}
-
-inline ReturnedValue Runtime::method_complement(const Value &value)
-{
- TRACE1(value);
-
- int n = value.toInt32();
- return Encode((int)~n);
-}
-
-inline ReturnedValue Runtime::method_uNot(const Value &value)
-{
- TRACE1(value);
-
- bool b = value.toBoolean();
- return Encode(!b);
-}
-
-// binary operators
-inline ReturnedValue Runtime::method_bitOr(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- int lval = left.toInt32();
- int rval = right.toInt32();
- return Encode(lval | rval);
-}
-
-inline ReturnedValue Runtime::method_bitXor(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- int lval = left.toInt32();
- int rval = right.toInt32();
- return Encode(lval ^ rval);
-}
-
-inline ReturnedValue Runtime::method_bitAnd(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- int lval = left.toInt32();
- int rval = right.toInt32();
- return Encode(lval & rval);
-}
-
-#ifndef V4_BOOTSTRAP
-inline ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- if (Q_LIKELY(left.isInteger() && right.isInteger()))
- return add_int32(left.integerValue(), right.integerValue());
- if (left.isNumber() && right.isNumber())
- return Primitive::fromDouble(left.asDouble() + right.asDouble()).asReturnedValue();
-
- return RuntimeHelpers::addHelper(engine, left, right);
-}
-#endif // V4_BOOTSTRAP
-
-inline ReturnedValue Runtime::method_sub(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- if (Q_LIKELY(left.isInteger() && right.isInteger()))
- return sub_int32(left.integerValue(), right.integerValue());
-
- double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
- double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
-
- return Primitive::fromDouble(lval - rval).asReturnedValue();
-}
-
-inline ReturnedValue Runtime::method_mul(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- if (Q_LIKELY(left.isInteger() && right.isInteger()))
- return mul_int32(left.integerValue(), right.integerValue());
-
- double lval = left.isNumber() ? left.asDouble() : left.toNumberImpl();
- double rval = right.isNumber() ? right.asDouble() : right.toNumberImpl();
-
- return Primitive::fromDouble(lval * rval).asReturnedValue();
-}
-
-inline ReturnedValue Runtime::method_div(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- if (Value::integerCompatible(left, right)) {
- int lval = left.integerValue();
- int rval = right.integerValue();
- if (rval != 0 && (lval % rval == 0))
- return Encode(int(lval / rval));
- else
- return Encode(double(lval) / rval);
- }
-
- double lval = left.toNumber();
- double rval = right.toNumber();
- return Primitive::fromDouble(lval / rval).asReturnedValue();
-}
-
-inline ReturnedValue Runtime::method_mod(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- if (Value::integerCompatible(left, right) && right.integerValue() != 0) {
- int intRes = left.integerValue() % right.integerValue();
- if (intRes != 0 || left.integerValue() >= 0)
- return Encode(intRes);
- }
-
- double lval = RuntimeHelpers::toNumber(left);
- double rval = RuntimeHelpers::toNumber(right);
- return Primitive::fromDouble(std::fmod(lval, rval)).asReturnedValue();
-}
-
-inline ReturnedValue Runtime::method_shl(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- int lval = left.toInt32();
- int rval = right.toInt32() & 0x1f;
- return Encode((int)(lval << rval));
-}
-
-inline ReturnedValue Runtime::method_shr(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- int lval = left.toInt32();
- unsigned rval = right.toUInt32() & 0x1f;
- return Encode((int)(lval >> rval));
-}
-
-inline ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- unsigned lval = left.toUInt32();
- unsigned rval = right.toUInt32() & 0x1f;
- uint res = lval >> rval;
-
- return Encode(res);
-}
-
-inline ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = method_compareGreaterThan(left, right);
- return Encode(r);
-}
-
-inline ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = method_compareLessThan(left, right);
- return Encode(r);
-}
-
-inline ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = method_compareGreaterEqual(left, right);
- return Encode(r);
-}
-
-inline ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = method_compareLessEqual(left, right);
- return Encode(r);
-}
-
-inline Bool Runtime::method_compareEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- if (left.rawValue() == right.rawValue())
- // NaN != NaN
- return !left.isNaN();
-
- if (left.type() == right.type()) {
- if (!left.isManaged())
- return false;
- if (left.isString() == right.isString())
- return left.cast<Managed>()->isEqualTo(right.cast<Managed>());
- }
-
- return RuntimeHelpers::equalHelper(left, right);
-}
-
-inline ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = method_compareEqual(left, right);
- return Encode(r);
-}
-
-inline ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = !method_compareEqual(left, right);
- return Encode(r);
-}
-
-inline ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = RuntimeHelpers::strictEqual(left, right);
- return Encode(r);
-}
-
-inline ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- bool r = ! RuntimeHelpers::strictEqual(left, right);
- return Encode(r);
-}
-
-inline Bool Runtime::method_compareNotEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- return !Runtime::method_compareEqual(left, right);
-}
-
-inline Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- return RuntimeHelpers::strictEqual(left, right);
-}
-
-inline Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right)
-{
- TRACE2(left, right);
-
- return ! RuntimeHelpers::strictEqual(left, right);
-}
-
-inline Bool Runtime::method_toBoolean(const Value &value)
-{
- return value.toBoolean();
-}
-
-inline ReturnedValue Runtime::method_accessQmlScopeObjectQRealProperty(const Value &context,
- QQmlAccessors *accessors)
-{
-#ifndef V4_BOOTSTRAP
- const QmlContext &c = static_cast<const QmlContext &>(context);
- qreal rv = 0;
- accessors->read(c.d()->qml->scopeObject, &rv);
- return QV4::Encode(rv);
-#else
- Q_UNUSED(context);
- Q_UNUSED(accessors);
- return QV4::Encode::undefined();
-#endif
-}
-
-inline ReturnedValue Runtime::method_accessQmlScopeObjectIntProperty(const Value &context,
- QQmlAccessors *accessors)
-{
-#ifndef V4_BOOTSTRAP
- const QmlContext &c = static_cast<const QmlContext &>(context);
- int rv = 0;
- accessors->read(c.d()->qml->scopeObject, &rv);
- return QV4::Encode(rv);
-#else
- Q_UNUSED(context);
- Q_UNUSED(accessors);
- return QV4::Encode::undefined();
-#endif
-}
-
-inline ReturnedValue Runtime::method_accessQmlScopeObjectBoolProperty(const Value &context,
- QQmlAccessors *accessors)
-{
-#ifndef V4_BOOTSTRAP
- const QmlContext &c = static_cast<const QmlContext &>(context);
- bool rv = false;
- accessors->read(c.d()->qml->scopeObject, &rv);
- return QV4::Encode(rv);
-#else
- Q_UNUSED(context);
- Q_UNUSED(accessors);
- return QV4::Encode::undefined();
-#endif
-}
-
-inline ReturnedValue Runtime::method_accessQmlScopeObjectQStringProperty(ExecutionEngine *engine,
- const Value &context,
- QQmlAccessors *accessors)
-{
-#ifndef V4_BOOTSTRAP
- const QmlContext &c = static_cast<const QmlContext &>(context);
- QString rv;
- accessors->read(c.d()->qml->scopeObject, &rv);
- return QV4::Encode(engine->newString(rv));
-#else
- Q_UNUSED(engine);
- Q_UNUSED(context);
- Q_UNUSED(accessors);
- return QV4::Encode::undefined();
-#endif
-}
-
} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index b97310c5b9..fa2409a85c 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -75,6 +75,9 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
// F(elementType, elementTypeName, sequenceType, defaultValue)
#define FOREACH_QML_SEQUENCE_TYPE(F) \
+ F(int, IntVector, QVector<int>, 0) \
+ F(qreal, RealVector, QVector<qreal>, 0.0) \
+ F(bool, BoolVector, QVector<bool>, false) \
F(int, Int, QList<int>, 0) \
F(qreal, Real, QList<qreal>, 0.0) \
F(bool, Bool, QList<bool>, false) \
@@ -578,6 +581,15 @@ Heap::QQmlSequence<Container>::QQmlSequence(QObject *object, int propertyIndex)
namespace QV4 {
+typedef QQmlSequence<QVector<int> > QQmlIntVectorList;
+template<>
+DEFINE_OBJECT_VTABLE(QQmlIntVectorList);
+typedef QQmlSequence<QVector<qreal> > QQmlRealVectorList;
+template<>
+DEFINE_OBJECT_VTABLE(QQmlRealVectorList);
+typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList;
+template<>
+DEFINE_OBJECT_VTABLE(QQmlBoolVectorList);
typedef QQmlSequence<QStringList> QQmlQStringList;
template<>
DEFINE_OBJECT_VTABLE(QQmlQStringList);
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index abef885249..7c965ce441 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -46,12 +46,19 @@
#include "qv4stringobject_p.h"
#endif
#include <QtCore/QHash>
+#include <QtCore/private/qnumeric_p.h>
using namespace QV4;
-static uint toArrayIndex(const QChar *ch, const QChar *end)
+static inline uint toUInt(const QChar *ch) { return ch->unicode(); }
+#ifndef V4_BOOTSTRAP
+static inline uint toUInt(const char *ch) { return *ch; }
+#endif
+
+template <typename T>
+static inline uint toArrayIndex(const T *ch, const T *end)
{
- uint i = ch->unicode() - '0';
+ uint i = toUInt(ch) - '0';
if (i > 9)
return UINT_MAX;
++ch;
@@ -60,14 +67,11 @@ static uint toArrayIndex(const QChar *ch, const QChar *end)
return UINT_MAX;
while (ch < end) {
- uint x = ch->unicode() - '0';
+ uint x = toUInt(ch) - '0';
if (x > 9)
return UINT_MAX;
- uint n = i*10 + x;
- if (n < i)
- // overflow
+ if (mul_overflow(i, uint(10), &i) || add_overflow(i, x, &i))
return UINT_MAX;
- i = n;
++ch;
}
return i;
@@ -75,30 +79,26 @@ static uint toArrayIndex(const QChar *ch, const QChar *end)
#ifndef V4_BOOTSTRAP
-static uint toArrayIndex(const char *ch, const char *end)
+template <typename T>
+static inline uint calculateHashValue(const T *ch, const T* end, uint *subtype)
{
- uint i = *ch - '0';
- if (i > 9)
- return UINT_MAX;
- ++ch;
- // reject "01", "001", ...
- if (i == 0 && ch != end)
- return UINT_MAX;
+ // array indices get their number as hash value
+ uint h = ::toArrayIndex(ch, end);
+ if (h != UINT_MAX) {
+ if (subtype)
+ *subtype = Heap::String::StringType_ArrayIndex;
+ return h;
+ }
while (ch < end) {
- uint x = *ch - '0';
- if (x > 9)
- return UINT_MAX;
- uint n = i*10 + x;
- if (n < i)
- // overflow
- return UINT_MAX;
- i = n;
+ h = 31 * h + toUInt(ch);
++ch;
}
- return i;
-}
+ if (subtype)
+ *subtype = Heap::String::StringType_Regular;
+ return h;
+}
DEFINE_MANAGED_VTABLE(String);
@@ -198,31 +198,6 @@ void Heap::String::simplifyString() const
mm->growUnmanagedHeapSizeUsage(size_t(text->size) * sizeof(QChar));
}
-void Heap::String::createHashValue() const
-{
- if (largestSubLength)
- simplifyString();
- Q_ASSERT(!largestSubLength);
- const QChar *ch = reinterpret_cast<const QChar *>(text->data());
- const QChar *end = ch + text->size;
-
- // array indices get their number as hash value
- stringHash = ::toArrayIndex(ch, end);
- if (stringHash != UINT_MAX) {
- subtype = Heap::String::StringType_ArrayIndex;
- return;
- }
-
- uint h = 0xffffffff;
- while (ch < end) {
- h = 31 * h + ch->unicode();
- ++ch;
- }
-
- stringHash = h;
- subtype = Heap::String::StringType_Regular;
-}
-
void Heap::String::append(const String *data, QChar *ch)
{
std::vector<const String *> worklist;
@@ -243,45 +218,26 @@ void Heap::String::append(const String *data, QChar *ch)
}
}
+void Heap::String::createHashValue() const
+{
+ if (largestSubLength)
+ simplifyString();
+ Q_ASSERT(!largestSubLength);
+ const QChar *ch = reinterpret_cast<const QChar *>(text->data());
+ const QChar *end = ch + text->size;
+ stringHash = calculateHashValue(ch, end, &subtype);
+}
-
-
-uint String::createHashValue(const QChar *ch, int length)
+uint String::createHashValue(const QChar *ch, int length, uint *subtype)
{
const QChar *end = ch + length;
-
- // array indices get their number as hash value
- uint stringHash = ::toArrayIndex(ch, end);
- if (stringHash != UINT_MAX)
- return stringHash;
-
- uint h = 0xffffffff;
- while (ch < end) {
- h = 31 * h + ch->unicode();
- ++ch;
- }
-
- return h;
+ return calculateHashValue(ch, end, subtype);
}
-uint String::createHashValue(const char *ch, int length)
+uint String::createHashValue(const char *ch, int length, uint *subtype)
{
const char *end = ch + length;
-
- // array indices get their number as hash value
- uint stringHash = ::toArrayIndex(ch, end);
- if (stringHash != UINT_MAX)
- return stringHash;
-
- uint h = 0xffffffff;
- while (ch < end) {
- if ((uchar)(*ch) >= 0x80)
- return UINT_MAX;
- h = 31 * h + *ch;
- ++ch;
- }
-
- return h;
+ return calculateHashValue(ch, end, subtype);
}
uint String::getLength(const Managed *m)
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 3196f49896..60e2655536 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -183,8 +183,8 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
void makeIdentifierImpl(ExecutionEngine *e) const;
- static uint createHashValue(const QChar *ch, int length);
- static uint createHashValue(const char *ch, int length);
+ static uint createHashValue(const QChar *ch, int length, uint *subtype);
+ static uint createHashValue(const char *ch, int length, uint *subtype);
bool startsWithUpper() const {
const String::Data *l = d();
diff --git a/src/qml/parser/qqmljsparser_p.h b/src/qml/parser/qqmljsparser_p.h
index 02dbe7d323..00ffb6aca3 100644
--- a/src/qml/parser/qqmljsparser_p.h
+++ b/src/qml/parser/qqmljsparser_p.h
@@ -174,7 +174,7 @@ public:
inline DiagnosticMessage diagnosticMessage() const
{
- foreach (const DiagnosticMessage &d, diagnostic_messages) {
+ for (const DiagnosticMessage &d : diagnostic_messages) {
if (d.kind != DiagnosticMessage::Warning)
return d;
}
diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp
index 37c1003748..5c5d2a31ac 100644
--- a/src/qml/qml/ftw/qhashedstring.cpp
+++ b/src/qml/qml/ftw/qhashedstring.cpp
@@ -41,12 +41,12 @@
inline quint32 stringHash(const QChar* data, int length)
{
- return QV4::String::createHashValue(data, length);
+ return QV4::String::createHashValue(data, length, Q_NULLPTR);
}
inline quint32 stringHash(const char *data, int length)
{
- return QV4::String::createHashValue(data, length);
+ return QV4::String::createHashValue(data, length, Q_NULLPTR);
}
void QHashedString::computeHash() const
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index e8ddfecbe3..1249e1b6c8 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -168,7 +168,7 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
return;
}
- QQmlBindingProfiler prof(ep->profiler, f);
+ QQmlBindingProfiler prof(ep->profiler, this, f);
setUpdatingFlag(true);
QQmlJavaScriptExpression::DeleteWatcher watcher(this);
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 9879763c72..b03edc9020 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -56,7 +56,6 @@
#include <private/qv4value_p.h>
-#include <QtCore/qstringbuilder.h>
#include <QtCore/qdebug.h>
@@ -81,9 +80,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
// Add some leading whitespace to account for the binding's column offset.
// It's 2 off because a, we start counting at 1 and b, the '(' below is not counted.
function.fill(QChar(QChar::Space), qMax(column, (quint16)2) - 2);
- function += QStringLiteral("(function ");
- function += handlerName;
- function += QLatin1Char('(');
+ function += QStringLiteral("(function ") + handlerName + QLatin1Char('(');
if (parameterString.isEmpty()) {
QString error;
@@ -99,10 +96,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
} else
function += parameterString;
- function += QStringLiteral(") { ");
- function += expression;
- function += QStringLiteral(" })");
-
+ function += QStringLiteral(") { ") + expression + QStringLiteral(" })");
m_function.set(v4, evalFunction(context(), scopeObject(), function, fileName, line));
if (m_function.isNullOrUndefined())
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 1c43a85de3..cbe70a7077 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -89,8 +89,6 @@ public:
QQmlEngine *engine;
- QString fileName() const { return compilationUnit->fileName(); }
- QUrl url() const { return compilationUnit->url(); }
QQmlTypeNameCache *importCache;
int metaTypeId;
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 61a4b701c0..6aa3710731 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -570,7 +570,7 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QQmlCompiledData *cc, int start
d->cc = cc;
cc->addref();
d->start = start;
- d->url = cc->url();
+ d->url = cc->compilationUnit->url();
d->progress = 1.0;
}
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 440840d3c9..18bee387dd 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -293,7 +293,7 @@ inline void QQmlEnginePrivate::dereferenceScarceResources()
// if the refcount is zero, then evaluation of the "top level"
// expression must have completed. We can safely release the
// scarce resources.
- if (scarceResourcesRefCount == 0) {
+ if (Q_LIKELY(scarceResourcesRefCount == 0)) {
QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine());
if (Q_UNLIKELY(!engine->scarceResources.isEmpty())) {
cleanupScarceResources();
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index 47c85c907c..74ceeabeb4 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -43,6 +43,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qfile.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qvector.h>
#include <private/qv4errorobject_p.h>
@@ -288,11 +289,11 @@ QDebug operator<<(QDebug debug, const QQmlError &error)
stream.setCodec("UTF-8");
#endif
const QString code = stream.readAll();
- const QStringList lines = code.split(QLatin1Char('\n'));
+ const auto lines = code.splitRef(QLatin1Char('\n'));
if (lines.count() >= error.line()) {
- const QString &line = lines.at(error.line() - 1);
- debug << "\n " << qPrintable(line);
+ const QStringRef &line = lines.at(error.line() - 1);
+ debug << "\n " << line.toLocal8Bit().constData();
if(error.column() > 0) {
int column = qMax(0, error.column() - 1);
diff --git a/src/qml/qml/qqmlextensioninterface.h b/src/qml/qml/qqmlextensioninterface.h
index 73e41a3b80..ef56d5e312 100644
--- a/src/qml/qml/qqmlextensioninterface.h
+++ b/src/qml/qml/qqmlextensioninterface.h
@@ -66,7 +66,7 @@ public:
Q_DECLARE_INTERFACE(QQmlTypesExtensionInterface, "org.qt-project.Qt.QQmlTypesExtensionInterface/1.0")
-#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
+#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface/1.0"
Q_DECLARE_INTERFACE(QQmlExtensionInterface, QQmlExtensionInterface_iid)
diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp
index 7a441dd9ff..4769402855 100644
--- a/src/qml/qml/qqmlfile.cpp
+++ b/src/qml/qml/qqmlfile.cpp
@@ -605,7 +605,7 @@ QString QQmlFile::urlToLocalFileOrQrc(const QString& url)
{
if (url.startsWith(QLatin1String("qrc:"), Qt::CaseInsensitive)) {
if (url.length() > 4)
- return QLatin1Char(':') + url.mid(4);
+ return QLatin1Char(':') + url.midRef(4);
return QString();
}
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index d6c81bcc49..01f1042de4 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -85,12 +85,11 @@ QString resolveLocalUrl(const QString &url, const QString &relative)
} else if (relative.at(0) == Slash || !url.contains(Slash)) {
return relative;
} else {
- QString base(url.left(url.lastIndexOf(Slash) + 1));
-
+ const QStringRef baseRef = url.leftRef(url.lastIndexOf(Slash) + 1);
if (relative == QLatin1String("."))
- return base;
+ return baseRef.toString();
- base.append(relative);
+ QString base = baseRef + relative;
// Remove any relative directory elements in the path
int length = base.length();
@@ -192,7 +191,7 @@ void qmlClearEnginePlugins()
{
StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
QMutexLocker lock(&plugins->mutex);
- foreach (RegisteredPlugin plugin, plugins->values()) {
+ for (auto &plugin : qAsConst(*plugins)) {
QPluginLoader* loader = plugin.loader;
if (loader && !loader->unload())
qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString()));
@@ -303,7 +302,7 @@ public:
int vmaj, int vmin, QV4::CompiledData::Import::ImportType type,
QList<QQmlError> *errors, bool lowPrecedence = false);
#ifndef QT_NO_LIBRARY
- bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri,
+ bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
const QString &qmldirPath, QList<QQmlError> *errors);
#endif
};
@@ -483,20 +482,58 @@ QList<QQmlImports::ScriptReference> QQmlImports::resolvedScripts() const
return scripts;
}
+static QString joinStringRefs(const QVector<QStringRef> &refs, const QChar &sep)
+{
+ QString str;
+ for (auto it = refs.cbegin(); it != refs.cend(); ++it) {
+ if (it != refs.cbegin())
+ str += sep;
+ str += *it;
+ }
+ return str;
+}
+
/*!
- Form a complete path to a qmldir file, from a base URL, a module URI and version specification.
+ Forms complete paths to a qmldir file, from a base URL, a module URI and version specification.
+
+ For example, QtQml.Models 2.0:
+ - base/QtQml/Models.2.0/qmldir
+ - base/QtQml.2.0/Models/qmldir
+ - base/QtQml/Models.2/qmldir
+ - base/QtQml.2/Models/qmldir
+ - base/QtQml/Models/qmldir
*/
-QString QQmlImports::completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin,
- ImportVersion version)
+QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin)
{
- QString url = uri;
- url.replace(Dot, Slash);
+ const QVector<QStringRef> parts = uri.splitRef(Dot, QString::SkipEmptyParts);
+
+ QStringList qmlDirPathsPaths;
+ // fully & partially versioned parts + 1 unversioned for each base path
+ qmlDirPathsPaths.reserve(basePaths.count() * (2 * parts.count() + 1));
+
+ for (int version = FullyVersioned; version <= Unversioned; ++version) {
+ const QString ver = versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version));
+
+ for (const QString &path : basePaths) {
+ QString dir = path;
+ if (!dir.endsWith(Slash) && !dir.endsWith(Backslash))
+ dir += Slash;
- QString dir = base;
- if (!dir.endsWith(Slash) && !dir.endsWith(Backslash))
- dir += Slash;
+ // append to the end
+ qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir;
- return dir + url + versionString(vmaj, vmin, version) + Slash_qmldir;
+ if (version != Unversioned) {
+ // insert in the middle
+ for (int index = parts.count() - 2; index >= 0; --index) {
+ qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash)
+ + ver + Slash
+ + joinStringRefs(parts.mid(index + 1), Slash) + Slash_qmldir;
+ }
+ }
+ }
+ }
+
+ return qmlDirPathsPaths;
}
QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
@@ -777,11 +814,11 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS
QString u1 = import->url;
QString u2 = import2->url;
if (base) {
- QString b = *base;
+ QStringRef b(base);
int dot = b.lastIndexOf(Dot);
if (dot >= 0) {
b = b.left(dot+1);
- QString l = b.left(dot);
+ QStringRef l = b.left(dot);
if (u1.startsWith(b))
u1 = u1.mid(b.count());
else if (u1 == l)
@@ -841,14 +878,34 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr
return 0;
}
+/*!
+ Returns the list of possible versioned URI combinations. For example, if \a uri is
+ QtQml.Models, \a vmaj is 2, and \a vmin is 0, this method returns the following:
+ [QtQml.Models.2.0, QtQml.2.0.Models, QtQml.Models.2, QtQml.2.Models, QtQml.Models]
+ */
+static QStringList versionUriList(const QString &uri, int vmaj, int vmin)
+{
+ QStringList result;
+ for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
+ int index = uri.length();
+ do {
+ QString versionUri = uri;
+ versionUri.insert(index, QQmlImports::versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version)));
+ result += versionUri;
+
+ index = uri.lastIndexOf(Dot, index - 1);
+ } while (index > 0 && version != QQmlImports::Unversioned);
+ }
+ return result;
+}
#ifndef QT_NO_LIBRARY
/*!
- Get all static plugins that are QML plugins and has a meta data URI that begins with \a uri.
- Note that if e.g uri == "a", and different plugins have meta data "a", "a.2.1", "a.b.c", all
- will be added to the result. So the result needs further version matching by the caller.
+ Get all static plugins that are QML plugins and has a meta data URI that matches with one of
+ \a versionUris, which is a list of all possible versioned URI combinations - see versionUriList()
+ above.
*/
-bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri,
+bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
const QString &qmldirPath, QList<QQmlError> *errors)
{
static QVector<QStaticPlugin> plugins;
@@ -856,8 +913,8 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
// To avoid traversing all static plugins for all imports, we cut down
// the list the first time called to only contain QML plugins:
foreach (const QStaticPlugin &plugin, QPluginLoader::staticPlugins()) {
- if (qobject_cast<QQmlExtensionPlugin *>(plugin.instance()))
- plugins.append(plugin);
+ if (plugin.metaData().value(QStringLiteral("IID")).toString() == QLatin1String(QQmlExtensionInterface_iid))
+ plugins.append(plugin);
}
}
@@ -877,7 +934,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
}
// A plugin can be set up to handle multiple URIs, so go through the list:
foreach (const QJsonValue &metaTagUri, metaTagsUriList) {
- if (metaTagUri.toString().startsWith(uri)) {
+ if (versionUris.contains(metaTagUri.toString())) {
result.append(qMakePair(plugin, metaTagsUriList));
break;
}
@@ -970,14 +1027,13 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
// versioned to unversioned, we need to compare with differnt version strings. If a module
// has several plugins, they must all have the same version. Start by populating pluginPairs
// with relevant plugins to cut the list short early on:
+ const QStringList versionUris = versionUriList(uri, vmaj, vmin);
QVector<StaticPluginPair> pluginPairs;
- if (!populatePluginPairVector(pluginPairs, uri, qmldirFilePath, errors))
+ if (!populatePluginPairVector(pluginPairs, uri, versionUris, qmldirFilePath, errors))
return false;
const QString basePath = QFileInfo(qmldirPath).absoluteFilePath();
- for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned && staticPluginsFound == 0; ++version) {
- QString versionUri = uri + QQmlImports::versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version));
-
+ for (const QString &versionUri : versionUris) {
foreach (const StaticPluginPair &pair, pluginPairs) {
foreach (const QJsonValue &metaTagUri, pair.second) {
if (versionUri == metaTagUri.toString()) {
@@ -998,6 +1054,8 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
}
}
}
+ if (staticPluginsFound > 0)
+ break;
}
}
@@ -1130,32 +1188,29 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ
QStringList localImportPaths = database->importPathList(QQmlImportDatabase::Local);
// Search local import paths for a matching version
- for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
- foreach (const QString &path, localImportPaths) {
- QString qmldirPath = QQmlImports::completeQmldirPath(uri, path, vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version));
-
- QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath);
- if (!absoluteFilePath.isEmpty()) {
- QString url;
- QString absolutePath = absoluteFilePath.left(absoluteFilePath.lastIndexOf(Slash)+1);
- if (absolutePath.at(0) == Colon)
- url = QLatin1String("qrc://") + absolutePath.mid(1);
- else
- url = QUrl::fromLocalFile(absolutePath).toString();
+ const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(uri, localImportPaths, vmaj, vmin);
+ for (const QString &qmldirPath : qmlDirPaths) {
+ QString absoluteFilePath = typeLoader.absoluteFilePath(qmldirPath);
+ if (!absoluteFilePath.isEmpty()) {
+ QString url;
+ const QStringRef absolutePath = absoluteFilePath.leftRef(absoluteFilePath.lastIndexOf(Slash) + 1);
+ if (absolutePath.at(0) == Colon)
+ url = QLatin1String("qrc://") + absolutePath.mid(1);
+ else
+ url = QUrl::fromLocalFile(absolutePath.toString()).toString();
- QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
- cache->versionMajor = vmaj;
- cache->versionMinor = vmin;
- cache->qmldirFilePath = absoluteFilePath;
- cache->qmldirPathUrl = url;
- cache->next = cacheHead;
- database->qmldirCache.insert(uri, cache);
+ QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
+ cache->versionMajor = vmaj;
+ cache->versionMinor = vmin;
+ cache->qmldirFilePath = absoluteFilePath;
+ cache->qmldirPathUrl = url;
+ cache->next = cacheHead;
+ database->qmldirCache.insert(uri, cache);
- *outQmldirFilePath = absoluteFilePath;
- *outQmldirPathUrl = url;
+ *outQmldirFilePath = absoluteFilePath;
+ *outQmldirPathUrl = url;
- return true;
- }
+ return true;
}
}
@@ -1647,10 +1702,7 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
resolvedPath += Slash;
foreach (const QString &suffix, suffixes) {
- QString pluginFileName = prefix;
-
- pluginFileName += baseName;
- pluginFileName += suffix;
+ QString pluginFileName = prefix + baseName + suffix;
QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + pluginFileName);
if (!absolutePath.isEmpty())
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 628564ae34..0e7848730f 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -130,8 +130,7 @@ public:
QList<CompositeSingletonReference> resolvedCompositeSingletons() const;
- static QString completeQmldirPath(const QString &uri, const QString &base, int vmaj, int vmin,
- QQmlImports::ImportVersion version);
+ static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin);
static QString versionString(int vmaj, int vmin, ImportVersion version);
static bool isLocal(const QString &url);
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index 235aa1bf44..eba93bfb1a 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -281,7 +281,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (!compiledData)
return;
- QML_MEMORY_SCOPE_URL(compiledData->url());
+ QML_MEMORY_SCOPE_URL(compiledData->compilationUnit->url());
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> protectThis(this);
@@ -292,7 +292,7 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (!vmeGuard.isOK()) {
QQmlError error;
- error.setUrl(compiledData->url());
+ error.setUrl(compiledData->compilationUnit->url());
error.setDescription(QQmlComponent::tr("Object destroyed during incubation"));
errors << error;
progress = QQmlIncubatorPrivate::Completed;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 576478b729..1c5a7ad8c1 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1914,14 +1914,11 @@ QList<QQmlType*> QQmlMetaType::qmlSingletonTypes()
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- QList<QQmlType*> alltypes = data->nameToType.values();
QList<QQmlType*> retn;
- foreach (QQmlType* t, alltypes) {
- if (t->isSingleton()) {
- retn.append(t);
- }
+ for (const auto type : qAsConst(data->nameToType)) {
+ if (type->isSingleton())
+ retn.append(type);
}
-
return retn;
}
@@ -1929,9 +1926,9 @@ const QQmlPrivate::CachedQmlUnit *QQmlMetaType::findCachedCompilationUnit(const
{
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- for (QVector<QQmlPrivate::QmlUnitCacheLookupFunction>::ConstIterator it = data->lookupCachedQmlUnit.constBegin(), end = data->lookupCachedQmlUnit.constEnd();
- it != end; ++it) {
- if (const QQmlPrivate::CachedQmlUnit *unit = (*it)(uri))
+
+ for (const auto lookup : qAsConst(data->lookupCachedQmlUnit)) {
+ if (const QQmlPrivate::CachedQmlUnit *unit = lookup(uri))
return unit;
}
return 0;
@@ -1961,8 +1958,7 @@ QString QQmlMetaType::prettyTypeName(const QObject *object)
marker = typeName.indexOf(QLatin1String("_QML_"));
if (marker != -1) {
- typeName = typeName.left(marker);
- typeName += QLatin1Char('*');
+ typeName = typeName.left(marker) + QLatin1Char('*');
type = QQmlMetaType::qmlType(QMetaType::type(typeName.toLatin1()));
if (type) {
typeName = type->qmlTypeName();
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 29fff04325..8d3c5962bd 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -375,7 +375,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
QString string = binding->valueAsString(qmlUnit);
// Encoded dir-separators defeat QUrl processing - decode them first
string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
- QUrl value = string.isEmpty() ? QUrl() : compiledData->url().resolved(QUrl(string));
+ QUrl value = string.isEmpty() ? QUrl() : compiledData->compilationUnit->url().resolved(QUrl(string));
// Apply URL interceptor
if (engine->urlInterceptor())
value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
@@ -570,7 +570,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
} else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String);
QString urlString = binding->valueAsString(qmlUnit);
- QUrl u = urlString.isEmpty() ? QUrl() : compiledData->url().resolved(QUrl(urlString));
+ QUrl u = urlString.isEmpty() ? QUrl() : compiledData->compilationUnit->url().resolved(QUrl(urlString));
QList<QUrl> value;
value.append(u);
argv[0] = reinterpret_cast<void *>(&value);
@@ -664,7 +664,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
if (qmlTypeForObject(_bindingTarget)) {
quint32 bindingSkipList = 0;
- QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultProperty != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
+ QQmlPropertyData *defaultProperty = _compiledObject->indexOfDefaultPropertyOrAlias != -1 ? _propertyCache->parent()->defaultProperty() : _propertyCache->defaultProperty();
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
@@ -999,7 +999,7 @@ void QQmlObjectCreator::setupFunctions()
void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location, const QString &description)
{
QQmlError error;
- error.setUrl(compiledData->url());
+ error.setUrl(compiledData->compilationUnit->url());
error.setLine(location.line);
error.setColumn(location.column);
error.setDescription(description);
@@ -1037,8 +1037,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (compiledData->isComponent(index)) {
isComponent = true;
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
- Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(QStringLiteral("<component>"),
- context->url(), obj->location.line, obj->location.column));
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
+ compiledData, obj, QStringLiteral("<component>"), context->url()));
QQmlComponentPrivate::get(component)->creationContext = context;
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
@@ -1048,8 +1048,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
installPropertyCache = !typeRef->isFullyDynamicType;
QQmlType *type = typeRef->type;
if (type) {
- Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(),
- context->url(), obj->location.line, obj->location.column));
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
+ compiledData, obj, type->qmlTypeName(), context->url()));
instance = type->create();
if (!instance) {
recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1071,8 +1071,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
sharedState->allCreatedObjects.push(instance);
} else {
Q_ASSERT(typeRef->component);
- Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->fileName(),
- context->url(), obj->location.line, obj->location.column));
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
+ compiledData, obj, typeRef->component->compilationUnit->fileName(),
+ context->url()));
if (typeRef->component->compilationUnit->data->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1115,7 +1116,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
parserStatus->classBegin();
// push() the profiler state here, together with the parserStatus, as we'll pop() them
// together, too.
- Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(profiler));
+ Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(obj));
sharedState->allParserStatusCallbacks.push(parserStatus);
parserStatus->d = &sharedState->allParserStatusCallbacks.top();
}
@@ -1288,7 +1289,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (!data.isEmpty()) {
Q_ASSERT(!cache.isNull());
// install on _object
- vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()));
+ vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()), compiledData->compilationUnit, _compiledObjectIndex);
if (_ddata->propertyCache)
_ddata->propertyCache->release();
_ddata->propertyCache = cache;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 22de5e1ae9..df2ff05de1 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -58,6 +58,7 @@
#include <private/qv4functionobject_p.h>
#include <QStringList>
+#include <QVector>
#include <private/qmetaobject_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <QtCore/qdebug.h>
@@ -240,14 +241,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QQmlTypeNameCache *typeNameCache = context?context->imports:0;
- QStringList path = name.split(QLatin1Char('.'));
+ const auto path = name.splitRef(QLatin1Char('.'));
if (path.isEmpty()) return;
QObject *currentObject = obj;
// Everything up to the last property must be an "object type" property
for (int ii = 0; ii < path.count() - 1; ++ii) {
- const QString &pathName = path.at(ii);
+ const QStringRef &pathName = path.at(ii);
if (typeNameCache) {
QQmlTypeNameCache::Result r = typeNameCache->query(pathName);
@@ -284,7 +285,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QQmlPropertyData local;
QQmlPropertyData *property =
- QQmlPropertyCache::property(engine, currentObject, pathName, context, local);
+ QQmlPropertyCache::property(engine, currentObject, pathName.toString(), context, local);
if (!property) return; // Not a property
if (property->isFunction())
@@ -324,14 +325,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
}
- const QString &terminal = path.last();
+ const QStringRef &terminal = path.last();
if (terminal.count() >= 3 &&
terminal.at(0) == QLatin1Char('o') &&
terminal.at(1) == QLatin1Char('n') &&
terminal.at(2).isUpper()) {
- QString signalName = terminal.mid(2);
+ QString signalName = terminal.mid(2).toString();
signalName[0] = signalName.at(0).toLower();
// XXX - this code treats methods as signals
@@ -376,13 +377,14 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
}
// Property
+ const QString terminalString = terminal.toString();
QQmlPropertyData local;
QQmlPropertyData *property =
- QQmlPropertyCache::property(engine, currentObject, terminal, context, local);
+ QQmlPropertyCache::property(engine, currentObject, terminalString, context, local);
if (property && !property->isFunction()) {
object = currentObject;
core = *property;
- nameCache = terminal;
+ nameCache = terminalString;
isNameCached = true;
}
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 15e8d62efc..c6299a1720 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -661,7 +661,7 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
Q_ASSERT(m_waitingFor.contains(blob));
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler,
- blob->url());
+ blob);
m_inCallback = true;
@@ -1121,6 +1121,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
}
#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16
+#define TYPELOADER_MINIMUM_TRIM_THRESHOLD 64
#ifndef QT_NO_NETWORK
void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
@@ -1225,7 +1226,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
{
QML_MEMORY_SCOPE_URL(blob->url());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob);
blob->m_inCallback = true;
@@ -1245,7 +1246,7 @@ void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
{
QML_MEMORY_SCOPE_URL(blob->url());
- QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob->url());
+ QQmlCompilingProfiler prof(QQmlEnginePrivate::get(engine())->profiler, blob);
blob->m_inCallback = true;
@@ -1398,13 +1399,10 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
// Probe for all possible locations
int priority = 0;
- for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
- foreach (const QString &path, remotePathList) {
- QString qmldirUrl = QQmlImports::completeQmldirPath(importUri, path, import->majorVersion, import->minorVersion,
- static_cast<QQmlImports::ImportVersion>(version));
- if (!fetchQmldir(QUrl(qmldirUrl), import, ++priority, errors))
- return false;
- }
+ const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(importUri, remotePathList, import->majorVersion, import->minorVersion);
+ for (const QString &qmldirPath : qmlDirPaths) {
+ if (!fetchQmldir(QUrl(qmldirPath), import, ++priority, errors))
+ return false;
}
}
}
@@ -1602,7 +1600,8 @@ bool QQmlTypeLoader::QmldirContent::designerSupported() const
Constructs a new type loader that uses the given \a engine.
*/
QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine)
- : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this))
+ : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this)),
+ m_typeCacheTrimThreshold(TYPELOADER_MINIMUM_TRIM_THRESHOLD)
{
}
@@ -1639,6 +1638,10 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
QQmlTypeData *typeData = m_typeCache.value(url);
if (!typeData) {
+ // Trim before adding the new type, so that we don't immediately trim it away
+ if (m_typeCache.size() >= m_typeCacheTrimThreshold)
+ trimCache();
+
typeData = new QQmlTypeData(url, this);
// TODO: if (compiledData == 0), is it safe to omit this insertion?
m_typeCache.insert(url, typeData);
@@ -1943,12 +1946,22 @@ void QQmlTypeLoader::clearCache()
qDeleteAll(m_importQmlDirCache);
m_typeCache.clear();
+ m_typeCacheTrimThreshold = TYPELOADER_MINIMUM_TRIM_THRESHOLD;
m_scriptCache.clear();
m_qmldirCache.clear();
m_importDirCache.clear();
m_importQmlDirCache.clear();
}
+void QQmlTypeLoader::updateTypeCacheTrimThreshold()
+{
+ int size = m_typeCache.size();
+ if (size > m_typeCacheTrimThreshold)
+ m_typeCacheTrimThreshold = size * 2;
+ if (size < m_typeCacheTrimThreshold / 2)
+ m_typeCacheTrimThreshold = qMax(size * 2, TYPELOADER_MINIMUM_TRIM_THRESHOLD);
+}
+
void QQmlTypeLoader::trimCache()
{
while (true) {
@@ -1973,6 +1986,8 @@ void QQmlTypeLoader::trimCache()
}
}
+ updateTypeCacheTrimThreshold();
+
// TODO: release any scripts which are no longer referenced by any types
}
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 49a4ac716a..12ab98e425 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -374,6 +374,7 @@ private:
NetworkReplies m_networkReplies;
#endif
TypeCache m_typeCache;
+ int m_typeCacheTrimThreshold;
ScriptCache m_scriptCache;
QmldirCache m_qmldirCache;
ImportDirCache m_importDirCache;
@@ -381,6 +382,7 @@ private:
template<typename Loader>
void doLoad(const Loader &loader, QQmlDataBlob *blob, Mode mode);
+ void updateTypeCacheTrimThreshold();
friend struct PlainLoader;
friend struct CachedLoader;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index d313557e98..fdac41a420 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -50,6 +50,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4variantobject_p.h>
#include <private/qv4alloca_p.h>
+#include <private/qv4objectiterator_p.h>
QT_BEGIN_NAMESPACE
@@ -244,6 +245,34 @@ PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, String *name)
return result ? Attr_Data : Attr_Invalid;
}
+void QQmlValueTypeWrapper::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+{
+ name->setM(0);
+ *index = UINT_MAX;
+
+ QQmlValueTypeWrapper *that = static_cast<QQmlValueTypeWrapper*>(m);
+
+ if (QQmlValueTypeReference *ref = that->as<QQmlValueTypeReference>()) {
+ if (!ref->readReferenceValue())
+ return;
+ }
+
+ if (that->d()->propertyCache) {
+ const QMetaObject *mo = that->d()->propertyCache->createMetaObject();
+ const int propertyCount = mo->propertyCount();
+ if (it->arrayIndex < static_cast<uint>(propertyCount)) {
+ Scope scope(that->engine());
+ ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
+ name->setM(propName->d());
+ ++it->arrayIndex;
+ *attributes = QV4::Attr_Data;
+ p->value = that->QV4::Object::get(propName);
+ return;
+ }
+ }
+ QV4::Object::advanceIterator(m, it, name, index, p, attributes);
+}
+
bool QQmlValueTypeWrapper::isEqual(const QVariant& value)
{
if (QQmlValueTypeReference *ref = as<QQmlValueTypeReference>())
@@ -302,8 +331,7 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->typeId, &convertResult, QMetaType::QString)) {
result = convertResult;
} else {
- result = QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId));
- result += QLatin1Char('(');
+ result = QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId)) + QLatin1Char('(');
const QMetaObject *mo = w->d()->propertyCache->metaObject();
const int propCount = mo->propertyCount();
for (int i = 0; i < propCount; ++i) {
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index c2861f5bfa..94eeba366a 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -99,6 +99,7 @@ public:
static void put(Managed *m, String *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
static PropertyAttributes query(const Managed *, String *name);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static QV4::ReturnedValue method_toString(CallContext *ctx);
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index a59d8e2aec..ac9db5c046 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -64,8 +64,6 @@
#include <private/qqmlengine_p.h>
#include <private/qfinitestack_p.h>
-#include <private/qqmlprofiler_p.h>
-
QT_BEGIN_NAMESPACE
class QObject;
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index ef00a582ef..b0b7995ae2 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -99,10 +99,10 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
return;
if (m_index >= 0) {
- QV4::ExecutionEngine *v4 = m_target->properties.engine();
+ QV4::ExecutionEngine *v4 = m_target->propertyAndMethodStorage.engine();
if (v4) {
QV4::Scope scope(v4);
- QV4::Scoped<QV4::MemberData> sp(scope, m_target->properties.value());
+ QV4::Scoped<QV4::MemberData> sp(scope, m_target->propertyAndMethodStorage.value());
if (sp)
*(sp->data() + m_index) = QV4::Primitive::nullValue();
}
@@ -140,17 +140,19 @@ void QQmlVMEMetaObjectEndpoint_callback(QQmlNotifierEndpoint *e, void **)
void QQmlVMEMetaObjectEndpoint::tryConnect()
{
+ Q_ASSERT(metaObject->compiledObject);
int aliasId = this - metaObject->aliasEndpoints;
if (metaObject.flag()) {
// This is actually notify
- int sigIdx = metaObject->methodOffset() + aliasId + metaObject->metaData->propertyCount;
+ int sigIdx = metaObject->methodOffset() + aliasId + metaObject->compiledObject->nProperties;
metaObject->activate(metaObject->object, sigIdx, 0);
} else {
+ const QV4::CompiledData::Alias *aliasData = &metaObject->compiledObject->aliasTable()[aliasId];
QQmlVMEMetaData::AliasData *d = metaObject->metaData->aliasData() + aliasId;
- if (!d->isObjectAlias()) {
+ if (!aliasData->isObjectAlias()) {
QQmlContextData *ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValues[d->contextIdx].data();
+ QObject *target = ctxt->idValues[aliasData->targetObjectId].data();
if (!target)
return;
@@ -304,135 +306,128 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje
QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
QQmlPropertyCache *cache,
- const QQmlVMEMetaData *meta)
+ const QQmlVMEMetaData *meta, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId)
: QQmlInterceptorMetaObject(obj, cache),
ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta),
- aliasEndpoints(0),
- methods(0)
+ aliasEndpoints(0), compilationUnit(qmlCompilationUnit), compiledObject(0)
{
cache->addref();
QQmlData::get(obj)->hasVMEMetaObject = true;
- int qobject_type = qMetaTypeId<QObject*>();
- int variant_type = qMetaTypeId<QVariant>();
- // Need JS wrapper to ensure properties are marked.
- // ### FIXME: I hope that this can be removed once we have the proper scope chain
- // set up and the JS wrappers always exist.
- bool needsJSWrapper = (metaData->propertyCount > 0);
-
- // ### Optimize
- for (int ii = 0; ii < metaData->propertyCount; ++ii) {
- int t = (metaData->propertyData() + ii)->propertyType;
- if (t == qobject_type || t == variant_type) {
- needsJSWrapper = true;
- break;
+ if (compilationUnit && qmlObjectId >= 0) {
+ compiledObject = compilationUnit->data->objectAt(qmlObjectId);
+
+ if (compiledObject->nProperties || compiledObject->nFunctions) {
+ Q_ASSERT(cache && cache->engine);
+ QV4::ExecutionEngine *v4 = cache->engine;
+ QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, compiledObject->nProperties + compiledObject->nFunctions);
+ propertyAndMethodStorage.set(v4, data);
+ std::fill(data->data, data->data + data->size, QV4::Encode::undefined());
+
+ // Need JS wrapper to ensure properties/methods are marked.
+ ensureQObjectWrapper();
}
}
-
- if (needsJSWrapper)
- ensureQObjectWrapper();
}
QQmlVMEMetaObject::~QQmlVMEMetaObject()
{
if (parent.isT1()) parent.asT1()->objectDestroyed(object);
delete [] aliasEndpoints;
- delete [] methods;
qDeleteAll(varObjectGuards);
cache->release();
}
-QV4::MemberData *QQmlVMEMetaObject::propertiesAsMemberData()
+QV4::MemberData *QQmlVMEMetaObject::propertyAndMethodStorageAsMemberData()
{
- if (properties.isUndefined()) {
- if (properties.valueRef())
+ if (propertyAndMethodStorage.isUndefined()) {
+ if (propertyAndMethodStorage.valueRef())
// in some situations, the QObject wrapper (and associated data,
// such as the varProperties array) will have been cleaned up, but the
// QObject ptr will not yet have been deleted (eg, waiting on deleteLater).
// In this situation, return 0.
return 0;
- allocateProperties();
}
- return static_cast<QV4::MemberData*>(properties.asManaged());
+ return static_cast<QV4::MemberData*>(propertyAndMethodStorage.asManaged());
}
void QQmlVMEMetaObject::writeProperty(int id, int v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = QV4::Primitive::fromInt32(v);
}
void QQmlVMEMetaObject::writeProperty(int id, bool v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = QV4::Primitive::fromBoolean(v);
}
void QQmlVMEMetaObject::writeProperty(int id, double v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = QV4::Primitive::fromDouble(v);
}
void QQmlVMEMetaObject::writeProperty(int id, const QString& v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = cache->engine->newString(v);
}
void QQmlVMEMetaObject::writeProperty(int id, const QUrl& v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDate& v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QDateTime& v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QPointF& v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QSizeF& v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
void QQmlVMEMetaObject::writeProperty(int id, const QRectF& v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = cache->engine->newVariantObject(QVariant::fromValue(v));
}
void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
*(md->data() + id) = QV4::QObjectWrapper::wrap(cache->engine, v);
@@ -447,7 +442,7 @@ void QQmlVMEMetaObject::writeProperty(int id, QObject* v)
int QQmlVMEMetaObject::readPropertyAsInt(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return 0;
@@ -460,7 +455,7 @@ int QQmlVMEMetaObject::readPropertyAsInt(int id)
bool QQmlVMEMetaObject::readPropertyAsBool(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return false;
@@ -473,7 +468,7 @@ bool QQmlVMEMetaObject::readPropertyAsBool(int id)
double QQmlVMEMetaObject::readPropertyAsDouble(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return 0.0;
@@ -486,7 +481,7 @@ double QQmlVMEMetaObject::readPropertyAsDouble(int id)
QString QQmlVMEMetaObject::readPropertyAsString(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return QString();
@@ -499,7 +494,7 @@ QString QQmlVMEMetaObject::readPropertyAsString(int id)
QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return QUrl();
@@ -513,7 +508,7 @@ QUrl QQmlVMEMetaObject::readPropertyAsUrl(int id)
QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return QDate();
@@ -527,7 +522,7 @@ QDate QQmlVMEMetaObject::readPropertyAsDate(int id)
QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return QDateTime();
@@ -541,7 +536,7 @@ QDateTime QQmlVMEMetaObject::readPropertyAsDateTime(int id)
QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return QSizeF();
@@ -555,7 +550,7 @@ QSizeF QQmlVMEMetaObject::readPropertyAsSizeF(int id)
QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return QPointF();
@@ -569,7 +564,7 @@ QPointF QQmlVMEMetaObject::readPropertyAsPointF(int id)
QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return 0;
@@ -583,7 +578,7 @@ QObject* QQmlVMEMetaObject::readPropertyAsQObject(int id)
QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return 0;
@@ -599,7 +594,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id)
QRectF QQmlVMEMetaObject::readPropertyAsRectF(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return QRectF();
@@ -621,15 +616,20 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (intercept(c, _id, a))
return -1;
+ const int propertyCount = compiledObject ? int(compiledObject->nProperties) : 0;
+ const int aliasCount = compiledObject ? int(compiledObject->nAliases) : 0;
+ const int signalCount = compiledObject ? int(compiledObject->nSignals) : 0;
+ const int methodCount = compiledObject ? int(compiledObject->nFunctions) : 0;
+
if (c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty || c == QMetaObject::ResetProperty) {
if (id >= propOffset()) {
id -= propOffset();
- if (id < metaData->propertyCount) {
- int t = (metaData->propertyData() + id)->propertyType;
+ if (id < propertyCount) {
+ const QV4::CompiledData::Property::Type t = static_cast<QV4::CompiledData::Property::Type>(compiledObject->propertyTable()[id].type);
bool needActivate = false;
- if (t == QQmlVMEMetaData::VarPropertyType) {
+ if (t == QV4::CompiledData::Property::Var) {
// the context can be null if accessing var properties from cpp after re-parenting an item.
QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine);
QV8Engine *v8e = (ep == 0) ? 0 : ep->v8engine();
@@ -645,131 +645,179 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
}
} else {
+ int fallbackMetaType = QMetaType::UnknownType;
+ switch (t) {
+ case QV4::CompiledData::Property::Font:
+ fallbackMetaType = QMetaType::QFont;
+ break;
+ case QV4::CompiledData::Property::Time:
+ fallbackMetaType = QMetaType::QTime;
+ break;
+ case QV4::CompiledData::Property::Color:
+ fallbackMetaType = QMetaType::QColor;
+ break;
+ case QV4::CompiledData::Property::Vector2D:
+ fallbackMetaType = QMetaType::QVector2D;
+ break;
+ case QV4::CompiledData::Property::Vector3D:
+ fallbackMetaType = QMetaType::QVector3D;
+ break;
+ case QV4::CompiledData::Property::Vector4D:
+ fallbackMetaType = QMetaType::QVector4D;
+ break;
+ case QV4::CompiledData::Property::Matrix4x4:
+ fallbackMetaType = QMetaType::QMatrix4x4;
+ break;
+ case QV4::CompiledData::Property::Quaternion:
+ fallbackMetaType = QMetaType::QQuaternion;
+ break;
+ default: break;
+ }
+
if (c == QMetaObject::ReadProperty) {
- switch(t) {
- case QVariant::Int:
+ switch (t) {
+ case QV4::CompiledData::Property::Int:
*reinterpret_cast<int *>(a[0]) = readPropertyAsInt(id);
break;
- case QVariant::Bool:
+ case QV4::CompiledData::Property::Bool:
*reinterpret_cast<bool *>(a[0]) = readPropertyAsBool(id);
break;
- case QVariant::Double:
+ case QV4::CompiledData::Property::Real:
*reinterpret_cast<double *>(a[0]) = readPropertyAsDouble(id);
break;
- case QVariant::String:
+ case QV4::CompiledData::Property::String:
*reinterpret_cast<QString *>(a[0]) = readPropertyAsString(id);
break;
- case QVariant::Url:
+ case QV4::CompiledData::Property::Url:
*reinterpret_cast<QUrl *>(a[0]) = readPropertyAsUrl(id);
break;
- case QVariant::Date:
+ case QV4::CompiledData::Property::Date:
*reinterpret_cast<QDate *>(a[0]) = readPropertyAsDate(id);
break;
- case QVariant::DateTime:
+ case QV4::CompiledData::Property::DateTime:
*reinterpret_cast<QDateTime *>(a[0]) = readPropertyAsDateTime(id);
break;
- case QVariant::RectF:
+ case QV4::CompiledData::Property::Rect:
*reinterpret_cast<QRectF *>(a[0]) = readPropertyAsRectF(id);
break;
- case QVariant::SizeF:
+ case QV4::CompiledData::Property::Size:
*reinterpret_cast<QSizeF *>(a[0]) = readPropertyAsSizeF(id);
break;
- case QVariant::PointF:
+ case QV4::CompiledData::Property::Point:
*reinterpret_cast<QPointF *>(a[0]) = readPropertyAsPointF(id);
break;
- case QMetaType::QObjectStar:
+ case QV4::CompiledData::Property::Custom:
*reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id);
break;
- case QMetaType::QVariant:
+ case QV4::CompiledData::Property::Variant:
*reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
break;
- default:
- {
- if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
- QList<QObject *> *list = readPropertyAsList(id);
- QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]);
- *p = QQmlListProperty<QObject>(object, list,
- list_append, list_count, list_at,
- list_clear);
- p->dummy1 = this;
- p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id));
- } else {
- QV4::MemberData *md = propertiesAsMemberData();
- if (md) {
- QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
- if (v)
- QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t);
- }
- }
+ case QV4::CompiledData::Property::CustomList: {
+ QList<QObject *> *list = readPropertyAsList(id);
+ QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]);
+ *p = QQmlListProperty<QObject>(object, list,
+ list_append, list_count, list_at,
+ list_clear);
+ p->dummy1 = this;
+ p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id));
break;
}
+ case QV4::CompiledData::Property::Font:
+ case QV4::CompiledData::Property::Time:
+ case QV4::CompiledData::Property::Color:
+ case QV4::CompiledData::Property::Vector2D:
+ case QV4::CompiledData::Property::Vector3D:
+ case QV4::CompiledData::Property::Vector4D:
+ case QV4::CompiledData::Property::Matrix4x4:
+ case QV4::CompiledData::Property::Quaternion:
+ Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
+ if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
+ QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
+ if (v)
+ QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], fallbackMetaType);
+ }
+ break;
+ case QV4::CompiledData::Property::Var:
+ Q_UNREACHABLE();
}
} else if (c == QMetaObject::WriteProperty) {
switch(t) {
- case QVariant::Int:
+ case QV4::CompiledData::Property::Int:
needActivate = *reinterpret_cast<int *>(a[0]) != readPropertyAsInt(id);
writeProperty(id, *reinterpret_cast<int *>(a[0]));
break;
- case QVariant::Bool:
+ case QV4::CompiledData::Property::Bool:
needActivate = *reinterpret_cast<bool *>(a[0]) != readPropertyAsBool(id);
writeProperty(id, *reinterpret_cast<bool *>(a[0]));
break;
- case QVariant::Double:
+ case QV4::CompiledData::Property::Real:
needActivate = *reinterpret_cast<double *>(a[0]) != readPropertyAsDouble(id);
writeProperty(id, *reinterpret_cast<double *>(a[0]));
break;
- case QVariant::String:
+ case QV4::CompiledData::Property::String:
needActivate = *reinterpret_cast<QString *>(a[0]) != readPropertyAsString(id);
writeProperty(id, *reinterpret_cast<QString *>(a[0]));
break;
- case QVariant::Url:
+ case QV4::CompiledData::Property::Url:
needActivate = *reinterpret_cast<QUrl *>(a[0]) != readPropertyAsUrl(id);
writeProperty(id, *reinterpret_cast<QUrl *>(a[0]));
break;
- case QVariant::Date:
+ case QV4::CompiledData::Property::Date:
needActivate = *reinterpret_cast<QDate *>(a[0]) != readPropertyAsDate(id);
writeProperty(id, *reinterpret_cast<QDate *>(a[0]));
break;
- case QVariant::DateTime:
+ case QV4::CompiledData::Property::DateTime:
needActivate = *reinterpret_cast<QDateTime *>(a[0]) != readPropertyAsDateTime(id);
writeProperty(id, *reinterpret_cast<QDateTime *>(a[0]));
break;
- case QVariant::RectF:
+ case QV4::CompiledData::Property::Rect:
needActivate = *reinterpret_cast<QRectF *>(a[0]) != readPropertyAsRectF(id);
writeProperty(id, *reinterpret_cast<QRectF *>(a[0]));
break;
- case QVariant::SizeF:
+ case QV4::CompiledData::Property::Size:
needActivate = *reinterpret_cast<QSizeF *>(a[0]) != readPropertyAsSizeF(id);
writeProperty(id, *reinterpret_cast<QSizeF *>(a[0]));
break;
- case QVariant::PointF:
+ case QV4::CompiledData::Property::Point:
needActivate = *reinterpret_cast<QPointF *>(a[0]) != readPropertyAsPointF(id);
writeProperty(id, *reinterpret_cast<QPointF *>(a[0]));
break;
- case QMetaType::QObjectStar:
+ case QV4::CompiledData::Property::Custom:
needActivate = *reinterpret_cast<QObject **>(a[0]) != readPropertyAsQObject(id);
writeProperty(id, *reinterpret_cast<QObject **>(a[0]));
break;
- case QMetaType::QVariant:
+ case QV4::CompiledData::Property::Variant:
writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
break;
- default: {
- QV4::MemberData *md = propertiesAsMemberData();
- if (md) {
+ case QV4::CompiledData::Property::CustomList:
+ // Writing such a property is not supported. Content is added through the list property
+ // methods.
+ break;
+ case QV4::CompiledData::Property::Font:
+ case QV4::CompiledData::Property::Time:
+ case QV4::CompiledData::Property::Color:
+ case QV4::CompiledData::Property::Vector2D:
+ case QV4::CompiledData::Property::Vector3D:
+ case QV4::CompiledData::Property::Vector4D:
+ case QV4::CompiledData::Property::Matrix4x4:
+ case QV4::CompiledData::Property::Quaternion:
+ Q_ASSERT(fallbackMetaType != QMetaType::UnknownType);
+ if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) {
QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
if (!v) {
*(md->data() + id) = cache->engine->newVariantObject(QVariant());
v = (md->data() + id)->as<QV4::VariantObject>();
- QQml_valueTypeProvider()->initValueType(t, v->d()->data);
+ QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data);
}
- needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], v->d()->data);
- QQml_valueTypeProvider()->writeValueType(t, a[0], v->d()->data);
+ needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data);
+ QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data);
}
break;
- }
+ case QV4::CompiledData::Property::Var:
+ Q_UNREACHABLE();
}
}
@@ -782,13 +830,12 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
return -1;
}
- id -= metaData->propertyCount;
+ id -= propertyCount;
- if (id < metaData->aliasCount) {
+ if (id < aliasCount) {
+ const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[id];
- QQmlVMEMetaData::AliasData *d = metaData->aliasData() + id;
-
- if (d->flags & QML_ALIAS_FLAG_PTR && c == QMetaObject::ReadProperty)
+ if ((aliasData->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject) && c == QMetaObject::ReadProperty)
*reinterpret_cast<void **>(a[0]) = 0;
if (!ctxt) return -1;
@@ -796,42 +843,52 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
QQmlContext *context = ctxt->asQQmlContext();
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
- QObject *target = ctxtPriv->data->idValues[d->contextIdx].data();
+ QObject *target = ctxtPriv->data->idValues[aliasData->targetObjectId].data();
if (!target)
return -1;
connectAlias(id);
- if (d->isObjectAlias()) {
+ if (aliasData->isObjectAlias()) {
*reinterpret_cast<QObject **>(a[0]) = target;
return -1;
}
+ QQmlData *targetDData = QQmlData::get(target, /*create*/false);
+ if (!targetDData)
+ return -1;
+
+ int coreIndex;
+ const int valueTypePropertyIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, &coreIndex);
+
// Remove binding (if any) on write
if(c == QMetaObject::WriteProperty) {
int flags = *reinterpret_cast<int*>(a[3]);
if (flags & QQmlPropertyPrivate::RemoveBindingOnAliasWrite) {
QQmlData *targetData = QQmlData::get(target);
- if (targetData && targetData->hasBindingBit(d->propertyIndex()))
- QQmlPropertyPrivate::removeBinding(target, d->propertyIdx);
+ if (targetData && targetData->hasBindingBit(coreIndex))
+ QQmlPropertyPrivate::removeBinding(target, aliasData->encodedMetaPropertyIndex);
}
}
- if (d->isValueTypeAlias()) {
+ if (valueTypePropertyIndex != -1) {
+ if (!targetDData->propertyCache)
+ return -1;
+ const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
// Value type property
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(d->valueType());
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType);
Q_ASSERT(valueType);
- valueType->read(target, d->propertyIndex());
- int rv = QMetaObject::metacall(valueType, c, d->valueTypeIndex(), a);
+ valueType->read(target, coreIndex);
+ int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a);
if (c == QMetaObject::WriteProperty)
- valueType->write(target, d->propertyIndex(), 0x00);
+ valueType->write(target, coreIndex, 0x00);
return rv;
} else {
- return QMetaObject::metacall(target, c, d->propertyIndex(), a);
+ return QMetaObject::metacall(target, c, coreIndex, a);
}
}
@@ -844,8 +901,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if (id >= methodOffset()) {
id -= methodOffset();
- int plainSignals = metaData->signalCount + metaData->propertyCount +
- metaData->aliasCount;
+ int plainSignals = signalCount + propertyCount + aliasCount;
if (id < plainSignals) {
activate(object, _id, a);
return -1;
@@ -853,7 +909,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
id -= plainSignals;
- if (id < metaData->methodCount) {
+ if (id < methodCount) {
if (!ctxt->engine)
return -1; // We can't run the method
@@ -877,12 +933,11 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
return -1; // The dynamic method with that id is not available.
}
- QQmlVMEMetaData::MethodData *data = metaData->methodData() + id;
-
- QV4::ScopedCallData callData(scope, data->parameterCount);
+ const unsigned int parameterCount = function->formalParameterCount();
+ QV4::ScopedCallData callData(scope, parameterCount);
callData->thisObject = ep->v8engine()->global();
- for (int ii = 0; ii < data->parameterCount; ++ii)
+ for (uint ii = 0; ii < parameterCount; ++ii)
callData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]);
QV4::ScopedValue result(scope);
@@ -911,22 +966,23 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
QV4::ReturnedValue QQmlVMEMetaObject::method(int index)
{
- if (!ctxt || !ctxt->isValid()) {
+ if (!ctxt || !ctxt->isValid() || !compiledObject) {
qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context");
return QV4::Encode::undefined();
}
- if (!methods)
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
+ if (!md)
return QV4::Encode::undefined();
- return methods[index].value();
+ return (md->data() + index + compiledObject->nProperties)->asReturnedValue();
}
QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id)
{
- Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
+ Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var);
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md)
return (md->data() + id)->asReturnedValue();
return QV4::Primitive::undefinedValue().asReturnedValue();
@@ -934,7 +990,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id)
QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
{
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md) {
const QV4::QObjectWrapper *wrapper = (md->data() + id)->as<QV4::QObjectWrapper>();
if (wrapper)
@@ -949,9 +1005,9 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
{
- Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType);
+ Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var);
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return;
@@ -989,8 +1045,8 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value)
void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
{
- if ((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType) {
- QV4::MemberData *md = propertiesAsMemberData();
+ if (compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var) {
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (!md)
return;
@@ -1020,7 +1076,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
needActivate = readPropertyAsQObject(id) != o; // TODO: still correct?
writeProperty(id, o);
} else {
- QV4::MemberData *md = propertiesAsMemberData();
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
if (md) {
QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
needActivate = (!v ||
@@ -1039,30 +1095,16 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
}
}
-quint16 QQmlVMEMetaObject::vmeMethodLineNumber(int index)
-{
- if (index < methodOffset()) {
- Q_ASSERT(parentVMEMetaObject());
- return parentVMEMetaObject()->vmeMethodLineNumber(index);
- }
-
- int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
-
- int rawIndex = index - methodOffset() - plainSignals;
-
- QQmlVMEMetaData::MethodData *data = metaData->methodData() + rawIndex;
- return data->lineNumber;
-}
-
QV4::ReturnedValue QQmlVMEMetaObject::vmeMethod(int index)
{
if (index < methodOffset()) {
Q_ASSERT(parentVMEMetaObject());
return parentVMEMetaObject()->vmeMethod(index);
}
- int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
+ if (!compiledObject)
+ return QV4::Primitive::undefinedValue().asReturnedValue();
+ const int plainSignals = compiledObject->nSignals + compiledObject->nProperties + compiledObject->nAliases;
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + int(compiledObject->nFunctions)));
return method(index - methodOffset() - plainSignals);
}
@@ -1073,14 +1115,16 @@ void QQmlVMEMetaObject::setVmeMethod(int index, const QV4::Value &function)
Q_ASSERT(parentVMEMetaObject());
return parentVMEMetaObject()->setVmeMethod(index, function);
}
- int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
- Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + metaData->methodCount));
-
- if (!methods)
- methods = new QV4::PersistentValue[metaData->methodCount];
+ if (!compiledObject)
+ return;
+ const int plainSignals = compiledObject->nSignals + compiledObject->nProperties + compiledObject->nAliases;
+ Q_ASSERT(index >= (methodOffset() + plainSignals) && index < (methodOffset() + plainSignals + int(compiledObject->nFunctions)));
int methodIndex = index - methodOffset() - plainSignals;
- methods[methodIndex].set(function.as<QV4::Object>()->engine(), function);
+ QV4::MemberData *md = propertyAndMethodStorageAsMemberData();
+ if (!md)
+ return;
+ *(md->data() + methodIndex + compiledObject->nProperties) = function;
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
@@ -1115,25 +1159,15 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e)
if (v4 != e)
return;
- properties.markOnce(e);
+ propertyAndMethodStorage.markOnce(e);
if (QQmlVMEMetaObject *parent = parentVMEMetaObject())
parent->mark(e);
}
-void QQmlVMEMetaObject::allocateProperties()
-{
- Q_ASSERT(cache && cache->engine);
- Q_ASSERT(!properties.valueRef());
- QV4::ExecutionEngine *v4 = cache->engine;
- QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount);
- properties.set(v4, data);
- std::fill(data->data, data->data + data->size, QV4::Encode::undefined());
-}
-
bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
{
- Q_ASSERT(index >= propOffset() + metaData->propertyCount);
+ Q_ASSERT(compiledObject && (index >= propOffset() + int(compiledObject->nProperties)));
*target = 0;
*coreIndex = -1;
@@ -1142,31 +1176,24 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
if (!ctxt)
return false;
- QQmlVMEMetaData::AliasData *d = metaData->aliasData() + (index - propOffset() - metaData->propertyCount);
- QQmlContext *context = ctxt->asQQmlContext();
- QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
-
- *target = ctxtPriv->data->idValues[d->contextIdx].data();
+ const int aliasId = index - propOffset() - compiledObject->nProperties;
+ const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
+ *target = ctxt->idValues[aliasData->targetObjectId].data();
if (!*target)
return false;
- if (d->isObjectAlias()) {
- } else if (d->isValueTypeAlias()) {
- *coreIndex = d->propertyIndex();
- *valueTypeIndex = d->valueTypeIndex();
- } else {
- *coreIndex = d->propertyIndex();
- }
-
+ if (!aliasData->isObjectAlias())
+ *valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(aliasData->encodedMetaPropertyIndex, coreIndex);
return true;
}
void QQmlVMEMetaObject::connectAlias(int aliasId)
{
+ Q_ASSERT(compiledObject);
if (!aliasEndpoints)
- aliasEndpoints = new QQmlVMEMetaObjectEndpoint[metaData->aliasCount];
+ aliasEndpoints = new QQmlVMEMetaObjectEndpoint[compiledObject->nAliases];
- QQmlVMEMetaData::AliasData *d = metaData->aliasData() + aliasId;
+ const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
QQmlVMEMetaObjectEndpoint *endpoint = aliasEndpoints + aliasId;
if (endpoint->metaObject.data()) {
@@ -1176,14 +1203,15 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
}
endpoint->metaObject = this;
- endpoint->connect(&ctxt->idValues[d->contextIdx].bindings);
+ endpoint->connect(&ctxt->idValues[aliasData->targetObjectId].bindings);
endpoint->tryConnect();
}
void QQmlVMEMetaObject::connectAliasSignal(int index, bool indexInSignalRange)
{
- int aliasId = (index - (indexInSignalRange ? signalOffset() : methodOffset())) - metaData->propertyCount;
- if (aliasId < 0 || aliasId >= metaData->aliasCount)
+ Q_ASSERT(compiledObject);
+ int aliasId = (index - (indexInSignalRange ? signalOffset() : methodOffset())) - compiledObject->nProperties;
+ if (aliasId < 0 || aliasId >= int(compiledObject->nAliases))
return;
connectAlias(aliasId);
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index fcdac3cc53..f9f9ec47af 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -74,69 +74,17 @@
QT_BEGIN_NAMESPACE
-#define QML_ALIAS_FLAG_PTR 0x00000001
-
struct QQmlVMEMetaData
{
- short propertyCount;
- short aliasCount;
- short signalCount;
- short methodCount;
// Make sure this structure is always aligned to int
+ int dummy;
struct AliasData {
- int contextIdx;
- int propertyIdx;
- int propType;
- int flags;
int notifySignal;
-
- bool isObjectAlias() const {
- return propertyIdx == -1;
- }
- bool isPropertyAlias() const {
- return !isObjectAlias() && valueTypeIndex() == -1;
- }
- bool isValueTypeAlias() const {
- return !isObjectAlias() && valueTypeIndex() != -1;
- }
- int propertyIndex() const {
- int index;
- QQmlPropertyData::decodeValueTypePropertyIndex(propertyIdx, &index);
- return index;
- }
- int valueTypeIndex() const {
- return QQmlPropertyData::decodeValueTypePropertyIndex(propertyIdx);
- }
- int valueType() const {
- return (valueTypeIndex() != -1) ? propType : 0;
- }
- };
-
- enum {
- VarPropertyType = -1
};
- struct PropertyData {
- int propertyType;
- };
-
- struct MethodData {
- int runtimeFunctionIndex;
- int parameterCount;
- quint16 lineNumber;
- };
-
- PropertyData *propertyData() const {
- return (PropertyData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData));
- }
-
AliasData *aliasData() const {
- return (AliasData *)(propertyData() + propertyCount);
- }
-
- MethodData *methodData() const {
- return (MethodData *)(aliasData() + aliasCount);
+ return (AliasData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData));
}
};
@@ -199,12 +147,11 @@ class QQmlVMEMetaObjectEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
{
public:
- QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data);
+ QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId);
~QQmlVMEMetaObject();
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
QV4::ReturnedValue vmeMethod(int index);
- quint16 vmeMethodLineNumber(int index);
void setVmeMethod(int index, const QV4::Value &function);
QV4::ReturnedValue vmeProperty(int index);
void setVMEProperty(int index, const QV4::Value &v);
@@ -230,9 +177,8 @@ public:
QQmlVMEMetaObjectEndpoint *aliasEndpoints;
- QV4::WeakValue properties;
- inline void allocateProperties();
- QV4::MemberData *propertiesAsMemberData();
+ QV4::WeakValue propertyAndMethodStorage;
+ QV4::MemberData *propertyAndMethodStorageAsMemberData();
int readPropertyAsInt(int id);
bool readPropertyAsBool(int id);
@@ -265,7 +211,6 @@ public:
void connectAlias(int aliasId);
- QV4::PersistentValue *methods;
QV4::ReturnedValue method(int);
QV4::ReturnedValue readVarProperty(int);
@@ -280,6 +225,12 @@ public:
QList<QQmlVMEVariantQObjectPtr *> varObjectGuards;
QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const;
+
+
+ // keep a reference to the compilation unit in order to still
+ // do property access when the context has been invalidated.
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ const QV4::CompiledData::Object *compiledObject;
};
QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj)
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index ac40b627d9..1f42cbf983 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -88,22 +88,18 @@ struct StaticQtMetaObject : public QObject
};
Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
+ : enumeratorIterator(0)
+ , keyIterator(0)
{
Scope scope(internalClass->engine);
ScopedObject o(scope, this);
- // Set all the enums from the "Qt" namespace
- const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
- ScopedString str(scope);
- ScopedValue v(scope);
- for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
- QMetaEnum enumerator = qtMetaObject->enumerator(ii);
- for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
- o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
- }
+ {
+ ScopedString str(scope);
+ ScopedValue v(scope);
+ o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
+ o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
}
- o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
- o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
@@ -154,6 +150,70 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
o->defineDefaultProperty(QStringLiteral("callLater"), QV4::QtObject::method_callLater);
}
+void QtObject::addAll()
+{
+ bool dummy = false;
+ findAndAdd(nullptr, dummy);
+}
+
+ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) const
+{
+ Scope scope(engine());
+ ScopedObject o(scope, this);
+ ScopedString key(scope);
+ ScopedValue value(scope);
+
+ const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
+ for (int enumCount = qtMetaObject->enumeratorCount(); d()->enumeratorIterator < enumCount;
+ ++d()->enumeratorIterator) {
+ QMetaEnum enumerator = qtMetaObject->enumerator(d()->enumeratorIterator);
+ for (int keyCount = enumerator.keyCount(); d()->keyIterator < keyCount; ++d()->keyIterator) {
+ key = scope.engine->newString(QString::fromUtf8(enumerator.key(d()->keyIterator)));
+ value = QV4::Primitive::fromInt32(enumerator.value(d()->keyIterator));
+ o->put(key, value);
+ if (name && key->toQString() == *name) {
+ ++d()->keyIterator;
+ foundProperty = true;
+ return value->asReturnedValue();
+ }
+ }
+ d()->keyIterator = 0;
+ }
+ d()->enumeratorIterator = Heap::QtObject::Finished;
+ foundProperty = false;
+ return Encode::undefined();
+}
+
+ReturnedValue QtObject::get(const Managed *m, String *name, bool *hasProperty)
+{
+ bool hasProp = false;
+ if (hasProperty == nullptr) {
+ hasProperty = &hasProp;
+ }
+
+ ReturnedValue ret = QV4::Object::get(m, name, hasProperty);
+ if (*hasProperty) {
+ return ret;
+ }
+
+ auto that = static_cast<const QtObject*>(m);
+ if (!that->d()->isComplete()) {
+ const QString key = name->toQString();
+ ret = that->findAndAdd(&key, *hasProperty);
+ }
+
+ return ret;
+}
+
+void QtObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+{
+ auto that = static_cast<QtObject*>(m);
+ if (!that->d()->isComplete()) {
+ that->addAll();
+ }
+
+ QV4::Object::advanceIterator(m, it, name, index, p, attributes);
+}
/*!
\qmlmethod bool Qt::isQtObject(object)
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 99c8b69724..5404ab3616 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -67,6 +67,13 @@ struct QtObject : Object {
QtObject(QQmlEngine *qmlEngine);
QObject *platform;
QObject *application;
+
+ enum { Finished = -1 };
+ int enumeratorIterator;
+ int keyIterator;
+
+ bool isComplete() const
+ { return enumeratorIterator == Finished; }
};
struct ConsoleObject : Object {
@@ -86,6 +93,9 @@ struct QtObject : Object
{
V4_OBJECT2(QtObject, Object)
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+
static ReturnedValue method_isQtObject(CallContext *ctx);
static ReturnedValue method_rgba(CallContext *ctx);
static ReturnedValue method_hsla(CallContext *ctx);
@@ -126,6 +136,10 @@ struct QtObject : Object
static ReturnedValue method_get_styleHints(CallContext *ctx);
static ReturnedValue method_callLater(CallContext *ctx);
+
+private:
+ void addAll();
+ ReturnedValue findAndAdd(const QString *name, bool &foundProperty) const;
};
struct ConsoleObject : Object
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 73128f6344..d8b0ef79f8 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -156,8 +156,7 @@ QV8Engine::QV8Engine(QJSEngine* qq)
QV8Engine::~QV8Engine()
{
- for (int ii = 0; ii < m_extensionData.count(); ++ii)
- delete m_extensionData[ii];
+ qDeleteAll(m_extensionData);
m_extensionData.clear();
#if !defined(QT_NO_XMLSTREAMREADER) && defined(QT_NO_NETWORK)
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 6e5fa516db..aee9fcd0a2 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -1040,7 +1040,7 @@ QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index
return QString();
int from = dot+1;
dot = name.indexOf(QLatin1Char('.'), from);
- value = obj->property(name.mid(from, dot-from).toUtf8());
+ value = obj->property(name.midRef(from, dot - from).toUtf8());
}
return value.toString();
}
@@ -1557,29 +1557,6 @@ bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const
return false;
}
-void QQmlDelegateModel::_q_layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_complete)
- return;
-
- if (hint == QAbstractItemModel::VerticalSortHint) {
- d->m_storedPersistentIndexes.clear();
- if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) {
- return;
- }
-
- for (int i = 0; i < d->m_count; ++i) {
- const QModelIndex index = d->m_adaptorModel.aim()->index(i, 0, d->m_adaptorModel.rootIndex);
- d->m_storedPersistentIndexes.append(index);
- }
- } else if (hint == QAbstractItemModel::HorizontalSortHint) {
- // Ignored
- } else {
- // Triggers model reset, no preparations for that are needed
- }
-}
-
void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
{
Q_D(QQmlDelegateModel);
@@ -1591,19 +1568,7 @@ void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &par
return;
}
- for (int i = 0, c = d->m_storedPersistentIndexes.count(); i < c; ++i) {
- const QPersistentModelIndex &index = d->m_storedPersistentIndexes.at(i);
- if (i == index.row())
- continue;
-
- _q_itemsMoved(i, index.row(), 1);
- }
-
- d->m_storedPersistentIndexes.clear();
-
- // layoutUpdate does not necessarily have any move changes, but it can
- // also mean data changes. We can't detect what exactly has changed, so
- // just emit it for all items
+ // mark all items as changed
_q_itemsChanged(0, d->m_count, QVector<int>());
} else if (hint == QAbstractItemModel::HorizontalSortHint) {
diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
index aea474de67..2986ec7ce5 100644
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ b/src/qml/types/qqmldelegatemodel_p.h
@@ -146,7 +146,6 @@ private Q_SLOTS:
void _q_rowsRemoved(const QModelIndex &,int,int);
void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
void _q_dataChanged(const QModelIndex&,const QModelIndex&,const QVector<int> &);
- void _q_layoutAboutToBeChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint);
void _q_layoutChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint);
private:
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 8e2d1c1cb3..76e55f718d 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -337,8 +337,6 @@ public:
};
QQmlDelegateModelGroup *m_groups[Compositor::MaximumGroupCount];
};
-
- QList<QPersistentModelIndex> m_storedPersistentIndexes;
};
class QQmlPartsModel : public QQmlInstanceModel, public QQmlDelegateModelGroupEmitter
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 15c547b5df..5fc2444b7c 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -470,8 +470,6 @@ public:
vdm, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
QObject::disconnect(aim, SIGNAL(modelReset()),
vdm, SLOT(_q_modelReset()));
- QObject::disconnect(aim, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- vdm, SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
QObject::disconnect(aim, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
vdm, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
}
@@ -928,8 +926,6 @@ void QQmlAdaptorModel::setModel(const QVariant &variant, QQmlDelegateModel *vdm,
vdm, QQmlDelegateModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
qmlobject_connect(model, QAbstractItemModel, SIGNAL(modelReset()),
vdm, QQmlDelegateModel, SLOT(_q_modelReset()));
- qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- vdm, QQmlDelegateModel, SLOT(_q_layoutAboutToBeChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
qmlobject_connect(model, QAbstractItemModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
vdm, QQmlDelegateModel, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
} else {
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 9ba93a1241..bc26a19033 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -352,7 +352,7 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
QTestRootObject::instance()->init();
QString path = fi.absoluteFilePath();
if (path.startsWith(QLatin1String(":/")))
- view->setSource(QUrl(QLatin1String("qrc:") + path.mid(2)));
+ view->setSource(QUrl(QLatin1String("qrc:") + path.midRef(2)));
else
view->setSource(QUrl::fromLocalFile(path));
diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp
index 46808f978b..63b4102b10 100644
--- a/src/quick/designer/qqmldesignermetaobject.cpp
+++ b/src/quick/designer/qqmldesignermetaobject.cpp
@@ -79,23 +79,9 @@ struct MetaPropertyData {
QVector<QPair<QVariant, bool> > m_data;
};
-static bool constructedMetaData(const QQmlVMEMetaData* data)
-{
- return data->propertyCount == 0
- && data->aliasCount == 0
- && data->signalCount == 0
- && data->methodCount == 0;
-}
-
static QQmlVMEMetaData* fakeMetaData()
{
- QQmlVMEMetaData* data = new QQmlVMEMetaData;
- data->propertyCount = 0;
- data->aliasCount = 0;
- data->signalCount = 0;
- data->methodCount = 0;
-
- return data;
+ return new QQmlVMEMetaData;
}
static const QQmlVMEMetaData* vMEMetaDataForObject(QObject *object)
@@ -125,7 +111,15 @@ QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObjec
return static_cast<QQmlDesignerMetaObject *>(parent);
// we just create one and the ownership goes automatically to the object in nodeinstance see init method
- return new QQmlDesignerMetaObject(object, engine);
+
+ QQmlData *ddata = QQmlData::get(object, false);
+
+ const bool hadVMEMetaObject = ddata ? ddata->hasVMEMetaObject : false;
+ QQmlDesignerMetaObject *mo = new QQmlDesignerMetaObject(object, engine);
+ //If our parent is not a VMEMetaObject we just set the flag to false again
+ if (ddata)
+ ddata->hasVMEMetaObject = hadVMEMetaObject;
+ return mo;
}
void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine)
@@ -140,20 +134,20 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine)
QObjectPrivate *op = QObjectPrivate::get(object);
op->metaObject = this;
- //create cache
- cache = m_cache = QQmlEnginePrivate::get(engine)->cache(this);
- cache->addref();
+ m_cache = QQmlEnginePrivate::get(engine)->cache(this);
- //If our parent is not a VMEMetaObject we just se the flag to false again
- if (constructedMetaData(metaData))
- QQmlData::get(object)->hasVMEMetaObject = false;
+ if (m_cache != cache) {
+ m_cache->addref();
+ cache->release();
+ cache = m_cache;
+ }
nodeInstanceMetaObjectList.insert(this, true);
hasAssignedMetaObjectData = true;
}
QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine)
- : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object)),
+ : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object), /*qml compilation unit*/nullptr, /*qmlObjectId*/-1),
m_context(engine->contextForObject(object)),
m_data(new MetaPropertyData),
m_cache(0)
@@ -161,22 +155,20 @@ QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engi
init(object, engine);
QQmlData *ddata = QQmlData::get(object, false);
-
//Assign cache to object
if (ddata && ddata->propertyCache) {
cache->setParent(ddata->propertyCache);
cache->invalidate(engine, this);
+ ddata->propertyCache->release();
ddata->propertyCache = m_cache;
+ m_cache->addref();
}
}
QQmlDesignerMetaObject::~QQmlDesignerMetaObject()
{
- if (cache->count() > 1) // qml is crashing because the property cache is not removed from the engine
- cache->release();
- else
- m_type->release();
+ m_type->release();
nodeInstanceMetaObjectList.remove(this);
}
diff --git a/src/quick/designer/qqmldesignermetaobject_p.h b/src/quick/designer/qqmldesignermetaobject_p.h
index c45f83dc1e..a5402ccbc4 100644
--- a/src/quick/designer/qqmldesignermetaobject_p.h
+++ b/src/quick/designer/qqmldesignermetaobject_p.h
@@ -70,7 +70,6 @@ public:
static void registerNotifyPropertyChangeCallBack(void (*callback)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName));
protected:
- QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine);
static QQmlDesignerMetaObject* getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine);
void createNewDynamicProperty(const QString &name);
@@ -95,6 +94,7 @@ protected:
void copyTypeMetaObject();
private:
+ QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine);
void init(QObject *, QQmlEngine *engine);
QPointer<QQmlContext> m_context;
diff --git a/src/quick/designer/qquickdesignersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp
index ec00eed18a..f063cd3a81 100644
--- a/src/quick/designer/qquickdesignersupport.cpp
+++ b/src/quick/designer/qquickdesignersupport.cpp
@@ -189,17 +189,17 @@ QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem)
return parentTransform;
}
-QString propertyNameForAnchorLine(const QQuickAnchorLine::AnchorLine &anchorLine)
+QString propertyNameForAnchorLine(const QQuickAnchors::Anchor &anchorLine)
{
switch (anchorLine) {
- case QQuickAnchorLine::Left: return QLatin1String("left");
- case QQuickAnchorLine::Right: return QLatin1String("right");
- case QQuickAnchorLine::Top: return QLatin1String("top");
- case QQuickAnchorLine::Bottom: return QLatin1String("bottom");
- case QQuickAnchorLine::HCenter: return QLatin1String("horizontalCenter");
- case QQuickAnchorLine::VCenter: return QLatin1String("verticalCenter");
- case QQuickAnchorLine::Baseline: return QLatin1String("baseline");
- case QQuickAnchorLine::Invalid:
+ case QQuickAnchors::LeftAnchor: return QLatin1String("left");
+ case QQuickAnchors::RightAnchor: return QLatin1String("right");
+ case QQuickAnchors::TopAnchor: return QLatin1String("top");
+ case QQuickAnchors::BottomAnchor: return QLatin1String("bottom");
+ case QQuickAnchors::HCenterAnchor: return QLatin1String("horizontalCenter");
+ case QQuickAnchors::VCenterAnchor: return QLatin1String("verticalCenter");
+ case QQuickAnchors::BaselineAnchor: return QLatin1String("baseline");
+ case QQuickAnchors::InvalidAnchor: // fallthrough:
default: return QString();
}
}
@@ -345,7 +345,7 @@ QPair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *ite
return QPair<QString, QObject*>();
QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
- if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
+ if (anchorLine.anchorLine != QQuickAnchors::InvalidAnchor) {
targetObject = anchorLine.item;
targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
}
diff --git a/src/quick/doc/snippets/qml/externaldrag.qml b/src/quick/doc/snippets/qml/externaldrag.qml
new file mode 100644
index 0000000000..096a7702b4
--- /dev/null
+++ b/src/quick/doc/snippets/qml/externaldrag.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd 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$
+**
+****************************************************************************/
+//![0]
+import QtQuick 2.8
+
+Item {
+ width: 200; height: 200
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: text.implicitWidth + 20; height: text.implicitHeight + 10
+ color: "green"
+ radius: 5
+
+ Drag.active: dragArea.drag.active
+ Drag.dragType: Drag.Automatic
+ Drag.supportedActions: Qt.CopyAction
+ Drag.mimeData: {
+ "text/plain": "Copied text"
+ }
+
+ Text {
+ id: text
+ anchors.centerIn: parent
+ text: "Drag me"
+ }
+
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+
+ drag.target: parent
+ onPressed: parent.grabToImage(function(result) {
+ parent.Drag.imageSource = result.url
+ })
+ }
+ }
+}
+//![0]
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index b43adac0c5..7e7b1fa062 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -66,6 +66,7 @@
#include <private/qv4scopedvalue_p.h>
#include <QtCore/qmath.h>
+#include <QtCore/qvector.h>
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/QRunnable>
#include <QtGui/qguiapplication.h>
@@ -205,7 +206,7 @@ QColor qt_color_from_string(const QV4::Value &name)
return QColor();
}
-static int qParseFontSizeFromToken(const QString &fontSizeToken, bool &ok)
+static int qParseFontSizeFromToken(const QStringRef &fontSizeToken, bool &ok)
{
ok = false;
float size = fontSizeToken.trimmed().toFloat(&ok);
@@ -221,11 +222,11 @@ static int qParseFontSizeFromToken(const QString &fontSizeToken, bool &ok)
\c true if successful. If the font size is invalid, \c false is returned
and a warning is printed.
*/
-static bool qSetFontSizeFromToken(QFont &font, const QString &fontSizeToken)
+static bool qSetFontSizeFromToken(QFont &font, const QStringRef &fontSizeToken)
{
- const QString trimmedToken = fontSizeToken.trimmed();
- const QString unitStr = trimmedToken.right(2);
- const QString value = trimmedToken.left(trimmedToken.size() - 2);
+ const QStringRef trimmedToken = fontSizeToken.trimmed();
+ const QStringRef unitStr = trimmedToken.right(2);
+ const QStringRef value = trimmedToken.left(trimmedToken.size() - 2);
bool ok = false;
int size = 0;
if (unitStr == QLatin1String("px")) {
@@ -251,7 +252,7 @@ static bool qSetFontSizeFromToken(QFont &font, const QString &fontSizeToken)
each family is separated by spaces. Families with spaces in their name
must be quoted.
*/
-static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesString)
+static QStringList qExtractFontFamiliesFromString(const QStringRef &fontFamiliesString)
{
QStringList extractedFamilies;
int quoteIndex = -1;
@@ -264,7 +265,7 @@ static QStringList qExtractFontFamiliesFromString(const QString &fontFamiliesStr
} else {
if (ch == fontFamiliesString.at(quoteIndex)) {
// Found the matching quote. +1/-1 because we don't want the quote as part of the name.
- const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1);
+ const QString family = fontFamiliesString.mid(quoteIndex + 1, index - quoteIndex - 1).toString();
extractedFamilies.push_back(family);
currentFamily.clear();
quoteIndex = -1;
@@ -395,16 +396,17 @@ static QFont qt_font_from_string(const QString& fontString, const QFont &current
fontSizeEnd += 3;
QFont newFont;
- if (!qSetFontSizeFromToken(newFont, fontString.mid(fontSizeStart, fontSizeEnd - fontSizeStart)))
+ if (!qSetFontSizeFromToken(newFont, fontString.midRef(fontSizeStart, fontSizeEnd - fontSizeStart)))
return currentFont;
// We don't want to parse the size twice, so remove it now.
QString remainingFontString = fontString;
remainingFontString.remove(fontSizeStart, fontSizeEnd - fontSizeStart);
+ QStringRef remainingFontStringRef(&remainingFontString);
// Next, we have to take any font families out, as QString::split() will ruin quoted family names.
- const QString fontFamiliesString = remainingFontString.mid(fontSizeStart);
- remainingFontString.chop(remainingFontString.length() - fontSizeStart);
+ const QStringRef fontFamiliesString = remainingFontStringRef.mid(fontSizeStart);
+ remainingFontStringRef.truncate(fontSizeStart);
QStringList fontFamilies = qExtractFontFamiliesFromString(fontFamiliesString);
if (fontFamilies.isEmpty()) {
return currentFont;
@@ -413,16 +415,16 @@ static QFont qt_font_from_string(const QString& fontString, const QFont &current
return currentFont;
// Now that we've removed the messy parts, we can split the font string on spaces.
- const QString trimmedTokensStr = remainingFontString.trimmed();
+ const QStringRef trimmedTokensStr = remainingFontStringRef.trimmed();
if (trimmedTokensStr.isEmpty()) {
// No optional properties.
return newFont;
}
- const QStringList tokens = trimmedTokensStr.split(QLatin1Char(' '));
+ const auto tokens = trimmedTokensStr.split(QLatin1Char(' '));
int usedTokens = NoTokens;
// Optional properties can be in any order, but font-size and font-family must be last.
- for (const QString &token : tokens) {
+ for (const QStringRef &token : tokens) {
if (token.compare(QLatin1String("normal")) == 0) {
if (!(usedTokens & FontStyle) || !(usedTokens & FontVariant) || !(usedTokens & FontWeight)) {
// Could be font-style, font-variant or font-weight.
@@ -943,7 +945,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionE
pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32);
pixelData->d()->image.fill(0x00000000);
} else {
- Q_ASSERT(image.width() == int(w) && image.height() == int(h));
+ Q_ASSERT(image.width() == qRound(w) && image.height() == qRound(h));
pixelData->d()->image = image.format() == QImage::Format_ARGB32 ? image : image.convertToFormat(QImage::Format_ARGB32);
}
@@ -1263,7 +1265,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::CallContext *c
double globalAlpha = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- if (!qIsFinite(globalAlpha))
+ if (!qt_is_finite(globalAlpha))
return QV4::Encode::undefined();
if (globalAlpha >= 0.0 && globalAlpha <= 1.0 && r->d()->context->state.globalAlpha != globalAlpha) {
@@ -1547,10 +1549,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::
qreal x1 = ctx->args()[2].toNumber();
qreal y1 = ctx->args()[3].toNumber();
- if (!qIsFinite(x0)
- || !qIsFinite(y0)
- || !qIsFinite(x1)
- || !qIsFinite(y1)) {
+ if (!qt_is_finite(x0)
+ || !qt_is_finite(y0)
+ || !qt_is_finite(x1)
+ || !qt_is_finite(y1)) {
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
}
QQuickContext2DEngineData *ed = engineData(scope.engine);
@@ -1592,12 +1594,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::
qreal y1 = ctx->args()[4].toNumber();
qreal r1 = ctx->args()[5].toNumber();
- if (!qIsFinite(x0)
- || !qIsFinite(y0)
- || !qIsFinite(x1)
- || !qIsFinite(r0)
- || !qIsFinite(r1)
- || !qIsFinite(y1)) {
+ if (!qt_is_finite(x0)
+ || !qt_is_finite(y0)
+ || !qt_is_finite(x1)
+ || !qt_is_finite(r0)
+ || !qt_is_finite(r1)
+ || !qt_is_finite(y1)) {
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createRadialGradient(): Incorrect arguments")
}
@@ -1639,11 +1641,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
qreal x = ctx->args()[0].toNumber();
qreal y = ctx->args()[1].toNumber();
qreal angle = DEGREES(ctx->args()[2].toNumber());
- if (!qIsFinite(x) || !qIsFinite(y)) {
+ if (!qt_is_finite(x) || !qt_is_finite(y)) {
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createConicalGradient(): Incorrect arguments");
}
- if (!qIsFinite(angle)) {
+ if (!qt_is_finite(angle)) {
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
}
@@ -1894,7 +1896,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::CallContext *ctx
qreal w = ctx->argc() ? ctx->args()[0].toNumber() : -1;
- if (w > 0 && qIsFinite(w) && w != r->d()->context->state.lineWidth) {
+ if (w > 0 && qt_is_finite(w) && w != r->d()->context->state.lineWidth) {
r->d()->context->state.lineWidth = w;
r->d()->context->buffer()->setLineWidth(w);
}
@@ -1923,7 +1925,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::CallContext *ct
qreal ml = ctx->argc() ? ctx->args()[0].toNumber() : -1;
- if (ml > 0 && qIsFinite(ml) && ml != r->d()->context->state.miterLimit) {
+ if (ml > 0 && qt_is_finite(ml) && ml != r->d()->context->state.miterLimit) {
r->d()->context->state.miterLimit = ml;
r->d()->context->buffer()->setMiterLimit(ml);
}
@@ -1952,7 +1954,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::CallContext *ct
qreal blur = ctx->argc() ? ctx->args()[0].toNumber() : -1;
- if (blur > 0 && qIsFinite(blur) && blur != r->d()->context->state.shadowBlur) {
+ if (blur > 0 && qt_is_finite(blur) && blur != r->d()->context->state.shadowBlur) {
r->d()->context->state.shadowBlur = blur;
r->d()->context->buffer()->setShadowBlur(blur);
}
@@ -2012,7 +2014,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::CallContext
CHECK_CONTEXT_SETTER(r)
qreal offsetX = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- if (qIsFinite(offsetX) && offsetX != r->d()->context->state.shadowOffsetX) {
+ if (qt_is_finite(offsetX) && offsetX != r->d()->context->state.shadowOffsetX) {
r->d()->context->state.shadowOffsetX = offsetX;
r->d()->context->buffer()->setShadowOffsetX(offsetX);
}
@@ -2040,7 +2042,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::CallContext
CHECK_CONTEXT_SETTER(r)
qreal offsetY = ctx->argc() ? ctx->args()[0].toNumber() : qt_qnan();
- if (qIsFinite(offsetY) && offsetY != r->d()->context->state.shadowOffsetY) {
+ if (qt_is_finite(offsetY) && offsetY != r->d()->context->state.shadowOffsetY) {
r->d()->context->state.shadowOffsetY = offsetY;
r->d()->context->buffer()->setShadowOffsetY(offsetY);
}
@@ -2170,7 +2172,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::CallContext *ctx)
qreal radius = ctx->args()[2].toNumber();
- if (qIsFinite(radius) && radius < 0)
+ if (qt_is_finite(radius) && radius < 0)
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
r->d()->context->arc(ctx->args()[0].toNumber(),
@@ -2216,7 +2218,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::CallContext *ct
if (ctx->argc() >= 5) {
qreal radius = ctx->args()[4].toNumber();
- if (qIsFinite(radius) && radius < 0)
+ if (qt_is_finite(radius) && radius < 0)
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "Incorrect argument radius");
r->d()->context->arcTo(ctx->args()[0].toNumber(),
@@ -2279,7 +2281,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::CallCon
qreal x = ctx->args()[4].toNumber();
qreal y = ctx->args()[5].toNumber();
- if (!qIsFinite(cp1x) || !qIsFinite(cp1y) || !qIsFinite(cp2x) || !qIsFinite(cp2y) || !qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(cp1x) || !qt_is_finite(cp1y) || !qt_is_finite(cp2x) || !qt_is_finite(cp2y) || !qt_is_finite(x) || !qt_is_finite(y))
return ctx->thisObject().asReturnedValue();
r->d()->context->bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
@@ -2375,7 +2377,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::CallContext *c
qreal x = ctx->args()[0].toNumber();
qreal y = ctx->args()[1].toNumber();
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return ctx->thisObject().asReturnedValue();
r->d()->context->lineTo(x, y);
@@ -2399,7 +2401,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::CallContext *c
qreal x = ctx->args()[0].toNumber();
qreal y = ctx->args()[1].toNumber();
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return ctx->thisObject().asReturnedValue();
r->d()->context->moveTo(x, y);
}
@@ -2425,7 +2427,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::Call
qreal x = ctx->args()[2].toNumber();
qreal y = ctx->args()[3].toNumber();
- if (!qIsFinite(cpx) || !qIsFinite(cpy) || !qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(cpx) || !qt_is_finite(cpy) || !qt_is_finite(x) || !qt_is_finite(y))
return ctx->thisObject().asReturnedValue();
r->d()->context->quadraticCurveTo(cpx, cpy, x, y);
@@ -2509,7 +2511,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::CallContext *ctx
qreal x = ctx->args()[1].toNumber();
qreal y = ctx->args()[2].toNumber();
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return ctx->thisObject().asReturnedValue();
r->d()->context->text(ctx->args()[0].toQStringNoThrow(), x, y);
}
@@ -2774,7 +2776,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::CallContext
if (ctx->argc() >= 3) {
qreal x = ctx->args()[1].toNumber();
qreal y = ctx->args()[2].toNumber();
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return ctx->thisObject().asReturnedValue();
QPainterPath textPath = r->d()->context->createTextGlyphs(x, y, ctx->args()[0].toQStringNoThrow());
r->d()->context->buffer()->fill(textPath);
@@ -2973,14 +2975,14 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext
return ctx->thisObject().asReturnedValue();
}
- if (!qIsFinite(sx)
- || !qIsFinite(sy)
- || !qIsFinite(sw)
- || !qIsFinite(sh)
- || !qIsFinite(dx)
- || !qIsFinite(dy)
- || !qIsFinite(dw)
- || !qIsFinite(dh))
+ if (!qt_is_finite(sx)
+ || !qt_is_finite(sy)
+ || !qt_is_finite(sw)
+ || !qt_is_finite(sh)
+ || !qt_is_finite(dx)
+ || !qt_is_finite(dy)
+ || !qt_is_finite(dw)
+ || !qt_is_finite(dh))
return ctx->thisObject().asReturnedValue();
if (sx < 0
@@ -3201,7 +3203,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC
qreal w = ctx->args()[0].toNumber();
qreal h = ctx->args()[1].toNumber();
- if (!qIsFinite(w) || !qIsFinite(h))
+ if (!qt_is_finite(w) || !qt_is_finite(h))
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments");
if (w > 0 && h > 0)
@@ -3227,7 +3229,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::CallCont
qreal y = ctx->args()[1].toNumber();
qreal w = ctx->args()[2].toNumber();
qreal h = ctx->args()[3].toNumber();
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "getImageData(): Invalid arguments");
if (w <= 0 || h <= 0)
@@ -3259,7 +3261,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont
qreal dy = ctx->args()[2].toNumber();
qreal w, h, dirtyX, dirtyY, dirtyWidth, dirtyHeight;
- if (!qIsFinite(dx) || !qIsFinite(dy))
+ if (!qt_is_finite(dx) || !qt_is_finite(dy))
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, arg0);
@@ -3277,7 +3279,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallCont
dirtyWidth = ctx->args()[5].toNumber();
dirtyHeight = ctx->args()[6].toNumber();
- if (!qIsFinite(dirtyX) || !qIsFinite(dirtyY) || !qIsFinite(dirtyWidth) || !qIsFinite(dirtyHeight))
+ if (!qt_is_finite(dirtyX) || !qt_is_finite(dirtyY) || !qt_is_finite(dirtyWidth) || !qt_is_finite(dirtyHeight))
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "putImageData() : Invalid arguments");
@@ -3364,7 +3366,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo
} else {
color = qt_color_from_string(ctx->args()[1]);
}
- if (pos < 0.0 || pos > 1.0 || !qIsFinite(pos)) {
+ if (pos < 0.0 || pos > 1.0 || !qt_is_finite(pos)) {
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "CanvasGradient: parameter offset out of range");
}
@@ -3384,7 +3386,7 @@ void QQuickContext2D::scale(qreal x, qreal y)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return;
QTransform newTransform = state.matrix;
@@ -3405,7 +3407,7 @@ void QQuickContext2D::rotate(qreal angle)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(angle))
+ if (!qt_is_finite(angle))
return;
QTransform newTransform =state.matrix;
@@ -3426,7 +3428,7 @@ void QQuickContext2D::shear(qreal h, qreal v)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(h) || !qIsFinite(v))
+ if (!qt_is_finite(h) || !qt_is_finite(v))
return ;
QTransform newTransform = state.matrix;
@@ -3447,7 +3449,7 @@ void QQuickContext2D::translate(qreal x, qreal y)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return ;
QTransform newTransform = state.matrix;
@@ -3468,7 +3470,7 @@ void QQuickContext2D::transform(qreal a, qreal b, qreal c, qreal d, qreal e, qre
if (!state.invertibleCTM)
return;
- if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f))
+ if (!qt_is_finite(a) || !qt_is_finite(b) || !qt_is_finite(c) || !qt_is_finite(d) || !qt_is_finite(e) || !qt_is_finite(f))
return;
QTransform transform(a, b, c, d, e, f);
@@ -3485,7 +3487,7 @@ void QQuickContext2D::transform(qreal a, qreal b, qreal c, qreal d, qreal e, qre
void QQuickContext2D::setTransform(qreal a, qreal b, qreal c, qreal d, qreal e, qreal f)
{
- if (!qIsFinite(a) || !qIsFinite(b) || !qIsFinite(c) || !qIsFinite(d) || !qIsFinite(e) || !qIsFinite(f))
+ if (!qt_is_finite(a) || !qt_is_finite(b) || !qt_is_finite(c) || !qt_is_finite(d) || !qt_is_finite(e) || !qt_is_finite(f))
return;
QTransform ctm = state.matrix;
@@ -3542,7 +3544,7 @@ void QQuickContext2D::fillRect(qreal x, qreal y, qreal w, qreal h)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
return;
buffer()->fillRect(QRectF(x, y, w, h));
@@ -3553,7 +3555,7 @@ void QQuickContext2D::strokeRect(qreal x, qreal y, qreal w, qreal h)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
return;
buffer()->strokeRect(QRectF(x, y, w, h));
@@ -3564,7 +3566,7 @@ void QQuickContext2D::clearRect(qreal x, qreal y, qreal w, qreal h)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
return;
buffer()->clearRect(QRectF(x, y, w, h));
@@ -3575,7 +3577,7 @@ void QQuickContext2D::drawText(const QString& text, qreal x, qreal y, bool fill)
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return;
QPainterPath textPath = createTextGlyphs(x, y, text);
@@ -3721,7 +3723,7 @@ void QQuickContext2D::arcTo(qreal x1, qreal y1,
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2) || !qIsFinite(radius))
+ if (!qt_is_finite(x1) || !qt_is_finite(y1) || !qt_is_finite(x2) || !qt_is_finite(y2) || !qt_is_finite(radius))
return;
QPointF st(x1, y1);
@@ -3739,7 +3741,7 @@ void QQuickContext2D::rect(qreal x, qreal y, qreal w, qreal h)
{
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
return;
if (!w && !h) {
@@ -3756,7 +3758,7 @@ void QQuickContext2D::roundedRect(qreal x, qreal y,
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h) || !qIsFinite(xr) || !qIsFinite(yr))
+ if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h) || !qt_is_finite(xr) || !qt_is_finite(yr))
return;
if (!w && !h) {
@@ -3772,7 +3774,7 @@ void QQuickContext2D::ellipse(qreal x, qreal y,
if (!state.invertibleCTM)
return;
- if (!qIsFinite(x) || !qIsFinite(y) || !qIsFinite(w) || !qIsFinite(h))
+ if (!qt_is_finite(x) || !qt_is_finite(y) || !qt_is_finite(w) || !qt_is_finite(h))
return;
if (!w && !h) {
@@ -3798,7 +3800,7 @@ void QQuickContext2D::arc(qreal xc, qreal yc, qreal radius, qreal sar, qreal ear
if (!state.invertibleCTM)
return;
- if (!qIsFinite(xc) || !qIsFinite(yc) || !qIsFinite(sar) || !qIsFinite(ear) || !qIsFinite(radius))
+ if (!qt_is_finite(xc) || !qt_is_finite(yc) || !qt_is_finite(sar) || !qt_is_finite(ear) || !qt_is_finite(radius))
return;
if (sar == ear)
@@ -3937,13 +3939,13 @@ bool QQuickContext2D::isPointInPath(qreal x, qreal y) const
if (!m_path.elementCount())
return false;
- if (!qIsFinite(x) || !qIsFinite(y))
+ if (!qt_is_finite(x) || !qt_is_finite(y))
return false;
QPointF point(x, y);
QTransform ctm = state.matrix;
QPointF p = ctm.inverted().map(point);
- if (!qIsFinite(p.x()) || !qIsFinite(p.y()))
+ if (!qt_is_finite(p.x()) || !qt_is_finite(p.y()))
return false;
const_cast<QQuickContext2D *>(this)->m_path.setFillRule(state.fillRule);
diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp
index d87669df56..4cbd41106e 100644
--- a/src/quick/items/qquickanchors.cpp
+++ b/src/quick/items/qquickanchors.cpp
@@ -39,19 +39,48 @@
#include "qquickanchors_p_p.h"
-#include "qquickitem.h"
#include "qquickitem_p.h"
#include <qqmlinfo.h>
QT_BEGIN_NAMESPACE
+static Q_ALWAYS_INLINE QQuickItem *readParentItem(const QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->parentItem;
+}
+
+static Q_ALWAYS_INLINE qreal readX(const QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->x;
+}
+
+static Q_ALWAYS_INLINE qreal readY(const QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->y;
+}
+
+static Q_ALWAYS_INLINE qreal readWidth(const QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->width;
+}
+
+static Q_ALWAYS_INLINE qreal readHeight(const QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->height;
+}
+
+static Q_ALWAYS_INLINE qreal readBaselineOffset(const QQuickItem *item)
+{
+ return QQuickItemPrivate::get(item)->baselineOffset;
+}
+
//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
//TODO: support non-parent, non-sibling (need to find lowest common ancestor)
-static inline qreal hcenter(QQuickItem const *item)
+static inline qreal hcenter(const QQuickItem *item)
{
- qreal width = item->width();
+ qreal width = readWidth(item);
if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
return width / 2;
@@ -63,9 +92,9 @@ static inline qreal hcenter(QQuickItem const *item)
return width / 2;
}
-static inline qreal vcenter(QQuickItem const *item)
+static inline qreal vcenter(const QQuickItem *item)
{
- qreal height = item->height();
+ qreal height = readHeight(item);
if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) {
if (!QQuickAnchorsPrivate::get(anchors)->centerAligned)
return height / 2;
@@ -78,30 +107,30 @@ static inline qreal vcenter(QQuickItem const *item)
}
//local position
-static qreal position(QQuickItem const *item, QQuickAnchorLine::AnchorLine anchorLine)
+static inline qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
{
qreal ret = 0.0;
switch (anchorLine) {
- case QQuickAnchorLine::Left:
- ret = item->x();
+ case QQuickAnchors::LeftAnchor:
+ ret = readX(item);
break;
- case QQuickAnchorLine::Right:
- ret = item->x() + item->width();
+ case QQuickAnchors::RightAnchor:
+ ret = readX(item) + readWidth(item);
break;
- case QQuickAnchorLine::Top:
- ret = item->y();
+ case QQuickAnchors::TopAnchor:
+ ret = readY(item);
break;
- case QQuickAnchorLine::Bottom:
- ret = item->y() + item->height();
+ case QQuickAnchors::BottomAnchor:
+ ret = readY(item) + readHeight(item);
break;
- case QQuickAnchorLine::HCenter:
- ret = item->x() + hcenter(item);
+ case QQuickAnchors::HCenterAnchor:
+ ret = readX(item) + hcenter(item);
break;
- case QQuickAnchorLine::VCenter:
- ret = item->y() + vcenter(item);
+ case QQuickAnchors::VCenterAnchor:
+ ret = readY(item) + vcenter(item);
break;
- case QQuickAnchorLine::Baseline:
- ret = item->y() + item->baselineOffset();
+ case QQuickAnchors::BaselineAnchor:
+ ret = readY(item) + readBaselineOffset(item);
break;
default:
break;
@@ -111,30 +140,30 @@ static qreal position(QQuickItem const *item, QQuickAnchorLine::AnchorLine ancho
}
//position when origin is 0,0
-static qreal adjustedPosition(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine)
+static inline qreal adjustedPosition(QQuickItem *item, QQuickAnchors::Anchor anchorLine)
{
qreal ret = 0.0;
switch (anchorLine) {
- case QQuickAnchorLine::Left:
+ case QQuickAnchors::LeftAnchor:
ret = 0.0;
break;
- case QQuickAnchorLine::Right:
- ret = item->width();
+ case QQuickAnchors::RightAnchor:
+ ret = readWidth(item);
break;
- case QQuickAnchorLine::Top:
+ case QQuickAnchors::TopAnchor:
ret = 0.0;
break;
- case QQuickAnchorLine::Bottom:
- ret = item->height();
+ case QQuickAnchors::BottomAnchor:
+ ret = readHeight(item);
break;
- case QQuickAnchorLine::HCenter:
+ case QQuickAnchors::HCenterAnchor:
ret = hcenter(item);
break;
- case QQuickAnchorLine::VCenter:
+ case QQuickAnchors::VCenterAnchor:
ret = vcenter(item);
break;
- case QQuickAnchorLine::Baseline:
- ret = item->baselineOffset();
+ case QQuickAnchors::BaselineAnchor:
+ ret = readBaselineOffset(item);
break;
default:
break;
@@ -154,13 +183,13 @@ QQuickAnchors::~QQuickAnchors()
d->inDestructor = true;
d->remDepend(d->fill);
d->remDepend(d->centerIn);
- d->remDepend(d->left.item);
- d->remDepend(d->right.item);
- d->remDepend(d->top.item);
- d->remDepend(d->bottom.item);
- d->remDepend(d->vCenter.item);
- d->remDepend(d->hCenter.item);
- d->remDepend(d->baseline.item);
+ d->remDepend(d->leftAnchorItem);
+ d->remDepend(d->rightAnchorItem);
+ d->remDepend(d->topAnchorItem);
+ d->remDepend(d->bottomAnchorItem);
+ d->remDepend(d->vCenterAnchorItem);
+ d->remDepend(d->hCenterAnchorItem);
+ d->remDepend(d->baselineAnchorItem);
}
void QQuickAnchorsPrivate::fillChanged()
@@ -174,12 +203,13 @@ void QQuickAnchorsPrivate::fillChanged()
qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
- if (fill == item->parentItem()) { //child-parent
+ if (fill == readParentItem(item)) { //child-parent
setItemPos(QPointF(horizontalMargin, topMargin));
- } else if (fill->parentItem() == item->parentItem()) { //siblings
- setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin));
+ } else if (readParentItem(fill) == readParentItem(item)) { //siblings
+ setItemPos(QPointF(readX(fill)+horizontalMargin, readY(fill) + topMargin));
}
- setItemSize(QSizeF(fill->width()-leftMargin-rightMargin, fill->height()-topMargin-bottomMargin));
+ setItemSize(QSizeF(readWidth(fill) - leftMargin - rightMargin,
+ readHeight(fill) - topMargin - bottomMargin));
--updatingFill;
} else {
@@ -199,12 +229,12 @@ void QQuickAnchorsPrivate::centerInChanged()
++updatingCenterIn;
qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
- if (centerIn == item->parentItem()) {
- QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset,
- vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
+ if (centerIn == readParentItem(item)) {
+ QPointF p(hcenter(readParentItem(item)) - hcenter(item) + effectiveHCenterOffset,
+ vcenter(readParentItem(item)) - vcenter(item) + vCenterOffset);
setItemPos(p);
- } else if (centerIn->parentItem() == item->parentItem()) {
+ } else if (readParentItem(centerIn) == readParentItem(item)) {
QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + effectiveHCenterOffset,
centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
setItemPos(p);
@@ -225,32 +255,32 @@ void QQuickAnchorsPrivate::clearItem(QQuickItem *item)
fill = 0;
if (centerIn == item)
centerIn = 0;
- if (left.item == item) {
- left.item = 0;
+ if (leftAnchorItem == item) {
+ leftAnchorItem = 0;
usedAnchors &= ~QQuickAnchors::LeftAnchor;
}
- if (right.item == item) {
- right.item = 0;
+ if (rightAnchorItem == item) {
+ rightAnchorItem = 0;
usedAnchors &= ~QQuickAnchors::RightAnchor;
}
- if (top.item == item) {
- top.item = 0;
+ if (topAnchorItem == item) {
+ topAnchorItem = 0;
usedAnchors &= ~QQuickAnchors::TopAnchor;
}
- if (bottom.item == item) {
- bottom.item = 0;
+ if (bottomAnchorItem == item) {
+ bottomAnchorItem = 0;
usedAnchors &= ~QQuickAnchors::BottomAnchor;
}
- if (vCenter.item == item) {
- vCenter.item = 0;
+ if (vCenterAnchorItem == item) {
+ vCenterAnchorItem = 0;
usedAnchors &= ~QQuickAnchors::VCenterAnchor;
}
- if (hCenter.item == item) {
- hCenter.item = 0;
+ if (hCenterAnchorItem == item) {
+ hCenterAnchorItem = 0;
usedAnchors &= ~QQuickAnchors::HCenterAnchor;
}
- if (baseline.item == item) {
- baseline.item = 0;
+ if (baselineAnchorItem == item) {
+ baselineAnchorItem = 0;
usedAnchors &= ~QQuickAnchors::BaselineAnchor;
}
}
@@ -263,7 +293,7 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem)
return dependency;
if (fill == controlItem) {
- if (controlItem == item->parentItem())
+ if (controlItem == readParentItem(item))
dependency |= QQuickItemPrivate::SizeChange;
else //sibling
dependency |= QQuickItemPrivate::GeometryChange;
@@ -271,27 +301,27 @@ int QQuickAnchorsPrivate::calculateDependency(QQuickItem *controlItem)
}
if (centerIn == controlItem) {
- if (controlItem == item->parentItem())
+ if (controlItem == readParentItem(item))
dependency |= QQuickItemPrivate::SizeChange;
else //sibling
dependency |= QQuickItemPrivate::GeometryChange;
return dependency; //exit early
}
- if ((usedAnchors & QQuickAnchors::LeftAnchor && left.item == controlItem) ||
- (usedAnchors & QQuickAnchors::RightAnchor && right.item == controlItem) ||
- (usedAnchors & QQuickAnchors::HCenterAnchor && hCenter.item == controlItem)) {
- if (controlItem == item->parentItem())
+ if ((usedAnchors & QQuickAnchors::LeftAnchor && leftAnchorItem == controlItem) ||
+ (usedAnchors & QQuickAnchors::RightAnchor && rightAnchorItem == controlItem) ||
+ (usedAnchors & QQuickAnchors::HCenterAnchor && hCenterAnchorItem == controlItem)) {
+ if (controlItem == readParentItem(item))
dependency |= QQuickItemPrivate::WidthChange;
else //sibling
dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::XChange | QQuickItemPrivate::WidthChange);
}
- if ((usedAnchors & QQuickAnchors::TopAnchor && top.item == controlItem) ||
- (usedAnchors & QQuickAnchors::BottomAnchor && bottom.item == controlItem) ||
- (usedAnchors & QQuickAnchors::VCenterAnchor && vCenter.item == controlItem) ||
- (usedAnchors & QQuickAnchors::BaselineAnchor && baseline.item == controlItem)) {
- if (controlItem == item->parentItem())
+ if ((usedAnchors & QQuickAnchors::TopAnchor && topAnchorItem == controlItem) ||
+ (usedAnchors & QQuickAnchors::BottomAnchor && bottomAnchorItem == controlItem) ||
+ (usedAnchors & QQuickAnchors::VCenterAnchor && vCenterAnchorItem == controlItem) ||
+ (usedAnchors & QQuickAnchors::BaselineAnchor && baselineAnchorItem == controlItem)) {
+ if (controlItem == readParentItem(item))
dependency |= QQuickItemPrivate::HeightChange;
else //sibling
dependency |= QFlags<QQuickItemPrivate::GeometryChangeType>(QQuickItemPrivate::YChange | QQuickItemPrivate::HeightChange);
@@ -422,13 +452,13 @@ void QQuickAnchorsPrivate::updateOnComplete()
QQuickItem *dependencies[9];
dependencies[0] = fill;
dependencies[1] = centerIn;
- dependencies[2] = left.item;
- dependencies[3] = right.item;
- dependencies[4] = hCenter.item;
- dependencies[5] = top.item;
- dependencies[6] = bottom.item;
- dependencies[7] = vCenter.item;
- dependencies[8] = baseline.item;
+ dependencies[2] = leftAnchorItem;
+ dependencies[3] = rightAnchorItem;
+ dependencies[4] = hCenterAnchorItem;
+ dependencies[5] = topAnchorItem;
+ dependencies[6] = bottomAnchorItem;
+ dependencies[7] = vCenterAnchorItem;
+ dependencies[8] = baselineAnchorItem;
std::sort(dependencies, dependencies + 9);
@@ -447,22 +477,38 @@ void QQuickAnchorsPrivate::updateOnComplete()
void QQuickAnchorsPrivate::update()
{
- fillChanged();
- centerInChanged();
- if (usedAnchors & QQuickAnchorLine::Horizontal_Mask)
- updateHorizontalAnchors();
- if (usedAnchors & QQuickAnchorLine::Vertical_Mask)
- updateVerticalAnchors();
+ if (!isItemComplete())
+ return;
+
+ if (fill) {
+ fillChanged();
+ } else if (centerIn) {
+ centerInChanged();
+ } else {
+ if (usedAnchors & QQuickAnchors::Horizontal_Mask)
+ updateHorizontalAnchors();
+ if (usedAnchors & QQuickAnchors::Vertical_Mask)
+ updateVerticalAnchors();
+ }
}
void QQuickAnchorsPrivate::itemGeometryChanged(QQuickItem *, const QRectF &newG, const QRectF &oldG)
{
- fillChanged();
- centerInChanged();
- if ((usedAnchors & QQuickAnchorLine::Horizontal_Mask) && (newG.x() != oldG.x() || newG.width() != oldG.width()))
- updateHorizontalAnchors();
- if ((usedAnchors & QQuickAnchorLine::Vertical_Mask) && (newG.y() != oldG.y() || newG.height() != oldG.height()))
- updateVerticalAnchors();
+ if (!isItemComplete())
+ return;
+
+ if (fill) {
+ fillChanged();
+ } else if (centerIn) {
+ centerInChanged();
+ } else {
+ if ((usedAnchors & QQuickAnchors::Horizontal_Mask)
+ && (newG.x() != oldG.x() || newG.width() != oldG.width()))
+ updateHorizontalAnchors();
+ if ((usedAnchors & QQuickAnchors::Vertical_Mask)
+ && (newG.y() != oldG.y() || newG.height() != oldG.height()))
+ updateVerticalAnchors();
+ }
}
QQuickItem *QQuickAnchors::fill() const
@@ -484,7 +530,7 @@ void QQuickAnchors::setFill(QQuickItem *f)
emit fillChanged();
return;
}
- if (f != d->item->parentItem() && f->parentItem() != d->item->parentItem()){
+ if (f != readParentItem(d->item) && readParentItem(f) != readParentItem(d->item)){
qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
return;
}
@@ -520,7 +566,7 @@ void QQuickAnchors::setCenterIn(QQuickItem* c)
emit centerInChanged();
return;
}
- if (c != d->item->parentItem() && c->parentItem() != d->item->parentItem()){
+ if (c != readParentItem(d->item) && readParentItem(c) != readParentItem(d->item)){
qmlInfo(d->item) << tr("Cannot anchor to an item that isn't a parent or sibling.");
return;
}
@@ -537,29 +583,31 @@ void QQuickAnchors::resetCenterIn()
setCenterIn(0);
}
-bool QQuickAnchorsPrivate::calcStretch(const QQuickAnchorLine &edge1,
- const QQuickAnchorLine &edge2,
- qreal offset1,
- qreal offset2,
- QQuickAnchorLine::AnchorLine line,
- qreal &stretch)
+bool QQuickAnchorsPrivate::calcStretch(QQuickItem *edge1Item,
+ QQuickAnchors::Anchor edge1Line,
+ QQuickItem *edge2Item,
+ QQuickAnchors::Anchor edge2Line,
+ qreal offset1,
+ qreal offset2,
+ QQuickAnchors::Anchor line,
+ qreal &stretch)
{
- bool edge1IsParent = (edge1.item == item->parentItem());
- bool edge2IsParent = (edge2.item == item->parentItem());
- bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
- bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
+ bool edge1IsParent = (edge1Item == readParentItem(item));
+ bool edge2IsParent = (edge2Item == readParentItem(item));
+ bool edge1IsSibling = (readParentItem(edge1Item) == readParentItem(item));
+ bool edge2IsSibling = (readParentItem(edge2Item) == readParentItem(item));
bool invalid = false;
if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
- stretch = (position(edge2.item, edge2.anchorLine) + offset2)
- - (position(edge1.item, edge1.anchorLine) + offset1);
+ stretch = (position(edge2Item, edge2Line) + offset2)
+ - (position(edge1Item, edge1Line) + offset1);
} else if (edge2IsParent && edge1IsSibling) {
- stretch = (position(edge2.item, edge2.anchorLine) + offset2)
- - (position(item->parentItem(), line)
- + position(edge1.item, edge1.anchorLine) + offset1);
+ stretch = (position(edge2Item, edge2Line) + offset2)
+ - (position(readParentItem(item), line)
+ + position(edge1Item, edge1Line) + offset1);
} else if (edge2IsSibling && edge1IsParent) {
- stretch = (position(item->parentItem(), line) + position(edge2.item, edge2.anchorLine) + offset2)
- - (position(edge1.item, edge1.anchorLine) + offset1);
+ stretch = (position(readParentItem(item), line) + position(edge2Item, edge2Line) + offset2)
+ - (position(edge1Item, edge1Line) + offset1);
} else
invalid = true;
@@ -578,52 +626,60 @@ void QQuickAnchorsPrivate::updateVerticalAnchors()
bool invalid = true;
qreal height = 0.0;
if (usedAnchors & QQuickAnchors::BottomAnchor) {
- invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QQuickAnchorLine::Top, height);
+ invalid = calcStretch(topAnchorItem, topAnchorLine,
+ bottomAnchorItem, bottomAnchorLine,
+ topMargin, -bottomMargin, QQuickAnchors::TopAnchor, height);
} else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
- invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QQuickAnchorLine::Top, height);
+ invalid = calcStretch(topAnchorItem, topAnchorLine,
+ vCenterAnchorItem, vCenterAnchorLine,
+ topMargin, vCenterOffset, QQuickAnchors::TopAnchor, height);
height *= 2;
}
if (!invalid)
setItemHeight(height);
//Handle top
- if (top.item == item->parentItem()) {
- setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin);
- } else if (top.item->parentItem() == item->parentItem()) {
- setItemY(position(top.item, top.anchorLine) + topMargin);
+ if (topAnchorItem == readParentItem(item)) {
+ setItemY(adjustedPosition(topAnchorItem, topAnchorLine) + topMargin);
+ } else if (readParentItem(topAnchorItem) == readParentItem(item)) {
+ setItemY(position(topAnchorItem, topAnchorLine) + topMargin);
}
} else if (usedAnchors & QQuickAnchors::BottomAnchor) {
//Handle stretching (top + bottom case is handled above)
if (usedAnchors & QQuickAnchors::VCenterAnchor) {
qreal height = 0.0;
- bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
- QQuickAnchorLine::Top, height);
+ bool invalid = calcStretch(vCenterAnchorItem, vCenterAnchorLine,
+ bottomAnchorItem, bottomAnchorLine,
+ vCenterOffset, -bottomMargin, QQuickAnchors::TopAnchor,
+ height);
if (!invalid)
setItemHeight(height*2);
}
//Handle bottom
- if (bottom.item == item->parentItem()) {
- setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
- } else if (bottom.item->parentItem() == item->parentItem()) {
- setItemY(position(bottom.item, bottom.anchorLine) - item->height() - bottomMargin);
+ if (bottomAnchorItem == readParentItem(item)) {
+ setItemY(adjustedPosition(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
+ } else if (readParentItem(bottomAnchorItem) == readParentItem(item)) {
+ setItemY(position(bottomAnchorItem, bottomAnchorLine) - readHeight(item) - bottomMargin);
}
} else if (usedAnchors & QQuickAnchors::VCenterAnchor) {
//(stetching handled above)
//Handle vCenter
- if (vCenter.item == item->parentItem()) {
- setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
+ if (vCenterAnchorItem == readParentItem(item)) {
+ setItemY(adjustedPosition(vCenterAnchorItem, vCenterAnchorLine)
- vcenter(item) + vCenterOffset);
- } else if (vCenter.item->parentItem() == item->parentItem()) {
- setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
+ } else if (readParentItem(vCenterAnchorItem) == readParentItem(item)) {
+ setItemY(position(vCenterAnchorItem, vCenterAnchorLine) - vcenter(item) + vCenterOffset);
}
} else if (usedAnchors & QQuickAnchors::BaselineAnchor) {
//Handle baseline
- if (baseline.item == item->parentItem()) {
- setItemY(adjustedPosition(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
- } else if (baseline.item->parentItem() == item->parentItem()) {
- setItemY(position(baseline.item, baseline.anchorLine) - item->baselineOffset() + baselineOffset);
+ if (baselineAnchorItem == readParentItem(item)) {
+ setItemY(adjustedPosition(baselineAnchorItem, baselineAnchorLine)
+ - readBaselineOffset(item) + baselineOffset);
+ } else if (readParentItem(baselineAnchorItem) == readParentItem(item)) {
+ setItemY(position(baselineAnchorItem, baselineAnchorLine)
+ - readBaselineOffset(item) + baselineOffset);
}
}
--updatingVerticalAnchor;
@@ -633,12 +689,12 @@ void QQuickAnchorsPrivate::updateVerticalAnchors()
}
}
-inline QQuickAnchorLine::AnchorLine reverseAnchorLine(QQuickAnchorLine::AnchorLine anchorLine)
+static inline QQuickAnchors::Anchor reverseAnchorLine(QQuickAnchors::Anchor anchorLine)
{
- if (anchorLine == QQuickAnchorLine::Left) {
- return QQuickAnchorLine::Right;
- } else if (anchorLine == QQuickAnchorLine::Right) {
- return QQuickAnchorLine::Left;
+ if (anchorLine == QQuickAnchors::LeftAnchor) {
+ return QQuickAnchors::RightAnchor;
+ } else if (anchorLine == QQuickAnchors::RightAnchor) {
+ return QQuickAnchors::LeftAnchor;
} else {
return anchorLine;
}
@@ -653,26 +709,30 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors()
if (updatingHorizontalAnchor < 3) {
++updatingHorizontalAnchor;
qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
- QQuickAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter;
+ QQuickItem *effectiveLeftItem, *effectiveRightItem, *effectiveHorizontalCenterItem;
+ QQuickAnchors::Anchor effectiveLeftLine, effectiveRightLine, effectiveHorizontalCenterLine;
QQuickAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
if (q->mirrored()) {
effectiveLeftAnchor = QQuickAnchors::RightAnchor;
effectiveRightAnchor = QQuickAnchors::LeftAnchor;
- effectiveLeft.item = right.item;
- effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine);
- effectiveRight.item = left.item;
- effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine);
- effectiveHorizontalCenter.item = hCenter.item;
- effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine);
+ effectiveLeftItem = rightAnchorItem;
+ effectiveLeftLine = reverseAnchorLine(rightAnchorLine);
+ effectiveRightItem = leftAnchorItem;
+ effectiveRightLine = reverseAnchorLine(leftAnchorLine);
+ effectiveHorizontalCenterItem = hCenterAnchorItem;
+ effectiveHorizontalCenterLine = reverseAnchorLine(hCenterAnchorLine);
effectiveLeftMargin = rightMargin;
effectiveRightMargin = leftMargin;
effectiveHorizontalCenterOffset = -hCenterOffset;
} else {
effectiveLeftAnchor = QQuickAnchors::LeftAnchor;
effectiveRightAnchor = QQuickAnchors::RightAnchor;
- effectiveLeft = left;
- effectiveRight = right;
- effectiveHorizontalCenter = hCenter;
+ effectiveLeftItem = leftAnchorItem;
+ effectiveLeftLine = leftAnchorLine;
+ effectiveRightItem = rightAnchorItem;
+ effectiveRightLine = rightAnchorLine;
+ effectiveHorizontalCenterItem = hCenterAnchorItem;
+ effectiveHorizontalCenterLine = hCenterAnchorLine;
effectiveLeftMargin = leftMargin;
effectiveRightMargin = rightMargin;
effectiveHorizontalCenterOffset = hCenterOffset;
@@ -683,42 +743,53 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors()
bool invalid = true;
qreal width = 0.0;
if (usedAnchors & effectiveRightAnchor) {
- invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QQuickAnchorLine::Left, width);
+ invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
+ effectiveRightItem, effectiveRightLine,
+ effectiveLeftMargin, -effectiveRightMargin,
+ QQuickAnchors::LeftAnchor, width);
} else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
- invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QQuickAnchorLine::Left, width);
+ invalid = calcStretch(effectiveLeftItem, effectiveLeftLine,
+ effectiveHorizontalCenterItem, effectiveHorizontalCenterLine,
+ effectiveLeftMargin, effectiveHorizontalCenterOffset,
+ QQuickAnchors::LeftAnchor, width);
width *= 2;
}
if (!invalid)
setItemWidth(width);
//Handle left
- if (effectiveLeft.item == item->parentItem()) {
- setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
- } else if (effectiveLeft.item->parentItem() == item->parentItem()) {
- setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin);
+ if (effectiveLeftItem == readParentItem(item)) {
+ setItemX(adjustedPosition(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
+ } else if (readParentItem(effectiveLeftItem) == readParentItem(item)) {
+ setItemX(position(effectiveLeftItem, effectiveLeftLine) + effectiveLeftMargin);
}
} else if (usedAnchors & effectiveRightAnchor) {
//Handle stretching (left + right case is handled in updateLeftAnchor)
if (usedAnchors & QQuickAnchors::HCenterAnchor) {
qreal width = 0.0;
- bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin,
- QQuickAnchorLine::Left, width);
+ bool invalid = calcStretch(effectiveHorizontalCenterItem,
+ effectiveHorizontalCenterLine,
+ effectiveRightItem, effectiveRightLine,
+ effectiveHorizontalCenterOffset, -effectiveRightMargin,
+ QQuickAnchors::LeftAnchor, width);
if (!invalid)
setItemWidth(width*2);
}
//Handle right
- if (effectiveRight.item == item->parentItem()) {
- setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
- } else if (effectiveRight.item->parentItem() == item->parentItem()) {
- setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - item->width() - effectiveRightMargin);
+ if (effectiveRightItem == readParentItem(item)) {
+ setItemX(adjustedPosition(effectiveRightItem, effectiveRightLine)
+ - readWidth(item) - effectiveRightMargin);
+ } else if (readParentItem(effectiveRightItem) == readParentItem(item)) {
+ setItemX(position(effectiveRightItem, effectiveRightLine)
+ - readWidth(item) - effectiveRightMargin);
}
} else if (usedAnchors & QQuickAnchors::HCenterAnchor) {
//Handle hCenter
- if (effectiveHorizontalCenter.item == item->parentItem()) {
- setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
- } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) {
- setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset);
+ if (effectiveHorizontalCenterItem == readParentItem(item)) {
+ setItemX(adjustedPosition(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
+ } else if (readParentItem(effectiveHorizontalCenterItem) == readParentItem(item)) {
+ setItemX(position(effectiveHorizontalCenterItem, effectiveHorizontalCenterLine) - hcenter(item) + effectiveHorizontalCenterOffset);
}
}
--updatingHorizontalAnchor;
@@ -731,13 +802,14 @@ void QQuickAnchorsPrivate::updateHorizontalAnchors()
QQuickAnchorLine QQuickAnchors::top() const
{
Q_D(const QQuickAnchors);
- return d->top;
+ return QQuickAnchorLine(d->topAnchorItem, d->topAnchorLine);
}
void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
{
Q_D(QQuickAnchors);
- if (!d->checkVAnchorValid(edge) || d->top == edge)
+ if (!d->checkVAnchorValid(edge) ||
+ (d->topAnchorItem == edge.item && d->topAnchorLine == edge.anchorLine))
return;
d->usedAnchors |= TopAnchor;
@@ -747,10 +819,11 @@ void QQuickAnchors::setTop(const QQuickAnchorLine &edge)
return;
}
- QQuickItem *oldTop = d->top.item;
- d->top = edge;
+ QQuickItem *oldTop = d->topAnchorItem;
+ d->topAnchorItem = edge.item;
+ d->topAnchorLine = edge.anchorLine;
d->remDepend(oldTop);
- d->addDepend(d->top.item);
+ d->addDepend(d->topAnchorItem);
emit topChanged();
d->updateVerticalAnchors();
}
@@ -759,8 +832,9 @@ void QQuickAnchors::resetTop()
{
Q_D(QQuickAnchors);
d->usedAnchors &= ~TopAnchor;
- d->remDepend(d->top.item);
- d->top = QQuickAnchorLine();
+ d->remDepend(d->topAnchorItem);
+ d->topAnchorItem = Q_NULLPTR;
+ d->topAnchorLine = QQuickAnchors::InvalidAnchor;
emit topChanged();
d->updateVerticalAnchors();
}
@@ -768,13 +842,14 @@ void QQuickAnchors::resetTop()
QQuickAnchorLine QQuickAnchors::bottom() const
{
Q_D(const QQuickAnchors);
- return d->bottom;
+ return QQuickAnchorLine(d->bottomAnchorItem, d->bottomAnchorLine);
}
void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
{
Q_D(QQuickAnchors);
- if (!d->checkVAnchorValid(edge) || d->bottom == edge)
+ if (!d->checkVAnchorValid(edge) ||
+ (d->bottomAnchorItem == edge.item && d->bottomAnchorLine == edge.anchorLine))
return;
d->usedAnchors |= BottomAnchor;
@@ -784,10 +859,11 @@ void QQuickAnchors::setBottom(const QQuickAnchorLine &edge)
return;
}
- QQuickItem *oldBottom = d->bottom.item;
- d->bottom = edge;
+ QQuickItem *oldBottom = d->bottomAnchorItem;
+ d->bottomAnchorItem = edge.item;
+ d->bottomAnchorLine = edge.anchorLine;
d->remDepend(oldBottom);
- d->addDepend(d->bottom.item);
+ d->addDepend(d->bottomAnchorItem);
emit bottomChanged();
d->updateVerticalAnchors();
}
@@ -796,8 +872,9 @@ void QQuickAnchors::resetBottom()
{
Q_D(QQuickAnchors);
d->usedAnchors &= ~BottomAnchor;
- d->remDepend(d->bottom.item);
- d->bottom = QQuickAnchorLine();
+ d->remDepend(d->bottomAnchorItem);
+ d->bottomAnchorItem = Q_NULLPTR;
+ d->bottomAnchorLine = QQuickAnchors::InvalidAnchor;
emit bottomChanged();
d->updateVerticalAnchors();
}
@@ -805,13 +882,14 @@ void QQuickAnchors::resetBottom()
QQuickAnchorLine QQuickAnchors::verticalCenter() const
{
Q_D(const QQuickAnchors);
- return d->vCenter;
+ return QQuickAnchorLine(d->vCenterAnchorItem, d->vCenterAnchorLine);
}
void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
{
Q_D(QQuickAnchors);
- if (!d->checkVAnchorValid(edge) || d->vCenter == edge)
+ if (!d->checkVAnchorValid(edge) ||
+ (d->vCenterAnchorItem == edge.item && d->vCenterAnchorLine == edge.anchorLine))
return;
d->usedAnchors |= VCenterAnchor;
@@ -821,10 +899,11 @@ void QQuickAnchors::setVerticalCenter(const QQuickAnchorLine &edge)
return;
}
- QQuickItem *oldVCenter = d->vCenter.item;
- d->vCenter = edge;
+ QQuickItem *oldVCenter = d->vCenterAnchorItem;
+ d->vCenterAnchorItem = edge.item;
+ d->vCenterAnchorLine = edge.anchorLine;
d->remDepend(oldVCenter);
- d->addDepend(d->vCenter.item);
+ d->addDepend(d->vCenterAnchorItem);
emit verticalCenterChanged();
d->updateVerticalAnchors();
}
@@ -833,8 +912,9 @@ void QQuickAnchors::resetVerticalCenter()
{
Q_D(QQuickAnchors);
d->usedAnchors &= ~VCenterAnchor;
- d->remDepend(d->vCenter.item);
- d->vCenter = QQuickAnchorLine();
+ d->remDepend(d->vCenterAnchorItem);
+ d->vCenterAnchorItem = Q_NULLPTR;
+ d->vCenterAnchorLine = QQuickAnchors::InvalidAnchor;
emit verticalCenterChanged();
d->updateVerticalAnchors();
}
@@ -842,13 +922,14 @@ void QQuickAnchors::resetVerticalCenter()
QQuickAnchorLine QQuickAnchors::baseline() const
{
Q_D(const QQuickAnchors);
- return d->baseline;
+ return QQuickAnchorLine(d->baselineAnchorItem, d->baselineAnchorLine);
}
void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
{
Q_D(QQuickAnchors);
- if (!d->checkVAnchorValid(edge) || d->baseline == edge)
+ if (!d->checkVAnchorValid(edge) ||
+ (d->baselineAnchorItem == edge.item && d->baselineAnchorLine == edge.anchorLine))
return;
d->usedAnchors |= BaselineAnchor;
@@ -858,10 +939,11 @@ void QQuickAnchors::setBaseline(const QQuickAnchorLine &edge)
return;
}
- QQuickItem *oldBaseline = d->baseline.item;
- d->baseline = edge;
+ QQuickItem *oldBaseline = d->baselineAnchorItem;
+ d->baselineAnchorItem = edge.item;
+ d->baselineAnchorLine = edge.anchorLine;
d->remDepend(oldBaseline);
- d->addDepend(d->baseline.item);
+ d->addDepend(d->baselineAnchorItem);
emit baselineChanged();
d->updateVerticalAnchors();
}
@@ -870,8 +952,9 @@ void QQuickAnchors::resetBaseline()
{
Q_D(QQuickAnchors);
d->usedAnchors &= ~BaselineAnchor;
- d->remDepend(d->baseline.item);
- d->baseline = QQuickAnchorLine();
+ d->remDepend(d->baselineAnchorItem);
+ d->baselineAnchorItem = Q_NULLPTR;
+ d->baselineAnchorLine = QQuickAnchors::InvalidAnchor;
emit baselineChanged();
d->updateVerticalAnchors();
}
@@ -879,13 +962,14 @@ void QQuickAnchors::resetBaseline()
QQuickAnchorLine QQuickAnchors::left() const
{
Q_D(const QQuickAnchors);
- return d->left;
+ return QQuickAnchorLine(d->leftAnchorItem, d->leftAnchorLine);
}
void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
{
Q_D(QQuickAnchors);
- if (!d->checkHAnchorValid(edge) || d->left == edge)
+ if (!d->checkHAnchorValid(edge) ||
+ (d->leftAnchorItem == edge.item && d->leftAnchorLine == edge.anchorLine))
return;
d->usedAnchors |= LeftAnchor;
@@ -895,10 +979,11 @@ void QQuickAnchors::setLeft(const QQuickAnchorLine &edge)
return;
}
- QQuickItem *oldLeft = d->left.item;
- d->left = edge;
+ QQuickItem *oldLeft = d->leftAnchorItem;
+ d->leftAnchorItem = edge.item;
+ d->leftAnchorLine = edge.anchorLine;
d->remDepend(oldLeft);
- d->addDepend(d->left.item);
+ d->addDepend(d->leftAnchorItem);
emit leftChanged();
d->updateHorizontalAnchors();
}
@@ -907,8 +992,9 @@ void QQuickAnchors::resetLeft()
{
Q_D(QQuickAnchors);
d->usedAnchors &= ~LeftAnchor;
- d->remDepend(d->left.item);
- d->left = QQuickAnchorLine();
+ d->remDepend(d->leftAnchorItem);
+ d->leftAnchorItem = Q_NULLPTR;
+ d->leftAnchorLine = QQuickAnchors::InvalidAnchor;
emit leftChanged();
d->updateHorizontalAnchors();
}
@@ -916,13 +1002,14 @@ void QQuickAnchors::resetLeft()
QQuickAnchorLine QQuickAnchors::right() const
{
Q_D(const QQuickAnchors);
- return d->right;
+ return QQuickAnchorLine(d->rightAnchorItem, d->rightAnchorLine);
}
void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
{
Q_D(QQuickAnchors);
- if (!d->checkHAnchorValid(edge) || d->right == edge)
+ if (!d->checkHAnchorValid(edge) ||
+ (d->rightAnchorItem == edge.item && d->rightAnchorLine == edge.anchorLine))
return;
d->usedAnchors |= RightAnchor;
@@ -932,10 +1019,11 @@ void QQuickAnchors::setRight(const QQuickAnchorLine &edge)
return;
}
- QQuickItem *oldRight = d->right.item;
- d->right = edge;
+ QQuickItem *oldRight = d->rightAnchorItem;
+ d->rightAnchorItem = edge.item;
+ d->rightAnchorLine = edge.anchorLine;
d->remDepend(oldRight);
- d->addDepend(d->right.item);
+ d->addDepend(d->rightAnchorItem);
emit rightChanged();
d->updateHorizontalAnchors();
}
@@ -944,8 +1032,9 @@ void QQuickAnchors::resetRight()
{
Q_D(QQuickAnchors);
d->usedAnchors &= ~RightAnchor;
- d->remDepend(d->right.item);
- d->right = QQuickAnchorLine();
+ d->remDepend(d->rightAnchorItem);
+ d->rightAnchorItem = Q_NULLPTR;
+ d->rightAnchorLine = QQuickAnchors::InvalidAnchor;
emit rightChanged();
d->updateHorizontalAnchors();
}
@@ -953,13 +1042,14 @@ void QQuickAnchors::resetRight()
QQuickAnchorLine QQuickAnchors::horizontalCenter() const
{
Q_D(const QQuickAnchors);
- return d->hCenter;
+ return QQuickAnchorLine(d->hCenterAnchorItem, d->hCenterAnchorLine);
}
void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
{
Q_D(QQuickAnchors);
- if (!d->checkHAnchorValid(edge) || d->hCenter == edge)
+ if (!d->checkHAnchorValid(edge) ||
+ (d->hCenterAnchorItem == edge.item && d->hCenterAnchorLine == edge.anchorLine))
return;
d->usedAnchors |= HCenterAnchor;
@@ -969,10 +1059,11 @@ void QQuickAnchors::setHorizontalCenter(const QQuickAnchorLine &edge)
return;
}
- QQuickItem *oldHCenter = d->hCenter.item;
- d->hCenter = edge;
+ QQuickItem *oldHCenter = d->hCenterAnchorItem;
+ d->hCenterAnchorItem = edge.item;
+ d->hCenterAnchorLine = edge.anchorLine;
d->remDepend(oldHCenter);
- d->addDepend(d->hCenter.item);
+ d->addDepend(d->hCenterAnchorItem);
emit horizontalCenterChanged();
d->updateHorizontalAnchors();
}
@@ -981,8 +1072,9 @@ void QQuickAnchors::resetHorizontalCenter()
{
Q_D(QQuickAnchors);
d->usedAnchors &= ~HCenterAnchor;
- d->remDepend(d->hCenter.item);
- d->hCenter = QQuickAnchorLine();
+ d->remDepend(d->hCenterAnchorItem);
+ d->hCenterAnchorItem = Q_NULLPTR;
+ d->hCenterAnchorLine = QQuickAnchors::InvalidAnchor;
emit horizontalCenterChanged();
d->updateHorizontalAnchors();
}
@@ -1230,7 +1322,7 @@ void QQuickAnchors::setBaselineOffset(qreal offset)
QQuickAnchors::Anchors QQuickAnchors::usedAnchors() const
{
Q_D(const QQuickAnchors);
- return d->usedAnchors;
+ return static_cast<QQuickAnchors::Anchors>(d->usedAnchors);
}
bool QQuickAnchorsPrivate::checkHValid() const
@@ -1250,10 +1342,11 @@ bool QQuickAnchorsPrivate::checkHAnchorValid(QQuickAnchorLine anchor) const
if (!anchor.item) {
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
return false;
- } else if (anchor.anchorLine & QQuickAnchorLine::Vertical_Mask) {
+ } else if (anchor.anchorLine & QQuickAnchors::Vertical_Mask) {
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a horizontal edge to a vertical edge.");
return false;
- } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ } else if (anchor.item != readParentItem(item)
+ && readParentItem(anchor.item) != readParentItem(item)) {
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
return false;
} else if (anchor.item == item) {
@@ -1287,10 +1380,11 @@ bool QQuickAnchorsPrivate::checkVAnchorValid(QQuickAnchorLine anchor) const
if (!anchor.item) {
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to a null item.");
return false;
- } else if (anchor.anchorLine & QQuickAnchorLine::Horizontal_Mask) {
+ } else if (anchor.anchorLine & QQuickAnchors::Horizontal_Mask) {
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor a vertical edge to a horizontal edge.");
return false;
- } else if (anchor.item != item->parentItem() && anchor.item->parentItem() != item->parentItem()){
+ } else if (anchor.item != readParentItem(item)
+ && readParentItem(anchor.item) != readParentItem(item)) {
qmlInfo(item) << QQuickAnchors::tr("Cannot anchor to an item that isn't a parent or sibling.");
return false;
} else if (anchor.item == item){
diff --git a/src/quick/items/qquickanchors_p.h b/src/quick/items/qquickanchors_p.h
index 0e02d80ae8..f00b8b5ba7 100644
--- a/src/quick/items/qquickanchors_p.h
+++ b/src/quick/items/qquickanchors_p.h
@@ -89,7 +89,14 @@ public:
QQuickAnchors(QQuickItem *item, QObject *parent=0);
virtual ~QQuickAnchors();
- enum Anchor {
+ enum Anchor
+#if defined(Q_CC_CLANG) || !defined(Q_CC_GNU) // meaning: clang and msvc, but NOT gcc proper (because, you know, Q_CC_CLANG implies Q_CC_GNU)
+ // Not specifying the enum base type will have MSVC 'interpret' it as signed instead of an unsigned bit-field.
+ // However, specifying the enum base type breaks many GCCs, which complain that it can't store all values in a 7 bit bitfield.
+ : uint
+#endif
+ {
+ InvalidAnchor = 0x0,
LeftAnchor = 0x01,
RightAnchor = 0x02,
TopAnchor = 0x04,
diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h
index 205d9a40da..da659946c0 100644
--- a/src/quick/items/qquickanchors_p_p.h
+++ b/src/quick/items/qquickanchors_p_p.h
@@ -60,24 +60,15 @@ QT_BEGIN_NAMESPACE
class QQuickAnchorLine
{
public:
- enum AnchorLine {
- Invalid = 0x0,
- Left = 0x01,
- Right = 0x02,
- Top = 0x04,
- Bottom = 0x08,
- HCenter = 0x10,
- VCenter = 0x20,
- Baseline = 0x40,
- Horizontal_Mask = Left | Right | HCenter,
- Vertical_Mask = Top | Bottom | VCenter | Baseline
- };
-
- QQuickAnchorLine() : item(0), anchorLine(Invalid) {}
- QQuickAnchorLine(QQuickItem *i, AnchorLine l) : item(i), anchorLine(l) {}
+ QQuickAnchorLine() : item(0), anchorLine(QQuickAnchors::InvalidAnchor) {}
+ QQuickAnchorLine(QQuickItem *i, QQuickAnchors::Anchor l) : item(i), anchorLine(l) {}
+ QQuickAnchorLine(QQuickItem *i, uint l)
+ : item(i)
+ , anchorLine(static_cast<QQuickAnchors::Anchor>(l))
+ { Q_ASSERT(l < ((QQuickAnchors::BaselineAnchor << 1) - 1)); }
QQuickItem *item;
- AnchorLine anchorLine;
+ QQuickAnchors::Anchor anchorLine;
};
inline bool operator==(const QQuickAnchorLine& a, const QQuickAnchorLine& b)
@@ -90,13 +81,44 @@ class QQuickAnchorsPrivate : public QObjectPrivate, public QQuickItemChangeListe
Q_DECLARE_PUBLIC(QQuickAnchors)
public:
QQuickAnchorsPrivate(QQuickItem *i)
- : componentComplete(true), updatingMe(false), inDestructor(false), centerAligned(true),
- leftMarginExplicit(false), rightMarginExplicit(false), topMarginExplicit(false),
- bottomMarginExplicit(false), updatingHorizontalAnchor(0),
- updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0),
- centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
- margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)
-
+ : leftMargin(0)
+ , rightMargin(0)
+ , topMargin(0)
+ , bottomMargin(0)
+ , margins(0)
+ , vCenterOffset(0)
+ , hCenterOffset(0)
+ , baselineOffset(0)
+ , item(i)
+ , fill(Q_NULLPTR)
+ , centerIn(Q_NULLPTR)
+ , leftAnchorItem(Q_NULLPTR)
+ , rightAnchorItem(Q_NULLPTR)
+ , topAnchorItem(Q_NULLPTR)
+ , bottomAnchorItem(Q_NULLPTR)
+ , vCenterAnchorItem(Q_NULLPTR)
+ , hCenterAnchorItem(Q_NULLPTR)
+ , baselineAnchorItem(Q_NULLPTR)
+ , leftAnchorLine(QQuickAnchors::InvalidAnchor)
+ , leftMarginExplicit(false)
+ , rightAnchorLine(QQuickAnchors::InvalidAnchor)
+ , rightMarginExplicit(false)
+ , topAnchorLine(QQuickAnchors::InvalidAnchor)
+ , topMarginExplicit(false)
+ , bottomAnchorLine(QQuickAnchors::InvalidAnchor)
+ , bottomMarginExplicit(false)
+ , vCenterAnchorLine(QQuickAnchors::InvalidAnchor)
+ , updatingMe(false)
+ , hCenterAnchorLine(QQuickAnchors::InvalidAnchor)
+ , inDestructor(false)
+ , baselineAnchorLine(QQuickAnchors::InvalidAnchor)
+ , centerAligned(true)
+ , updatingFill(0)
+ , updatingCenterIn(0)
+ , updatingHorizontalAnchor(0)
+ , updatingVerticalAnchor(0)
+ , componentComplete(true)
+ , usedAnchors(QQuickAnchors::InvalidAnchor)
{
}
@@ -107,19 +129,6 @@ public:
void remDepend(QQuickItem *);
bool isItemComplete() const;
- bool componentComplete:1;
- bool updatingMe:1;
- bool inDestructor:1;
- bool centerAligned:1;
- bool leftMarginExplicit : 1;
- bool rightMarginExplicit : 1;
- bool topMarginExplicit : 1;
- bool bottomMarginExplicit : 1;
- uint updatingHorizontalAnchor:2;
- uint updatingVerticalAnchor:2;
- uint updatingFill:2;
- uint updatingCenterIn:2;
-
void setItemHeight(qreal);
void setItemWidth(qreal);
void setItemX(qreal);
@@ -139,7 +148,9 @@ public:
bool checkVValid() const;
bool checkHAnchorValid(QQuickAnchorLine anchor) const;
bool checkVAnchorValid(QQuickAnchorLine anchor) const;
- bool calcStretch(const QQuickAnchorLine &edge1, const QQuickAnchorLine &edge2, qreal offset1, qreal offset2, QQuickAnchorLine::AnchorLine line, qreal &stretch);
+ bool calcStretch(QQuickItem *edge1Item, QQuickAnchors::Anchor edge1Line,
+ QQuickItem *edge2Item, QQuickAnchors::Anchor edge2Line,
+ qreal offset1, qreal offset2, QQuickAnchors::Anchor line, qreal &stretch);
bool isMirrored() const;
void updateHorizontalAnchors();
@@ -147,20 +158,6 @@ public:
void fillChanged();
void centerInChanged();
- QQuickItem *item;
- QQuickAnchors::Anchors usedAnchors;
-
- QQuickItem *fill;
- QQuickItem *centerIn;
-
- QQuickAnchorLine left;
- QQuickAnchorLine right;
- QQuickAnchorLine top;
- QQuickAnchorLine bottom;
- QQuickAnchorLine vCenter;
- QQuickAnchorLine hCenter;
- QQuickAnchorLine baseline;
-
qreal leftMargin;
qreal rightMargin;
qreal topMargin;
@@ -170,6 +167,44 @@ public:
qreal hCenterOffset;
qreal baselineOffset;
+ QQuickItem *item;
+
+ QQuickItem *fill;
+ QQuickItem *centerIn;
+
+ QQuickItem *leftAnchorItem;
+ QQuickItem *rightAnchorItem;
+ QQuickItem *topAnchorItem;
+ QQuickItem *bottomAnchorItem;
+ QQuickItem *vCenterAnchorItem;
+ QQuickItem *hCenterAnchorItem;
+ QQuickItem *baselineAnchorItem;
+
+ // The bit fields below are carefully laid out in chunks of 1 byte, so the compiler doesn't
+ // need to generate 2 loads (and combining shifts/ors) to create a single field.
+
+ QQuickAnchors::Anchor leftAnchorLine : 7;
+ uint leftMarginExplicit : 1;
+ QQuickAnchors::Anchor rightAnchorLine : 7;
+ uint rightMarginExplicit : 1;
+ QQuickAnchors::Anchor topAnchorLine : 7;
+ uint topMarginExplicit : 1;
+ QQuickAnchors::Anchor bottomAnchorLine : 7;
+ uint bottomMarginExplicit : 1;
+
+ QQuickAnchors::Anchor vCenterAnchorLine : 7;
+ uint updatingMe : 1;
+ QQuickAnchors::Anchor hCenterAnchorLine : 7;
+ uint inDestructor : 1;
+ QQuickAnchors::Anchor baselineAnchorLine : 7;
+ uint centerAligned : 1;
+ uint updatingFill : 2;
+ uint updatingCenterIn : 2;
+ uint updatingHorizontalAnchor : 2;
+ uint updatingVerticalAnchor : 2;
+
+ uint componentComplete : 1;
+ uint usedAnchors : 7; // QQuickAnchors::Anchors
static inline QQuickAnchorsPrivate *get(QQuickAnchors *o) {
return static_cast<QQuickAnchorsPrivate *>(QObjectPrivate::get(o));
diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp
index 42033b6135..6f14bf15fe 100644
--- a/src/quick/items/qquickanimatedimage.cpp
+++ b/src/quick/items/qquickanimatedimage.cpp
@@ -306,8 +306,9 @@ void QQuickAnimatedImage::load()
d->status = Null;
emit statusChanged(d->status);
- if (sourceSize() != d->oldSourceSize) {
- d->oldSourceSize = sourceSize();
+ d->currentSourceSize = QSize(0, 0);
+ if (d->currentSourceSize != d->oldSourceSize) {
+ d->oldSourceSize = d->currentSourceSize;
emit sourceSizeChanged();
}
if (isPlaying() != d->oldPlaying)
@@ -383,8 +384,9 @@ void QQuickAnimatedImage::movieRequestFinished()
d->status = Error;
emit statusChanged(d->status);
- if (sourceSize() != d->oldSourceSize) {
- d->oldSourceSize = sourceSize();
+ d->currentSourceSize = QSize(0, 0);
+ if (d->currentSourceSize != d->oldSourceSize) {
+ d->oldSourceSize = d->currentSourceSize;
emit sourceSizeChanged();
}
if (isPlaying() != d->oldPlaying)
@@ -421,8 +423,14 @@ void QQuickAnimatedImage::movieRequestFinished()
if (isPlaying() != d->oldPlaying)
emit playingChanged();
- if (sourceSize() != d->oldSourceSize) {
- d->oldSourceSize = sourceSize();
+
+ if (d->_movie)
+ d->currentSourceSize = d->_movie->currentPixmap().size();
+ else
+ d->currentSourceSize = QSize(0, 0);
+
+ if (d->currentSourceSize != d->oldSourceSize) {
+ d->oldSourceSize = d->currentSourceSize;
emit sourceSizeChanged();
}
}
@@ -475,9 +483,7 @@ void QQuickAnimatedImage::onCacheChanged()
QSize QQuickAnimatedImage::sourceSize()
{
Q_D(QQuickAnimatedImage);
- if (!d->_movie)
- return QSize(0, 0);
- return QSize(d->_movie->currentPixmap().size());
+ return d->currentSourceSize;
}
void QQuickAnimatedImage::componentComplete()
diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h
index 9b284f966d..ed735d1c9c 100644
--- a/src/quick/items/qquickanimatedimage_p_p.h
+++ b/src/quick/items/qquickanimatedimage_p_p.h
@@ -72,6 +72,7 @@ public:
#ifndef QT_NO_NETWORK
, reply(0), redirectCount(0)
#endif
+ , currentSourceSize(0, 0)
{
}
@@ -87,6 +88,7 @@ public:
int redirectCount;
#endif
QMap<int, QQuickPixmap *> frameMap;
+ QSize currentSourceSize;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 4aa54b71df..cc30199253 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -45,6 +45,7 @@
#include <private/qquickitem_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
#include <private/qquickitemchangelistener_p.h>
+#include <private/qquickpixmapcache_p.h>
#include <private/qv8engine_p.h>
#include <private/qv4scopedvalue_p.h>
#include <QtCore/qmimedata.h>
@@ -110,6 +111,8 @@ public:
bool eventQueued : 1;
bool overrideActions : 1;
QPointF hotSpot;
+ QUrl imageSource;
+ QQuickPixmap pixmapLoader;
QStringList keys;
QVariantMap externalMimeData;
QQuickDrag::DragType dragType;
@@ -307,13 +310,14 @@ void QQuickDragAttached::setActive(bool active)
else if (active) {
if (d->dragType == QQuickDrag::Internal) {
d->start(d->supportedActions);
- }
- else if (d->dragType == QQuickDrag::Automatic) {
- // There are different semantics than start() since startDrag()
- // may be called after an internal drag is already started.
- active = true;
+ } else {
+ d->active = true;
emit activeChanged();
- d->startDrag(d->supportedActions);
+ if (d->dragType == QQuickDrag::Automatic) {
+ // There are different semantics than start() since startDrag()
+ // may be called after an internal drag is already started.
+ d->startDrag(d->supportedActions);
+ }
}
}
else
@@ -408,6 +412,43 @@ void QQuickDragAttached::setHotSpot(const QPointF &hotSpot)
}
/*!
+ \qmlattachedproperty QUrl QtQuick::Drag::imageSource
+ \since 5.8
+
+ This property holds the URL of the image which will be used to represent
+ the data during the drag and drop operation. Changing this property after
+ the drag operation has started will have no effect.
+
+ The example below uses an item's contents as a drag image:
+
+ \snippet qml/externaldrag.qml 0
+
+ \sa Item::grabToImage()
+*/
+
+QUrl QQuickDragAttached::imageSource() const
+{
+ Q_D(const QQuickDragAttached);
+ return d->imageSource;
+}
+
+void QQuickDragAttached::setImageSource(const QUrl &url)
+{
+ Q_D(QQuickDragAttached);
+ if (d->imageSource != url) {
+ d->imageSource = url;
+
+ if (url.isEmpty()) {
+ d->pixmapLoader.clear();
+ } else {
+ d->pixmapLoader.load(qmlEngine(this), url);
+ }
+
+ Q_EMIT imageSourceChanged();
+ }
+}
+
+/*!
\qmlattachedproperty stringlist QtQuick::Drag::keys
This property holds a list of keys that can be used by a DropArea to filter drag events.
@@ -726,9 +767,9 @@ Qt::DropAction QQuickDragAttachedPrivate::startDrag(Qt::DropActions supportedAct
mimeData->setData(it.key(), it.value().toString().toUtf8());
drag->setMimeData(mimeData);
-
- // TODO: how to handle drag image?
- // drag->setPixmap(iconPixmap);
+ if (pixmapLoader.isReady()) {
+ drag->setPixmap(QPixmap::fromImage(pixmapLoader.image()));
+ }
emit q->dragStarted();
diff --git a/src/quick/items/qquickdrag_p.h b/src/quick/items/qquickdrag_p.h
index c1695e49f0..17721251d9 100644
--- a/src/quick/items/qquickdrag_p.h
+++ b/src/quick/items/qquickdrag_p.h
@@ -58,6 +58,7 @@
#include <QtCore/qmimedata.h>
#include <QtCore/qstringlist.h>
+#include <QtCore/qurl.h>
#ifndef QT_NO_DRAGANDDROP
@@ -247,6 +248,7 @@ class QQuickDragAttached : public QObject
Q_PROPERTY(QObject *source READ source WRITE setSource NOTIFY sourceChanged RESET resetSource)
Q_PROPERTY(QObject *target READ target NOTIFY targetChanged)
Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot NOTIFY hotSpotChanged)
+ Q_PROPERTY(QUrl imageSource READ imageSource WRITE setImageSource NOTIFY imageSourceChanged REVISION 8)
Q_PROPERTY(QStringList keys READ keys WRITE setKeys NOTIFY keysChanged)
Q_PROPERTY(QVariantMap mimeData READ mimeData WRITE setMimeData NOTIFY mimeDataChanged)
Q_PROPERTY(Qt::DropActions supportedActions READ supportedActions WRITE setSupportedActions NOTIFY supportedActionsChanged)
@@ -268,6 +270,9 @@ public:
QPointF hotSpot() const;
void setHotSpot(const QPointF &hotSpot);
+ QUrl imageSource() const;
+ void setImageSource(const QUrl &url);
+
QStringList keys() const;
void setKeys(const QStringList &keys);
@@ -300,6 +305,7 @@ Q_SIGNALS:
void sourceChanged();
void targetChanged();
void hotSpotChanged();
+ void imageSourceChanged();
void keysChanged();
void mimeDataChanged();
void supportedActionsChanged();
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index b0245f402b..ae138d7ceb 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -881,6 +881,10 @@ QQuickFlickableVisibleArea *QQuickFlickable::visibleArea()
\e contentHeight is not equal to the \e height of the Flickable.
Allows flicking horizontally if the \e contentWidth is not equal
to the \e width of the Flickable.
+ \li Flickable.AutoFlickIfNeeded - allows flicking vertically if the
+ \e contentHeight is greater than the \e height of the Flickable.
+ Allows flicking horizontally if the \e contentWidth is greater than
+ to the \e width of the Flickable.
\li Flickable.HorizontalFlick - allows flicking horizontally.
\li Flickable.VerticalFlick - allows flicking vertically.
\li Flickable.HorizontalAndVerticalFlick - allows flicking in both directions.
@@ -2167,6 +2171,8 @@ qreal QQuickFlickable::vHeight() const
bool QQuickFlickable::xflick() const
{
Q_D(const QQuickFlickable);
+ if ((d->flickableDirection & QQuickFlickable::AutoFlickIfNeeded) && (vWidth() > width()))
+ return true;
if (d->flickableDirection == QQuickFlickable::AutoFlickDirection)
return std::floor(qAbs(vWidth() - width()));
return d->flickableDirection & QQuickFlickable::HorizontalFlick;
@@ -2175,6 +2181,8 @@ bool QQuickFlickable::xflick() const
bool QQuickFlickable::yflick() const
{
Q_D(const QQuickFlickable);
+ if ((d->flickableDirection & QQuickFlickable::AutoFlickIfNeeded) && (vHeight() > height()))
+ return true;
if (d->flickableDirection == QQuickFlickable::AutoFlickDirection)
return std::floor(qAbs(vHeight() - height()));
return d->flickableDirection & QQuickFlickable::VerticalFlick;
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index 6cf78dcf63..318b8ce473 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -192,7 +192,8 @@ public:
QQuickItem *contentItem();
- enum FlickableDirection { AutoFlickDirection=0x00, HorizontalFlick=0x01, VerticalFlick=0x02, HorizontalAndVerticalFlick=0x03 };
+ enum FlickableDirection { AutoFlickDirection=0x0, HorizontalFlick=0x1, VerticalFlick=0x2, HorizontalAndVerticalFlick=0x3,
+ AutoFlickIfNeeded=0xc };
Q_ENUM(FlickableDirection)
FlickableDirection flickableDirection() const;
void setFlickableDirection(FlickableDirection);
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index 34b8f0ac49..c04a526bd0 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -714,9 +714,9 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
sourceRect.height() / nsHeight);
if (targetRect.isEmpty()
- || !qIsFinite(targetRect.width()) || !qIsFinite(targetRect.height())
+ || !qt_is_finite(targetRect.width()) || !qt_is_finite(targetRect.height())
|| nsrect.isEmpty()
- || !qIsFinite(nsrect.width()) || !qIsFinite(nsrect.height())) {
+ || !qt_is_finite(nsrect.width()) || !qt_is_finite(nsrect.height())) {
delete node;
return 0;
}
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 8117baa2fe..60e31631c0 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -225,7 +225,7 @@ void QQuickImageBase::load()
// sourceSize is set. If sourceSize is not set then the provider default size
// will be used, as usual.
bool setDevicePixelRatio = false;
- if (!d->sourcesize.isValid()) {
+ if (d->sourcesize.isValid()) {
if (loadUrl.scheme() == QLatin1String("image")) {
setDevicePixelRatio = true;
} else {
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 1100b12cbc..d6fdf5795e 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -1632,7 +1632,7 @@ void QQuickItemPrivate::setLayoutMirror(bool mirror)
*/
/*!
- \qmlproperty enumeration QtQuick::EnterKey::type
+ \qmlattachedproperty enumeration QtQuick::EnterKey::type
Holds the type of the Enter key.
@@ -2647,7 +2647,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
QQuickItem *scopeItem = 0;
- if (hasFocus())
+ if (hasFocus() || op->subFocusItem == this)
scopeFocusedItem = this;
else if (!isFocusScope() && d->subFocusItem)
scopeFocusedItem = d->subFocusItem;
@@ -3117,7 +3117,6 @@ QQuickItemPrivate::QQuickItemPrivate()
, flags(0)
, widthValid(false)
, heightValid(false)
- , baselineOffsetValid(false)
, componentComplete(true)
, keepMouse(false)
, keepTouch(false)
@@ -3192,7 +3191,7 @@ void QQuickItemPrivate::init(QQuickItem *parent)
registerAccessorProperties();
- baselineOffsetValid = false;
+ baselineOffset = 0.0;
if (parent) {
q->setParentItem(parent);
@@ -4168,6 +4167,23 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
if (d->extra.isAllocated() && d->extra->enterKeyAttached)
v = d->extra->enterKeyAttached->type();
break;
+ case Qt::ImInputItemClipRectangle:
+ if (!(!window() ||!isVisible() || qFuzzyIsNull(opacity()))) {
+ QRectF rect = QRectF(0,0, width(), height());
+ const QQuickItem *par = this;
+ while (QQuickItem *parpar = par->parentItem()) {
+ rect = parpar->mapRectFromItem(par, rect);
+ if (parpar->clip())
+ rect = rect.intersected(parpar->clipRect());
+ par = parpar;
+ }
+ rect = par->mapRectToScene(rect);
+ // once we have the rect in scene coordinates, clip to window
+ rect = rect.intersected(QRectF(QPoint(0,0), window()->size()));
+ // map it back to local coordinates
+ v = mapRectFromScene(rect);
+ }
+ break;
default:
break;
}
@@ -4179,43 +4195,43 @@ QVariant QQuickItem::inputMethodQuery(Qt::InputMethodQuery query) const
QQuickAnchorLine QQuickItemPrivate::left() const
{
Q_Q(const QQuickItem);
- return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Left);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::LeftAnchor);
}
QQuickAnchorLine QQuickItemPrivate::right() const
{
Q_Q(const QQuickItem);
- return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Right);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::RightAnchor);
}
QQuickAnchorLine QQuickItemPrivate::horizontalCenter() const
{
Q_Q(const QQuickItem);
- return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::HCenter);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::HCenterAnchor);
}
QQuickAnchorLine QQuickItemPrivate::top() const
{
Q_Q(const QQuickItem);
- return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Top);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::TopAnchor);
}
QQuickAnchorLine QQuickItemPrivate::bottom() const
{
Q_Q(const QQuickItem);
- return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Bottom);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BottomAnchor);
}
QQuickAnchorLine QQuickItemPrivate::verticalCenter() const
{
Q_Q(const QQuickItem);
- return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::VCenter);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::VCenterAnchor);
}
QQuickAnchorLine QQuickItemPrivate::baseline() const
{
Q_Q(const QQuickItem);
- return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchorLine::Baseline);
+ return QQuickAnchorLine(const_cast<QQuickItem *>(q), QQuickAnchors::BaselineAnchor);
}
/*!
@@ -4243,11 +4259,7 @@ QQuickAnchorLine QQuickItemPrivate::baseline() const
qreal QQuickItem::baselineOffset() const
{
Q_D(const QQuickItem);
- if (d->baselineOffsetValid) {
- return d->baselineOffset;
- } else {
- return 0.0;
- }
+ return d->baselineOffset;
}
void QQuickItem::setBaselineOffset(qreal offset)
@@ -4257,7 +4269,6 @@ void QQuickItem::setBaselineOffset(qreal offset)
return;
d->baselineOffset = offset;
- d->baselineOffsetValid = true;
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
@@ -6253,6 +6264,8 @@ QPointF QQuickItem::position() const
void QQuickItem::setX(qreal v)
{
Q_D(QQuickItem);
+ if (qIsNaN(v))
+ return;
if (d->x == v)
return;
@@ -6268,6 +6281,8 @@ void QQuickItem::setX(qreal v)
void QQuickItem::setY(qreal v)
{
Q_D(QQuickItem);
+ if (qIsNaN(v))
+ return;
if (d->y == v)
return;
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 46b08b11fb..846063a58b 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -401,7 +401,6 @@ public:
quint32 flags:5;
bool widthValid:1;
bool heightValid:1;
- bool baselineOffsetValid:1;
bool componentComplete:1;
bool keepMouse:1;
bool keepTouch:1;
@@ -410,8 +409,8 @@ public:
bool antialiasing:1;
bool focus:1;
bool activeFocus:1;
- // Bit 16
bool notifiedFocus:1;
+ // Bit 16
bool notifiedActiveFocus:1;
bool filtersChildMouseEvents:1;
bool explicitVisible:1;
@@ -427,8 +426,8 @@ public:
bool isAccessible:1;
bool culled:1;
bool hasCursor:1;
- // Bit 32
bool hasCursorInChild:1;
+ // Bit 32
bool hasHoverInChild:1;
bool activeFocusOnTab:1;
bool implicitAntialiasing:1;
diff --git a/src/quick/items/qquickitemgrabresult.cpp b/src/quick/items/qquickitemgrabresult.cpp
index f69b5b3f4b..807a2ae304 100644
--- a/src/quick/items/qquickitemgrabresult.cpp
+++ b/src/quick/items/qquickitemgrabresult.cpp
@@ -59,6 +59,7 @@ class QQuickItemGrabResultPrivate : public QObjectPrivate
public:
QQuickItemGrabResultPrivate()
: cacheEntry(0)
+ , qmlEngine(0)
, texture(0)
{
}
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index fb5bc3683f..3ccbf4b140 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -292,6 +292,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickGridView, 7>(uri, 2, 7, "GridView");
qmlRegisterType<QQuickTextInput, 7>(uri, 2, 7, "TextInput");
qmlRegisterType<QQuickTextEdit, 7>(uri, 2, 7, "TextEdit");
+ qmlRegisterType<QQuickPathView, 7>(uri, 2, 7, "PathView");
qmlRegisterUncreatableType<QQuickMouseEvent, 7>(uri, 2, 7, nullptr, QQuickMouseEvent::tr("MouseEvent is only available within handlers in MouseArea"));
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index f6f2503cd0..312721ed04 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -774,7 +774,6 @@ QSGNode *QQuickOpenGLShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuic
builder.appendSourceFile(QStringLiteral(":/qt-project.org/items/shaders/shadereffect.vert"));
s.sourceCode[Key::VertexShader] = builder.source();
}
- s.className = metaObject()->className();
material->setProgramSource(s);
material->attributes = m_common.attributes;
diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp
index 864c968505..c4dd8d5c63 100644
--- a/src/quick/items/qquickopenglshadereffectnode.cpp
+++ b/src/quick/items/qquickopenglshadereffectnode.cpp
@@ -334,8 +334,6 @@ const char *QQuickCustomMaterialShader::fragmentShader() const
bool QQuickOpenGLShaderEffectMaterialKey::operator == (const QQuickOpenGLShaderEffectMaterialKey &other) const
{
- if (className != other.className)
- return false;
for (int shaderType = 0; shaderType < ShaderTypeCount; ++shaderType) {
if (sourceCode[shaderType] != other.sourceCode[shaderType])
return false;
@@ -350,7 +348,7 @@ bool QQuickOpenGLShaderEffectMaterialKey::operator != (const QQuickOpenGLShaderE
uint qHash(const QQuickOpenGLShaderEffectMaterialKey &key)
{
- uint hash = qHash((const void *)key.className);
+ uint hash = 1;
typedef QQuickOpenGLShaderEffectMaterialKey Key;
for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType)
hash = hash * 31337 + qHash(key.sourceCode[shaderType]);
diff --git a/src/quick/items/qquickopenglshadereffectnode_p.h b/src/quick/items/qquickopenglshadereffectnode_p.h
index 1adfa4dd29..adf5ef730b 100644
--- a/src/quick/items/qquickopenglshadereffectnode_p.h
+++ b/src/quick/items/qquickopenglshadereffectnode_p.h
@@ -72,7 +72,6 @@ struct QQuickOpenGLShaderEffectMaterialKey {
};
QByteArray sourceCode[ShaderTypeCount];
- const char *className;
bool operator == (const QQuickOpenGLShaderEffectMaterialKey &other) const;
bool operator != (const QQuickOpenGLShaderEffectMaterialKey &other) const;
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp
index 5813b4b115..d21eb93dbf 100644
--- a/src/quick/items/qquickpainteditem.cpp
+++ b/src/quick/items/qquickpainteditem.cpp
@@ -674,4 +674,11 @@ QSGTextureProvider *QQuickPaintedItem::textureProvider() const
return d->textureProvider;
}
+void QQuickPaintedItem::itemChange(ItemChange change, const ItemChangeData &value)
+{
+ if (change == ItemDevicePixelRatioHasChanged)
+ update();
+ QQuickItem::itemChange(change, value);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index f9e3c91a42..e8b471ac01 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -121,6 +121,7 @@ protected:
QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = Q_NULLPTR);
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
void releaseResources() Q_DECL_OVERRIDE;
+ void itemChange(ItemChange, const ItemChangeData &) Q_DECL_OVERRIDE;
private Q_SLOTS:
void invalidateSceneGraph();
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index f0bbb1e732..e3d218ff01 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -105,7 +105,8 @@ QQuickPathViewPrivate::QQuickPathViewPrivate()
, dragMargin(0), deceleration(100), maximumFlickVelocity(QML_FLICK_DEFAULTMAXVELOCITY)
, moveOffset(this, &QQuickPathViewPrivate::setAdjustedOffset), flickDuration(0)
, pathItems(-1), requestedIndex(-1), cacheSize(0), requestedZ(0)
- , moveReason(Other), moveDirection(Shortest), attType(0), highlightComponent(0), highlightItem(0)
+ , moveReason(Other), movementDirection(QQuickPathView::Shortest), moveDirection(QQuickPathView::Shortest)
+ , attType(0), highlightComponent(0), highlightItem(0)
, moveHighlight(this, &QQuickPathViewPrivate::setHighlightPosition)
, highlightPosition(0)
, highlightRangeStart(0), highlightRangeEnd(0)
@@ -790,7 +791,7 @@ QQuickItem *QQuickPathView::currentItem() const
void QQuickPathView::incrementCurrentIndex()
{
Q_D(QQuickPathView);
- d->moveDirection = QQuickPathViewPrivate::Positive;
+ d->moveDirection = QQuickPathView::Positive;
setCurrentIndex(currentIndex()+1);
}
@@ -804,7 +805,7 @@ void QQuickPathView::incrementCurrentIndex()
void QQuickPathView::decrementCurrentIndex()
{
Q_D(QQuickPathView);
- d->moveDirection = QQuickPathViewPrivate::Negative;
+ d->moveDirection = QQuickPathView::Negative;
setCurrentIndex(currentIndex()-1);
}
@@ -1373,6 +1374,48 @@ void QQuickPathView::setSnapMode(SnapMode mode)
}
/*!
+ \qmlproperty enumeration QtQuick::PathView::movementDirection
+ \since 5.7
+
+ This property determines the direction in which items move when setting the current index.
+ The possible values are:
+
+ \list
+ \li PathView.Shortest (default) - the items move in the direction that requires the least
+ movement, which could be either \c Negative or \c Positive.
+ \li PathView.Negative - the items move backwards towards their destination.
+ \li PathView.Positive - the items move forwards towards their destination.
+ \endlist
+
+ For example, suppose that there are 5 items in the model, and \l currentIndex is \c 0.
+ If currentIndex is set to \c 2,
+
+ \list
+ \li a \c Positive movement direction will result in the following order: 0, 1, 2
+ \li a \c Negative movement direction will result in the following order: 0, 5, 4, 3, 2
+ \li a \c Shortest movement direction will result in same order with \c Positive .
+ \endlist
+
+ \note this property doesn't affect the movement of \l incrementCurrentIndex() and \l decrementCurrentIndex().
+*/
+QQuickPathView::MovementDirection QQuickPathView::movementDirection() const
+{
+ Q_D(const QQuickPathView);
+ return d->movementDirection;
+}
+
+void QQuickPathView::setMovementDirection(QQuickPathView::MovementDirection dir)
+{
+ Q_D(QQuickPathView);
+ if (dir == d->movementDirection)
+ return;
+ d->movementDirection = dir;
+ if (!d->tl.isActive())
+ d->moveDirection = d->movementDirection;
+ emit movementDirectionChanged();
+}
+
+/*!
\qmlmethod QtQuick::PathView::positionViewAtIndex(int index, PositionMode mode)
Positions the view such that the \a index is at the position specified by
@@ -1910,7 +1953,7 @@ void QQuickPathView::refill()
if (lcItemViewDelegateLifecycle().isDebugEnabled()) {
QQuickText *text = qmlobject_cast<QQuickText*>(item);
if (text)
- qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ": QQuickText" << text->objectName() << text->text().left(40);
+ qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ": QQuickText" << text->objectName() << text->text().leftRef(40);
else
qCDebug(lcItemViewDelegateLifecycle) << "idx" << idx << "@" << pos << ":" << item;
}
@@ -2231,6 +2274,7 @@ void QQuickPathView::movementEnding()
emit movingChanged();
emit movementEnded();
}
+ d->moveDirection = d->movementDirection;
}
// find the item closest to the snap position
@@ -2340,7 +2384,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason)
if (!duration) {
tl.set(moveOffset, targetOffset);
- } else if (moveDirection == Positive || (moveDirection == Shortest && targetOffset - offset > modelCount/2.0)) {
+ } else if (moveDirection == QQuickPathView::Positive || (moveDirection == QQuickPathView::Shortest && targetOffset - offset > modelCount/2.0)) {
qreal distance = modelCount - targetOffset + offset;
if (targetOffset > moveOffset) {
tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance));
@@ -2349,7 +2393,7 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason)
} else {
tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
}
- } else if (moveDirection == Negative || targetOffset - offset <= -modelCount/2.0) {
+ } else if (moveDirection == QQuickPathView::Negative || targetOffset - offset <= -modelCount/2.0) {
qreal distance = modelCount - offset + targetOffset;
if (targetOffset < moveOffset) {
tl.move(moveOffset, modelCount, QEasingCurve(targetOffset == 0 ? QEasingCurve::InOutQuad : QEasingCurve::InQuad), int(duration * (modelCount-offset) / distance));
@@ -2361,7 +2405,6 @@ void QQuickPathViewPrivate::snapToIndex(int index, MovementReason reason)
} else {
tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
}
- moveDirection = Shortest;
}
QQuickPathViewAttached *QQuickPathView::qmlAttachedProperties(QObject *obj)
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
index 341af02013..daec965f02 100644
--- a/src/quick/items/qquickpathview_p.h
+++ b/src/quick/items/qquickpathview_p.h
@@ -92,6 +92,7 @@ class Q_AUTOTEST_EXPORT QQuickPathView : public QQuickItem
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount RESET resetPathItemCount NOTIFY pathItemCountChanged)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
+ Q_PROPERTY(MovementDirection movementDirection READ movementDirection WRITE setMovementDirection NOTIFY movementDirectionChanged REVISION 7)
Q_PROPERTY(int cacheItemCount READ cacheItemCount WRITE setCacheItemCount NOTIFY cacheItemCountChanged)
@@ -164,6 +165,11 @@ public:
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
+ enum MovementDirection { Shortest, Negative, Positive };
+ Q_ENUM(MovementDirection)
+ MovementDirection movementDirection() const;
+ void setMovementDirection(MovementDirection dir);
+
enum PositionMode { Beginning, Center, End, Contain=4, SnapPosition }; // 3 == Visible in other views
Q_ENUM(PositionMode)
Q_INVOKABLE void positionViewAtIndex(int index, int mode);
@@ -201,6 +207,7 @@ Q_SIGNALS:
void highlightMoveDurationChanged();
void movementStarted();
void movementEnded();
+ Q_REVISION(7) void movementDirectionChanged();
void flickStarted();
void flickEnded();
void dragStarted();
diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index 8236d9efd2..d9c4baf572 100644
--- a/src/quick/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
@@ -171,8 +171,8 @@ public:
QPointer<QQmlInstanceModel> model;
QVariant modelVariant;
MovementReason moveReason;
- enum MovementDirection { Shortest, Negative, Positive };
- MovementDirection moveDirection;
+ QQuickPathView::MovementDirection movementDirection; // default
+ QQuickPathView::MovementDirection moveDirection; // next movement
QQmlOpenMetaObjectType *attType;
QQmlComponent *highlightComponent;
QQuickItem *highlightItem;
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index 74ca0f482a..b8c680433e 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -44,7 +44,6 @@
#include <private/qsgadaptationlayer_p.h>
#include <QtGui/qpixmapcache.h>
-#include <QtCore/qstringbuilder.h>
#include <QtCore/qmath.h>
#include <QtCore/qmetaobject.h>
diff --git a/src/quick/items/qquickscalegrid.cpp b/src/quick/items/qquickscalegrid.cpp
index f860c08bad..d7a0f1b681 100644
--- a/src/quick/items/qquickscalegrid.cpp
+++ b/src/quick/items/qquickscalegrid.cpp
@@ -136,39 +136,38 @@ QQuickGridScaledImage::QQuickGridScaledImage(QIODevice *data)
if (colonId <= 0)
return;
- QStringList list;
- list.append(line.left(colonId).trimmed());
- list.append(line.mid(colonId+1).trimmed());
-
- if (list[0] == QLatin1String("border.left"))
- l = list[1].toInt();
- else if (list[0] == QLatin1String("border.right"))
- r = list[1].toInt();
- else if (list[0] == QLatin1String("border.top"))
- t = list[1].toInt();
- else if (list[0] == QLatin1String("border.bottom"))
- b = list[1].toInt();
- else if (list[0] == QLatin1String("source"))
- imgFile = list[1];
- else if (list[0] == QLatin1String("horizontalTileRule") || list[0] == QLatin1String("horizontalTileMode"))
- _h = stringToRule(list[1]);
- else if (list[0] == QLatin1String("verticalTileRule") || list[0] == QLatin1String("verticalTileMode"))
- _v = stringToRule(list[1]);
+ const QStringRef property = line.leftRef(colonId).trimmed();
+ QStringRef value = line.midRef(colonId + 1).trimmed();
+
+ if (property == QLatin1String("border.left")) {
+ l = value.toInt();
+ } else if (property == QLatin1String("border.right")) {
+ r = value.toInt();
+ } else if (property == QLatin1String("border.top")) {
+ t = value.toInt();
+ } else if (property == QLatin1String("border.bottom")) {
+ b = value.toInt();
+ } else if (property == QLatin1String("source")) {
+ if (value.startsWith(QLatin1Char('"')) && value.endsWith(QLatin1Char('"')))
+ value = value.mid(1, value.size() - 2); // remove leading/trailing quotes.
+ imgFile = value.toString();
+ } else if (property == QLatin1String("horizontalTileRule") || property == QLatin1String("horizontalTileMode")) {
+ _h = stringToRule(value);
+ } else if (property == QLatin1String("verticalTileRule") || property == QLatin1String("verticalTileMode")) {
+ _v = stringToRule(value);
+ }
}
if (l < 0 || r < 0 || t < 0 || b < 0 || imgFile.isEmpty())
return;
_l = l; _r = r; _t = t; _b = b;
-
_pix = imgFile;
- if (_pix.startsWith(QLatin1Char('"')) && _pix.endsWith(QLatin1Char('"')))
- _pix = _pix.mid(1, _pix.size() - 2); // remove leading/trailing quotes.
}
-QQuickBorderImage::TileMode QQuickGridScaledImage::stringToRule(const QString &s)
+QQuickBorderImage::TileMode QQuickGridScaledImage::stringToRule(const QStringRef &s)
{
- QString string = s;
+ QStringRef string = s;
if (string.startsWith(QLatin1Char('"')) && string.endsWith(QLatin1Char('"')))
string = string.mid(1, string.size() - 2); // remove leading/trailing quotes.
diff --git a/src/quick/items/qquickscalegrid_p_p.h b/src/quick/items/qquickscalegrid_p_p.h
index a424002dfb..7f6a31a7bd 100644
--- a/src/quick/items/qquickscalegrid_p_p.h
+++ b/src/quick/items/qquickscalegrid_p_p.h
@@ -116,7 +116,7 @@ public:
QString pixmapUrl() const;
private:
- static QQuickBorderImage::TileMode stringToRule(const QString &);
+ static QQuickBorderImage::TileMode stringToRule(const QStringRef &);
private:
int _l;
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index 0b35ad5f91..40dbd51f39 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -254,16 +254,16 @@ Q_SIGNALS:
void fontChanged(const QFont &font);
void colorChanged();
void linkColorChanged();
- void styleChanged(TextStyle style);
+ void styleChanged(QQuickText::TextStyle style);
void styleColorChanged();
- void horizontalAlignmentChanged(HAlignment alignment);
- void verticalAlignmentChanged(VAlignment alignment);
+ void horizontalAlignmentChanged(QQuickText::HAlignment alignment);
+ void verticalAlignmentChanged(QQuickText::VAlignment alignment);
void wrapModeChanged();
void lineCountChanged();
void truncatedChanged();
void maximumLineCountChanged();
- void textFormatChanged(TextFormat textFormat);
- void elideModeChanged(TextElideMode mode);
+ void textFormatChanged(QQuickText::TextFormat textFormat);
+ void elideModeChanged(QQuickText::TextElideMode mode);
void contentSizeChanged();
void lineHeightChanged(qreal lineHeight);
void lineHeightModeChanged(LineHeightMode mode);
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index 8b6cc221d5..45238e2d0c 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -109,6 +109,7 @@ QQuickTextControlPrivate::QQuickTextControlPrivate()
overwriteMode(false),
acceptRichText(true),
cursorVisible(false),
+ cursorBlinkingEnabled(false),
hasFocus(false),
hadSelectionOnMousePress(false),
wordSelectionEnabled(false),
@@ -463,14 +464,30 @@ void QQuickTextControlPrivate::_q_updateCursorPosChanged(const QTextCursor &some
void QQuickTextControlPrivate::setBlinkingCursorEnabled(bool enable)
{
- Q_Q(QQuickTextControl);
+ if (cursorBlinkingEnabled == enable)
+ return;
+
+ cursorBlinkingEnabled = enable;
+ updateCursorFlashTime();
- if (enable && QGuiApplication::styleHints()->cursorFlashTime() > 0)
- cursorBlinkTimer.start(QGuiApplication::styleHints()->cursorFlashTime() / 2, q);
+ if (enable)
+ connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextControlPrivate::updateCursorFlashTime);
else
- cursorBlinkTimer.stop();
+ disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextControlPrivate::updateCursorFlashTime);
+}
- cursorOn = enable;
+void QQuickTextControlPrivate::updateCursorFlashTime()
+{
+ // Note: cursorOn represents the current blinking state controlled by a timer, and
+ // should not be confused with cursorVisible or cursorBlinkingEnabled. However, we
+ // interpretate a cursorFlashTime of 0 to mean "always on, never blink".
+ cursorOn = true;
+ int flashTime = QGuiApplication::styleHints()->cursorFlashTime();
+
+ if (cursorBlinkingEnabled && flashTime >= 2)
+ cursorBlinkTimer.start(flashTime / 2, q_func());
+ else
+ cursorBlinkTimer.stop();
repaintCursor();
}
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index f312fcb1ce..0f78feb5de 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -97,6 +97,7 @@ public:
void _q_updateCursorPosChanged(const QTextCursor &someCursor);
void setBlinkingCursorEnabled(bool enable);
+ void updateCursorFlashTime();
void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition);
void extendBlockwiseSelection(int suggestedNewPosition);
@@ -156,6 +157,7 @@ public:
bool overwriteMode : 1;
bool acceptRichText : 1;
bool cursorVisible : 1; // used to hide the cursor in the preedit area
+ bool cursorBlinkingEnabled : 1;
bool hasFocus : 1;
bool hadSelectionOnMousePress : 1;
bool wordSelectionEnabled : 1;
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 8bb788d008..36eb5d3cde 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1901,6 +1901,9 @@ QVariant QQuickTextEdit::inputMethodQuery(Qt::InputMethodQuery property, QVarian
case Qt::ImHints:
v = (int)d->effectiveInputMethodHints();
break;
+ case Qt::ImInputItemClipRectangle:
+ v = QQuickItem::inputMethodQuery(property);
+ break;
default:
if (property == Qt::ImCursorPosition && !argument.isNull())
argument = QVariant(argument.toPointF() - QPointF(d->xoff, d->yoff));
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index f361d46424..9b7eb4ea4b 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -792,12 +792,8 @@ void QQuickTextInput::setCursorVisible(bool on)
d->cursorVisible = on;
if (on && isComponentComplete())
QQuickTextUtil::createCursor(d);
- if (!d->cursorItem) {
- d->setCursorBlinkPeriod(on ? QGuiApplication::styleHints()->cursorFlashTime() : 0);
- d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
- polish();
- update();
- }
+ if (!d->cursorItem)
+ d->updateCursorBlinking();
emit cursorVisibleChanged(d->cursorVisible);
}
@@ -1858,7 +1854,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
node = new QQuickTextNode(this);
d->textNode = node;
- const bool showCursor = !isReadOnly() && d->cursorItem == 0 && d->cursorVisible && (d->m_blinkStatus || d->m_blinkPeriod == 0);
+ const bool showCursor = !isReadOnly() && d->cursorItem == 0 && d->cursorVisible && d->m_blinkStatus;
if (!d->textLayoutDirty && oldNode != 0) {
if (showCursor)
@@ -1954,7 +1950,7 @@ QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property, QVaria
return QVariant(d->m_text.mid(d->m_cursor));
case Qt::ImTextBeforeCursor:
if (argument.isValid())
- return QVariant(d->m_text.left(d->m_cursor).right(argument.toInt()));
+ return QVariant(d->m_text.leftRef(d->m_cursor).right(argument.toInt()).toString());
return QVariant(d->m_text.left(d->m_cursor));
default:
return QQuickItem::inputMethodQuery(property);
@@ -2594,8 +2590,10 @@ void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event)
{
Q_Q(QQuickTextInput);
bool focus = event->gotFocus();
- if (!m_readOnly)
+ if (!m_readOnly) {
q->setCursorVisible(focus);
+ setBlinkingCursorEnabled(focus);
+ }
if (focus) {
q->q_updateAlignment();
#ifndef QT_NO_IM
@@ -4295,26 +4293,39 @@ bool QQuickTextInputPrivate::emitCursorPositionChanged()
}
-void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec)
+void QQuickTextInputPrivate::setBlinkingCursorEnabled(bool enable)
{
- Q_Q(QQuickTextInput);
- if (msec == m_blinkPeriod)
+ if (enable == m_blinkEnabled)
return;
+
+ m_blinkEnabled = enable;
+ updateCursorBlinking();
+
+ if (enable)
+ connect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextInputPrivate::updateCursorBlinking);
+ else
+ disconnect(qApp->styleHints(), &QStyleHints::cursorFlashTimeChanged, this, &QQuickTextInputPrivate::updateCursorBlinking);
+}
+
+void QQuickTextInputPrivate::updateCursorBlinking()
+{
+ Q_Q(QQuickTextInput);
+
if (m_blinkTimer) {
q->killTimer(m_blinkTimer);
- }
- if (msec) {
- m_blinkTimer = q->startTimer(msec / 2);
- m_blinkStatus = 1;
- } else {
m_blinkTimer = 0;
- if (m_blinkStatus == 1) {
- updateType = UpdatePaintNode;
- q->polish();
- q->update();
- }
}
- m_blinkPeriod = msec;
+
+ if (m_blinkEnabled && cursorVisible && !cursorItem && !m_readOnly) {
+ int flashTime = QGuiApplication::styleHints()->cursorFlashTime();
+ if (flashTime >= 2)
+ m_blinkTimer = q->startTimer(flashTime / 2);
+ }
+
+ m_blinkStatus = 1;
+ updateType = UpdatePaintNode;
+ q->polish();
+ q->update();
}
void QQuickTextInput::timerEvent(QTimerEvent *event)
@@ -4351,20 +4362,8 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
return;
}
- if (m_blinkPeriod > 0) {
- if (m_blinkTimer)
- q->killTimer(m_blinkTimer);
-
- m_blinkTimer = q->startTimer(m_blinkPeriod / 2);
-
- if (m_blinkStatus == 0) {
- m_blinkStatus = 1;
-
- updateType = UpdatePaintNode;
- q->polish();
- q->update();
- }
- }
+ if (m_blinkEnabled)
+ updateCursorBlinking();
if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit
&& !m_passwordEchoEditing
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index d2dee2c284..d0461f551e 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -323,8 +323,8 @@ Q_SIGNALS:
void selectionColorChanged();
void selectedTextColorChanged();
void fontChanged(const QFont &font);
- void horizontalAlignmentChanged(HAlignment alignment);
- void verticalAlignmentChanged(VAlignment alignment);
+ void horizontalAlignmentChanged(QQuickTextInput::HAlignment alignment);
+ void verticalAlignmentChanged(QQuickTextInput::VAlignment alignment);
void wrapModeChanged();
void readOnlyChanged(bool isReadOnly);
void cursorVisibleChanged(bool isCursorVisible);
@@ -333,7 +333,7 @@ Q_SIGNALS:
void maximumLengthChanged(int maximumLength);
void validatorChanged();
void inputMaskChanged(const QString &inputMask);
- void echoModeChanged(EchoMode echoMode);
+ void echoModeChanged(QQuickTextInput::EchoMode echoMode);
void passwordCharacterChanged();
Q_REVISION(3) void passwordMaskDelayChanged(int delay);
void displayTextChanged();
@@ -341,7 +341,7 @@ Q_SIGNALS:
void activeFocusOnPressChanged(bool activeFocusOnPress);
void autoScrollChanged(bool autoScroll);
void selectByMouseChanged(bool selectByMouse);
- void mouseSelectionModeChanged(SelectionMode mode);
+ void mouseSelectionModeChanged(QQuickTextInput::SelectionMode mode);
void persistentSelectionChanged();
void canPasteChanged();
void canUndoChanged();
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index e6bd29bf67..93a8778c40 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -107,7 +107,7 @@ public:
#ifndef QT_NO_IM
, m_preeditCursor(0)
#endif
- , m_blinkPeriod(0)
+ , m_blinkEnabled(false)
, m_blinkTimer(0)
, m_maxLength(32767)
, m_lastCursorPos(-1)
@@ -243,7 +243,7 @@ public:
#ifndef QT_NO_IM
int m_preeditCursor;
#endif
- int m_blinkPeriod; // 0 for non-blinking cursor
+ bool m_blinkEnabled;
int m_blinkTimer;
int m_maxLength;
int m_lastCursorPos;
@@ -309,8 +309,9 @@ public:
return !tripleClickTimer.hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval());
}
- void setNativeCursorEnabled(bool enabled) {
- setCursorBlinkPeriod(enabled && cursorVisible ? QGuiApplication::styleHints()->cursorFlashTime() : 0); }
+ void setNativeCursorEnabled(bool) {
+ updateCursorBlinking();
+ }
int nextMaskBlank(int pos)
{
@@ -445,7 +446,8 @@ public:
#endif
void processKeyEvent(QKeyEvent* ev);
- void setCursorBlinkPeriod(int msec);
+ void setBlinkingCursorEnabled(bool enable);
+ void updateCursorBlinking();
void updateLayout();
void updateBaselineOffset();
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index f38b3e7693..cdde780932 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -102,6 +102,7 @@ void QQuickWindowPrivate::updateFocusItemTransform()
QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus);
QGuiApplication::inputMethod()->setInputItemTransform(focusPrivate->itemToWindowTransform());
QGuiApplication::inputMethod()->setInputItemRectangle(QRectF(0, 0, focusPrivate->width, focusPrivate->height));
+ focus->updateInputMethod(Qt::ImInputItemClipRectangle);
}
#endif
}
@@ -260,6 +261,26 @@ void QQuickWindow::focusInEvent(QFocusEvent *ev)
d->updateFocusItemTransform();
}
+#ifndef QT_NO_IM
+static bool transformDirtyOnItemOrAncestor(const QQuickItem *item)
+{
+ while (item) {
+ if (QQuickItemPrivate::get(item)->dirtyAttributes & (
+ QQuickItemPrivate::TransformOrigin |
+ QQuickItemPrivate::Transform |
+ QQuickItemPrivate::BasicTransform |
+ QQuickItemPrivate::Position |
+ QQuickItemPrivate::Size |
+ QQuickItemPrivate::ParentChanged |
+ QQuickItemPrivate::Clip)) {
+ return true;
+ }
+ item = item->parentItem();
+ }
+ return false;
+}
+#endif
+
void QQuickWindowPrivate::polishItems()
{
// An item can trigger polish on another item, or itself for that matter,
@@ -279,7 +300,17 @@ void QQuickWindowPrivate::polishItems()
if (recursionSafeguard == 0)
qWarning("QQuickWindow: possible QQuickItem::polish() loop");
- updateFocusItemTransform();
+#ifndef QT_NO_IM
+ if (QQuickItem *focusItem = q_func()->activeFocusItem()) {
+ // If the current focus item, or any of its anchestors, has changed location
+ // inside the window, we need inform IM about it. This to ensure that overlays
+ // such as selection handles will be updated.
+ const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject());
+ const bool hasImEnabled = focusItem->inputMethodQuery(Qt::ImEnabled).toBool();
+ if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(focusItem))
+ updateFocusItemTransform();
+ }
+#endif
}
/*!
@@ -4083,6 +4114,12 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
+ \qmlproperty Item Window::contentItem
+ \readonly
+ \brief The invisible root item of the scene.
+*/
+
+/*!
\qmlproperty Qt::ScreenOrientation Window::contentOrientation
This is a hint to the window manager in case it needs to display
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index f277475dbf..5af79747a7 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -496,11 +496,6 @@ void Updater::visitGeometryNode(Node *n)
if (e->batch)
renderer->invalidateBatchAndOverlappingRenderOrders(e->batch);
}
- if (n->dirtyState & QSGNode::DirtyMaterial) {
- Element *e = n->element();
- if (e->batch && e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare)
- renderer->invalidateBatchAndOverlappingRenderOrders(e->batch);
- }
}
SHADOWNODE_TRAVERSE(n) visitNode(child);
@@ -598,13 +593,13 @@ void Element::computeBounds()
}
bounds.map(*node->matrix());
- if (!qIsFinite(bounds.tl.x) || bounds.tl.x == FLT_MAX)
+ if (!qt_is_finite(bounds.tl.x) || bounds.tl.x == FLT_MAX)
bounds.tl.x = -FLT_MAX;
- if (!qIsFinite(bounds.tl.y) || bounds.tl.y == FLT_MAX)
+ if (!qt_is_finite(bounds.tl.y) || bounds.tl.y == FLT_MAX)
bounds.tl.y = -FLT_MAX;
- if (!qIsFinite(bounds.br.x) || bounds.br.x == -FLT_MAX)
+ if (!qt_is_finite(bounds.br.x) || bounds.br.x == -FLT_MAX)
bounds.br.x = FLT_MAX;
- if (!qIsFinite(bounds.br.y) || bounds.br.y == -FLT_MAX)
+ if (!qt_is_finite(bounds.br.y) || bounds.br.y == -FLT_MAX)
bounds.br.y = FLT_MAX;
Q_ASSERT(bounds.tl.x <= bounds.br.x);
@@ -1241,7 +1236,10 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
if (e->isMaterialBlended != blended) {
m_rebuild |= Renderer::FullRebuild;
e->isMaterialBlended = blended;
- } else if (!e->batch) {
+ } else if (e->batch) {
+ if (e->batch->isMaterialCompatible(e) == BatchBreaksOnCompare)
+ invalidateBatchAndOverlappingRenderOrders(e->batch);
+ } else {
m_rebuild |= Renderer::BuildBatches;
}
}
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index c56f15d655..01e517e65b 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -529,7 +529,7 @@ public:
float lastOpacity;
};
- ShaderManager(QSGDefaultRenderContext *ctx) : blitProgram(0), visualizeProgram(0), context(ctx) { }
+ ShaderManager(QSGDefaultRenderContext *ctx) : visualizeProgram(0), blitProgram(0), context(ctx) { }
~ShaderManager() {
qDeleteAll(rewrittenShaders);
qDeleteAll(stockShaders);
@@ -542,11 +542,13 @@ public:
Shader *prepareMaterial(QSGMaterial *material);
Shader *prepareMaterialNoRewrite(QSGMaterial *material);
+ QOpenGLShaderProgram *visualizeProgram;
+
+private:
QHash<QSGMaterialType *, Shader *> rewrittenShaders;
QHash<QSGMaterialType *, Shader *> stockShaders;
QOpenGLShaderProgram *blitProgram;
- QOpenGLShaderProgram *visualizeProgram;
QSGDefaultRenderContext *context;
};
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 06c4129a33..098a4a666b 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -128,6 +128,7 @@ Atlas::Atlas(const QSize &size)
: m_allocator(size)
, m_texture_id(0)
, m_size(size)
+ , m_atlas_transient_image_threshold(0)
, m_allocated(false)
{
@@ -177,6 +178,11 @@ Atlas::Atlas(const QSize &size)
m_use_bgra_fallback = qEnvironmentVariableIsSet("QSG_ATLAS_USE_BGRA_FALLBACK");
m_debug_overlay = qEnvironmentVariableIsSet("QSG_ATLAS_OVERLAY");
+
+ // images smaller than this will retain their QImage.
+ // by default no images are retained (favoring memory)
+ // set to a very large value to retain all images (allowing quick removal from the atlas)
+ m_atlas_transient_image_threshold = qt_sg_envInt("QSG_ATLAS_TRANSIENT_IMAGE_THRESHOLD", 0);
}
Atlas::~Atlas()
@@ -399,7 +405,10 @@ void Atlas::bind(QSGTexture::Filtering filtering)
} else {
upload(t);
}
- t->releaseImage();
+ const QSize textureSize = t->textureSize();
+ if (textureSize.width() > m_atlas_transient_image_threshold ||
+ textureSize.height() > m_atlas_transient_image_threshold)
+ t->releaseImage();
qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed()
<< "ms (" << t->textureSize().width() << "x"
diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h
index da5acb3fea..cd24645fcf 100644
--- a/src/quick/scenegraph/util/qsgatlastexture_p.h
+++ b/src/quick/scenegraph/util/qsgatlastexture_p.h
@@ -116,6 +116,8 @@ private:
uint m_internalFormat;
uint m_externalFormat;
+ int m_atlas_transient_image_threshold;
+
uint m_allocated : 1;
uint m_use_bgra_fallback: 1;
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
index ec1d316f78..caa296451e 100644
--- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
@@ -382,9 +382,9 @@ QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const
int idx = path.lastIndexOf(QLatin1Char('.'));
QString resolvedPath;
if (idx != -1)
- resolvedPath = path.left(idx)
- + QStringLiteral("_core")
- + path.right(path.length() - idx);
+ resolvedPath = path.leftRef(idx)
+ + QLatin1String("_core")
+ + path.rightRef(path.length() - idx);
return resolvedPath;
}
}
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index adf8f600a0..741a583803 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -986,7 +986,7 @@ void QQuickScriptActionPrivate::debugAction(QDebug d, int indentLevel) const
QByteArray ind(indentLevel, ' ');
QString exprStr = expr.expression();
int endOfFirstLine = exprStr.indexOf('\n');
- d << "\n" << ind.constData() << exprStr.left(endOfFirstLine);
+ d << "\n" << ind.constData() << exprStr.leftRef(endOfFirstLine);
if (endOfFirstLine != -1 && endOfFirstLine < exprStr.length())
d << "...";
}
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 4ad6fdd854..7692cc79f9 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -172,8 +172,8 @@ public:
int index = s.indexOf(QLatin1Char(','));
bool xGood, yGood;
- float xCoord = s.left(index).toFloat(&xGood);
- float yCoord = s.mid(index+1).toFloat(&yGood);
+ float xCoord = s.leftRef(index).toFloat(&xGood);
+ float yCoord = s.midRef(index + 1).toFloat(&yGood);
if (xGood && yGood) {
if (ok) *ok = true;
@@ -192,9 +192,9 @@ public:
int index2 = s.indexOf(QLatin1Char(','), index+1);
bool xGood, yGood, zGood;
- float xCoord = s.left(index).toFloat(&xGood);
- float yCoord = s.mid(index+1, index2-index-1).toFloat(&yGood);
- float zCoord = s.mid(index2+1).toFloat(&zGood);
+ float xCoord = s.leftRef(index).toFloat(&xGood);
+ float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood);
+ float zCoord = s.midRef(index2 + 1).toFloat(&zGood);
if (xGood && yGood && zGood) {
if (ok) *ok = true;
@@ -214,10 +214,10 @@ public:
int index3 = s.indexOf(QLatin1Char(','), index2+1);
bool xGood, yGood, zGood, wGood;
- float xCoord = s.left(index).toFloat(&xGood);
- float yCoord = s.mid(index+1, index2-index-1).toFloat(&yGood);
- float zCoord = s.mid(index2+1, index3-index2-1).toFloat(&zGood);
- float wCoord = s.mid(index3+1).toFloat(&wGood);
+ float xCoord = s.leftRef(index).toFloat(&xGood);
+ float yCoord = s.midRef(index + 1, index2 - index - 1).toFloat(&yGood);
+ float zCoord = s.midRef(index2 + 1, index3 - index2 - 1).toFloat(&zGood);
+ float wCoord = s.midRef(index3 + 1).toFloat(&wGood);
if (xGood && yGood && zGood && wGood) {
if (ok) *ok = true;
@@ -257,10 +257,10 @@ public:
if (s.count(QLatin1Char(',')) == 15) {
float matValues[16];
bool vOK = true;
- QString mutableStr = s;
+ QStringRef mutableStr(&s);
for (int i = 0; vOK && i < 16; ++i) {
int cidx = mutableStr.indexOf(QLatin1Char(','));
- matValues[i] = mutableStr.leftRef(cidx).toDouble(&vOK);
+ matValues[i] = mutableStr.left(cidx).toDouble(&vOK);
mutableStr = mutableStr.mid(cidx + 1);
}
diff --git a/src/quick/util/qquickpath_p.h b/src/quick/util/qquickpath_p.h
index d554e2156a..e2c99de44e 100644
--- a/src/quick/util/qquickpath_p.h
+++ b/src/quick/util/qquickpath_p.h
@@ -335,7 +335,7 @@ class Q_AUTOTEST_EXPORT QQuickPathPercent : public QQuickPathElement
Q_OBJECT
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
public:
- QQuickPathPercent(QObject *parent=0) : QQuickPathElement(parent) {}
+ QQuickPathPercent(QObject *parent=0) : QQuickPathElement(parent), _value(0) {}
qreal value() const;
void setValue(qreal value);
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 2b6e8f68c3..597613c9fd 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -455,13 +455,19 @@ QQuickPixmapReader::~QQuickPixmapReader()
}
jobs.clear();
#ifndef QT_NO_NETWORK
- QList<QQuickPixmapReply*> activeJobs = networkJobs.values() + asyncResponses.values();
- foreach (QQuickPixmapReply *reply, activeJobs ) {
+
+ const auto cancelJob = [this](QQuickPixmapReply *reply) {
if (reply->loading) {
cancelled.append(reply);
reply->data = 0;
}
- }
+ };
+
+ for (auto *reply : qAsConst(networkJobs))
+ cancelJob(reply);
+
+ for (auto *reply : qAsConst(asyncResponses))
+ cancelJob(reply);
#endif
if (threadObject) threadObject->processJobs();
mutex.unlock();
diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp
index b7eadf5e30..d4956983fb 100644
--- a/src/quick/util/qquicksmoothedanimation.cpp
+++ b/src/quick/util/qquicksmoothedanimation.cpp
@@ -377,9 +377,8 @@ QQuickSmoothedAnimation::~QQuickSmoothedAnimation()
}
QQuickSmoothedAnimationPrivate::QQuickSmoothedAnimationPrivate()
- : anim(0)
+ : anim(new QSmoothedAnimation)
{
- anim = new QSmoothedAnimation;
}
QQuickSmoothedAnimationPrivate::~QQuickSmoothedAnimationPrivate()
diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp
index 791e38e45d..200f243a1b 100644
--- a/src/quick/util/qquickstategroup.cpp
+++ b/src/quick/util/qquickstategroup.cpp
@@ -44,9 +44,9 @@
#include <private/qqmlbinding_p.h>
#include <private/qqmlglobal_p.h>
-#include <QtCore/qstringbuilder.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qvector.h>
#include <private/qobject_p.h>
#include <qqmlinfo.h>
@@ -305,7 +305,7 @@ void QQuickStateGroup::componentComplete()
for (int ii = 0; ii < d->states.count(); ++ii) {
QQuickState *state = d->states.at(ii);
if (!state->isNamed())
- state->setName(QLatin1String("anonymousState") % QString::number(++d->unnamedCount));
+ state->setName(QLatin1String("anonymousState") + QString::number(++d->unnamedCount));
}
if (d->updateAutoState()) {
@@ -379,28 +379,29 @@ QQuickTransition *QQuickStateGroupPrivate::findTransition(const QString &from, c
(t->fromState() == QLatin1String("*") &&
t->toState() == QLatin1String("*"))))
break;
- QStringList fromState;
- QStringList toState;
+ const QString fromStateStr = t->fromState();
+ const QString toStateStr = t->toState();
- fromState = t->fromState().split(QLatin1Char(','));
+ QVector<QStringRef> fromState = fromStateStr.splitRef(QLatin1Char(','));
for (int jj = 0; jj < fromState.count(); ++jj)
fromState[jj] = fromState.at(jj).trimmed();
- toState = t->toState().split(QLatin1Char(','));
+ QVector<QStringRef> toState = toStateStr.splitRef(QLatin1Char(','));
for (int jj = 0; jj < toState.count(); ++jj)
toState[jj] = toState.at(jj).trimmed();
if (ii == 1)
qSwap(fromState, toState);
int tScore = 0;
- if (fromState.contains(from))
+ const QString asterisk = QStringLiteral("*");
+ if (fromState.contains(QStringRef(&from)))
tScore += 2;
- else if (fromState.contains(QLatin1String("*")))
+ else if (fromState.contains(QStringRef(&asterisk)))
tScore += 1;
else
continue;
- if (toState.contains(to))
+ if (toState.contains(QStringRef(&to)))
tScore += 2;
- else if (toState.contains(QLatin1String("*")))
+ else if (toState.contains(QStringRef(&asterisk)))
tScore += 1;
else
continue;
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
index d1db2af367..dd7cb2055d 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
@@ -26,10 +26,10 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
- Timer {
+QtObject {
+ property var timer: Timer {
running: true
interval: 1
onTriggered: {
@@ -38,7 +38,7 @@ Rectangle {
}
}
- Timer {
+ property var stopTimer: Timer {
id: stopTimer
interval: 1000
onTriggered: {
@@ -47,7 +47,7 @@ Rectangle {
}
}
- Timer {
+ property var endTimer: Timer {
id: endTimer
interval: 1000
onTriggered: Qt.quit();
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml
index b250524caa..4236d70ea3 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/exit.qml
@@ -1,6 +1,6 @@
-import QtQuick 2.0
+import QtQml 2.0
-Item {
+QtObject {
Timer {
running: true
interval: 1
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
index 0555d49652..e25c7524f4 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/javascript.qml
@@ -1,6 +1,6 @@
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
+QtObject {
function something(i) {
if (i > 10) {
something(i / 4);
@@ -9,8 +9,8 @@ Rectangle {
}
}
- width: 400
- height: 400
+ property int width: 400
+ property int height: 400
onWidthChanged: something(width);
Component.onCompleted: width = 500;
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
index 25e63669c4..0eff9e9030 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/signalSourceLocation.qml
@@ -1,8 +1,8 @@
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
- width: 400
- height: 400
+QtObject {
+ property int width: 400
+ property int height: 400
onWidthChanged: console.log(width);
Component.onCompleted: width = 500;
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml
index 9c36e13c5b..5dd5caf12f 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/test.qml
@@ -1,5 +1,5 @@
-import QtQuick 2.0
+import QtQml 2.0
-Item {
+QtObject {
}
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
index 18b8947172..4af555a27b 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/timer.qml
@@ -1,10 +1,10 @@
-import QtQuick 2.0
+import QtQml 2.0
-Rectangle {
- width: 100
- height: 62
+QtObject {
+ property int width: 100
+ property int height: 62
- Timer {
+ property var timer: Timer {
running: true
repeat: true
interval: 50
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 2187383a31..c1de5ff594 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -663,11 +663,11 @@ void tst_QQmlProfilerService::signalSourceLocation()
QLatin1String("signalSourceLocation.qml"));
expected.line = 8;
expected.column = 28;
- VERIFY(MessageListQML, 13, expected, CheckAll);
+ VERIFY(MessageListQML, 9, expected, CheckAll);
expected.line = 7;
expected.column = 21;
- VERIFY(MessageListQML, 15, expected, CheckAll);
+ VERIFY(MessageListQML, 11, expected, CheckAll);
}
void tst_QQmlProfilerService::javascript()
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index adf944c7e1..99c18f91a1 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -137,6 +137,7 @@ private slots:
void functionDeclarationsInConditionals();
void arrayPop_QTBUG_35979();
+ void array_unshift_QTBUG_52065();
void regexpLastMatch();
void indexedAccesses();
@@ -3045,6 +3046,20 @@ void tst_QJSEngine::arrayPop_QTBUG_35979()
QCOMPARE(result.toString(), QString("1,3"));
}
+void tst_QJSEngine::array_unshift_QTBUG_52065()
+{
+ QJSEngine eng;
+ QJSValue result = eng.evaluate("[1, 2, 3, 4, 5, 6, 7, 8, 9]");
+ QJSValue unshift = result.property(QStringLiteral("unshift"));
+ unshift.callWithInstance(result, QJSValueList() << QJSValue(0));
+
+ int len = result.property(QStringLiteral("length")).toInt();
+ QCOMPARE(len, 10);
+
+ for (int i = 0; i < len; ++i)
+ QCOMPARE(result.property(i).toInt(), i);
+}
+
void tst_QJSEngine::regexpLastMatch()
{
QJSEngine eng;
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index 5e798f3b48..28f04be5d7 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -69,7 +69,8 @@ qtHaveModule(widgets) {
qjsvalue
}
-SUBDIRS += $$PUBLICTESTS
+SUBDIRS += $$PUBLICTESTS \
+ qqmlextensionplugin
SUBDIRS += $$METATYPETESTS
!winrt { # no QProcess on winrt
!contains(QT_CONFIG, no-qml-debug): SUBDIRS += debugger
diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_52340.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_52340.qml
new file mode 100644
index 0000000000..03f90c15c8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qtbug_52340.qml
@@ -0,0 +1,13 @@
+import QtQml 2.0
+
+QtObject {
+ property bool someProperty: true
+ function testCall() {
+ try {
+ someProperty(); // should throw
+ return false
+ } catch (e) {
+ return true
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
index b130408c18..74c7cda9a3 100644
--- a/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
+++ b/tests/auto/qml/qqmlecmascript/data/sequenceSort.qml
@@ -64,6 +64,16 @@ Item {
var actual = msc.reals(realList);
return checkResults(expected, actual, fn);
}
+ function doIntVectorTest(intList, fn) {
+ var expected = createExpected(intList, fn);
+ var actual = msc.integerVector(intList);
+ return checkResults(expected, actual, fn);
+ }
+ function doRealVectorTest(realList, fn) {
+ var expected = createExpected(realList, fn);
+ var actual = msc.realVector(realList);
+ return checkResults(expected, actual, fn);
+ }
function test_qtbug_25269(useCustomCompare) {
return doStringTest( [ "one", "two", "three" ], null );
@@ -92,4 +102,20 @@ Item {
var fn = useCustomCompare ? compareNumbers : null;
return doRealTest( [ -3.4, 1, 10, 4.23, -30.1, 4.24, 4.21, -1, -1, 12, -100, 87.4, 101.3, -8.88888, 7.76, 10.10, 1.1, -1.1, -0, 11, 12.8, 0.001, -11, -0.75, 99999.99, 11.12, 32.3, 3.333333, 9.876 ], fn );
}
+ function test_number_vector_insertionSort(useCustomCompare) {
+ var fn = useCustomCompare ? compareNumbers : null;
+ return doIntVectorTest( [ 7, 3, 9, 1, 0, -1, 20, -11 ], fn );
+ }
+ function test_number_vector_quickSort(useCustomCompare) {
+ var fn = useCustomCompare ? compareNumbers : null;
+ return doIntVectorTest( [ 7, 3, 37, 9, 1, 0, -1, 20, -11, -300, -87, 1, 3, -2, 100, 108, 96, 9, 99999, 12, 11, 11, 12, 11, 13, -13, 10, 10, 10, 8, 12 ], fn );
+ }
+ function test_real_vector_insertionSort(useCustomCompare) {
+ var fn = useCustomCompare ? compareNumbers : null;
+ return doRealVectorTest( [ -3.4, 1, 10, 4.23, -30.1, 4.24, 4.21, -1, -1 ], fn );
+ }
+ function test_real_vector_quickSort(useCustomCompare) {
+ var fn = useCustomCompare ? compareNumbers : null;
+ return doRealVectorTest( [ -3.4, 1, 10, 4.23, -30.1, 4.24, 4.21, -1, -1, 12, -100, 87.4, 101.3, -8.88888, 7.76, 10.10, 1.1, -1.1, -0, 11, 12.8, 0.001, -11, -0.75, 99999.99, 11.12, 32.3, 3.333333, 9.876 ], fn );
+ }
}
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index 2afa21ddd6..d9ddcd71a7 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -295,6 +295,18 @@ public:
{
return v;
}
+ Q_INVOKABLE QVector<int> integerVector(QVector<int> v) const
+ {
+ return v;
+ }
+ Q_INVOKABLE QVector<qreal> realVector(QVector<qreal> v) const
+ {
+ return v;
+ }
+ Q_INVOKABLE QVector<bool> boolVector(QVector<bool> v) const
+ {
+ return v;
+ }
};
static MyInheritedQmlObject *theSingletonObject = 0;
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index 81b9b8d7bf..47fb2a56e7 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -791,6 +791,8 @@ public:
Q_INVOKABLE void method_QScriptValue(QJSValue a) { invoke(14); m_actuals << qVariantFromValue(a); }
Q_INVOKABLE void method_intQScriptValue(int a, QJSValue b) { invoke(15); m_actuals << a << qVariantFromValue(b); }
Q_INVOKABLE void method_QByteArray(QByteArray value) { invoke(29); m_actuals << value; }
+ Q_INVOKABLE QJSValue method_intQJSValue(int a, QJSValue b) { invoke(30); m_actuals << a << qVariantFromValue(b); return b.call(); }
+ Q_INVOKABLE QJSValue method_intQJSValue(int a, int b) { m_actuals << a << b; return QJSValue();} // Should never be called.
Q_INVOKABLE void method_overload(int a) { invoke(16); m_actuals << a; }
Q_INVOKABLE void method_overload(int a, int b) { invoke(17); m_actuals << a << b; }
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index f71d7efe3a..2f78df1f11 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -322,6 +322,7 @@ private slots:
void writeUnregisteredQObjectProperty();
void switchExpression();
void qtbug_46022();
+ void qtbug_52340();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -2944,6 +2945,18 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->invoked(), 29);
QCOMPARE(o->actuals().count(), 1);
QCOMPARE(qvariant_cast<QByteArray>(o->actuals().at(0)), QByteArray("Hello"));
+
+ o->reset();
+ QV4::ScopedValue ret(scope, EVALUATE("object.method_intQJSValue(123, function() { return \"Hello world!\";})"));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 30);
+ QVERIFY(ret->isString());
+ QCOMPARE(ret->toQStringNoThrow(), QString("Hello world!"));
+ QCOMPARE(o->actuals().count(), 2);
+ QCOMPARE(o->actuals().at(0), QVariant(123));
+ QJSValue callback = qvariant_cast<QJSValue>(o->actuals().at(1));
+ QVERIFY(!callback.isNull());
+ QVERIFY(callback.isCallable());
}
// QTBUG-13047 (check that you can pass registered object types as args)
@@ -7331,7 +7344,7 @@ void tst_qqmlecmascript::sequenceSort_data()
QTest::newRow("qtbug_25269") << "test_qtbug_25269" << false;
- const char *types[] = { "alphabet", "numbers", "reals" };
+ const char *types[] = { "alphabet", "numbers", "reals", "number_vector", "real_vector" };
const char *sort[] = { "insertionSort", "quickSort" };
for (size_t t=0 ; t < sizeof(types)/sizeof(types[0]) ; ++t) {
@@ -7898,6 +7911,17 @@ void tst_qqmlecmascript::qtbug_46022()
QCOMPARE(obj->property("test2").toBool(), true);
}
+void tst_qqmlecmascript::qtbug_52340()
+{
+ QQmlComponent component(&engine, testFileUrl("qtbug_52340.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QVariant returnValue;
+ QVERIFY(QMetaObject::invokeMethod(object.data(), "testCall", Q_RETURN_ARG(QVariant, returnValue)));
+ QVERIFY(returnValue.isValid());
+ QVERIFY(returnValue.toBool());
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlextensionplugin/qqmlextensionplugin.pro b/tests/auto/qml/qqmlextensionplugin/qqmlextensionplugin.pro
new file mode 100644
index 0000000000..af74707c4a
--- /dev/null
+++ b/tests/auto/qml/qqmlextensionplugin/qqmlextensionplugin.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+TARGET = tst_qqmlextensionplugin
+SOURCES += tst_qqmlextensionplugin.cpp
+osx:CONFIG -= app_bundle
+QT += qml testlib
diff --git a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
new file mode 100644
index 0000000000..ab5e958323
--- /dev/null
+++ b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtTest>
+#include <QtQml>
+
+#if defined(Q_OS_WIN)
+# define SUFFIX QLatin1String(".dll")
+# define DEBUG_SUFFIX QLatin1String("d.dll")
+
+#elif defined(Q_OS_DARWIN)
+# define SUFFIX QLatin1String(".dylib")
+# define DEBUG_SUFFIX QLatin1String("_debug.dylib")
+
+# else // Unix
+# define SUFFIX QLatin1String(".so")
+#endif
+
+
+class tst_qqmlextensionplugin : public QObject
+{
+ Q_OBJECT
+
+ bool isDuplicate(QString file, const QList<QString> & files) {
+#ifndef DEBUG_SUFFIX
+ Q_UNUSED(file)
+ Q_UNUSED(files)
+ return false;
+#else
+# ifdef QT_DEBUG
+ return !file.endsWith(DEBUG_SUFFIX) && files.contains(file.replace(SUFFIX, DEBUG_SUFFIX));
+# else
+ return file.endsWith(DEBUG_SUFFIX) && files.contains(file.replace(DEBUG_SUFFIX, SUFFIX));
+# endif
+#endif
+ }
+
+public:
+ tst_qqmlextensionplugin() {}
+
+private Q_SLOTS:
+ void iidCheck_data();
+ void iidCheck();
+};
+
+
+void tst_qqmlextensionplugin::iidCheck_data()
+{
+ QList<QString> files;
+ for (QDirIterator it(QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath), QDirIterator::Subdirectories); it.hasNext(); ) {
+ QString file = it.next();
+ if (file.endsWith(SUFFIX)) {
+ files << file;
+ }
+ }
+
+ for (QMutableListIterator<QString> it(files); it.hasNext(); ) {
+ QString file = it.next();
+ if (isDuplicate(file, files)) {
+ it.remove();
+ }
+ }
+
+ QTest::addColumn<QString>("filePath");
+ foreach (const QString &file, files) {
+ QFileInfo fileInfo(file);
+ QTest::newRow(fileInfo.baseName().toLatin1().data()) << fileInfo.absoluteFilePath();
+ }
+}
+
+
+void tst_qqmlextensionplugin::iidCheck()
+{
+ QFETCH(QString, filePath);
+
+ QPluginLoader loader(filePath);
+ QVERIFY(loader.load());
+ QVERIFY(loader.instance() != Q_NULLPTR);
+
+ if (qobject_cast<QQmlExtensionPlugin *>(loader.instance())) {
+ QString iid = loader.metaData().value(QStringLiteral("IID")).toString();
+ QCOMPARE(iid, QLatin1String(QQmlExtensionInterface_iid));
+ }
+}
+
+
+QTEST_APPLESS_MAIN(tst_qqmlextensionplugin)
+#include "tst_qqmlextensionplugin.moc"
diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
index bfa7e2f13f..68739886c4 100644
--- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
+++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
@@ -41,6 +41,8 @@ private slots:
void importPathOrder();
void testDesignerSupported();
void uiFormatLoading();
+ void completeQmldirPaths_data();
+ void completeQmldirPaths();
void cleanup();
};
@@ -146,6 +148,43 @@ void tst_QQmlImport::importPathOrder()
QCOMPARE(expectedImportPaths, engine.importPathList());
}
+Q_DECLARE_METATYPE(QQmlImports::ImportVersion)
+
+void tst_QQmlImport::completeQmldirPaths_data()
+{
+ QTest::addColumn<QString>("uri");
+ QTest::addColumn<QStringList>("basePaths");
+ QTest::addColumn<int>("majorVersion");
+ QTest::addColumn<int>("minorVersion");
+ QTest::addColumn<QStringList>("expectedPaths");
+
+ QTest::newRow("QtQml") << "QtQml" << (QStringList() << "qtbase/qml/" << "path/to/qml") << 2 << 7
+ << (QStringList() << "qtbase/qml/QtQml.2.7/qmldir" << "path/to/qml/QtQml.2.7/qmldir"
+ << "qtbase/qml/QtQml.2/qmldir" << "path/to/qml/QtQml.2/qmldir"
+ << "qtbase/qml/QtQml/qmldir" << "path/to/qml/QtQml/qmldir");
+
+ QTest::newRow("QtQml.Models") << "QtQml.Models" << QStringList("qtbase/qml/") << 2 << 2
+ << (QStringList() << "qtbase/qml/QtQml/Models.2.2/qmldir" << "qtbase/qml/QtQml.2.2/Models/qmldir"
+ << "qtbase/qml/QtQml/Models.2/qmldir" << "qtbase/qml/QtQml.2/Models/qmldir"
+ << "qtbase/qml/QtQml/Models/qmldir");
+
+ QTest::newRow("org.qt-project.foo.bar") << "org.qt-project.foo.bar" << QStringList("qtbase/qml/") << 0 << 1
+ << (QStringList() << "qtbase/qml/org/qt-project/foo/bar.0.1/qmldir" << "qtbase/qml/org/qt-project/foo.0.1/bar/qmldir" << "qtbase/qml/org/qt-project.0.1/foo/bar/qmldir" << "qtbase/qml/org.0.1/qt-project/foo/bar/qmldir"
+ << "qtbase/qml/org/qt-project/foo/bar.0/qmldir" << "qtbase/qml/org/qt-project/foo.0/bar/qmldir" << "qtbase/qml/org/qt-project.0/foo/bar/qmldir" << "qtbase/qml/org.0/qt-project/foo/bar/qmldir"
+ << "qtbase/qml/org/qt-project/foo/bar/qmldir");
+}
+
+void tst_QQmlImport::completeQmldirPaths()
+{
+ QFETCH(QString, uri);
+ QFETCH(QStringList, basePaths);
+ QFETCH(int, majorVersion);
+ QFETCH(int, minorVersion);
+ QFETCH(QStringList, expectedPaths);
+
+ QCOMPARE(QQmlImports::completeQmldirPaths(uri, basePaths, majorVersion, minorVersion), expectedPaths);
+}
+
QTEST_MAIN(tst_QQmlImport)
#include "tst_qqmlimport.moc"
diff --git a/tests/auto/qml/qqmllanguage/BLACKLIST b/tests/auto/qml/qqmllanguage/BLACKLIST
deleted file mode 100644
index c1c7e56df9..0000000000
--- a/tests/auto/qml/qqmllanguage/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[importsPath]
-windows
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 1ac1661ea8..98a97ebd66 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -4135,8 +4135,6 @@ void tst_qqmllanguage::dataAlignment()
{
QVERIFY(sizeof(QQmlVMEMetaData) % sizeof(int) == 0);
QVERIFY(sizeof(QQmlVMEMetaData::AliasData) % sizeof(int) == 0);
- QVERIFY(sizeof(QQmlVMEMetaData::PropertyData) % sizeof(int) == 0);
- QVERIFY(sizeof(QQmlVMEMetaData::MethodData) % sizeof(int) == 0);
}
void tst_qqmllanguage::deleteSingletons()
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/child.qml b/tests/auto/qml/qqmlmoduleplugin/data/child.qml
new file mode 100644
index 0000000000..a11ae297d7
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/child.qml
@@ -0,0 +1,3 @@
+import org.qtproject.AutoTestQmlPluginType.ChildPlugin 1.0
+
+MyChildPluginType { value: 123 }
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/child2.qml b/tests/auto/qml/qqmlmoduleplugin/data/child2.qml
new file mode 100644
index 0000000000..667164516a
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/child2.qml
@@ -0,0 +1,3 @@
+import org.qtproject.AutoTestQmlPluginType.ChildPlugin 2.0
+
+MyChildPluginType { valueOnlyIn2: 123 }
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/child21.qml b/tests/auto/qml/qqmlmoduleplugin/data/child21.qml
new file mode 100644
index 0000000000..064d5474e0
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/data/child21.qml
@@ -0,0 +1,3 @@
+import org.qtproject.AutoTestQmlPluginType.ChildPlugin 2.1
+
+MyChildPluginType { valueOnlyIn2: 123 }
diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
index 82c3c926fd..fa9782f8c2 100644
--- a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
index bb2a344811..fe01507412 100644
--- a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp
index bb2a344811..fe01507412 100644
--- a/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/invalidStrictModule/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
index 4ca5eb5402..92d30351a7 100644
--- a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
@@ -56,7 +56,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
index f48ab16b03..5fc05b91bd 100644
--- a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
new file mode 100644
index 0000000000..515d56a3c4
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QStringList>
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqml.h>
+#include <QDebug>
+
+class MyChildPluginType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+ Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue)
+
+public:
+ MyChildPluginType(QObject *parent=0) : QObject(parent)
+ {
+ qWarning("child import2.1 worked");
+ }
+
+ int value() const { return v; }
+ void setValue(int i) { v = i; }
+
+private:
+ int v;
+};
+
+
+class MyChildPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ MyChildPlugin()
+ {
+ qWarning("child plugin2.1 created");
+ }
+
+ void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlPluginType.ChildPlugin");
+ qmlRegisterType<MyChildPluginType>(uri, 2, 1, "MyChildPluginType");
+ }
+};
+
+#include "childplugin.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.pro b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.pro
new file mode 100644
index 0000000000..7a0cd6f80f
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.pro
@@ -0,0 +1,12 @@
+TEMPLATE = lib
+CONFIG += childplugin
+SOURCES = childplugin.cpp
+QT = core qml
+DESTDIR = ../../imports/org/qtproject/AutoTestQmlPluginType.2.1/ChildPlugin
+
+QT += core-private gui-private qml-private
+
+IMPORT_FILES = \
+ qmldir
+
+include (../../../../shared/imports.pri)
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/qmldir
new file mode 100644
index 0000000000..c8d6488065
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/qmldir
@@ -0,0 +1 @@
+plugin childplugin
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
index 2dc771fad1..6cae5254bc 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
@@ -53,7 +53,7 @@ private:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
new file mode 100644
index 0000000000..56545cfa3c
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QStringList>
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqml.h>
+#include <QDebug>
+
+class MyChildPluginType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+ Q_PROPERTY(int valueOnlyIn2 READ value WRITE setValue)
+
+public:
+ MyChildPluginType(QObject *parent=0) : QObject(parent)
+ {
+ qWarning("child import2 worked");
+ }
+
+ int value() const { return v; }
+ void setValue(int i) { v = i; }
+
+private:
+ int v;
+};
+
+
+class MyChildPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ MyChildPlugin()
+ {
+ qWarning("child plugin2 created");
+ }
+
+ void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlPluginType.ChildPlugin");
+ qmlRegisterType<MyChildPluginType>(uri, 2, 0, "MyChildPluginType");
+ }
+};
+
+#include "childplugin.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.pro b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.pro
new file mode 100644
index 0000000000..c9283411f3
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.pro
@@ -0,0 +1,13 @@
+TEMPLATE = lib
+CONFIG += childplugin
+SOURCES = childplugin.cpp
+QT = core qml
+DESTDIR = ../../imports/org/qtproject/AutoTestQmlPluginType.2/ChildPlugin
+
+QT += core-private gui-private qml-private
+
+IMPORT_DIR = DESTDIR
+IMPORT_FILES = \
+ qmldir
+
+include (../../../../shared/imports.pri)
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/qmldir
new file mode 100644
index 0000000000..c8d6488065
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/qmldir
@@ -0,0 +1 @@
+plugin childplugin
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
index 4b25181a86..49a2a747a4 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
@@ -53,7 +53,7 @@ private:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
new file mode 100644
index 0000000000..28490d3d98
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QStringList>
+#include <QtQml/qqmlextensionplugin.h>
+#include <QtQml/qqml.h>
+#include <QDebug>
+
+class MyChildPluginType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int value READ value WRITE setValue)
+
+public:
+ MyChildPluginType(QObject *parent=0) : QObject(parent)
+ {
+ qWarning("child import worked");
+ }
+
+ int value() const { return v; }
+ void setValue(int i) { v = i; }
+
+private:
+ int v;
+};
+
+
+class MyChildPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ MyChildPlugin()
+ {
+ qWarning("child plugin created");
+ }
+
+ void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == "org.qtproject.AutoTestQmlPluginType.ChildPlugin");
+ qmlRegisterType<MyChildPluginType>(uri, 1, 0, "MyChildPluginType");
+ }
+};
+
+#include "childplugin.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.pro b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.pro
new file mode 100644
index 0000000000..5f5c01f77e
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.pro
@@ -0,0 +1,12 @@
+TEMPLATE = lib
+CONFIG += childplugin
+SOURCES = childplugin.cpp
+QT = core qml
+DESTDIR = ../../imports/org/qtproject/AutoTestQmlPluginType/ChildPlugin
+
+QT += core-private gui-private qml-private
+
+IMPORT_FILES = \
+ qmldir
+
+include (../../../../shared/imports.pri)
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/qmldir b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/qmldir
new file mode 100644
index 0000000000..c8d6488065
--- /dev/null
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/qmldir
@@ -0,0 +1 @@
+plugin childplugin
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
index 7147769406..db51185de6 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
@@ -52,7 +52,7 @@ private:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
index 8ae091bc0f..e780d4a7fd 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
@@ -43,7 +43,7 @@ public:
class MyMixedPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyMixedPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
index 4be0ad4c66..470da6c35f 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
@@ -43,7 +43,7 @@ public:
class MyMixedPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyMixedPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
index 2c1047450a..60a0a4a3e2 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
@@ -33,7 +33,7 @@
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
index 4eb875be43..7669d65568 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
@@ -52,7 +52,7 @@ private:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin()
diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
index bace4644b3..92211ebf9d 100644
--- a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
index a98398ac94..3df3e9cc81 100644
--- a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
index df85d4a327..afdeea80f4 100644
--- a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
@@ -40,7 +40,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
index 5c30d8cc00..889968f6cc 100644
--- a/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
+++ b/tests/auto/qml/qqmlmoduleplugin/qqmlmoduleplugin.pro
@@ -17,7 +17,10 @@ SUBDIRS =\
preemptedStrictModule\
invalidNamespaceModule\
invalidFirstCommandModule\
- protectedModule
+ protectedModule\
+ plugin/childplugin\
+ plugin.2/childplugin\
+ plugin.2.1/childplugin
tst_qqmlmoduleplugin_pro.depends += plugin
SUBDIRS += tst_qqmlmoduleplugin.pro
diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
index 1e86c0da49..4f5176ae62 100644
--- a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
index ad53ac95f3..eaa9aeb1d0 100644
--- a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
@@ -41,7 +41,7 @@ public:
class MyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
MyPlugin() {}
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index 6ae1a6654f..265492b435 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -70,6 +70,9 @@ private slots:
void importStrictModule();
void importStrictModule_data();
void importProtectedModule();
+ void importsChildPlugin();
+ void importsChildPlugin2();
+ void importsChildPlugin21();
private:
QString m_importsDirectory;
@@ -575,6 +578,57 @@ void tst_qqmlmoduleplugin::importProtectedModule()
QVERIFY(object != 0);
}
+void tst_qqmlmoduleplugin::importsChildPlugin()
+{
+ QQmlEngine engine;
+ engine.addImportPath(m_importsDirectory);
+ QTest::ignoreMessage(QtWarningMsg, "child plugin created");
+ QTest::ignoreMessage(QtWarningMsg, "child import worked");
+ QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
+ QQmlComponent component(&engine, testFileUrl(QStringLiteral("child.qml")));
+ foreach (QQmlError err, component.errors())
+ qWarning() << err;
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("value").toInt(),123);
+ delete object;
+}
+
+void tst_qqmlmoduleplugin::importsChildPlugin2()
+{
+ QQmlEngine engine;
+ engine.addImportPath(m_importsDirectory);
+ QTest::ignoreMessage(QtWarningMsg, "child plugin2 created");
+ QTest::ignoreMessage(QtWarningMsg, "child import2 worked");
+ QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
+ QQmlComponent component(&engine, testFileUrl(QStringLiteral("child2.qml")));
+ foreach (QQmlError err, component.errors())
+ qWarning() << err;
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("value").toInt(),123);
+ delete object;
+}
+
+void tst_qqmlmoduleplugin::importsChildPlugin21()
+{
+ QQmlEngine engine;
+ engine.addImportPath(m_importsDirectory);
+ QTest::ignoreMessage(QtWarningMsg, "child plugin2.1 created");
+ QTest::ignoreMessage(QtWarningMsg, "child import2.1 worked");
+ QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
+ QQmlComponent component(&engine, testFileUrl(QStringLiteral("child21.qml")));
+ foreach (QQmlError err, component.errors())
+ qWarning() << err;
+ VERIFY_ERRORS(0);
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("value").toInt(),123);
+ delete object;
+}
+
QTEST_MAIN(tst_qqmlmoduleplugin)
#include "tst_qqmlmoduleplugin.moc"
diff --git a/tests/auto/qml/qqmlqt/data/qtObjectContents.qml b/tests/auto/qml/qqmlqt/data/qtObjectContents.qml
new file mode 100644
index 0000000000..c85e7986e9
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/qtObjectContents.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+QtObject {
+ property var values: Object()
+ Component.onCompleted: {
+ for (var key in Qt) {
+ values[key] = Qt[key]
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 413feb0eb4..8150241e4a 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -90,6 +90,7 @@ private slots:
void resolvedUrl();
void later_data();
void later();
+ void qtObjectContents();
private:
QQmlEngine engine;
@@ -1093,6 +1094,51 @@ void tst_qqmlqt::later()
delete root;
}
+void tst_qqmlqt::qtObjectContents()
+{
+ struct StaticQtMetaObject : public QObject
+ {
+ static const QMetaObject *get()
+ { return &staticQtMetaObject; }
+ };
+
+ QQmlComponent component(&engine, testFileUrl("qtObjectContents.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(object->property("values").canConvert<QJSValue>());
+ QVariantMap values = object->property("values").value<QJSValue>().toVariant().toMap();
+
+ QSet<const char *> keys;
+ int uniqueKeys = 0;
+ const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
+ for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
+ QMetaEnum enumerator = qtMetaObject->enumerator(ii);
+ for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
+ auto key = enumerator.key(jj);
+// qDebug() << "key:" << key;
+ if (!keys.contains(key)) {
+ ++uniqueKeys;
+ keys.insert(key);
+ }
+ QVERIFY(values.contains(key));
+ QVariant value = values.value(key);
+ QVERIFY(value.canConvert<int>());
+ QCOMPARE(value.toInt(), enumerator.value(jj));
+ }
+ }
+ QVERIFY(values.contains("Asynchronous"));
+ QCOMPARE(values.value("Asynchronous").toInt(), 0);
+ ++uniqueKeys;
+ QVERIFY(values.contains("Synchronous"));
+ QCOMPARE(values.value("Synchronous").toInt(), 1);
+ ++uniqueKeys;
+ QCOMPARE(values.count(), uniqueKeys);
+
+ delete object;
+}
+
QTEST_MAIN(tst_qqmlqt)
#include "tst_qqmlqt.moc"
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
index d3a3b81832..34b3920a38 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
@@ -35,7 +35,7 @@
class SlowPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri);
diff --git a/tests/auto/qml/qqmltypeloader/data/trim_cache.qml b/tests/auto/qml/qqmltypeloader/data/trim_cache.qml
new file mode 100644
index 0000000000..74303977dd
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/trim_cache.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.2
+Rectangle
+{
+ objectName: "dings"
+ width: 100
+ height: 100
+ color: "blue"
+}
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 24358897f7..ef1ea3a897 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -30,6 +30,9 @@
#include <QtQml/qqmlengine.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
+#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qqmltypeloader_p.h>
+#include <QtQml/private/qqmlcompiler_p.h>
#include "../../shared/util.h"
class tst_QQMLTypeLoader : public QQmlDataTest
@@ -39,6 +42,7 @@ class tst_QQMLTypeLoader : public QQmlDataTest
private slots:
void testLoadComplete();
void loadComponentSynchronously();
+ void trimCache();
};
void tst_QQMLTypeLoader::testLoadComplete()
@@ -68,6 +72,32 @@ void tst_QQMLTypeLoader::loadComponentSynchronously()
QVERIFY(o);
}
+void tst_QQMLTypeLoader::trimCache()
+{
+ QQmlEngine engine;
+ QQmlTypeLoader &loader = QQmlEnginePrivate::get(&engine)->typeLoader;
+ for (int i = 0; i < 256; ++i) {
+ QUrl url = testFileUrl("trim_cache.qml");
+ url.setQuery(QString::number(i));
+
+ QQmlTypeData *data = loader.getType(url);
+ if (i % 5 == 0) // keep references to some of them so that they aren't trimmed
+ data->compiledData()->addref();
+
+ data->release();
+ }
+
+ for (int i = 0; i < 256; ++i) {
+ QUrl url = testFileUrl("trim_cache.qml");
+ url.setQuery(QString::number(i));
+ if (i % 5 == 0)
+ QVERIFY(loader.isTypeLoaded(url));
+ else if (i < 128)
+ QVERIFY(!loader.isTypeLoaded(url));
+ // The cache is free to keep the others.
+ }
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 300f5b90e5..f506d0f53a 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -30,6 +30,7 @@
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>
+#include <QJSValueIterator>
#include <private/qquickvaluetypes_p.h>
#include <private/qqmlglobal_p.h>
#include "../../shared/util.h"
@@ -89,6 +90,7 @@ private slots:
void customValueTypeInQml();
void gadgetInheritance();
void toStringConversion();
+ void enumerableProperties();
private:
QQmlEngine engine;
@@ -1649,6 +1651,25 @@ void tst_qqmlvaluetypes::toStringConversion()
QCOMPARE(stringConversion.toString(), StringLessGadget_to_QString(g));
}
+void tst_qqmlvaluetypes::enumerableProperties()
+{
+ QJSEngine engine;
+ DerivedGadget g;
+ QJSValue value = engine.toScriptValue(g);
+ QSet<QString> names;
+ QJSValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ const QString name = it.name();
+ QVERIFY(!names.contains(name));
+ names.insert(name);
+ }
+
+ QCOMPARE(names.count(), 2);
+ QVERIFY(names.contains(QStringLiteral("baseProperty")));
+ QVERIFY(names.contains(QStringLiteral("derivedProperty")));
+}
+
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
index ab111a6cd3..77fa1292c4 100644
--- a/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
+++ b/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp
@@ -39,7 +39,6 @@
#include "../shared/visualtestutil.h"
Q_DECLARE_METATYPE(QQuickAnchors::Anchor)
-Q_DECLARE_METATYPE(QQuickAnchorLine::AnchorLine)
using namespace QQuickVisualTestUtil;
@@ -351,14 +350,13 @@ void tst_qquickanchors::illegalSets_data()
void tst_qquickanchors::reset()
{
QFETCH(QString, side);
- QFETCH(QQuickAnchorLine::AnchorLine, anchorLine);
- QFETCH(QQuickAnchors::Anchor, usedAnchor);
+ QFETCH(QQuickAnchors::Anchor, anchor);
QQuickItem *baseItem = new QQuickItem;
- QQuickAnchorLine anchor;
- anchor.item = baseItem;
- anchor.anchorLine = anchorLine;
+ QQuickAnchorLine anchorLine;
+ anchorLine.item = baseItem;
+ anchorLine.anchorLine = anchor;
QQuickItem *item = new QQuickItem;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
@@ -366,11 +364,11 @@ void tst_qquickanchors::reset()
const QMetaObject *meta = itemPrivate->anchors()->metaObject();
QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
- QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
- QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), true);
+ QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchorLine)));
+ QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(anchor), true);
QVERIFY(p.reset(itemPrivate->anchors()));
- QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), false);
+ QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(anchor), false);
delete item;
delete baseItem;
@@ -379,17 +377,16 @@ void tst_qquickanchors::reset()
void tst_qquickanchors::reset_data()
{
QTest::addColumn<QString>("side");
- QTest::addColumn<QQuickAnchorLine::AnchorLine>("anchorLine");
- QTest::addColumn<QQuickAnchors::Anchor>("usedAnchor");
+ QTest::addColumn<QQuickAnchors::Anchor>("anchor");
- QTest::newRow("left") << "left" << QQuickAnchorLine::Left << QQuickAnchors::LeftAnchor;
- QTest::newRow("top") << "top" << QQuickAnchorLine::Top << QQuickAnchors::TopAnchor;
- QTest::newRow("right") << "right" << QQuickAnchorLine::Right << QQuickAnchors::RightAnchor;
- QTest::newRow("bottom") << "bottom" << QQuickAnchorLine::Bottom << QQuickAnchors::BottomAnchor;
+ QTest::newRow("left") << "left" << QQuickAnchors::LeftAnchor;
+ QTest::newRow("top") << "top" << QQuickAnchors::TopAnchor;
+ QTest::newRow("right") << "right" << QQuickAnchors::RightAnchor;
+ QTest::newRow("bottom") << "bottom" << QQuickAnchors::BottomAnchor;
- QTest::newRow("hcenter") << "horizontalCenter" << QQuickAnchorLine::HCenter << QQuickAnchors::HCenterAnchor;
- QTest::newRow("vcenter") << "verticalCenter" << QQuickAnchorLine::VCenter << QQuickAnchors::VCenterAnchor;
- QTest::newRow("baseline") << "baseline" << QQuickAnchorLine::Baseline << QQuickAnchors::BaselineAnchor;
+ QTest::newRow("hcenter") << "horizontalCenter" << QQuickAnchors::HCenterAnchor;
+ QTest::newRow("vcenter") << "verticalCenter" << QQuickAnchors::VCenterAnchor;
+ QTest::newRow("baseline") << "baseline" << QQuickAnchors::BaselineAnchor;
}
void tst_qquickanchors::resetConvenience()
diff --git a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
index b0f0f886a0..b34f58f7c4 100644
--- a/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
+++ b/tests/auto/quick/qquickanimatedimage/tst_qquickanimatedimage.cpp
@@ -60,6 +60,7 @@ private slots:
void remote_data();
void sourceSize();
void sourceSizeChanges();
+ void sourceSizeChanges_intermediate();
void sourceSizeReadOnly();
void invalidSource();
void qtbug_16520();
@@ -205,16 +206,12 @@ void tst_qquickanimatedimage::mirror_notRunning()
int frame = anim->currentFrame();
bool playing = anim->isPlaying();
- bool paused = anim->isPlaying();
+ bool paused = anim->isPaused();
anim->setProperty("mirror", true);
screenshot = window.grabWindow();
screenshot.save("screen.png");
-#if defined(Q_OS_WIN)
- // QTBUG-36717
- QSKIP("This test is failing in the CI system under mysterious circumstances");
-#endif
QCOMPARE(screenshot, expected);
// mirroring should not change the current frame or playing status
@@ -374,6 +371,28 @@ void tst_qquickanimatedimage::sourceSizeChanges()
delete anim;
}
+void tst_qquickanimatedimage::sourceSizeChanges_intermediate()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nAnimatedImage { readonly property int testWidth: status === AnimatedImage.Ready ? sourceSize.width : -1; source: srcImage }", QUrl::fromLocalFile(""));
+ QTRY_VERIFY(component.isReady());
+ QQmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", "");
+
+ QScopedPointer<QQuickAnimatedImage> anim(qobject_cast<QQuickAnimatedImage*>(component.create()));
+ QVERIFY(anim != 0);
+
+ ctxt->setContextProperty("srcImage", testFileUrl("hearts.gif"));
+ QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
+ QTRY_COMPARE(anim->property("testWidth").toInt(), anim->sourceSize().width());
+
+ ctxt->setContextProperty("srcImage", testFileUrl("hearts_copy.gif"));
+ QTRY_COMPARE(anim->status(), QQuickAnimatedImage::Ready);
+ QTRY_COMPARE(anim->property("testWidth").toInt(), anim->sourceSize().width());
+}
+
+
void tst_qquickanimatedimage::qtbug_16520()
{
TestHTTPServer server;
diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
new file mode 100644
index 0000000000..7095602ea2
--- /dev/null
+++ b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+import QtTest 1.1
+
+CanvasTestCase {
+ id:testCase
+ name: "imagedata"
+ function init_data() { return testData("2d"); }
+ function test_rounding(row) {
+ var canvas = createCanvasObject(row);
+ var ctx = canvas.getContext('2d');
+ var size = 17
+ ctx.reset();
+ ctx.fillStyle = Qt.rgba(0.7, 0.8, 0.9, 1.0);
+ ctx.fillRect(0, 0, size, size);
+
+ var center = size / 2;
+ var imageData = ctx.getImageData(center, center, center, center);
+ comparePixel(ctx, center, center, imageData.data[0], imageData.data[1], imageData.data[2], imageData.data[3]);
+
+ canvas.destroy();
+ }
+}
diff --git a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
index 3c41d498e5..c6d2a69f8c 100644
--- a/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
+++ b/tests/auto/quick/qquickcanvasitem/qquickcanvasitem.pro
@@ -25,6 +25,7 @@ OTHER_FILES += \
data/tst_arcto.qml \
data/tst_arc.qml \
data/tst_context.qml \
+ data/tst_imagedata.qml \
data/CanvasTestCase.qml \
data/CanvasComponent.qml \
data/tst_image.qml \
diff --git a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
index a7b5f4943e..6a919d048e 100644
--- a/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
+++ b/tests/auto/quick/qquickdrag/tst_qquickdrag.cpp
@@ -139,6 +139,8 @@ private slots:
void cleanupTestCase();
void active();
+ void setActive_data();
+ void setActive();
void drop();
void move();
void parentChange();
@@ -374,6 +376,50 @@ void tst_QQuickDrag::active()
QCOMPARE(dropTarget.enterEvents, 0); QCOMPARE(dropTarget.leaveEvents, 0); QCOMPARE(dropTarget.moveEvents, 0);
}
+void tst_QQuickDrag::setActive_data()
+{
+ QTest::addColumn<QString>("dragType");
+
+ QTest::newRow("default") << "";
+ QTest::newRow("internal") << "Drag.dragType: Drag.Internal";
+ QTest::newRow("none") << "Drag.dragType: Drag.None";
+ /* We don't test Drag.Automatic, because that causes QDrag::exec() to be
+ * invoked, and on some platforms tha's implemented by running a main loop
+ * until the drag has finished -- and at that point, the Drag.active will
+ * be false again. */
+}
+
+// QTBUG-52540
+void tst_QQuickDrag::setActive()
+{
+ QFETCH(QString, dragType);
+
+ QQuickWindow window;
+ TestDropTarget dropTarget(window.contentItem());
+ dropTarget.setSize(QSizeF(100, 100));
+ QQmlComponent component(&engine);
+ component.setData(
+ "import QtQuick 2.0\n"
+ "Item {\n"
+ "property bool dragActive: Drag.active\n"
+ "property Item dragTarget: Drag.target\n" +
+ dragType.toUtf8() + "\n"
+ "x: 50; y: 50\n"
+ "width: 10; height: 10\n"
+ "}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickItem *item = qobject_cast<QQuickItem *>(object.data());
+ QVERIFY(item);
+ item->setParentItem(&dropTarget);
+
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), false);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), false);
+
+ evaluate<void>(item, "Drag.active = true");
+ QCOMPARE(evaluate<bool>(item, "Drag.active"), true);
+ QCOMPARE(evaluate<bool>(item, "dragActive"), true);
+}
+
void tst_QQuickDrag::drop()
{
QQuickWindow window;
diff --git a/tests/auto/quick/qquickpathview/data/movementDirection.qml b/tests/auto/quick/qquickpathview/data/movementDirection.qml
new file mode 100644
index 0000000000..fce914dd68
--- /dev/null
+++ b/tests/auto/quick/qquickpathview/data/movementDirection.qml
@@ -0,0 +1,43 @@
+import QtQuick 2.0
+
+Item {
+ id: root
+ width: 320; height: 480
+
+ PathView {
+ id: view
+ objectName: "view"
+ anchors.fill: parent
+
+ model: ListModel {
+ ListElement { lColor: "red" }
+ ListElement { lColor: "green" }
+ ListElement { lColor: "yellow" }
+ ListElement { lColor: "blue" }
+ ListElement { lColor: "purple" }
+ ListElement { lColor: "gray" }
+ ListElement { lColor: "brown" }
+ ListElement { lColor: "thistle" }
+ }
+
+ delegate: Component {
+ id: photoDelegate
+ Rectangle {
+ id: wrapper
+ objectName: "wrapper"
+ width: 40; height: 40; color: lColor
+
+ Text { text: index }
+ }
+ }
+
+ snapMode: PathView.SnapToItem
+ highlightMoveDuration: 1000
+ path: Path {
+ startX: 0+20; startY: root.height/2
+ PathLine { x: root.width*2; y: root.height/2 }
+ }
+
+ Text { text: "Offset: " + view.offset }
+ }
+}
diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
index 51c772f540..6761313210 100644
--- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
+++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp
@@ -137,6 +137,8 @@ private slots:
void jsArrayChange();
void qtbug42716();
void addCustomAttribute();
+ void movementDirection_data();
+ void movementDirection();
};
class TestObject : public QObject
@@ -2383,6 +2385,72 @@ void tst_QQuickPathView::addCustomAttribute()
window->show();
}
+void tst_QQuickPathView::movementDirection_data()
+{
+ QTest::addColumn<QQuickPathView::MovementDirection>("movementdirection");
+ QTest::addColumn<int>("toidx");
+ QTest::addColumn<qreal>("fromoffset");
+ QTest::addColumn<qreal>("tooffset");
+
+ QTest::newRow("default-shortest") << QQuickPathView::Shortest << 3 << 8.0 << 5.0;
+ QTest::newRow("negative") << QQuickPathView::Negative << 2 << 0.0 << 6.0;
+ QTest::newRow("positive") << QQuickPathView::Positive << 3 << 8.0 << 5.0;
+
+}
+
+static void verify_offsets(QQuickPathView *pathview, int toidx, qreal fromoffset, qreal tooffset)
+{
+ pathview->setCurrentIndex(toidx);
+ bool started = false;
+ qreal first, second;
+ QTest::qWait(100);
+ first = pathview->offset();
+ while (1) {
+ QTest::qWait(10); // highlightMoveDuration: 1000
+ second = pathview->offset();
+ if (!started && second != first) { // animation started
+ started = true;
+ break;
+ }
+ }
+
+ if (tooffset > fromoffset) {
+ QVERIFY(fromoffset <= first);
+ QVERIFY(first <= second);
+ QVERIFY(second <= tooffset);
+ } else {
+ QVERIFY(fromoffset >= first);
+ QVERIFY(first >= second);
+ QVERIFY(second >= tooffset);
+ }
+ QTRY_COMPARE(pathview->offset(), tooffset);
+}
+
+void tst_QQuickPathView::movementDirection()
+{
+ QFETCH(QQuickPathView::MovementDirection, movementdirection);
+ QFETCH(int, toidx);
+ QFETCH(qreal, fromoffset);
+ QFETCH(qreal, tooffset);
+
+ QScopedPointer<QQuickView> window(createView());
+ QQuickViewTestUtil::moveMouseAway(window.data());
+ window->setSource(testFileUrl("movementDirection.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QCOMPARE(window.data(), qGuiApp->focusWindow());
+
+ QQuickPathView *pathview = window->rootObject()->findChild<QQuickPathView*>("view");
+ QVERIFY(pathview != 0);
+ QVERIFY(pathview->offset() == 0.0);
+ QVERIFY(pathview->currentIndex() == 0);
+ pathview->setMovementDirection(movementdirection);
+ QVERIFY(pathview->movementDirection() == movementdirection);
+
+ verify_offsets(pathview, toidx, fromoffset, tooffset);
+}
+
QTEST_MAIN(tst_QQuickPathView)
#include "tst_qquickpathview.moc"
diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
index 562d53bceb..9b152b0676 100644
--- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp
+++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp
@@ -698,7 +698,7 @@ void tst_qquickstates::anchorChanges()
rectPrivate->setState("right");
QCOMPARE(innerRect->x(), qreal(150));
QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchors::InvalidAnchor); //### was reset (how do we distinguish from not set at all)
QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
@@ -891,7 +891,7 @@ void tst_qquickstates::anchorChangesRTL()
rectPrivate->setState("right");
QCOMPARE(innerRect->x(), offsetRTL(rect, innerRect) - qreal(150));
QCOMPARE(aChanges->object(), qobject_cast<QQuickItem*>(innerRect));
- QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchorLine::Invalid); //### was reset (how do we distinguish from not set at all)
+ QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->left().anchorLine, QQuickAnchors::InvalidAnchor); //### was reset (how do we distinguish from not set at all)
QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().item, rectPrivate->right().item);
QCOMPARE(QQuickItemPrivate::get(aChanges->object())->anchors()->right().anchorLine, rectPrivate->right().anchorLine);
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 7ea36bbafa..8b7d8c0711 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -701,7 +701,7 @@ void tst_qquicktext::textFormat()
QQuickText *text = qobject_cast<QQuickText *>(object.data());
QVERIFY(text);
- QSignalSpy spy(text, SIGNAL(textFormatChanged(TextFormat)));
+ QSignalSpy spy(text, &QQuickText::textFormatChanged);
QCOMPARE(text->textFormat(), QQuickText::AutoText);
@@ -915,8 +915,10 @@ void tst_qquicktext::hAlignImplicitWidth()
// Try to check whether alignment works by checking the number of black
// pixels in the thirds of the grabbed image.
- const int windowWidth = 220;
- const int textWidth = qCeil(text->implicitWidth());
+ // QQuickWindow::grabWindow() scales the returned image by the devicePixelRatio of the screen.
+ const qreal devicePixelRatio = view.screen()->devicePixelRatio();
+ const int windowWidth = 220 * devicePixelRatio;
+ const int textWidth = qCeil(text->implicitWidth()) * devicePixelRatio;
QVERIFY2(textWidth < windowWidth, "System font too large.");
const int sectionWidth = textWidth / 3;
const int centeredSection1 = (windowWidth - textWidth) / 2;
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index e26bf6f4e4..24cfadc2d3 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -1390,7 +1390,7 @@ void tst_qquicktextinput::mouseSelectionMode_accessors()
QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
QVERIFY(input);
- QSignalSpy spy(input, SIGNAL(mouseSelectionModeChanged(SelectionMode)));
+ QSignalSpy spy(input, &QQuickTextInput::mouseSelectionModeChanged);
QCOMPARE(input->mouseSelectionMode(), QQuickTextInput::SelectCharacters);
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index a528810cae..fecd1aea58 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -81,6 +81,7 @@ QUICKTESTS = \
qquickvisualdatamodel \
qquickview \
qquickcanvasitem \
+ qquickdesignersupport \
qquickscreen \
touchmouse \
scenegraph
diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp
index 2c8aa04a6a..fa94fd4d46 100644
--- a/tests/benchmarks/qml/creation/tst_creation.cpp
+++ b/tests/benchmarks/qml/creation/tst_creation.cpp
@@ -74,6 +74,9 @@ private slots:
void bindings_parent_qml();
+ void anchors_creation();
+ void anchors_heightChange();
+
private:
QQmlEngine engine;
};
@@ -462,6 +465,38 @@ void tst_creation::bindings_parent_qml()
delete obj;
}
+void tst_creation::anchors_creation()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nItem { Item { anchors.bottom: parent.bottom } }", QUrl());
+
+ QObject *obj = component.create();
+ delete obj;
+
+ QBENCHMARK {
+ QObject *obj = component.create();
+ delete obj;
+ }
+}
+
+void tst_creation::anchors_heightChange()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nItem { Item { anchors.bottom: parent.bottom } }", QUrl());
+
+ QObject *obj = component.create();
+ auto item = qobject_cast<QQuickItem *>(obj);
+ Q_ASSERT(item);
+ int height = 1;
+
+ QBENCHMARK {
+ item->setHeight(height);
+ height += 1;
+ }
+
+ delete obj;
+}
+
QTEST_MAIN(tst_creation)
#include "tst_creation.moc"
diff --git a/tests/manual/highdpi/imageprovider.cpp b/tests/manual/highdpi/imageprovider.cpp
index 1856a1ea9a..33a69cb87e 100644
--- a/tests/manual/highdpi/imageprovider.cpp
+++ b/tests/manual/highdpi/imageprovider.cpp
@@ -79,7 +79,7 @@ public:
class ImageProviderExtensionPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
{
@@ -95,7 +95,4 @@ public:
};
-#define QQmlExtensionInterface_iid "org.qt-project.Qt.QQmlExtensionInterface"
-
-
#include "imageprovider.moc"
diff --git a/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h b/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h
index 739eae0f8a..86e80e6a08 100644
--- a/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h
+++ b/tests/manual/qmlplugindump/tests/dumper/Dummy/dummy_plugin.h
@@ -34,7 +34,7 @@
class DummyPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri);
diff --git a/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h b/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h
index 7c136dea30..fd09584d47 100644
--- a/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h
+++ b/tests/manual/qmlplugindump/tests/dumper/Imports/imports_plugin.h
@@ -34,7 +34,7 @@
class ImportsPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri);
diff --git a/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h b/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h
index 91e9ce4174..4ba68a8125 100644
--- a/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h
+++ b/tests/manual/qmlplugindump/tests/dumper/Versions/versions_plugin.h
@@ -34,7 +34,7 @@
class VersionsPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri);
diff --git a/tests/manual/qmltypememory/TestPlugin/plugin.cpp b/tests/manual/qmltypememory/TestPlugin/plugin.cpp
index ddc5430b43..d6cbf05a55 100644
--- a/tests/manual/qmltypememory/TestPlugin/plugin.cpp
+++ b/tests/manual/qmltypememory/TestPlugin/plugin.cpp
@@ -50,7 +50,7 @@ class TestType : public QObject
class TestPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
diff --git a/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps2.qml b/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps2.qml
new file mode 100644
index 0000000000..c16bc9cdf7
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/text/textedit_multiline_selected_linebreaks_and_linewraps2.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.0
+
+Item {
+ width: 550
+ height: 480
+
+ TextEdit {
+ id: textEdit
+ anchors.centerIn: parent
+ width: 550
+ textFormat: TextEdit.RichText
+ text: "A<br />
+ This is a long message to demenostrate a text selection issue. I need to type some more text here. This is line 3<br />
+ This is a long message to demenostrate a text selection issue. I need to type some more text here. This is line 4"
+ wrapMode: TextEdit.Wrap
+
+ Component.onCompleted: {
+ textEdit.selectAll()
+ }
+ }
+
+}
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index dcb9709bb8..2569d78c63 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -157,24 +157,46 @@ QVariantMap pluginsForModulePath(const QString &modulePath) {
// Search for a given qml import in g_qmlImportPaths.
QString resolveImportPath(const QString &uri, const QString &version)
{
- // Create path from uri (QtQuick.Controls -> QtQuick/Controls)
- QString path = uri;
- path.replace(QLatin1Char('.'), QLatin1Char('/'));
- // search for the most spesifc version first
- QString versionedName = path + QLatin1Char('.') + version;
+ const QLatin1Char dot('.');
+ const QLatin1Char slash('/');
+ const QStringList parts = uri.split(dot, QString::SkipEmptyParts);
+
+ QString ver = version;
while (true) {
- // look in all g_qmlImportPaths
foreach (const QString &qmlImportPath, g_qmlImportPaths) {
- QString candidatePath = QDir::cleanPath(qmlImportPath + QLatin1Char('/') + versionedName);
- if (QDir(candidatePath).exists())
- return candidatePath; // import found
+ // Search for the most specific version first, and search
+ // also for the version in parent modules. For example:
+ // - qml/QtQml/Models.2.0
+ // - qml/QtQml.2.0/Models
+ // - qml/QtQml/Models.2
+ // - qml/QtQml.2/Models
+ // - qml/QtQml/Models
+ if (ver.isEmpty()) {
+ const QString candidatePath = QDir::cleanPath(qmlImportPath + slash + parts.join(slash));
+ if (QDir(candidatePath).exists())
+ return candidatePath; // import found
+ } else {
+ for (int index = parts.count() - 1; index >= 0; --index) {
+ const QString candidatePath = QDir::cleanPath(qmlImportPath + slash
+ + parts.mid(0, index + 1).join(slash)
+ + dot + ver + slash
+ + parts.mid(index + 1).join(slash));
+
+ if (QDir(candidatePath).exists())
+ return candidatePath; // import found
+ }
+ }
}
// remove the last version digit; stop if there are none left
- int lastDot = versionedName.lastIndexOf(QLatin1Char('.'));
- if (lastDot == -1)
+ if (ver.isEmpty())
break;
- versionedName = versionedName.mid(0, lastDot);
+
+ int lastDot = ver.lastIndexOf(dot);
+ if (lastDot == -1)
+ ver.clear();
+ else
+ ver = ver.mid(0, lastDot);
}
return QString(); // not found
diff --git a/tools/qmlplugindump/Info.plist b/tools/qmlplugindump/Info.plist
index f35846d048..e6c4914ca0 100644
--- a/tools/qmlplugindump/Info.plist
+++ b/tools/qmlplugindump/Info.plist
@@ -5,11 +5,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
- <string>@TYPEINFO@</string>
+ <string>????</string>
<key>CFBundleExecutable</key>
- <string>@EXECUTABLE@</string>
+ <string>qmlplugindump</string>
<key>CFBundleIdentifier</key>
- <string>com.nokia.qt.qmlplugindump</string>
+ <string>org.qt-project.qt.qmlplugindump</string>
<key>LSUIElement</key>
<string>1</string>
</dict>
diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp
index 7870e3a9df..d0d70fd0fe 100644
--- a/tools/qmlplugindump/main.cpp
+++ b/tools/qmlplugindump/main.cpp
@@ -771,7 +771,7 @@ static bool readDependenciesData(QString dependenciesFile, const QByteArray &fil
QString version = obj.value(QStringLiteral("version")).toString();
if (name.isEmpty() || urisToSkip.contains(name) || version.isEmpty())
continue;
- if (name.endsWith(QLatin1String("Private"))) {
+ if (name.endsWith(QLatin1String("Private"), Qt::CaseInsensitive)) {
if (verbose)
std::cerr << "skipping private dependecy "
<< qPrintable( name ) << " " << qPrintable(version) << std::endl;