aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--examples/quick/demos/demos.pro3
-rw-r--r--src/3rdparty/masm/masm-defs.pri3
-rw-r--r--src/3rdparty/masm/wtf/StdLibExtras.h2
-rw-r--r--src/particles/qquickparticleemitter_p.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp6
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp22
-rw-r--r--src/qml/compiler/compiler.pri9
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp15
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h10
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp46
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp18
-rw-r--r--src/qml/compiler/qv4compilationunitmapper.cpp89
-rw-r--r--src/qml/compiler/qv4compilationunitmapper_p.h87
-rw-r--r--src/qml/compiler/qv4compilationunitmapper_unix.cpp99
-rw-r--r--src/qml/compiler/qv4compilationunitmapper_win.cpp128
-rw-r--r--src/qml/compiler/qv4compileddata.cpp72
-rw-r--r--src/qml/compiler/qv4compileddata_p.h5
-rw-r--r--src/qml/compiler/qv4isel_p.cpp18
-rw-r--r--src/qml/compiler/qv4jsir.cpp4
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc12
-rw-r--r--src/qml/doc/src/javascript/hostenvironment.qdoc4
-rw-r--r--src/qml/jit/qv4assembler_p.h56
-rw-r--r--src/qml/jit/qv4binop.cpp14
-rw-r--r--src/qml/jit/qv4binop_p.h1
-rw-r--r--src/qml/jit/qv4isel_masm.cpp37
-rw-r--r--src/qml/jit/qv4isel_masm_p.h4
-rw-r--r--src/qml/jit/qv4unop.cpp8
-rw-r--r--src/qml/jsapi/qjsvalue.cpp11
-rw-r--r--src/qml/jsapi/qjsvalue_p.h1
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp22
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp13
-rw-r--r--src/qml/jsruntime/qv4engine_p.h1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp13
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp156
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp6
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h33
-rw-r--r--src/qml/memory/qv4mm.cpp3
-rw-r--r--src/qml/qml/ftw/ftw.pri1
-rw-r--r--src/qml/qml/ftw/qdeferredcleanup_p.h74
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp3
-rw-r--r--src/qml/qml/qqmlbinding.cpp150
-rw-r--r--src/qml/qml/qqmlbinding_p.h8
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp4
-rw-r--r--src/qml/qml/qqmlcomponent.cpp4
-rw-r--r--src/qml/qml/qqmlcontext.cpp2
-rw-r--r--src/qml/qml/qqmldata_p.h37
-rw-r--r--src/qml/qml/qqmlengine.cpp59
-rw-r--r--src/qml/qml/qqmlengine.h1
-rw-r--r--src/qml/qml/qqmlengine_p.h1
-rw-r--r--src/qml/qml/qqmlerror.cpp4
-rw-r--r--src/qml/qml/qqmlimport.cpp27
-rw-r--r--src/qml/qml/qqmllist.cpp6
-rw-r--r--src/qml/qml/qqmlmetatype.cpp8
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp138
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlproperty.cpp166
-rw-r--r--src/qml/qml/qqmlproperty_p.h18
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp226
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h246
-rw-r--r--src/qml/qml/qqmlproxymetaobject.cpp6
-rw-r--r--src/qml/qml/qqmltypeloader.cpp54
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp7
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp29
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp16
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp29
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp37
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h1
-rw-r--r--src/qmltest/qmltest.pro2
-rw-r--r--src/qmltest/quicktest.cpp13
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp4
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h22
-rw-r--r--src/quick/items/qquickevents.cpp502
-rw-r--r--src/quick/items/qquickevents_p_p.h312
-rw-r--r--src/quick/items/qquickgridview.cpp18
-rw-r--r--src/quick/items/qquickimagebase.cpp2
-rw-r--r--src/quick/items/qquickitem.cpp2
-rw-r--r--src/quick/items/qquickitemanimation.cpp4
-rw-r--r--src/quick/items/qquickitemview.cpp33
-rw-r--r--src/quick/items/qquicklistview.cpp24
-rw-r--r--src/quick/items/qquickmousearea.cpp8
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp35
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h2
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp6
-rw-r--r--src/quick/items/qquickpathview.cpp12
-rw-r--r--src/quick/items/qquickspriteengine.cpp114
-rw-r--r--src/quick/items/qquickspriteengine_p.h34
-rw-r--r--src/quick/items/qquickwindow.cpp861
-rw-r--r--src/quick/items/qquickwindow_p.h67
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp10
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp2
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp2
-rw-r--r--src/quick/util/qquickfontloader.cpp4
-rw-r--r--src/quick/util/qquickpath.cpp8
-rw-r--r--src/quick/util/qquickpixmapcache.cpp2
-rw-r--r--src/quick/util/qquickpropertychanges.cpp4
-rw-r--r--src/quick/util/qquicksmoothedanimation.cpp2
-rw-r--r--src/quick/util/qquicktimeline.cpp2
-rw-r--r--src/quickwidgets/qquickwidget.cpp12
-rw-r--r--src/quickwidgets/quickwidgets.pro2
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp1
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp8
-rw-r--r--tests/auto/qml/qmldiskcache/qmldiskcache.pro2
-rw-r--r--tests/auto/qml/qmldiskcache/test.qml4
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp28
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp9
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp6
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp72
-rw-r--r--tests/auto/qml/qqmlqt/data/exit.qml7
-rw-r--r--tests/auto/qml/qqmlqt/data/timeRoundtrip.qml8
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp127
-rw-r--r--tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp4
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp32
-rw-r--r--tests/auto/quick/qquickloader/data/qmldir1
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp10
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp4
-rw-r--r--tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp2
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp1
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp143
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp46
-rw-r--r--tests/auto/quick/touchmouse/data/touchpointdeliveryorder.qml39
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp142
-rw-r--r--tools/fdegen/fdegen.pro8
-rw-r--r--tools/fdegen/main.cpp362
-rw-r--r--tools/qml/main.cpp17
-rw-r--r--tools/qmleasing/splineeditor.cpp15
-rw-r--r--tools/qmlimportscanner/main.cpp6
-rw-r--r--tools/qmlprofiler/qmlprofilerapplication.cpp6
-rw-r--r--tools/qmlprofiler/qmlprofilerdata.cpp6
-rw-r--r--tools/qmlscene/main.cpp1
132 files changed, 3506 insertions, 2145 deletions
diff --git a/.gitignore b/.gitignore
index f33da3c8b3..e0af30c299 100644
--- a/.gitignore
+++ b/.gitignore
@@ -284,3 +284,7 @@ src/qml/udis86_itab.h
# Generated HLSL bytecode headers
*.hlslh
+
+# Compiled QML/JS code
+*.qmlc
+*.jsc
diff --git a/examples/quick/demos/demos.pro b/examples/quick/demos/demos.pro
index e6937683ab..0644b81a22 100644
--- a/examples/quick/demos/demos.pro
+++ b/examples/quick/demos/demos.pro
@@ -5,8 +5,7 @@ SUBDIRS = samegame \
tweetsearch \
maroon \
photosurface \
- photoviewer \
stocqt
-qtHaveModule(xmlpatterns): SUBDIRS += rssnews
+qtHaveModule(xmlpatterns): SUBDIRS += rssnews photoviewer
diff --git a/src/3rdparty/masm/masm-defs.pri b/src/3rdparty/masm/masm-defs.pri
index b5480babc6..fa0d3d3c55 100644
--- a/src/3rdparty/masm/masm-defs.pri
+++ b/src/3rdparty/masm/masm-defs.pri
@@ -24,7 +24,8 @@ INCLUDEPATH += $$PWD
disassembler {
if(isEqual(QT_ARCH, "i386")|isEqual(QT_ARCH, "x86_64")): DEFINES += WTF_USE_UDIS86=1
- if(isEqual(QT_ARCH, "arm")): DEFINES += WTF_USE_ARMV7_DISASSEMBLER=1 WTF_USE_ARM64_DISASSEMBLER=1
+ if(isEqual(QT_ARCH, "arm")): DEFINES += WTF_USE_ARMV7_DISASSEMBLER=1
+ if(isEqual(QT_ARCH, "arm64")): DEFINES += WTF_USE_ARM64_DISASSEMBLER=1
if(isEqual(QT_ARCH, "mips")): DEFINES += WTF_USE_MIPS32_DISASSEMBLER=1
} else {
DEFINES += WTF_USE_UDIS86=0
diff --git a/src/3rdparty/masm/wtf/StdLibExtras.h b/src/3rdparty/masm/wtf/StdLibExtras.h
index 605f98ec82..f0d792ed52 100644
--- a/src/3rdparty/masm/wtf/StdLibExtras.h
+++ b/src/3rdparty/masm/wtf/StdLibExtras.h
@@ -166,7 +166,7 @@ template<typename T> char (&ArrayLengthHelperFunction(T (&)[0]))[0];
// Efficient implementation that takes advantage of powers of two.
inline size_t roundUpToMultipleOf(size_t divisor, size_t x)
{
- ASSERT(divisor && !(divisor & (divisor - 1)));
+ Q_ASSERT(divisor && !(divisor & (divisor - 1)));
size_t remainderMask = divisor - 1;
return (x + remainderMask) & ~remainderMask;
}
diff --git a/src/particles/qquickparticleemitter_p.h b/src/particles/qquickparticleemitter_p.h
index dd55fdc7a6..b3f96ae3e6 100644
--- a/src/particles/qquickparticleemitter_p.h
+++ b/src/particles/qquickparticleemitter_p.h
@@ -62,7 +62,7 @@
#include <QPointF>
QT_BEGIN_NAMESPACE
-class QQuickParticleEmitter : public QQuickItem
+class Q_QUICKPARTICLES_PRIVATE_EXPORT QQuickParticleEmitter : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QQuickParticleSystem* system READ system WRITE setSystem NOTIFY systemChanged)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index 12ed987ca0..f72b8a51f9 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -753,7 +753,7 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
if (!prop || !prop->isVMEFunction())
return false;
- QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
+ QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex());
QList<QByteArray> paramNames = metaMethod.parameterNames();
QString paramStr;
@@ -772,12 +772,12 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
QV4::Scope scope(v4);
int lineNumber = 0;
- QV4::ScopedFunctionObject oldMethod(scope, vmeMetaObject->vmeMethod(prop->coreIndex));
+ 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);
+ vmeMetaObject->setVmeMethod(prop->coreIndex(), v);
return true;
}
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
index e32ecdc138..87215d5b54 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12engine.cpp
@@ -75,7 +75,7 @@ DECLARE_DEBUG_VAR(buffer)
DECLARE_DEBUG_VAR(texture)
// Except for system info on startup.
-Q_LOGGING_CATEGORY(QSG_LOG_INFO, "qt.scenegraph.general")
+Q_LOGGING_CATEGORY(QSG_LOG_INFO_GENERAL, "qt.scenegraph.general")
// Any changes to the defaults below must be reflected in adaptations.qdoc as
@@ -197,7 +197,7 @@ static void getHardwareAdapter(IDXGIFactory1 *factory, IDXGIAdapter1 **outAdapte
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
const QString name = QString::fromUtf16((char16_t *) desc.Description);
- qCDebug(QSG_LOG_INFO, "Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags);
+ qCDebug(QSG_LOG_INFO_GENERAL, "Adapter %d: '%s' (flags 0x%x)", adapterIndex, qPrintable(name), desc.Flags);
}
if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX")) {
@@ -207,7 +207,7 @@ static void getHardwareAdapter(IDXGIFactory1 *factory, IDXGIAdapter1 **outAdapte
const QString name = QString::fromUtf16((char16_t *) desc.Description);
HRESULT hr = D3D12CreateDevice(adapter.Get(), fl, _uuidof(ID3D12Device), nullptr);
if (SUCCEEDED(hr)) {
- qCDebug(QSG_LOG_INFO, "Using requested adapter '%s'", qPrintable(name));
+ qCDebug(QSG_LOG_INFO_GENERAL, "Using requested adapter '%s'", qPrintable(name));
*outAdapter = adapter.Detach();
return;
} else {
@@ -223,7 +223,7 @@ static void getHardwareAdapter(IDXGIFactory1 *factory, IDXGIAdapter1 **outAdapte
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), fl, _uuidof(ID3D12Device), nullptr))) {
const QString name = QString::fromUtf16((char16_t *) desc.Description);
- qCDebug(QSG_LOG_INFO, "Using adapter '%s'", qPrintable(name));
+ qCDebug(QSG_LOG_INFO_GENERAL, "Using adapter '%s'", qPrintable(name));
break;
}
}
@@ -287,7 +287,7 @@ void QSGD3D12DeviceManager::ensureCreated()
}
if (warp) {
- qCDebug(QSG_LOG_INFO, "Using WARP");
+ qCDebug(QSG_LOG_INFO_GENERAL, "Using WARP");
m_factory->EnumWarpAdapter(IID_PPV_ARGS(&adapter));
HRESULT hr = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
if (FAILED(hr)) {
@@ -300,12 +300,12 @@ void QSGD3D12DeviceManager::ensureCreated()
if (SUCCEEDED(adapter.As(&adapter3))) {
DXGI_QUERY_VIDEO_MEMORY_INFO vidMemInfo;
if (SUCCEEDED(adapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &vidMemInfo))) {
- qCDebug(QSG_LOG_INFO, "Video memory info: LOCAL: Budget %llu KB CurrentUsage %llu KB AvailableForReservation %llu KB CurrentReservation %llu KB",
+ qCDebug(QSG_LOG_INFO_GENERAL, "Video memory info: LOCAL: Budget %llu KB CurrentUsage %llu KB AvailableForReservation %llu KB CurrentReservation %llu KB",
vidMemInfo.Budget / 1024, vidMemInfo.CurrentUsage / 1024,
vidMemInfo.AvailableForReservation / 1024, vidMemInfo.CurrentReservation / 1024);
}
if (SUCCEEDED(adapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &vidMemInfo))) {
- qCDebug(QSG_LOG_INFO, "Video memory info: NON-LOCAL: Budget %llu KB CurrentUsage %llu KB AvailableForReservation %llu KB CurrentReservation %llu KB",
+ qCDebug(QSG_LOG_INFO_GENERAL, "Video memory info: NON-LOCAL: Budget %llu KB CurrentUsage %llu KB AvailableForReservation %llu KB CurrentReservation %llu KB",
vidMemInfo.Budget / 1024, vidMemInfo.CurrentUsage / 1024,
vidMemInfo.AvailableForReservation / 1024, vidMemInfo.CurrentReservation / 1024);
}
@@ -726,16 +726,16 @@ void QSGD3D12EnginePrivate::initialize(WId w, const QSize &size, float dpr, int
waitableSwapChainMaxLatency = qBound(0, qEnvironmentVariableIntValue(latReqEnvVar), 16);
if (qEnvironmentVariableIsSet("QSG_INFO"))
- const_cast<QLoggingCategory &>(QSG_LOG_INFO()).setEnabled(QtDebugMsg, true);
+ const_cast<QLoggingCategory &>(QSG_LOG_INFO_GENERAL()).setEnabled(QtDebugMsg, true);
- qCDebug(QSG_LOG_INFO, "d3d12 engine init. swap chain buffer count %d, max frames prepared without blocking %d",
+ qCDebug(QSG_LOG_INFO_GENERAL, "d3d12 engine init. swap chain buffer count %d, max frames prepared without blocking %d",
swapChainBufferCount, frameInFlightCount);
if (waitableSwapChainMaxLatency)
- qCDebug(QSG_LOG_INFO, "Swap chain frame latency waitable object enabled. Frame latency is %d", waitableSwapChainMaxLatency);
+ qCDebug(QSG_LOG_INFO_GENERAL, "Swap chain frame latency waitable object enabled. Frame latency is %d", waitableSwapChainMaxLatency);
const bool debugLayer = qEnvironmentVariableIntValue("QT_D3D_DEBUG") != 0;
if (debugLayer) {
- qCDebug(QSG_LOG_INFO, "Enabling debug layer");
+ qCDebug(QSG_LOG_INFO_GENERAL, "Enabling debug layer");
ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
debugController->EnableDebugLayer();
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index ad73c26b15..e49f5c40a5 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -28,7 +28,8 @@ HEADERS += \
$$PWD/qv4isel_moth_p.h \
$$PWD/qv4instr_moth_p.h \
$$PWD/qqmlpropertycachecreator_p.h \
- $$PWD/qqmlpropertyvalidator_p.h
+ $$PWD/qqmlpropertyvalidator_p.h \
+ $$PWD/qv4compilationunitmapper_p.h
SOURCES += \
@@ -36,6 +37,10 @@ SOURCES += \
$$PWD/qv4instr_moth.cpp \
$$PWD/qv4isel_moth.cpp \
$$PWD/qqmlpropertycachecreator.cpp \
- $$PWD/qqmlpropertyvalidator.cpp
+ $$PWD/qqmlpropertyvalidator.cpp \
+ $$PWD/qv4compilationunitmapper.cpp
+
+unix: SOURCES += $$PWD/qv4compilationunitmapper_unix.cpp
+else: SOURCES += $$PWD/qv4compilationunitmapper_win.cpp
}
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index ed72054e1e..ef8ffa8620 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1725,7 +1725,11 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine,
member->kind = QV4::IR::Member::MemberOfSingletonObject;
return newResolver->resolveMember(qmlEngine, newResolver, member);
}
- } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType(qmlEngine)) {
+ }
+#if 0
+ else if (const QMetaObject *attachedMeta = type->attachedPropertiesType(qmlEngine)) {
+ // Right now the attached property IDs are not stable and cannot be embedded in the
+ // code that is cached on disk.
QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta);
auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>();
newResolver->owner = resolver->owner;
@@ -1733,6 +1737,7 @@ static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine,
member->setAttachedPropertiesId(type->attachedPropertiesId(qmlEngine));
return newResolver->resolveMember(qmlEngine, newResolver, member);
}
+#endif
return result;
}
@@ -1840,20 +1845,20 @@ static QV4::IR::DiscoveredType resolveMetaObjectProperty(
if (property->isEnum())
return QV4::IR::VarType;
- switch (property->propType) {
+ switch (property->propType()) {
case QMetaType::Bool: result = QV4::IR::BoolType; break;
case QMetaType::Int: result = QV4::IR::SInt32Type; break;
case QMetaType::Double: result = QV4::IR::DoubleType; break;
case QMetaType::QString: result = QV4::IR::StringType; break;
default:
if (property->isQObject()) {
- if (QQmlPropertyCache *cache = qmlEngine->propertyCacheForType(property->propType)) {
+ if (QQmlPropertyCache *cache = qmlEngine->propertyCacheForType(property->propType())) {
auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>();
newResolver->owner = resolver->owner;
initMetaObjectResolver(newResolver, cache);
return QV4::IR::DiscoveredType(newResolver);
}
- } else if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType)) {
+ } else if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType())) {
if (QQmlPropertyCache *cache = qmlEngine->cache(valueTypeMetaObject)) {
auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>();
newResolver->owner = resolver->owner;
@@ -2048,7 +2053,7 @@ QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevis
d = property(propName, notInRevision);
if (d)
- return cache->signal(d->notifyIndex);
+ return cache->signal(d->notifyIndex());
}
return 0;
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index a1b0a14890..10bcd1dbc1 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -124,7 +124,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObje
// group properties and value type group properties. For the former the base type is derived from
// the property that references us, for the latter we only need a meta-object on the referencing object
// because interceptors can't go to the shared value type instances.
- if (context.instantiatingProperty && QQmlValueTypeFactory::isValueType(context.instantiatingProperty->propType)) {
+ if (context.instantiatingProperty && QQmlValueTypeFactory::isValueType(context.instantiatingProperty->propType())) {
if (!propertyCaches->needsVMEMetaObject(context.referencingObjectIndex)) {
const CompiledObject *obj = objectContainer->objectAt(context.referencingObjectIndex);
auto *typeRef = objectContainer->resolvedTypes.value(obj->inheritedTypeNameIndex);
@@ -180,8 +180,8 @@ inline QQmlPropertyCache *QQmlPropertyCacheCreator<ObjectContainer>::propertyCac
{
if (context.instantiatingProperty) {
if (context.instantiatingProperty->isQObject()) {
- return enginePrivate->rawPropertyCacheForType(context.instantiatingProperty->propType);
- } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(context.instantiatingProperty->propType)) {
+ return enginePrivate->rawPropertyCacheForType(context.instantiatingProperty->propType());
+ } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(context.instantiatingProperty->propType())) {
return enginePrivate->cache(vtmo);
}
} else if (obj->inheritedTypeNameIndex != 0) {
@@ -664,7 +664,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias
QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
Q_ASSERT(targetProperty);
- *type = targetProperty->propType;
+ *type = targetProperty->propType();
writable = targetProperty->isWritable();
resettable = targetProperty->isResettable();
@@ -680,7 +680,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias
*type = QVariant::Int;
} else {
// Copy type flags
- propertyFlags->copyPropertyTypeFlags(targetProperty->getFlags());
+ propertyFlags->copyPropertyTypeFlags(targetProperty->flags());
if (targetProperty->isVarProperty())
propertyFlags->type = QQmlPropertyData::Flags::QVariantType;
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index c644330e97..45379d5155 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -206,7 +206,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
}
if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
- const QVector<QQmlCompileError> subObjectValidatorErrors = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
+ const QVector<QQmlCompileError> subObjectValidatorErrors = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType()));
if (!subObjectValidatorErrors.isEmpty())
return subObjectValidatorErrors;
}
@@ -240,7 +240,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
if (!pd->isQList() && (binding->flags & QV4::CompiledData::Binding::IsListItem)) {
QString error;
- if (pd->propType == qMetaTypeId<QQmlScriptString>())
+ if (pd->propType() == qMetaTypeId<QQmlScriptString>())
error = tr( "Cannot assign multiple values to a script property");
else
error = tr( "Cannot assign multiple values to a singular property");
@@ -255,7 +255,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
if (loc < (*assignedGroupProperty)->valueLocation)
loc = (*assignedGroupProperty)->valueLocation;
- if (pd && QQmlValueTypeFactory::isValueType(pd->propType))
+ if (pd && QQmlValueTypeFactory::isValueType(pd->propType()))
return recordError(loc, tr("Property has already been assigned a value"));
return recordError(loc, tr("Cannot assign a value directly to a grouped property"));
}
@@ -269,8 +269,8 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
if (bindingError.isSet())
return recordError(bindingError);
} else if (binding->isGroupProperty()) {
- if (QQmlValueTypeFactory::isValueType(pd->propType)) {
- if (QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)) {
+ if (QQmlValueTypeFactory::isValueType(pd->propType())) {
+ if (QQmlValueTypeFactory::metaObjectForMetaType(pd->propType())) {
if (!pd->isWritable()) {
return recordError(binding->location, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name));
}
@@ -278,7 +278,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
return recordError(binding->location, tr("Invalid grouped property access"));
}
} else {
- if (!enginePrivate->propertyCacheForType(pd->propType)) {
+ if (!enginePrivate->propertyCacheForType(pd->propType())) {
return recordError(binding->location, tr("Invalid grouped property access"));
}
}
@@ -334,7 +334,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
return noError;
QString value = binding->valueAsString(qmlUnit);
- QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex);
+ QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex());
bool ok;
if (p.isFlagType()) {
p.enumerator().keysToValue(value.toUtf8().constData(), &ok);
@@ -347,7 +347,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
return noError;
}
- switch (property->propType) {
+ switch (property->propType()) {
case QMetaType::QVariant:
break;
case QVariant::String: {
@@ -541,12 +541,12 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
default: {
// generate single literal value assignment to a list property if required
- if (property->propType == qMetaTypeId<QList<qreal> >()) {
+ if (property->propType() == qMetaTypeId<QList<qreal> >()) {
if (binding->type != QV4::CompiledData::Binding::Type_Number) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: number or array of numbers expected"));
}
break;
- } else if (property->propType == qMetaTypeId<QList<int> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<int> >()) {
bool ok = (binding->type == QV4::CompiledData::Binding::Type_Number);
if (ok) {
double n = binding->valueAsNumber();
@@ -556,31 +556,31 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
if (!ok)
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: int or array of ints expected"));
break;
- } else if (property->propType == qMetaTypeId<QList<bool> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<bool> >()) {
if (binding->type != QV4::CompiledData::Binding::Type_Boolean) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: bool or array of bools expected"));
}
break;
- } else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<QUrl> >()) {
if (binding->type != QV4::CompiledData::Binding::Type_String) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: url or array of urls expected"));
}
break;
- } else if (property->propType == qMetaTypeId<QList<QString> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<QString> >()) {
if (!binding->evaluatesToString()) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: string or array of strings expected"));
}
break;
- } else if (property->propType == qMetaTypeId<QJSValue>()) {
+ } else if (property->propType() == qMetaTypeId<QJSValue>()) {
break;
- } else if (property->propType == qMetaTypeId<QQmlScriptString>()) {
+ } else if (property->propType() == qMetaTypeId<QQmlScriptString>()) {
break;
}
// otherwise, try a custom type assignment
- QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
+ QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType());
if (!converter) {
- return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType))));
+ return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: unsupported type \"%1\"").arg(QString::fromLatin1(QMetaType::typeName(property->propType()))));
}
}
break;
@@ -652,15 +652,15 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
return noError;
}
- if (QQmlMetaType::isInterface(property->propType)) {
+ if (QQmlMetaType::isInterface(property->propType())) {
// Can only check at instantiation time if the created sub-object successfully casts to the
// target interface.
return noError;
- } else if (property->propType == QMetaType::QVariant) {
+ } else if (property->propType() == QMetaType::QVariant) {
// We can convert everything to QVariant :)
return noError;
} else if (property->isQList()) {
- const int listType = enginePrivate->listType(property->propType);
+ const int listType = enginePrivate->listType(property->propType());
if (!QQmlMetaType::isInterface(listType)) {
QQmlPropertyCache *source = propertyCaches.at(binding->value.objectIndex);
if (!canCoerce(listType, source)) {
@@ -672,15 +672,15 @@ QQmlCompileError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *
return noError;
} else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
return noError;
- } else if (QQmlValueTypeFactory::isValueType(property->propType)) {
+ } else if (QQmlValueTypeFactory::isValueType(property->propType())) {
return QQmlCompileError(binding->location, tr("Unexpected object assignment"));
- } else if (property->propType == qMetaTypeId<QQmlScriptString>()) {
+ } else if (property->propType() == qMetaTypeId<QQmlScriptString>()) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: script expected"));
} else {
// We want to raw metaObject here as the raw metaobject is the
// actual property type before we applied any extensions that might
// effect the properties on the type, but don't effect assignability
- QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType);
+ QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(property->propType());
// Will be true if the assgned type inherits propertyMetaObject
bool isAssignable = false;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index e1166286c2..4b33363d09 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -390,7 +390,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
bool notInRevision = false;
QQmlPropertyData *signal = resolver.signal(propertyName, &notInRevision);
if (signal) {
- int sigIndex = propertyCache->methodIndexToSignalIndex(signal->coreIndex);
+ int sigIndex = propertyCache->methodIndexToSignalIndex(signal->coreIndex());
sigIndex = propertyCache->originalClone(sigIndex);
bool unnamedParameter = false;
@@ -547,7 +547,7 @@ bool QQmlEnumTypeResolver::resolveEnumBindings()
if (!pd)
continue;
- if (!pd->isEnum() && pd->propType != QMetaType::Int)
+ if (!pd->isEnum() && pd->propType() != QMetaType::Int)
continue;
if (!tryQualifiedEnumAssignment(obj, propertyCache, pd, binding))
@@ -577,7 +577,7 @@ bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QS
bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache, const QQmlPropertyData *prop, QmlIR::Binding *binding)
{
- bool isIntProp = (prop->propType == QMetaType::Int) && !prop->isEnum();
+ bool isIntProp = (prop->propType() == QMetaType::Int) && !prop->isEnum();
if (!prop->isEnum() && !isIntProp)
return true;
@@ -621,7 +621,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
auto *tr = resolvedTypes->value(obj->inheritedTypeNameIndex);
if (type && tr && tr->type == type) {
- QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex);
+ QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
// When these two match, we can short cut the search
if (mprop.isFlagType()) {
@@ -758,7 +758,7 @@ void QQmlScriptStringScanner::scan()
continue;
bool notInRevision = false;
QQmlPropertyData *pd = binding->propertyNameIndex != quint32(0) ? resolver.property(stringAt(binding->propertyNameIndex), &notInRevision) : defaultProperty;
- if (!pd || pd->propType != scriptStringMetaType)
+ if (!pd || pd->propType() != scriptStringMetaType)
continue;
QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex);
@@ -815,7 +815,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
if (!pd || !pd->isQObject())
continue;
- QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType);
+ QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType());
const QMetaObject *mo = pc->firstCppMetaObject();
while (mo) {
if (mo == &QQmlComponent::staticMetaObject)
@@ -1116,15 +1116,15 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
}
}
- if (!targetProperty || targetProperty->coreIndex > 0x0000FFFF) {
+ if (!targetProperty || targetProperty->coreIndex() > 0x0000FFFF) {
*error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(property.toString()));
break;
}
- propIdx = QQmlPropertyIndex(targetProperty->coreIndex);
+ propIdx = QQmlPropertyIndex(targetProperty->coreIndex());
if (!subProperty.isEmpty()) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(targetProperty->propType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(targetProperty->propType());
if (!valueTypeMetaObject) {
*error = QQmlCompileError(alias->referenceLocation, tr("Invalid alias target location: %1").arg(subProperty.toString()));
break;
diff --git a/src/qml/compiler/qv4compilationunitmapper.cpp b/src/qml/compiler/qv4compilationunitmapper.cpp
new file mode 100644
index 0000000000..b53b7cf784
--- /dev/null
+++ b/src/qml/compiler/qv4compilationunitmapper.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4compilationunitmapper_p.h"
+
+#include "qv4compileddata_p.h"
+#include <QFileInfo>
+#include <QDateTime>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QV4;
+
+CompilationUnitMapper::CompilationUnitMapper()
+ : dataPtr(nullptr)
+{
+
+}
+
+CompilationUnitMapper::~CompilationUnitMapper()
+{
+ close();
+}
+
+bool CompilationUnitMapper::verifyHeader(const CompiledData::Unit *header, const QString &sourcePath, QString *errorString)
+{
+ if (strncmp(header->magic, CompiledData::magic_str, sizeof(header->magic))) {
+ *errorString = QStringLiteral("Magic bytes in the header do not match");
+ return false;
+ }
+
+ if (header->version != quint32(QV4_DATA_STRUCTURE_VERSION)) {
+ *errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2").arg(header->version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16);
+ return false;
+ }
+
+ if (header->qtVersion != quint32(QT_VERSION)) {
+ *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2").arg(header->qtVersion, 0, 16).arg(QT_VERSION, 0, 16);
+ return false;
+ }
+
+ {
+ QFileInfo sourceCode(sourcePath);
+ if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != header->sourceTimeStamp) {
+ *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compilationunitmapper_p.h b/src/qml/compiler/qv4compilationunitmapper_p.h
new file mode 100644
index 0000000000..5b6939f1cf
--- /dev/null
+++ b/src/qml/compiler/qv4compilationunitmapper_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4COMPILATIONUNITMAPPER_H
+#define QV4COMPILATIONUNITMAPPER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4global_p.h>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace CompiledData {
+struct Unit;
+}
+
+class CompilationUnitMapper
+{
+public:
+ CompilationUnitMapper();
+ ~CompilationUnitMapper();
+
+ CompiledData::Unit *open(const QString &cacheFilePath, const QString &sourcePath, QString *errorString);
+ void close();
+
+private:
+ static bool verifyHeader(const QV4::CompiledData::Unit *header, const QString &sourcePath, QString *errorString);
+
+#if defined(Q_OS_UNIX)
+ size_t length;
+#endif
+ void *dataPtr;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4COMPILATIONUNITMAPPER_H
diff --git a/src/qml/compiler/qv4compilationunitmapper_unix.cpp b/src/qml/compiler/qv4compilationunitmapper_unix.cpp
new file mode 100644
index 0000000000..1aa3e05f5f
--- /dev/null
+++ b/src/qml/compiler/qv4compilationunitmapper_unix.cpp
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4compilationunitmapper_p.h"
+
+#include <sys/mman.h>
+#include <functional>
+#include <private/qcore_unix_p.h>
+#include <private/qdeferredcleanup_p.h>
+
+#include "qv4compileddata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QV4;
+
+CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QString &sourcePath, QString *errorString)
+{
+ close();
+
+ int fd = qt_safe_open(QFile::encodeName(cacheFileName).constData(), O_RDONLY);
+ if (fd == -1) {
+ *errorString = qt_error_string(errno);
+ return nullptr;
+ }
+
+ QDeferredCleanup cleanup([fd]{
+ qt_safe_close(fd) ;
+ });
+
+ CompiledData::Unit header;
+ qint64 bytesRead = qt_safe_read(fd, reinterpret_cast<char *>(&header), sizeof(header));
+
+ if (bytesRead != sizeof(header)) {
+ *errorString = QStringLiteral("File too small for the header fields");
+ return nullptr;
+ }
+
+ if (!verifyHeader(&header, sourcePath, errorString))
+ return nullptr;
+
+ // Data structure and qt version matched, so now we can access the rest of the file safely.
+
+ length = static_cast<size_t>(lseek(fd, 0, SEEK_END));
+
+ void *ptr = mmap(nullptr, length, PROT_READ, MAP_SHARED, fd, /*offset*/0);
+ if (ptr == MAP_FAILED) {
+ *errorString = qt_error_string(errno);
+ return nullptr;
+ }
+ dataPtr = ptr;
+
+ return reinterpret_cast<CompiledData::Unit*>(dataPtr);
+}
+
+void CompilationUnitMapper::close()
+{
+ if (dataPtr != nullptr)
+ munmap(dataPtr, length);
+ dataPtr = nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compilationunitmapper_win.cpp b/src/qml/compiler/qv4compilationunitmapper_win.cpp
new file mode 100644
index 0000000000..7e62cbfe8b
--- /dev/null
+++ b/src/qml/compiler/qv4compilationunitmapper_win.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4compilationunitmapper_p.h"
+
+#include "qv4compileddata_p.h"
+#include <private/qdeferredcleanup_p.h>
+#include <QFileInfo>
+#include <QDateTime>
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QV4;
+
+CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QString &sourcePath, QString *errorString)
+{
+ close();
+
+ // ### TODO: fix up file encoding/normalization/unc handling once QFileSystemEntry
+ // is exported from QtCore.
+ HANDLE handle =
+#if defined(Q_OS_WINRT)
+ CreateFile2(reinterpret_cast<const wchar_t*>(cacheFileName.constData()),
+ GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ,
+ OPEN_EXISTING, nullptr);
+#else
+ CreateFile(reinterpret_cast<const wchar_t*>(cacheFileName.constData()),
+ GENERIC_READ | GENERIC_EXECUTE, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ nullptr);
+#endif
+ if (handle == INVALID_HANDLE_VALUE) {
+ *errorString = qt_error_string(GetLastError());
+ return nullptr;
+ }
+
+ QDeferredCleanup fileHandleCleanup([handle]{
+ CloseHandle(handle);
+ });
+
+#if defined(Q_OS_WINRT)
+ *errorString = QStringLiteral("Compilation unit mapping not supported on WinRT yet");
+ return nullptr;
+#else
+ CompiledData::Unit header;
+ DWORD bytesRead;
+ if (!ReadFile(handle, reinterpret_cast<char *>(&header), sizeof(header), &bytesRead, nullptr)) {
+ *errorString = qt_error_string(GetLastError());
+ return false;
+ }
+
+ if (bytesRead != sizeof(header)) {
+ *errorString = QStringLiteral("File too small for the header fields");
+ return nullptr;
+ }
+
+ if (!verifyHeader(&header, sourcePath, errorString))
+ return nullptr;
+
+ // Data structure and qt version matched, so now we can access the rest of the file safely.
+
+ HANDLE fileMappingHandle = CreateFileMapping(handle, 0, PAGE_EXECUTE_READ, 0, 0, 0);
+ if (!fileMappingHandle) {
+ *errorString = qt_error_string(GetLastError());
+ return false;
+ }
+
+ QDeferredCleanup mappingCleanup([fileMappingHandle]{
+ CloseHandle(fileMappingHandle);
+ });
+
+ dataPtr = MapViewOfFile(fileMappingHandle, FILE_MAP_READ | FILE_MAP_EXECUTE, 0, 0, 0);
+ if (!dataPtr) {
+ *errorString = qt_error_string(GetLastError());
+ return nullptr;
+ }
+
+ return reinterpret_cast<CompiledData::Unit*>(dataPtr);
+#endif
+}
+
+void CompilationUnitMapper::close()
+{
+#if !defined(Q_OS_WINRT)
+ if (dataPtr != nullptr)
+ UnmapViewOfFile(dataPtr);
+#endif
+ dataPtr = nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 98eb7188cc..35f61b4f69 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -49,12 +49,15 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmltypeloader_p.h>
#include <private/qqmlengine_p.h>
+#include "qv4compilationunitmapper_p.h"
#include <QQmlPropertyMap>
#include <QDateTime>
#include <QSaveFile>
#include <QFile>
#include <QFileInfo>
#include <QScopedValueRollback>
+#include <QStandardPaths>
+#include <QDir>
#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
@@ -320,6 +323,19 @@ bool CompilationUnit::verifyChecksum(QQmlEngine *engine,
sizeof(data->dependencyMD5Checksum)) == 0;
}
+static QString cacheFilePath(const QUrl &url)
+{
+ const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
+ const QString localCachePath = localSourcePath + QLatin1Char('c');
+ if (QFileInfo(QFileInfo(localSourcePath).dir().absolutePath()).isWritable())
+ return localCachePath;
+ QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
+ fileNameHash.addData(localSourcePath.toUtf8());
+ QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
+ QDir::root().mkpath(directory);
+ return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + QFileInfo(localCachePath).completeSuffix();
+}
+
bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
{
errorString->clear();
@@ -329,13 +345,13 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
return false;
}
- if (!unitUrl.isLocalFile()) {
+ if (!QQmlFile::isLocalFile(unitUrl)) {
*errorString = QStringLiteral("File has to be a local file.");
return false;
}
// Foo.qml -> Foo.qmlc
- QSaveFile cacheFile(unitUrl.toLocalFile() + QLatin1Char('c'));
+ QSaveFile cacheFile(cacheFilePath(unitUrl));
if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
*errorString = cacheFile.errorString();
return false;
@@ -370,62 +386,20 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString)
{
- if (!url.isLocalFile()) {
+ if (!QQmlFile::isLocalFile(url)) {
*errorString = QStringLiteral("File has to be a local file.");
return false;
}
const QString sourcePath = url.toLocalFile();
- QScopedPointer<QFile> cacheFile(new QFile(sourcePath + QLatin1Char('c')));
+ QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
- if (!cacheFile->open(QIODevice::ReadOnly)) {
- *errorString = cacheFile->errorString();
+ CompiledData::Unit *mappedUnit = cacheFile->open(cacheFilePath(url), sourcePath, errorString);
+ if (!mappedUnit)
return false;
- }
-
- {
- CompiledData::Unit header;
- qint64 bytesRead = cacheFile->read(reinterpret_cast<char *>(&header), sizeof(header));
-
- if (bytesRead != sizeof(header)) {
- *errorString = QStringLiteral("File too small for the header fields");
- return false;
- }
-
- if (strncmp(header.magic, CompiledData::magic_str, sizeof(header.magic))) {
- *errorString = QStringLiteral("Magic bytes in the header do not match");
- return false;
- }
-
- if (header.version != quint32(QV4_DATA_STRUCTURE_VERSION)) {
- *errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2").arg(header.version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16);
- return false;
- }
-
- if (header.qtVersion != quint32(QT_VERSION)) {
- *errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2").arg(header.qtVersion, 0, 16).arg(QT_VERSION, 0, 16);
- return false;
- }
-
- {
- QFileInfo sourceCode(sourcePath);
- if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != header.sourceTimeStamp) {
- *errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
- return false;
- }
- }
-
- }
- // Data structure and qt version matched, so now we can access the rest of the file safely.
-
- uchar *cacheData = cacheFile->map(/*offset*/0, cacheFile->size());
- if (!cacheData) {
- *errorString = cacheFile->errorString();
- return false;
- }
const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
- QScopedValueRollback<const Unit *> dataPtrChange(data, reinterpret_cast<const Unit *>(cacheData));
+ QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit);
{
const QString foundArchitecture = stringAt(data->architectureIndex);
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 639c79f79b..a6ca1594a4 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -71,7 +71,7 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
-#define QV4_DATA_STRUCTURE_VERSION 0x01
+#define QV4_DATA_STRUCTURE_VERSION 0x02
class QIODevice;
class QQmlPropertyCache;
@@ -92,6 +92,7 @@ struct Function;
struct Function;
class EvalISelFactory;
+class CompilationUnitMapper;
namespace CompiledData {
@@ -874,7 +875,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
int listMetaTypeId;
bool isRegisteredWithEngine;
- QScopedPointer<QIODevice> backingFile;
+ QScopedPointer<CompilationUnitMapper> backingFile;
// --- interface for QQmlPropertyCacheCreator
typedef Object CompiledObject;
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index d97eec5e1d..72e6c276a9 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -149,18 +149,18 @@ void IRDecoder::visitMove(IR::Move *s)
if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) {
if (m->kind == IR::Member::MemberOfQmlContextObject) {
- _function->contextObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
+ _function->contextObjectPropertyDependencies.insert(m->property->coreIndex(), m->property->notifyIndex());
captureRequired = false;
} else if (m->kind == IR::Member::MemberOfQmlScopeObject) {
- _function->scopeObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
+ _function->scopeObjectPropertyDependencies.insert(m->property->coreIndex(), m->property->notifyIndex());
captureRequired = false;
}
}
if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
- getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex, s->target);
+ getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex(), s->target);
return;
}
- getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target);
+ getQObjectProperty(m->base, m->property->coreIndex(), captureRequired, isSingletonProperty, attachedPropertiesId, s->target);
#endif // V4_BOOTSTRAP
return;
} else if (m->kind == IR::Member::MemberOfIdObjectsArray) {
@@ -187,7 +187,7 @@ void IRDecoder::visitMove(IR::Move *s)
#ifndef V4_BOOTSTRAP
Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
- callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, s->target);
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex(), c->args, s->target);
return;
}
#endif
@@ -216,10 +216,10 @@ void IRDecoder::visitMove(IR::Move *s)
Q_UNIMPLEMENTED();
#else
if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) {
- setQmlContextProperty(s->source, m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex);
+ setQmlContextProperty(s->source, m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex());
return;
}
- setQObjectProperty(s->source, m->base, m->property->coreIndex);
+ setQObjectProperty(s->source, m->base, m->property->coreIndex());
#endif
return;
} else {
@@ -263,7 +263,7 @@ void IRDecoder::visitExp(IR::Exp *s)
#ifndef V4_BOOTSTRAP
Q_ASSERT(member->kind != IR::Member::MemberOfIdObjectsArray);
if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
- callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex, c->args, 0);
+ callQmlContextProperty(member->base, (IR::Member::MemberKind)member->kind, member->property->coreIndex(), c->args, 0);
return;
}
#endif
@@ -295,7 +295,7 @@ void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
if (member->kind == IR::Member::MemberOfQmlScopeObject || member->kind == IR::Member::MemberOfQmlContextObject) {
callBuiltinTypeofQmlContextProperty(member->base,
IR::Member::MemberKind(member->kind),
- member->property->coreIndex, result);
+ member->property->coreIndex(), result);
return;
}
#endif
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index b6c5226894..5687834b00 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -911,8 +911,8 @@ void IRPrinter::visitMember(Member *e)
*out << '.' << *e->name;
#ifndef V4_BOOTSTRAP
if (e->property)
- *out << " (meta-property " << e->property->coreIndex
- << " <" << QMetaType::typeName(e->property->propType)
+ *out << " (meta-property " << e->property->coreIndex()
+ << " <" << QMetaType::typeName(e->property->propType())
<< ">)";
else if (e->kind == Member::MemberOfIdObjectsArray)
*out << "(id object " << e->idIndex << ")";
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index 7bb4d701e2..cc2fe90483 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -249,6 +249,18 @@ parameter, the value can be created as a JavaScript \c Date object in QML, and
is automatically converted to a QDateTime value when it is passed to C++.
+\section2 QTime to JavaScript Date
+
+The QML engine provides automatic type conversion from QTime values to
+JavaScript \c Date objects. The date component of the resulting Date
+object should not be relied upon, as it is operating system dependent.
+Specifically, the year (and month and day) are set to zero. Conversion
+from a JavaScript \c Date object to QTime is done by converting to a
+QDateTime, and then relying on QVariant to convert it to a QTime. The end
+effect is that the date part of the \c Date object is ignored, but the
+local timezone will be used ignoring any DST complications it may have.
+
+
\section2 Sequence Type to JavaScript Array
Certain C++ sequence types are supported transparently in QML as JavaScript
diff --git a/src/qml/doc/src/javascript/hostenvironment.qdoc b/src/qml/doc/src/javascript/hostenvironment.qdoc
index e613c4fcfb..de8b967d72 100644
--- a/src/qml/doc/src/javascript/hostenvironment.qdoc
+++ b/src/qml/doc/src/javascript/hostenvironment.qdoc
@@ -110,7 +110,7 @@ console.log("Result: " + a);
\endcode
Any attempt to modify the global object - either implicitly or explicitly - will
-cause an exception. If uncaught, this will result in an warning being printed,
+cause an exception. If uncaught, this will result in a warning being printed,
that includes the file and line number of the offending code.
\li Global code is run in a reduced scope.
@@ -120,7 +120,7 @@ code, it is executed in a scope that contains only the external file itself and
the global object. That is, it will not have access to the QML objects and
properties it \l {Scope and Naming Resolution}{normally would}.
-Global code that only accesses script local variable is permitted. This is an
+Global code that only accesses script local variables is permitted. This is an
example of valid global code.
\code
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index d76a21c74c..2ef0db78c0 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -84,7 +84,7 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit
void linkBackendToEngine(QV4::ExecutionEngine *engine) Q_DECL_OVERRIDE;
void prepareCodeOffsetsForDiskStorage(CompiledData::Unit *unit) Q_DECL_OVERRIDE;
bool saveCodeToDisk(QIODevice *device, const CompiledData::Unit *unit, QString *errorString) Q_DECL_OVERRIDE;
- bool memoryMapCode(QString *errorString);
+ bool memoryMapCode(QString *errorString) Q_DECL_OVERRIDE;
// Coderef + execution engine
@@ -108,36 +108,6 @@ struct RuntimeCall {
bool isValid() const { return addr.offset >= 0; }
};
-template <typename T>
-struct ExceptionCheck {
- enum { NeedsCheck = 1 };
-};
-// push_catch and pop context methods shouldn't check for exceptions
-template <>
-struct ExceptionCheck<void (*)(QV4::ExecutionEngine *)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A>
-struct ExceptionCheck<void (*)(A, QV4::NoThrowEngine)> {
- enum { NeedsCheck = 0 };
-};
-template <>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A, typename B>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A, B)> {
- enum { NeedsCheck = 0 };
-};
-template <typename A, typename B, typename C>
-struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
- enum { NeedsCheck = 0 };
-};
-
class Assembler : public JSC::MacroAssembler, public TargetPlatform
{
Q_DISABLE_COPY(Assembler)
@@ -809,7 +779,7 @@ public:
};
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6>
- void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6)
+ void generateFunctionCallImp(bool needsExceptionCheck, ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6)
{
int stackSpaceNeeded = SizeOnStack<0, Arg1>::Size
+ SizeOnStack<1, Arg2>::Size
@@ -852,7 +822,7 @@ public:
if (stackSpaceNeeded)
addPtr(TrustedImm32(stackSpaceNeeded), StackPointerRegister);
- if (ExceptionCheck<Callable>::NeedsCheck) {
+ if (needsExceptionCheck) {
checkException();
}
@@ -861,33 +831,33 @@ public:
}
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
- void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
+ void generateFunctionCallImp(bool needsExceptionCheck, ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
{
- generateFunctionCallImp(r, functionName, function, arg1, arg2, arg3, arg4, arg5, VoidType());
+ generateFunctionCallImp(needsExceptionCheck, r, functionName, function, arg1, arg2, arg3, arg4, arg5, VoidType());
}
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
- void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ void generateFunctionCallImp(bool needsExceptionCheck, ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
- generateFunctionCallImp(r, functionName, function, arg1, arg2, arg3, arg4, VoidType(), VoidType());
+ generateFunctionCallImp(needsExceptionCheck, r, functionName, function, arg1, arg2, arg3, arg4, VoidType(), VoidType());
}
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3>
- void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ void generateFunctionCallImp(bool needsExceptionCheck, ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
- generateFunctionCallImp(r, functionName, function, arg1, arg2, arg3, VoidType(), VoidType(), VoidType());
+ generateFunctionCallImp(needsExceptionCheck, r, functionName, function, arg1, arg2, arg3, VoidType(), VoidType(), VoidType());
}
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2>
- void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2)
+ void generateFunctionCallImp(bool needsExceptionCheck, ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2)
{
- generateFunctionCallImp(r, functionName, function, arg1, arg2, VoidType(), VoidType(), VoidType(), VoidType());
+ generateFunctionCallImp(needsExceptionCheck, r, functionName, function, arg1, arg2, VoidType(), VoidType(), VoidType(), VoidType());
}
template <typename ArgRet, typename Callable, typename Arg1>
- void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1)
+ void generateFunctionCallImp(bool needsExceptionCheck, ArgRet r, const char* functionName, Callable function, Arg1 arg1)
{
- generateFunctionCallImp(r, functionName, function, arg1, VoidType(), VoidType(), VoidType(), VoidType(), VoidType());
+ generateFunctionCallImp(needsExceptionCheck, r, functionName, function, arg1, VoidType(), VoidType(), VoidType(), VoidType(), VoidType());
}
Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset)
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index 45cc9259c3..9c535bb0bb 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -45,17 +45,17 @@ using namespace QV4;
using namespace JIT;
#define OP(op) \
- { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, 0, 0 }
+ { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, 0, 0, QV4::Runtime::Method_##op##_NeedsExceptionCheck }
#define OPCONTEXT(op) \
- { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), 0, 0 }
+ { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), 0, 0, QV4::Runtime::Method_##op##_NeedsExceptionCheck }
#define INLINE_OP(op, memOp, immOp) \
- { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, memOp, immOp }
+ { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, memOp, immOp, QV4::Runtime::Method_##op##_NeedsExceptionCheck }
#define INLINE_OPCONTEXT(op, memOp, immOp) \
- { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), memOp, immOp }
+ { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), memOp, immOp, QV4::Runtime::Method_##op##_NeedsExceptionCheck }
#define NULL_OP \
- { 0, 0, 0, 0, 0 }
+ { 0, 0, 0, 0, 0, false }
const Binop::OpInfo Binop::operations[IR::LastAluOp + 1] = {
NULL_OP, // OpInvalid
@@ -128,11 +128,11 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
RuntimeCall fallBack(info.fallbackImplementation);
RuntimeCall context(info.contextImplementation);
if (fallBack.isValid()) {
- as->generateFunctionCallImp(target, info.name, fallBack,
+ as->generateFunctionCallImp(info.needsExceptionCheck, target, info.name, fallBack,
Assembler::PointerToValue(lhs),
Assembler::PointerToValue(rhs));
} else if (context.isValid()) {
- as->generateFunctionCallImp(target, info.name, context,
+ as->generateFunctionCallImp(info.needsExceptionCheck, target, info.name, context,
Assembler::EngineRegister,
Assembler::PointerToValue(lhs),
Assembler::PointerToValue(rhs));
diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h
index c246ee43b0..37601f54ba 100644
--- a/src/qml/jit/qv4binop_p.h
+++ b/src/qml/jit/qv4binop_p.h
@@ -81,6 +81,7 @@ struct Binop {
int contextImplementation; // offsetOf(Runtime,...)
MemRegOp inlineMemRegOp;
ImmRegOp inlineImmRegOp;
+ bool needsExceptionCheck;
};
static const OpInfo operations[IR::LastAluOp + 1];
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index da28df817d..c1c42f876c 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -970,9 +970,15 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
}
#define setOp(op, opName, operation) \
- do { op = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); } while (0)
+ do { \
+ op = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \
+ needsExceptionCheck = QV4::Runtime::Method_##operation##_NeedsExceptionCheck; \
+ } while (0)
#define setOpContext(op, opName, operation) \
- do { opContext = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); } while (0)
+ do { \
+ opContext = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \
+ needsExceptionCheck = QV4::Runtime::Method_##operation##_NeedsExceptionCheck; \
+ } while (0)
void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target)
{
@@ -1446,18 +1452,19 @@ void InstructionSelection::visitCJump(IR::CJump *s)
RuntimeCall op;
RuntimeCall opContext;
const char *opName = 0;
+ bool needsExceptionCheck;
switch (b->op) {
default: Q_UNREACHABLE(); Q_ASSERT(!"todo"); break;
- case IR::OpGt: setOp(op, opName, Runtime::compareGreaterThan); break;
- case IR::OpLt: setOp(op, opName, Runtime::compareLessThan); break;
- case IR::OpGe: setOp(op, opName, Runtime::compareGreaterEqual); break;
- case IR::OpLe: setOp(op, opName, Runtime::compareLessEqual); break;
- case IR::OpEqual: setOp(op, opName, Runtime::compareEqual); break;
- case IR::OpNotEqual: setOp(op, opName, Runtime::compareNotEqual); break;
- case IR::OpStrictEqual: setOp(op, opName, Runtime::compareStrictEqual); break;
- case IR::OpStrictNotEqual: setOp(op, opName, Runtime::compareStrictNotEqual); break;
- case IR::OpInstanceof: setOpContext(op, opName, Runtime::compareInstanceof); break;
- case IR::OpIn: setOpContext(op, opName, Runtime::compareIn); break;
+ case IR::OpGt: setOp(op, opName, compareGreaterThan); break;
+ case IR::OpLt: setOp(op, opName, compareLessThan); break;
+ case IR::OpGe: setOp(op, opName, compareGreaterEqual); break;
+ case IR::OpLe: setOp(op, opName, compareLessEqual); break;
+ case IR::OpEqual: setOp(op, opName, compareEqual); break;
+ case IR::OpNotEqual: setOp(op, opName, compareNotEqual); break;
+ case IR::OpStrictEqual: setOp(op, opName, compareStrictEqual); break;
+ case IR::OpStrictNotEqual: setOp(op, opName, compareStrictNotEqual); break;
+ case IR::OpInstanceof: setOpContext(op, opName, compareInstanceof); break;
+ case IR::OpIn: setOpContext(op, opName, compareIn); break;
} // switch
// TODO: in SSA optimization, do constant expression evaluation.
@@ -1466,12 +1473,14 @@ void InstructionSelection::visitCJump(IR::CJump *s)
// Of course, after folding the CJUMP to a JUMP, dead-code (dead-basic-block)
// elimination (which isn't there either) would remove the whole else block.
if (opContext.isValid())
- _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, opContext,
+ _as->generateFunctionCallImp(needsExceptionCheck,
+ Assembler::ReturnValueRegister, opName, opContext,
Assembler::EngineRegister,
Assembler::PointerToValue(b->left),
Assembler::PointerToValue(b->right));
else
- _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, op,
+ _as->generateFunctionCallImp(needsExceptionCheck,
+ Assembler::ReturnValueRegister, opName, op,
Assembler::PointerToValue(b->left),
Assembler::PointerToValue(b->right));
diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h
index 93453f71be..5bca879a77 100644
--- a/src/qml/jit/qv4isel_masm_p.h
+++ b/src/qml/jit/qv4isel_masm_p.h
@@ -244,7 +244,7 @@ private:
#define isel_stringIfy(s) isel_stringIfyx(s)
#define generateRuntimeCall(t, function, ...) \
- _as->generateFunctionCallImp(t, "Runtime::" isel_stringIfy(function), RuntimeCall(qOffsetOf(QV4::Runtime, function)), __VA_ARGS__)
+ _as->generateFunctionCallImp(Runtime::Method_##function##_NeedsExceptionCheck, t, "Runtime::" isel_stringIfy(function), RuntimeCall(qOffsetOf(QV4::Runtime, function)), __VA_ARGS__)
int prepareVariableArguments(IR::ExprList* args);
int prepareCallData(IR::ExprList* args, IR::Expr *thisObject);
@@ -260,7 +260,7 @@ private:
// address.
Assembler::Pointer lookupAddr(Assembler::ReturnValueRegister, index * sizeof(QV4::Lookup));
- _as->generateFunctionCallImp(retval, "lookup getter/setter",
+ _as->generateFunctionCallImp(true, retval, "lookup getter/setter",
LookupCall(lookupAddr, getterSetterOffset), lookupAddr,
arg1, arg2, arg3);
}
diff --git a/src/qml/jit/qv4unop.cpp b/src/qml/jit/qv4unop.cpp
index 6a32069ac4..799103849b 100644
--- a/src/qml/jit/qv4unop.cpp
+++ b/src/qml/jit/qv4unop.cpp
@@ -47,10 +47,14 @@ using namespace JIT;
#define stringIfyx(s) #s
#define stringIfy(s) stringIfyx(s)
#define setOp(operation) \
- do { call = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); name = "Runtime::" stringIfy(operation); } while (0)
+ do { \
+ call = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); name = "Runtime::" stringIfy(operation); \
+ needsExceptionCheck = Runtime::Method_##operation##_NeedsExceptionCheck; \
+ } while (0)
void Unop::generate(IR::Expr *source, IR::Expr *target)
{
+ bool needsExceptionCheck;
RuntimeCall call;
const char *name = 0;
switch (op) {
@@ -71,7 +75,7 @@ void Unop::generate(IR::Expr *source, IR::Expr *target)
} // switch
Q_ASSERT(call.isValid());
- _as->generateFunctionCallImp(target, name, call, Assembler::PointerToValue(source));
+ _as->generateFunctionCallImp(needsExceptionCheck, target, name, call, Assembler::PointerToValue(source));
}
void Unop::generateUMinus(IR::Expr *source, IR::Expr *target)
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index e5c1dcdb80..a4a96a96a7 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -178,7 +178,7 @@ QJSValue::QJSValue(SpecialValue value)
: d(0)
{
if (value == NullValue)
- QJSValuePrivate::setVariant(this, QVariant(QMetaType::VoidStar, (void *)0));
+ QJSValuePrivate::setVariant(this, QVariant::fromValue(nullptr));
}
/*!
@@ -293,7 +293,10 @@ bool QJSValue::isNull() const
if (val)
return val->isNull();
QVariant *variant = QJSValuePrivate::getVariant(this);
- return variant && variant->userType() == QMetaType::VoidStar;
+ if (!variant)
+ return false;
+ const int type = variant->userType();
+ return type == QMetaType::Nullptr || type == QMetaType::VoidStar;
}
/*!
@@ -582,7 +585,7 @@ quint32 QJSValue::toUInt() const
\table
\header \li Input Type \li Result
\row \li Undefined \li An invalid QVariant.
- \row \li Null \li A QVariant containing a null pointer (QMetaType::VoidStar).
+ \row \li Null \li A QVariant containing a null pointer (QMetaType::Nullptr).
\row \li Boolean \li A QVariant containing the value of the boolean.
\row \li Number \li A QVariant containing the value of the number.
\row \li String \li A QVariant containing the value of the string.
@@ -619,7 +622,7 @@ QVariant QJSValue::toVariant() const
return QVariant(val->asDouble());
}
if (val->isNull())
- return QVariant(QMetaType::VoidStar, 0);
+ return QVariant(QMetaType::Nullptr, 0);
Q_ASSERT(val->isUndefined());
return QVariant();
}
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 25afd9275c..c4761ad6ea 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -132,6 +132,7 @@ public:
case QMetaType::Void:
*v = QV4::Encode::undefined();
break;
+ case QMetaType::Nullptr:
case QMetaType::VoidStar:
*v = QV4::Encode::null();
break;
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index df648ba9ee..04358fe3b5 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -639,6 +639,28 @@ Heap::DateObject::DateObject(const QDateTime &date)
this->date = date.isValid() ? date.toMSecsSinceEpoch() : qt_qnan();
}
+Heap::DateObject::DateObject(const QTime &time)
+{
+ if (!time.isValid()) {
+ date = qt_qnan();
+ return;
+ }
+
+ /* All programmers know that stuff starts at 0. Whatever that may mean in this context (and
+ * local timezone), it's before the epoch, so there is defenitely no DST problem. Specifically:
+ * you can't start with a date before the epoch, add some[*] hours, and end up with a date
+ * after. That's a problem for timezones where new year happens during DST, like
+ * Australia/Hobart, because we have to ignore DST before the epoch (but honor it after the
+ * epoch).
+ *
+ * [*] Well, when "some" is in the range 0-24. If you add something like 1M then this might
+ * still happen.
+ */
+ static const double d = MakeDay(0, 0, 0);
+ double t = MakeTime(time.hour(), time.minute(), time.second(), time.msec());
+ date = TimeClip(UTC(MakeDate(d, t)));
+}
+
QDateTime DateObject::toQDateTime() const
{
return ToDateTime(date(), Qt::LocalTime);
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 13e9e04040..c67acdcfa2 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -74,6 +74,8 @@ struct DateObject : Object {
}
DateObject(const QDateTime &date);
double date;
+
+ DateObject(const QTime &time);
};
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index f5bae4b258..27397fe3d8 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -621,6 +621,13 @@ Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
return object->d();
}
+Heap::DateObject *ExecutionEngine::newDateObjectFromTime(const QTime &t)
+{
+ Scope scope(this);
+ Scoped<DateObject> object(scope, memoryManager->allocObject<DateObject>(t));
+ return object->d();
+}
+
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
{
bool global = (flags & IR::RegExp::RegExp_Global);
@@ -1130,7 +1137,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
if (value.isUndefined())
return QVariant();
if (value.isNull())
- return QVariant(QMetaType::VoidStar, (void *)0);
+ return QVariant::fromValue(nullptr);
if (value.isBoolean())
return value.booleanValue();
if (value.isInteger())
@@ -1255,6 +1262,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
case QMetaType::UnknownType:
case QMetaType::Void:
return QV4::Encode::undefined();
+ case QMetaType::Nullptr:
case QMetaType::VoidStar:
return QV4::Encode::null();
case QMetaType::Bool:
@@ -1290,7 +1298,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
case QMetaType::QDate:
return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr))));
case QMetaType::QTime:
- return QV4::Encode(newDateObject(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr))));
+ return QV4::Encode(newDateObjectFromTime(*reinterpret_cast<const QTime *>(ptr)));
case QMetaType::QRegExp:
return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr)));
case QMetaType::QObjectStar:
@@ -1426,6 +1434,7 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
case QMetaType::UnknownType:
case QMetaType::Void:
return QV4::Encode::undefined();
+ case QMetaType::Nullptr:
case QMetaType::VoidStar:
return QV4::Encode::null();
case QMetaType::Bool:
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index f42f727295..843a6f4d94 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -419,6 +419,7 @@ public:
Heap::DateObject *newDateObject(const Value &value);
Heap::DateObject *newDateObject(const QDateTime &dt);
+ Heap::DateObject *newDateObjectFromTime(const QTime &t);
Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
Heap::RegExpObject *newRegExpObject(RegExp *re, bool global);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 276a069a77..b08ad24fbe 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -166,14 +166,14 @@ ReturnedValue FunctionObject::name() const
return get(scope()->engine->id_name());
}
-ReturnedValue FunctionObject::construct(const Managed *that, CallData *)
+void FunctionObject::construct(const Managed *that, Scope &scope, CallData *)
{
- return static_cast<const FunctionObject *>(that)->engine()->throwTypeError();
+ scope.result = static_cast<const FunctionObject *>(that)->engine()->throwTypeError();
}
-ReturnedValue FunctionObject::call(const Managed *, CallData *)
+void FunctionObject::call(const Managed *, Scope &scope, CallData *)
{
- return Encode::undefined();
+ scope.result = Encode::undefined();
}
void FunctionObject::markObjects(Heap::Base *that, ExecutionEngine *e)
@@ -548,8 +548,11 @@ void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData
if (f->function()->compiledFunction->hasQmlDependencies())
QQmlPropertyCapture::registerQmlDependencies(f->function()->compiledFunction, scope);
- if (!scope.result.isManaged() || !scope.result.managed())
+ if (v4->hasException) {
+ scope.result = Encode::undefined();
+ } else if (!scope.result.isObject()) {
scope.result = callData->thisObject;
+ }
}
void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *callData)
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index be80b87873..182b762606 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -147,8 +147,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
using Object::construct;
using Object::call;
- static ReturnedValue construct(const Managed *that, CallData *);
- static ReturnedValue call(const Managed *that, CallData *d);
+ static void construct(const Managed *that, Scope &scope, CallData *);
+ static void call(const Managed *that, Scope &scope, CallData *d);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
static Heap::FunctionObject *createQmlFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 074d3bf866..624c37a694 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -124,7 +124,7 @@ struct ReadAccessor {
Q_UNUSED(n);
void *args[] = { output, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex(), args);
}
static inline void Direct(QObject *object, const QQmlPropertyData &property,
@@ -134,16 +134,16 @@ struct ReadAccessor {
Q_UNUSED(n);
void *args[] = { output, 0 };
- object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args);
+ object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex(), args);
}
static inline void Accessor(QObject *object, const QQmlPropertyData &property,
void *output, QQmlNotifier **n)
{
- Q_ASSERT(property.accessors);
+ Q_ASSERT(property.accessors());
- property.accessors->read(object, output);
- if (n) property.accessors->notifier(object, n);
+ property.accessors()->read(object, output);
+ if (n) property.accessors()->notifier(object, n);
}
};
@@ -162,32 +162,32 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
ReadFunction(object, property, &rv, notifier);
return QV4::QObjectWrapper::wrap(v4, rv);
} else if (property.isQList()) {
- return QmlListWrapper::create(v4, object, property.coreIndex, property.propType);
- } else if (property.propType == QMetaType::QReal) {
+ return QmlListWrapper::create(v4, object, property.coreIndex(), property.propType());
+ } else if (property.propType() == QMetaType::QReal) {
qreal v = 0;
ReadFunction(object, property, &v, notifier);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Int || property.isEnum()) {
+ } else if (property.propType() == QMetaType::Int || property.isEnum()) {
int v = 0;
ReadFunction(object, property, &v, notifier);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Bool) {
+ } else if (property.propType() == QMetaType::Bool) {
bool v = false;
ReadFunction(object, property, &v, notifier);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::QString) {
+ } else if (property.propType() == QMetaType::QString) {
QString v;
ReadFunction(object, property, &v, notifier);
return v4->newString(v)->asReturnedValue();
- } else if (property.propType == QMetaType::UInt) {
+ } else if (property.propType() == QMetaType::UInt) {
uint v = 0;
ReadFunction(object, property, &v, notifier);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Float) {
+ } else if (property.propType() == QMetaType::Float) {
float v = 0;
ReadFunction(object, property, &v, notifier);
return QV4::Encode(v);
- } else if (property.propType == QMetaType::Double) {
+ } else if (property.propType() == QMetaType::Double) {
double v = 0;
ReadFunction(object, property, &v, notifier);
return QV4::Encode(v);
@@ -195,7 +195,7 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
QQmlV4Handle handle;
ReadFunction(object, property, &handle, notifier);
return handle;
- } else if (property.propType == qMetaTypeId<QJSValue>()) {
+ } else if (property.propType() == qMetaTypeId<QJSValue>()) {
QJSValue v;
ReadFunction(object, property, &v, notifier);
return QJSValuePrivate::convertedToValue(v4, v);
@@ -205,32 +205,32 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
if (QQmlValueTypeFactory::isValueType(v.userType())) {
if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(v.userType()))
- return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex, valueTypeMetaObject, v.userType()); // VariantReference value-type.
+ return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, v.userType()); // VariantReference value-type.
}
return scope.engine->fromVariant(v);
- } else if (QQmlValueTypeFactory::isValueType(property.propType)) {
+ } else if (QQmlValueTypeFactory::isValueType(property.propType())) {
Q_ASSERT(notifier == 0);
- if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType))
- return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex, valueTypeMetaObject, property.propType);
+ if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType()))
+ return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex(), valueTypeMetaObject, property.propType());
} else {
Q_ASSERT(notifier == 0);
// see if it's a sequence type
bool succeeded = false;
- QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType, object, property.coreIndex, &succeeded));
+ QV4::ScopedValue retn(scope, QV4::SequencePrototype::newSequence(v4, property.propType(), object, property.coreIndex(), &succeeded));
if (succeeded)
return retn->asReturnedValue();
}
- if (property.propType == QMetaType::UnknownType) {
- QMetaProperty p = object->metaObject()->property(property.coreIndex);
+ if (property.propType() == QMetaType::UnknownType) {
+ QMetaProperty p = object->metaObject()->property(property.coreIndex());
qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property "
"'%s::%s'", p.typeName(), object->metaObject()->className(), p.name());
return QV4::Encode::undefined();
} else {
- QVariant v(property.propType, (void *)0);
+ QVariant v(property.propType(), (void *)0);
ReadFunction(object, property, v.data(), notifier);
return scope.engine->fromVariant(v);
}
@@ -328,25 +328,25 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *object, QQmlPropertyData *property, bool captureRequired)
{
- QQmlData::flushPendingBinding(object, property->encodedIndex());
+ QQmlData::flushPendingBinding(object, QQmlPropertyIndex(property->coreIndex()));
if (property->isFunction() && !property->isVarProperty()) {
if (property->isVMEFunction()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- return vmemo->vmeMethod(property->coreIndex);
+ return vmemo->vmeMethod(property->coreIndex());
} else if (property->isV4Function()) {
Scope scope(engine);
ScopedContext global(scope, engine->qmlContext());
if (!global)
global = engine->rootContext();
- return QV4::QObjectMethod::create(global, object, property->coreIndex);
+ return QV4::QObjectMethod::create(global, object, property->coreIndex());
} else if (property->isSignalHandler()) {
QmlSignalHandler::initProto(engine);
- return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex)->asReturnedValue();
+ return engine->memoryManager->allocObject<QV4::QmlSignalHandler>(object, property->coreIndex())->asReturnedValue();
} else {
ExecutionContext *global = engine->rootContext();
- return QV4::QObjectMethod::create(global, object, property->coreIndex);
+ return QV4::QObjectMethod::create(global, object, property->coreIndex());
}
}
@@ -356,19 +356,19 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
QQmlNotifier *n = 0;
QQmlNotifier **nptr = 0;
- if (ep && ep->propertyCapture && property->accessors->notifier)
+ if (ep && ep->propertyCapture && property->accessors()->notifier)
nptr = &n;
Scope scope(engine);
QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(engine, object, *property, nptr));
if (captureRequired && !property->isConstant()) {
- if (property->accessors->notifier) {
+ if (property->accessors()->notifier) {
if (n && ep->propertyCapture)
ep->propertyCapture->captureProperty(n);
} else {
if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
+ ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
}
}
@@ -376,12 +376,12 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionEngine *engine, QObject *obje
}
if (captureRequired && ep && ep->propertyCapture && !property->isConstant())
- ep->propertyCapture->captureProperty(object, property->coreIndex, property->notifyIndex);
+ ep->propertyCapture->captureProperty(object, property->coreIndex(), property->notifyIndex());
if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- return vmemo->vmeProperty(property->coreIndex);
+ return vmemo->vmeProperty(property->coreIndex());
} else if (property->isDirect()) {
return LoadProperty<ReadAccessor::Direct>(engine, object, *property, 0);
} else {
@@ -448,13 +448,13 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
QV4::ScopedFunctionObject f(scope, value);
if (f) {
if (!f->isBinding()) {
- if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) {
+ if (!property->isVarProperty() && property->propType() != qMetaTypeId<QJSValue>()) {
// assigning a JS function to a non var or QJSValue property or is not allowed.
QString error = QLatin1String("Cannot assign JavaScript function to ");
- if (!QMetaType::typeName(property->propType))
+ if (!QMetaType::typeName(property->propType()))
error += QLatin1String("[unknown property type]");
else
- error += QLatin1String(QMetaType::typeName(property->propType));
+ error += QLatin1String(QMetaType::typeName(property->propType()));
scope.engine->throwError(error);
return;
}
@@ -466,20 +466,20 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
bindingFunction->initBindingLocation();
newBinding = QQmlBinding::create(property, value, object, callingQmlContext);
- newBinding->setTarget(object, *property);
+ newBinding->setTarget(object, *property, nullptr);
}
}
if (newBinding)
QQmlPropertyPrivate::setBinding(newBinding);
else
- QQmlPropertyPrivate::removeBinding(object, property->encodedIndex());
+ QQmlPropertyPrivate::removeBinding(object, QQmlPropertyIndex(property->coreIndex()));
if (!newBinding && property->isVarProperty()) {
// allow assignment of "special" values (null, undefined, function) to var properties
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(property->coreIndex, value);
+ vmemo->setVMEProperty(property->coreIndex(), value);
return;
}
@@ -488,44 +488,44 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
int status = -1; \
int flags = 0; \
void *argv[] = { &o, 0, &status, &flags }; \
- QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex(), argv);
if (value.isNull() && property->isQObject()) {
PROPERTY_STORE(QObject*, 0);
} else if (value.isUndefined() && property->isResettable()) {
void *a[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a);
- } else if (value.isUndefined() && property->propType == qMetaTypeId<QVariant>()) {
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex(), a);
+ } else if (value.isUndefined() && property->propType() == qMetaTypeId<QVariant>()) {
PROPERTY_STORE(QVariant, QVariant());
- } else if (value.isUndefined() && property->propType == QMetaType::QJsonValue) {
+ } else if (value.isUndefined() && property->propType() == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
- } else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) {
+ } else if (!newBinding && property->propType() == qMetaTypeId<QJSValue>()) {
PROPERTY_STORE(QJSValue, QJSValue(scope.engine, value.asReturnedValue()));
- } else if (value.isUndefined() && property->propType != qMetaTypeId<QQmlScriptString>()) {
+ } else if (value.isUndefined() && property->propType() != qMetaTypeId<QQmlScriptString>()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
- if (!QMetaType::typeName(property->propType))
+ if (!QMetaType::typeName(property->propType()))
error += QLatin1String("[unknown property type]");
else
- error += QLatin1String(QMetaType::typeName(property->propType));
+ error += QLatin1String(QMetaType::typeName(property->propType()));
scope.engine->throwError(error);
return;
} else if (value.as<FunctionObject>()) {
// this is handled by the binding creation above
- } else if (property->propType == QMetaType::Int && value.isNumber()) {
+ } else if (property->propType() == QMetaType::Int && value.isNumber()) {
PROPERTY_STORE(int, value.asDouble());
- } else if (property->propType == QMetaType::QReal && value.isNumber()) {
+ } else if (property->propType() == QMetaType::QReal && value.isNumber()) {
PROPERTY_STORE(qreal, qreal(value.asDouble()));
- } else if (property->propType == QMetaType::Float && value.isNumber()) {
+ } else if (property->propType() == QMetaType::Float && value.isNumber()) {
PROPERTY_STORE(float, float(value.asDouble()));
- } else if (property->propType == QMetaType::Double && value.isNumber()) {
+ } else if (property->propType() == QMetaType::Double && value.isNumber()) {
PROPERTY_STORE(double, double(value.asDouble()));
- } else if (property->propType == QMetaType::QString && value.isString()) {
+ } else if (property->propType() == QMetaType::QString && value.isString()) {
PROPERTY_STORE(QString, value.toQStringNoThrow());
} else if (property->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(property->coreIndex, value);
- } else if (property->propType == qMetaTypeId<QQmlScriptString>() && (value.isUndefined() || value.isPrimitive())) {
+ vmemo->setVMEProperty(property->coreIndex(), value);
+ } else if (property->propType() == qMetaTypeId<QQmlScriptString>() && (value.isUndefined() || value.isPrimitive())) {
QQmlScriptString ss(value.toQStringNoThrow(), 0 /* context */, object);
if (value.isNumber()) {
ss.d->numberValue = value.toNumber();
@@ -540,7 +540,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
if (property->isQList())
v = scope.engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = scope.engine->toVariant(value, property->propType);
+ v = scope.engine->toVariant(value, property->propType());
QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
@@ -548,7 +548,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
if (v.userType() == QVariant::Invalid) valueType = "null";
else valueType = QMetaType::typeName(v.userType());
- const char *targetTypeName = QMetaType::typeName(property->propType);
+ const char *targetTypeName = QMetaType::typeName(property->propType());
if (!targetTypeName)
targetTypeName = "an unregistered type";
@@ -648,6 +648,9 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, int propertyIndex, con
void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, int propertyIndex, const Value &value)
{
+ Q_ASSERT(propertyIndex < 0xffff);
+ Q_ASSERT(propertyIndex >= 0);
+
if (QQmlData::wasDeleted(object))
return;
QQmlData *ddata = QQmlData::get(object, /*create*/false);
@@ -1247,6 +1250,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
}
} else if (actual.isNull()) {
switch (conversionType) {
+ case QMetaType::Nullptr:
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
case QMetaType::QJsonValue:
@@ -1319,34 +1323,34 @@ static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object,
if (!current->isOverload())
return 0;
- Q_ASSERT(!current->overrideIndexIsProperty);
+ Q_ASSERT(!current->overrideIndexIsProperty());
if (propertyCache) {
- return propertyCache->method(current->overrideIndex);
+ return propertyCache->method(current->overrideIndex());
} else {
const QMetaObject *mo = object.metaObject();
int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
- while (methodOffset > current->overrideIndex) {
+ while (methodOffset > current->overrideIndex()) {
mo = mo->superClass();
methodOffset -= QMetaObject_methods(mo);
}
// If we've been called before with the same override index, then
// we can't go any further...
- if (&dummy == current && dummy.coreIndex == current->overrideIndex)
+ if (&dummy == current && dummy.coreIndex() == current->overrideIndex())
return 0;
- QMetaMethod method = mo->method(current->overrideIndex);
+ QMetaMethod method = mo->method(current->overrideIndex());
dummy.load(method);
// Look for overloaded methods
QByteArray methodName = method.name();
- for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) {
+ for (int ii = current->overrideIndex() - 1; ii >= methodOffset; --ii) {
if (methodName == mo->method(ii).name()) {
dummy.setOverload(true);
- dummy.overrideIndexIsProperty = 0;
- dummy.overrideIndex = ii;
+ dummy.setOverrideIndexIsProperty(0);
+ dummy.setOverrideIndex(ii);
return &dummy;
}
}
@@ -1376,9 +1380,9 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
if (data.isConstructor())
args = static_cast<const QQmlStaticMetaObject&>(object).constructorParameterTypes(
- data.coreIndex, &storage, &unknownTypeError);
+ data.coreIndex(), &storage, &unknownTypeError);
else
- args = object.methodParameterTypes(data.coreIndex, &storage, &unknownTypeError);
+ args = object.methodParameterTypes(data.coreIndex(), &storage, &unknownTypeError);
if (!args) {
QString typeName = QString::fromLatin1(unknownTypeError);
@@ -1391,11 +1395,11 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
return engine->throwError(error);
}
- return CallMethod(object, data.coreIndex, returnType, args[0], args + 1, engine, callArgs, callType);
+ return CallMethod(object, data.coreIndex(), returnType, args[0], args + 1, engine, callArgs, callType);
} else {
- return CallMethod(object, data.coreIndex, returnType, 0, 0, engine, callArgs, callType);
+ return CallMethod(object, data.coreIndex(), returnType, 0, 0, engine, callArgs, callType);
}
}
@@ -1434,7 +1438,7 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const
int methodArgumentCount = 0;
int *methodArgTypes = 0;
if (attempt->hasArguments()) {
- int *args = object.methodParameterTypes(attempt->coreIndex, &storage, 0);
+ int *args = object.methodParameterTypes(attempt->coreIndex(), &storage, 0);
if (!args) // Must be an unknown argument
continue;
@@ -1471,7 +1475,7 @@ static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const
const QQmlPropertyData *candidate = &data;
while (candidate) {
error += QLatin1String("\n ") +
- QString::fromUtf8(object.metaObject()->method(candidate->coreIndex)
+ QString::fromUtf8(object.metaObject()->method(candidate->coreIndex())
.methodSignature());
candidate = RelatedMethod(object, candidate, dummy, propertyCache);
}
@@ -1855,7 +1859,7 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const
const QMetaMethod moMethod = mo->method(d()->index);
method.load(moMethod);
- if (method.coreIndex == -1) {
+ if (method.coreIndex() == -1) {
scope.result = QV4::Encode::undefined();
return;
}
@@ -1866,8 +1870,8 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const
for (int ii = d()->index - 1; ii >= methodOffset; --ii) {
if (methodName == mo->method(ii).name()) {
method.setOverload(true);
- method.overrideIndexIsProperty = 0;
- method.overrideIndex = ii;
+ method.setOverrideIndexIsProperty(0);
+ method.setOverrideIndex(ii);
break;
}
}
@@ -1879,7 +1883,7 @@ void QObjectMethod::callInternal(CallData *callData, Scope &scope) const
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
- object.metacall(QMetaObject::InvokeMetaMethod, method.coreIndex, args);
+ object.metacall(QMetaObject::InvokeMetaMethod, method.coreIndex(), args);
return;
}
@@ -1919,7 +1923,7 @@ void Heap::QMetaObjectWrapper::ensureConstructorsCache() {
QMetaMethod method = metaObject->constructor(i);
QQmlPropertyData d;
d.load(method);
- d.coreIndex = i;
+ d.setCoreIndex(i);
constructors << d;
}
}
@@ -2006,7 +2010,7 @@ ReturnedValue QMetaObjectWrapper::callOverloadedConstructor(QV4::ExecutionEngine
int *methodArgTypes = 0;
if (attempt.hasArguments()) {
QQmlMetaObject::ArgTypeStorage storage;
- int *args = object.constructorParameterTypes(attempt.coreIndex, &storage, 0);
+ int *args = object.constructorParameterTypes(attempt.coreIndex(), &storage, 0);
if (!args) // Must be an unknown argument
continue;
@@ -2042,7 +2046,7 @@ ReturnedValue QMetaObjectWrapper::callOverloadedConstructor(QV4::ExecutionEngine
for (int i = 0; i < numberOfConstructors; i++) {
const QQmlPropertyData & candidate = d()->constructors.at(i);
error += QLatin1String("\n ") +
- QString::fromUtf8(d()->metaObject->constructor(candidate.coreIndex)
+ QString::fromUtf8(d()->metaObject->constructor(candidate.coreIndex())
.methodSignature());
}
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index a69874cacb..c95e767bb0 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -259,7 +259,7 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
result->append(QString(decpt - result->length(), zero));
}
- if (sign)
+ if (sign && num)
result->prepend(QLatin1Char('-'));
return;
@@ -1716,6 +1716,8 @@ ReturnedValue Runtime::method_ushr(const Value &left, const Value &right)
return Encode(res);
}
+#endif // V4_BOOTSTRAP
+
ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right)
{
TRACE2(left, right);
@@ -1824,8 +1826,6 @@ Bool Runtime::method_toBoolean(const Value &value)
return value.toBoolean();
}
-#endif // V4_BOOTSTRAP
-
} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index cbc7a2ddc1..582cdcf4e9 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -58,8 +58,41 @@ namespace QV4 {
struct NoThrowEngine;
+namespace {
+template <typename T>
+struct ExceptionCheck {
+ enum { NeedsCheck = 1 };
+};
+// push_catch and pop context methods shouldn't check for exceptions
+template <>
+struct ExceptionCheck<void (*)(QV4::ExecutionEngine *)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A>
+struct ExceptionCheck<void (*)(A, QV4::NoThrowEngine)> {
+ enum { NeedsCheck = 0 };
+};
+template <>
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A>
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A, typename B>
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A, B)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A, typename B, typename C>
+struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
+ enum { NeedsCheck = 0 };
+};
+} // anonymous namespace
+
#define RUNTIME_METHOD(returnvalue, name, args) \
typedef returnvalue (*Method_##name)args; \
+ enum { Method_##name##_NeedsExceptionCheck = ExceptionCheck<Method_##name>::NeedsCheck }; \
static returnvalue method_##name args; \
const Method_##name name
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index a6d7c3b1ed..53b9ebfe2a 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -48,6 +48,7 @@
#include <QTime>
#include <QMap>
+#include <QScopedValueRollback>
#include <iostream>
#include <cstdlib>
@@ -574,6 +575,8 @@ void MemoryManager::runGC()
return;
}
+ QScopedValueRollback<bool> gcBlocker(m_d->gcBlocked, true);
+
if (!m_d->gcStats) {
mark();
sweep();
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index addf1d9ff8..2d4a82e2f4 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -13,6 +13,7 @@ HEADERS += \
$$PWD/qflagpointer_p.h \
$$PWD/qlazilyallocated_p.h \
$$PWD/qqmlnullablevalue_p.h \
+ $$PWD/qdeferredcleanup_p.h \
SOURCES += \
$$PWD/qintrusivelist.cpp \
diff --git a/src/qml/qml/ftw/qdeferredcleanup_p.h b/src/qml/qml/ftw/qdeferredcleanup_p.h
new file mode 100644
index 0000000000..6b59f04a77
--- /dev/null
+++ b/src/qml/qml/ftw/qdeferredcleanup_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDEFERREDCLEANUP_P_H
+#define QDEFERREDCLEANUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+struct QDeferredCleanup
+{
+ std::function<void()> callback;
+ template <typename Callback>
+ QDeferredCleanup(Callback &&cb)
+ : callback(cb)
+ {}
+ ~QDeferredCleanup() { callback(); }
+ QDeferredCleanup(const QDeferredCleanup &) = delete;
+ QDeferredCleanup &operator=(const QDeferredCleanup &) = delete;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDEFERREDCLEANUP_P_H
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 8c342e0592..fef2da753b 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -69,6 +69,7 @@ void QQmlApplicationEnginePrivate::init()
q->connect(&statusMapper, SIGNAL(mapped(QObject*)),
q, SLOT(_q_finishLoad(QObject*)));
q->connect(q, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
+ q->connect(q, &QQmlApplicationEngine::exit, QCoreApplication::instance(), &QCoreApplication::exit);
#ifndef QT_NO_TRANSLATION
QTranslator* qtTranslator = new QTranslator;
if (qtTranslator->load(QLatin1String("qt_") + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
@@ -134,7 +135,7 @@ void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o)
break;
case QQmlComponent::Ready:
objects << c->create();
- q->objectCreated(objects.last(), c->url());
+ q->objectCreated(objects.constLast(), c->url());
break;
case QQmlComponent::Loading:
case QQmlComponent::Null:
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index d4a8b87aaa..8ed7641610 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -170,7 +170,11 @@ void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
// Check for a binding update loop
if (Q_UNLIKELY(updatingFlag())) {
- QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), getPropertyData(), 0);
+ QQmlPropertyData *d = nullptr;
+ QQmlPropertyData vtd;
+ getPropertyData(&d, &vtd);
+ Q_ASSERT(d);
+ QQmlProperty p = QQmlPropertyPrivate::restore(targetObject(), *d, &vtd, 0);
QQmlAbstractBinding::printBindingLoopError(p);
return;
}
@@ -205,8 +209,10 @@ protected:
QQmlPropertyData::WriteFlags flags, QV4::Scope &,
const QV4::ScopedFunctionObject &) Q_DECL_OVERRIDE Q_DECL_FINAL
{
- QQmlPropertyData pd = getPropertyData();
- pd.writeProperty(*m_target, &binding, flags);
+ Q_ASSERT(!m_targetIndex.hasValueTypeIndex());
+ QQmlPropertyData *pd = nullptr;
+ getPropertyData(&pd, nullptr);
+ pd->writeProperty(*m_target, &binding, flags);
}
};
@@ -260,13 +266,18 @@ protected:
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
{
- QQmlPropertyData pd = getPropertyData();
+ Q_ASSERT(targetObject());
+
+ QQmlPropertyData *pd;
+ QQmlPropertyData vpd;
+ getPropertyData(&pd, &vpd);
+ Q_ASSERT(pd);
+
int propertyType = StaticPropType; // If the binding is specialized to a type, the if and switch below will be constant-folded.
if (propertyType == QMetaType::UnknownType)
- propertyType = pd.propType;
- Q_ASSERT(targetObject());
+ propertyType = pd->propType();
- if (Q_LIKELY(!isUndefined && !pd.isValueTypeVirtual())) {
+ if (Q_LIKELY(!isUndefined && !vpd.isValid())) {
switch (propertyType) {
case QMetaType::Bool:
if (result.isBoolean())
@@ -293,32 +304,34 @@ protected:
break;
default:
if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) {
- if (vtw->d()->valueType->typeId == pd.propType) {
- return vtw->write(m_target.data(), pd.coreIndex);
+ if (vtw->d()->valueType->typeId == pd->propType()) {
+ return vtw->write(m_target.data(), pd->coreIndex());
}
}
break;
}
}
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vpd, result, isUndefined, flags);
}
template <typename T>
- Q_ALWAYS_INLINE bool doStore(T value, const QQmlPropertyData &pd, QQmlPropertyData::WriteFlags flags) const
+ Q_ALWAYS_INLINE bool doStore(T value, const QQmlPropertyData *pd, QQmlPropertyData::WriteFlags flags) const
{
void *o = &value;
- return pd.writeProperty(targetObject(), o, flags);
+ return pd->writeProperty(targetObject(), o, flags);
}
};
-Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const QV4::Value &result,
+Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
+ const QQmlPropertyData &valueTypeData,
+ const QV4::Value &result,
bool isUndefined, QQmlPropertyData::WriteFlags flags)
{
QQmlEngine *engine = context()->engine;
QV8Engine *v8engine = QQmlEnginePrivate::getV8Engine(engine);
- int type = core.isValueTypeVirtual() ? core.valueTypePropType : core.propType;
+ int type = valueTypeData.isValid() ? valueTypeData.propType() : core.propType();
QQmlJavaScriptExpression::DeleteWatcher watcher(this);
@@ -330,7 +343,7 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const Q
value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
} else if (result.isNull() && core.isQObject()) {
value = QVariant::fromValue((QObject *)0);
- } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
+ } else if (core.propType() == qMetaTypeId<QList<QUrl> >()) {
value = QQmlPropertyPrivate::resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context());
} else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
value = QV8Engine::getV4(v8engine)->toVariant(result, type);
@@ -349,28 +362,27 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const Q
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(m_target.data());
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(core.coreIndex, result);
+ vmemo->setVMEProperty(core.coreIndex(), result);
} else if (isUndefined && core.isResettable()) {
void *args[] = { 0 };
- QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex, args);
+ QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex(), args);
} else if (isUndefined && type == qMetaTypeId<QVariant>()) {
- QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant(), context(), flags);
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant(), context(), flags);
} else if (type == qMetaTypeId<QJSValue>()) {
const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
if (f && f->isBinding()) {
delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
return false;
}
- QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, QVariant::fromValue(
+ QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant::fromValue(
QJSValue(QV8Engine::getV4(v8engine), result.asReturnedValue())),
context(), flags);
} else if (isUndefined) {
- QString errorStr = QLatin1String("Unable to assign [undefined] to ");
- if (!QMetaType::typeName(type))
- errorStr += QLatin1String("[unknown property type]");
- else
- errorStr += QLatin1String(QMetaType::typeName(type));
- delayedError()->setErrorDescription(errorStr);
+ const QLatin1String typeName(QMetaType::typeName(type)
+ ? QMetaType::typeName(type)
+ : "[unknown property type]");
+ delayedError()->setErrorDescription(QLatin1String("Unable to assign [undefined] to ")
+ + typeName);
return false;
} else if (const QV4::FunctionObject *f = result.as<QV4::FunctionObject>()) {
if (f->isBinding())
@@ -378,7 +390,7 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const Q
else
delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
return false;
- } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, value, context(), flags)) {
+ } else if (!QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, value, context(), flags)) {
if (watcher.wasDeleted())
return true;
@@ -386,7 +398,8 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const Q
const char *valueType = 0;
const char *propertyType = 0;
- if (value.userType() == QMetaType::QObjectStar) {
+ const int userType = value.userType();
+ if (userType == QMetaType::QObjectStar) {
if (QObject *o = *(QObject *const *)value.constData()) {
valueType = o->metaObject()->className();
@@ -394,11 +407,11 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core, const Q
if (!propertyMetaObject.isNull())
propertyType = propertyMetaObject.className();
}
- } else if (value.userType() != QVariant::Invalid) {
- if (value.userType() == QMetaType::VoidStar)
+ } else if (userType != QVariant::Invalid) {
+ if (userType == QMetaType::Nullptr || userType == QMetaType::VoidStar)
valueType = "null";
else
- valueType = QMetaType::typeName(value.userType());
+ valueType = QMetaType::typeName(userType);
}
if (!valueType)
@@ -444,8 +457,7 @@ QString QQmlBinding::expressionIdentifier()
QString url = function->sourceFile();
quint16 lineNumber = function->compiledFunction->location.line;
quint16 columnNumber = function->compiledFunction->location.column;
-
- return url + QLatin1Char(':') + QString::number(lineNumber) + QLatin1Char(':') + QString::number(columnNumber);
+ return url + QString::asprintf(":%u:%u", uint(lineNumber), uint(columnNumber));
}
void QQmlBinding::expressionChanged()
@@ -482,10 +494,11 @@ QString QQmlBinding::expression() const
void QQmlBinding::setTarget(const QQmlProperty &prop)
{
- setTarget(prop.object(), QQmlPropertyPrivate::get(prop)->core);
+ auto pd = QQmlPropertyPrivate::get(prop);
+ setTarget(prop.object(), pd->core, &pd->valueTypeData);
}
-void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
+void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, const QQmlPropertyData *valueType)
{
m_target = object;
@@ -494,11 +507,9 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
return;
}
- QQmlPropertyData pd = core;
-
- while (pd.isAlias()) {
- int coreIndex = pd.coreIndex;
- int valueTypeIndex = pd.getValueTypeCoreIndex();
+ int coreIndex = core.coreIndex();
+ int valueTypeIndex = valueType ? valueType->coreIndex() : -1;
+ for (bool isAlias = core.isAlias(); isAlias; ) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
int aValueTypeIndex;
@@ -520,18 +531,10 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
Q_ASSERT(propertyData);
m_target = object;
- pd = *propertyData;
- if (valueTypeIndex != -1) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(pd.propType);
- Q_ASSERT(valueTypeMetaObject);
- QMetaProperty vtProp = valueTypeMetaObject->property(valueTypeIndex);
- pd.setAsValueTypeVirtual();
- pd.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- pd.valueTypePropType = vtProp.userType();
- pd.valueTypeCoreIndex = valueTypeIndex;
- }
+ isAlias = propertyData->isAlias();
+ coreIndex = propertyData->coreIndex();
}
- m_targetIndex = pd.encodedIndex();
+ m_targetIndex = QQmlPropertyIndex(coreIndex, valueTypeIndex);
QQmlData *data = QQmlData::get(*m_target, true);
if (!data->propertyCache) {
@@ -540,25 +543,24 @@ void QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core)
}
}
-QQmlPropertyData QQmlBinding::getPropertyData() const
+void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const
{
+ Q_ASSERT(propertyData);
+
QQmlData *data = QQmlData::get(*m_target, false);
Q_ASSERT(data && data->propertyCache);
- QQmlPropertyData *propertyData = data->propertyCache->property(m_targetIndex.coreIndex());
- Q_ASSERT(propertyData);
+ *propertyData = data->propertyCache->property(m_targetIndex.coreIndex());
+ Q_ASSERT(*propertyData);
- QQmlPropertyData d = *propertyData;
- if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex())) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d.propType);
+ if (Q_UNLIKELY(m_targetIndex.hasValueTypeIndex() && valueTypeData)) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType((*propertyData)->propType());
Q_ASSERT(valueTypeMetaObject);
QMetaProperty vtProp = valueTypeMetaObject->property(m_targetIndex.valueTypeIndex());
- d.setAsValueTypeVirtual();
- d.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- d.valueTypePropType = vtProp.userType();
- d.valueTypeCoreIndex = m_targetIndex.valueTypeIndex();
+ valueTypeData->setFlags(QQmlPropertyData::flagsForProperty(vtProp));
+ valueTypeData->setPropType(vtProp.userType());
+ valueTypeData->setCoreIndex(m_targetIndex.valueTypeIndex());
}
- return d;
}
class QObjectPointerBinding: public QQmlNonbindingBinding
@@ -574,20 +576,22 @@ protected:
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
QQmlPropertyData::WriteFlags flags) Q_DECL_OVERRIDE Q_DECL_FINAL
{
- QQmlPropertyData pd = getPropertyData();
- if (Q_UNLIKELY(isUndefined || pd.isValueTypeVirtual()))
- return slowWrite(pd, result, isUndefined, flags);
+ QQmlPropertyData *pd;
+ QQmlPropertyData vtpd;
+ getPropertyData(&pd, &vtpd);
+ if (Q_UNLIKELY(isUndefined || vtpd.isValid()))
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
// Check if the result is a QObject:
QObject *resultObject = nullptr;
QQmlMetaObject resultMo;
if (result.isNull()) {
// Special case: we can always write a nullptr. Don't bother checking anything else.
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
} else if (auto wrapper = result.as<QV4::QObjectWrapper>()) {
resultObject = wrapper->object();
if (!resultObject)
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
if (QQmlData *ddata = QQmlData::get(resultObject, false))
resultMo = ddata->propertyCache;
if (resultMo.isNull()) {
@@ -598,22 +602,22 @@ protected:
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context());
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType());
if (resultMo.isNull())
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
resultObject = *static_cast<QObject *const *>(value.constData());
} else {
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
}
// Compare & set:
if (QQmlMetaObject::canConvert(resultMo, targetMetaObject)) {
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
} else if (!resultObject && QQmlMetaObject::canConvert(targetMetaObject, resultMo)) {
// In the case of a null QObject, we assign the null if there is
// any change that the null variant type could be up or down cast to
// the property type.
- return pd.writeProperty(targetObject(), &resultObject, flags);
+ return pd->writeProperty(targetObject(), &resultObject, flags);
} else {
- return slowWrite(pd, result, isUndefined, flags);
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
}
}
};
@@ -621,9 +625,9 @@ protected:
QQmlBinding *QQmlBinding::newBinding(QQmlEnginePrivate *engine, const QQmlPropertyData *property)
{
if (property && property->isQObject())
- return new QObjectPointerBinding(engine, property->propType);
+ return new QObjectPointerBinding(engine, property->propType());
- const int type = (property && property->isFullyResolved()) ? property->propType : QMetaType::UnknownType;
+ const int type = (property && property->isFullyResolved()) ? property->propType() : QMetaType::UnknownType;
if (type == qMetaTypeId<QQmlBinding *>()) {
return new QQmlBindingBinding;
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 94fc0ccfc0..1801c3040c 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -81,7 +81,7 @@ public:
~QQmlBinding();
void setTarget(const QQmlProperty &);
- void setTarget(QObject *, const QQmlPropertyData &);
+ void setTarget(QObject *, const QQmlPropertyData &, const QQmlPropertyData *valueType);
void setNotifyOnValueChanged(bool);
@@ -106,11 +106,11 @@ protected:
QQmlPropertyData::WriteFlags flags, QV4::Scope &scope,
const QV4::ScopedFunctionObject &f) = 0;
- QQmlPropertyData getPropertyData() const;
+ void getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyData *valueTypeData) const;
int getPropertyType() const;
- bool slowWrite(const QQmlPropertyData &core, const QV4::Value &result, bool isUndefined,
- QQmlPropertyData::WriteFlags flags);
+ bool slowWrite(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
+ const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags);
private:
inline bool updatingFlag() const;
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index ef837183db..4e63790290 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -80,8 +80,8 @@ 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 += QLatin1String("(function ") + handlerName + QLatin1Char('(');
+ function += QString(qMax(column, (quint16)2) - 2, QChar(QChar::Space))
+ + QLatin1String("(function ") + handlerName + QLatin1Char('(');
if (parameterString.isEmpty()) {
QString error;
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 9c7b4fe1c0..5a440bdaf4 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -61,6 +61,7 @@
#include <private/qv4objectiterator_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <QDir>
#include <QStack>
#include <QStringList>
#include <QThreadStorage>
@@ -549,7 +550,8 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, const QString &fileName,
: QQmlComponent(engine, parent)
{
Q_D(QQmlComponent);
- d->loadUrl(d->engine->baseUrl().resolved(QUrl::fromLocalFile(fileName)), mode);
+ const QUrl url = QDir::isAbsolutePath(fileName) ? QUrl::fromLocalFile(fileName) : d->engine->baseUrl().resolved(QUrl(fileName));
+ d->loadUrl(url, mode);
}
/*!
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 6621f48e20..018841b9b1 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -383,7 +383,7 @@ QVariant QQmlContext::contextProperty(const QString &name) const
QQmlPropertyData *property =
QQmlPropertyCache::property(data->engine, obj, name, data, local);
- if (property) value = obj->metaObject()->property(property->coreIndex).read(obj);
+ if (property) value = obj->metaObject()->property(property->coreIndex()).read(obj);
}
if (!value.isValid() && parentContext())
value = parentContext()->contextProperty(name);
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index d9a69a9ca3..dce75c51aa 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -129,14 +129,16 @@ public:
quint32 parentFrozen:1;
quint32 dummy:21;
- // When bindingBitsSize < 32, we store the binding bit flags inside
- // bindingBitsValue. When we need more than 32 bits, we allocated
+ // When bindingBitsSize < sizeof(ptr), we store the binding bit flags inside
+ // bindingBitsValue. When we need more than sizeof(ptr) bits, we allocated
// sufficient space and use bindingBits to point to it.
int bindingBitsSize;
+ typedef quintptr BindingBitsType;
union {
- quint32 *bindingBits;
- quint32 bindingBitsValue;
+ BindingBitsType *bindingBits;
+ BindingBitsType bindingBitsValue;
};
+ enum { MaxInlineBits = sizeof(BindingBitsType) * 8 };
struct NotifyList {
quint64 connectionMask;
@@ -236,6 +238,17 @@ private:
mutable QQmlDataExtended *extendedData;
void flushPendingBindingImpl(QQmlPropertyIndex index);
+
+ Q_ALWAYS_INLINE bool hasBitSet(int bit) const
+ {
+ if (bindingBitsSize <= bit)
+ return false;
+
+ if (bindingBitsSize == MaxInlineBits)
+ return bindingBitsValue & (BindingBitsType(1) << bit);
+ else
+ return bindingBits[bit / MaxInlineBits] & (BindingBitsType(1) << (bit % MaxInlineBits));
+ }
};
bool QQmlData::wasDeleted(QObject *object)
@@ -281,20 +294,18 @@ inline bool QQmlData::signalHasEndpoint(int index) const
bool QQmlData::hasBindingBit(int coreIndex) const
{
- int bit = coreIndex * 2;
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
- return bindingBitsSize > bit &&
- ((bindingBitsSize == 32) ? (bindingBitsValue & (1 << bit)) :
- (bindingBits[bit / 32] & (1 << (bit % 32))));
+ return hasBitSet(coreIndex * 2);
}
-bool QQmlData::hasPendingBindingBit(int index) const
+bool QQmlData::hasPendingBindingBit(int coreIndex) const
{
- int bit = index * 2 + 1;
+ Q_ASSERT(coreIndex >= 0);
+ Q_ASSERT(coreIndex <= 0xffff);
- return bindingBitsSize > bit &&
- ((bindingBitsSize == 32) ? (bindingBitsValue & (1 << bit)) :
- (bindingBits[bit / 32] & (1 << (bit % 32))));
+ return hasBitSet(coreIndex * 2 + 1);
}
void QQmlData::flushPendingBinding(QObject *o, QQmlPropertyIndex propertyIndex)
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 4acc74ee43..c939af93ef 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -106,6 +106,9 @@ Q_DECLARE_METATYPE(QQmlProperty)
QT_BEGIN_NAMESPACE
+typedef QQmlData::BindingBitsType BindingBitsType;
+enum { MaxInlineBits = QQmlData::MaxInlineBits };
+
void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
{
QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
@@ -679,7 +682,8 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
QQmlData::QQmlData()
: ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
- hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0),
+ hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
+ bindingBitsSize(MaxInlineBits), bindingBitsValue(0), notifyList(0), context(0), outerContext(0),
bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
lineNumber(0), columnNumber(0), jsEngineId(0), compilationUnit(0), deferredData(0),
propertyCache(0), guards(0), extendedData(0)
@@ -980,8 +984,19 @@ QQmlEngine::~QQmlEngine()
/*! \fn void QQmlEngine::quit()
This signal is emitted when the QML loaded by the engine would like to quit.
+
+ \sa exit()
+ */
+
+/*! \fn void QQmlEngine::exit(int retCode)
+ This signal is emitted when the QML loaded by the engine would like to exit
+ from the event loop with the specified return code.
+
+ \since 5.8
+ \sa quit()
*/
+
/*! \fn void QQmlEngine::warnings(const QList<QQmlError> &warnings)
This signal is emitted when \a warnings messages are generated by QML.
*/
@@ -1692,7 +1707,7 @@ void QQmlData::destroyed(QObject *object)
signalHandler = next;
}
- if (bindingBitsSize > 32)
+ if (bindingBitsSize > MaxInlineBits)
free(bindingBits);
if (propertyCache)
@@ -1742,31 +1757,27 @@ void QQmlData::parentChanged(QObject *object, QObject *parent)
static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
{
- if (data->bindingBitsSize == 0 && bit < 32) {
- data->bindingBitsSize = 32;
- }
-
- if (data->bindingBitsSize <= bit) {
+ if (Q_UNLIKELY(data->bindingBitsSize <= bit)) {
int props = QQmlMetaObject(obj).propertyCount();
Q_ASSERT(bit < 2 * props);
- int arraySize = (2 * props + 31) / 32;
+ int arraySize = (2 * props + MaxInlineBits - 1) / MaxInlineBits;
Q_ASSERT(arraySize > 1);
// special handling for 32 here is to make sure we wipe the first byte
// when going from bindingBitsValue to bindingBits, and preserve the old
// set bits so we can restore them after the allocation
- int oldArraySize = data->bindingBitsSize > 32 ? data->bindingBitsSize / 32 : 0;
- quint32 oldValue = data->bindingBitsSize == 32 ? data->bindingBitsValue : 0;
+ int oldArraySize = data->bindingBitsSize > MaxInlineBits ? data->bindingBitsSize / MaxInlineBits : 0;
+ quintptr oldValue = data->bindingBitsSize == MaxInlineBits ? data->bindingBitsValue : 0;
- data->bindingBits = (quint32 *)realloc((data->bindingBitsSize == 32) ? 0 : data->bindingBits,
- arraySize * sizeof(quint32));
+ data->bindingBits = static_cast<BindingBitsType *>(realloc((data->bindingBitsSize == MaxInlineBits) ? 0 : data->bindingBits,
+ arraySize * sizeof(BindingBitsType)));
memset(data->bindingBits + oldArraySize,
0x00,
- sizeof(quint32) * (arraySize - oldArraySize));
+ sizeof(BindingBitsType) * (arraySize - oldArraySize));
- data->bindingBitsSize = arraySize * 32;
+ data->bindingBitsSize = arraySize * MaxInlineBits;
// reinstate bindingBitsValue after we dropped it
if (oldValue) {
@@ -1774,19 +1785,19 @@ static void QQmlData_setBit(QQmlData *data, QObject *obj, int bit)
}
}
- if (data->bindingBitsSize == 32)
- data->bindingBitsValue |= (1 << (bit % 32));
+ if (data->bindingBitsSize == MaxInlineBits)
+ data->bindingBitsValue |= BindingBitsType(1) << bit;
else
- data->bindingBits[bit / 32] |= (1 << (bit % 32));
+ data->bindingBits[bit / MaxInlineBits] |= (BindingBitsType(1) << (bit % MaxInlineBits));
}
static void QQmlData_clearBit(QQmlData *data, int bit)
{
if (data->bindingBitsSize > bit) {
- if (data->bindingBitsSize == 32)
- data->bindingBitsValue &= ~(1 << (bit % 32));
+ if (data->bindingBitsSize == MaxInlineBits)
+ data->bindingBitsValue &= ~(BindingBitsType(1) << (bit % MaxInlineBits));
else
- data->bindingBits[bit / 32] &= ~(1 << (bit % 32));
+ data->bindingBits[bit / MaxInlineBits] &= ~(BindingBitsType(1) << (bit % MaxInlineBits));
}
}
@@ -1839,6 +1850,14 @@ void QQmlEnginePrivate::sendQuit()
}
}
+void QQmlEnginePrivate::sendExit(int retCode)
+{
+ Q_Q(QQmlEngine);
+ if (q->receivers(SIGNAL(exit(int))) == 0)
+ qWarning("Signal QQmlEngine::exit() emitted, but no receivers connected to handle it.");
+ emit q->exit(retCode);
+}
+
static void dumpwarning(const QQmlError &error)
{
QMessageLogger(error.url().toString().toLatin1().constData(),
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 132af78f80..bbb9c36ce9 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -155,6 +155,7 @@ protected:
Q_SIGNALS:
void quit();
+ void exit(int retCode);
void warnings(const QList<QQmlError> &warnings);
private:
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 949060f395..713b03dbf3 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -227,6 +227,7 @@ public:
bool isScriptLoaded(const QUrl &url) const;
void sendQuit();
+ void sendExit(int retCode = 0);
void warning(const QQmlError &);
void warning(const QList<QQmlError> &);
void warning(QQmlDelayedError *);
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index 74ceeabeb4..b309550ca8 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -249,9 +249,9 @@ QString QQmlError::toString() const
int l(line());
if (u.isEmpty() || (u.isLocalFile() && u.path().isEmpty()))
- rv = QLatin1String("<Unknown File>");
+ rv += QLatin1String("<Unknown File>");
else
- rv = u.toString();
+ rv += u.toString();
if (l != -1) {
rv += QLatin1Char(':') + QString::number(l);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 9393f74a8d..63e8da3aa8 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -399,9 +399,7 @@ bool excludeBaseUrl(const QString &importUrl, const QString &fileName, const QSt
if (baseUrl.startsWith(importUrl))
{
- QString typeUrl(importUrl);
- typeUrl.append(fileName);
- if (typeUrl == baseUrl)
+ if (fileName == baseUrl.midRef(importUrl.size()))
return false;
}
@@ -540,10 +538,10 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
{
if (version == QQmlImports::FullyVersioned) {
// extension with fully encoded version number (eg. MyModule.3.2)
- return QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin);
+ return QString::asprintf(".%d.%d", vmaj, vmin);
} else if (version == QQmlImports::PartiallyVersioned) {
// extension with encoded version major (eg. MyModule.3)
- return QString(QLatin1String(".%1")).arg(vmaj);
+ return QString::asprintf(".%d", vmaj);
} // else extension without version number (eg. MyModule)
return QString();
}
@@ -1395,15 +1393,9 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
// The uri for this import. For library imports this is the same as uri
// specified by the user, but it may be different in the case of file imports.
QString importUri = uri;
-
- QString qmldirPath = importUri;
- if (importUri.endsWith(Slash))
- qmldirPath += String_qmldir;
- else
- qmldirPath += Slash_qmldir;
-
- QString qmldirUrl = resolveLocalUrl(base, qmldirPath);
-
+ QString qmldirUrl = resolveLocalUrl(base, importUri + (importUri.endsWith(Slash)
+ ? String_qmldir
+ : Slash_qmldir));
QString qmldirIdentifier;
if (QQmlFile::isLocalFile(qmldirUrl)) {
@@ -1701,10 +1693,9 @@ QString QQmlImportDatabase::resolvePlugin(QQmlTypeLoader *typeLoader,
if (!resolvedPath.endsWith(Slash))
resolvedPath += Slash;
+ resolvedPath += prefix + baseName;
foreach (const QString &suffix, suffixes) {
- QString pluginFileName = prefix + baseName + suffix;
-
- QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + pluginFileName);
+ const QString absolutePath = typeLoader->absoluteFilePath(resolvedPath + suffix);
if (!absolutePath.isEmpty())
return absolutePath;
}
@@ -1957,7 +1948,7 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
#ifndef QT_NO_LIBRARY
// Dynamic plugins are differentiated by their filepath. For static plugins we
// don't have that information so we use their address as key instead.
- QString uniquePluginID = QString().sprintf("%p", instance);
+ const QString uniquePluginID = QString::asprintf("%p", instance);
StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
QMutexLocker lock(&plugins->mutex);
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index d0b7fb4853..a719956483 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -143,16 +143,16 @@ QQmlListReference::QQmlListReference(QObject *object, const char *property, QQml
QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):0;
- int listType = p?p->listType(data->propType):QQmlMetaType::listType(data->propType);
+ int listType = p?p->listType(data->propType()):QQmlMetaType::listType(data->propType());
if (listType == -1) return;
d = new QQmlListReferencePrivate;
d->object = object;
d->elementType = p?p->rawMetaObjectForType(listType):QQmlMetaType::qmlType(listType)->baseMetaObject();
- d->propertyType = data->propType;
+ d->propertyType = data->propType();
void *args[] = { &d->property, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex, args);
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex(), args);
}
/*! \internal */
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 271b4f1b31..ce0f4b798a 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -634,7 +634,7 @@ void QQmlTypePrivate::init() const
QMetaObject *mmo = builder.toMetaObject();
mmo->d.superdata = baseMetaObject;
if (!metaObjects.isEmpty())
- metaObjects.last().metaObject->d.superdata = mmo;
+ metaObjects.constLast().metaObject->d.superdata = mmo;
QQmlProxyMetaObject::ProxyData data = { mmo, t->d->extraData.cd->extFunc, 0, 0 };
metaObjects << data;
}
@@ -656,7 +656,7 @@ void QQmlTypePrivate::init() const
if (metaObjects.isEmpty())
mo = baseMetaObject;
else
- mo = metaObjects.first().metaObject;
+ mo = metaObjects.constFirst().metaObject;
for (int ii = 0; !containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) {
if (isPropertyRevisioned(mo, ii))
@@ -851,7 +851,7 @@ const QMetaObject *QQmlType::metaObject() const
if (d->metaObjects.isEmpty())
return d->baseMetaObject;
else
- return d->metaObjects.first().metaObject;
+ return d->metaObjects.constFirst().metaObject;
}
@@ -1861,7 +1861,7 @@ QQmlType *QQmlMetaType::qmlTypeFromIndex(int idx)
if (idx < 0 || idx >= data->types.count())
return 0;
- return data->types[idx];
+ return data->types.at(idx);
}
/*!
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 1e1c238b19..f9794ec26a 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -281,7 +281,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
QQmlPropertyData::WriteFlags propertyWriteFlags = QQmlPropertyData::BypassInterceptor | QQmlPropertyData::RemoveBindingOnAliasWrite;
QV4::Scope scope(v4);
- int propertyType = property->propType;
+ int propertyType = property->propType();
if (property->isEnum()) {
if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum) {
@@ -302,7 +302,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
double n = binding->valueAsNumber();
if (double(int(n)) == n) {
if (property->isVarProperty()) {
- _vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromInt32(int(n)));
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Primitive::fromInt32(int(n)));
} else {
int i = int(n);
QVariant value(i);
@@ -310,7 +310,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
}
} else {
if (property->isVarProperty()) {
- _vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromDouble(n));
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Primitive::fromDouble(n));
} else {
QVariant value(n);
property->writeProperty(_qobject, &value, propertyWriteFlags);
@@ -318,7 +318,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
}
} else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
if (property->isVarProperty()) {
- _vmeMetaObject->setVMEProperty(property->coreIndex, QV4::Primitive::fromBoolean(binding->valueAsBoolean()));
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Primitive::fromBoolean(binding->valueAsBoolean()));
} else {
QVariant value(binding->valueAsBoolean());
property->writeProperty(_qobject, &value, propertyWriteFlags);
@@ -327,7 +327,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
QString stringValue = binding->valueAsString(qmlUnit);
if (property->isVarProperty()) {
QV4::ScopedString s(scope, v4->newString(stringValue));
- _vmeMetaObject->setVMEProperty(property->coreIndex, s);
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), s);
} else {
QVariant value = QQmlStringConverters::variantFromString(stringValue);
property->writeProperty(_qobject, &value, propertyWriteFlags);
@@ -398,7 +398,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(qmlUnit), &ok);
Q_ASSERT(ok);
struct { void *data[4]; } buffer;
- if (QQml_valueTypeProvider()->storeValueType(property->propType, &colorValue, &buffer, sizeof(buffer))) {
+ if (QQml_valueTypeProvider()->storeValueType(property->propType(), &colorValue, &buffer, sizeof(buffer))) {
property->writeProperty(_qobject, &buffer, propertyWriteFlags);
}
}
@@ -534,26 +534,26 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
break;
default: {
// generate single literal value assignment to a list property if required
- if (property->propType == qMetaTypeId<QList<qreal> >()) {
+ if (property->propType() == qMetaTypeId<QList<qreal> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
QList<qreal> value;
value.append(binding->valueAsNumber());
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<int> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<int> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number);
double n = binding->valueAsNumber();
QList<int> value;
value.append(int(n));
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<bool> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<bool> >()) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean);
QList<bool> value;
value.append(binding->valueAsBoolean());
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<QUrl> >()) {
+ } 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() : compilationUnit->url().resolved(QUrl(urlString));
@@ -561,13 +561,13 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
value.append(u);
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QList<QString> >()) {
+ } else if (property->propType() == qMetaTypeId<QList<QString> >()) {
Q_ASSERT(binding->evaluatesToString());
QList<QString> value;
value.append(binding->valueAsString(qmlUnit));
property->writeProperty(_qobject, &value, propertyWriteFlags);
break;
- } else if (property->propType == qMetaTypeId<QJSValue>()) {
+ } else if (property->propType() == qMetaTypeId<QJSValue>()) {
QJSValue value;
if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
value = QJSValue(binding->valueAsBoolean());
@@ -586,12 +586,12 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
// otherwise, try a custom type assignment
QString stringValue = binding->valueAsString(qmlUnit);
- QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType);
+ QQmlMetaType::StringConverter converter = QQmlMetaType::customStringConverter(property->propType());
Q_ASSERT(converter);
QVariant value = (*converter)(stringValue);
- QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex);
- if (value.isNull() || ((int)metaProperty.type() != property->propType && metaProperty.userType() != property->propType)) {
+ QMetaProperty metaProperty = _qobject->metaObject()->property(property->coreIndex());
+ if (value.isNull() || ((int)metaProperty.type() != property->propType() && metaProperty.userType() != property->propType())) {
recordError(binding->location, tr("Cannot assign value %1 to property %2").arg(stringValue).arg(QString::fromUtf8(metaProperty.name())));
break;
}
@@ -623,7 +623,7 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
if (_compiledObject->idNameIndex) {
const QQmlPropertyData *idProperty = propertyData.last();
Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
- if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
+ if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType() == QMetaType::QString) {
QV4::CompiledData::Binding idBinding;
idBinding.propertyNameIndex = 0; // Not used
idBinding.flags = 0;
@@ -636,10 +636,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
// ### this is best done through type-compile-time binding skip lists.
if (_valueTypeProperty) {
- QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex));
+ QQmlAbstractBinding *binding = QQmlPropertyPrivate::binding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
if (binding && !binding->isValueTypeProxy()) {
- QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex));
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(_valueTypeProperty->coreIndex()));
} else if (binding) {
QQmlValueTypeProxyBinding *proxy = static_cast<QQmlValueTypeProxyBinding *>(binding);
@@ -652,7 +652,7 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
if (property)
- bindingSkipList |= (1 << property->coreIndex);
+ bindingSkipList |= (1 << property->coreIndex());
}
proxy->removeBindings(bindingSkipList);
@@ -678,10 +678,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
const QQmlPropertyData *property = propertyData.at(i);
if (property && property->isQList()) {
- if (property->coreIndex != currentListPropertyIndex) {
+ if (property->coreIndex() != currentListPropertyIndex) {
void *argv[1] = { (void*)&_currentList };
- QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
- currentListPropertyIndex = property->coreIndex;
+ QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
+ currentListPropertyIndex = property->coreIndex();
}
} else if (_currentList.object) {
_currentList = QQmlListProperty<void>();
@@ -717,7 +717,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
}
// ### resolve this at compile time
- if (property && property->propType == qMetaTypeId<QQmlScriptString>()) {
+ if (property && property->propType() == qMetaTypeId<QQmlScriptString>()) {
QQmlScriptString ss(binding->valueAsScriptString(qmlUnit), context->asQQmlContext(), _scopeObject);
ss.d.data()->bindingId = binding->type == QV4::CompiledData::Binding::Type_Script ? binding->value.compiledScriptIndex : (quint32)QQmlBinding::Invalid;
ss.d.data()->lineNumber = binding->location.line;
@@ -730,7 +730,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlPropertyData::RemoveBindingOnAliasWrite;
int propertyWriteStatus = -1;
void *argv[] = { &ss, 0, &propertyWriteStatus, &propertyWriteFlags };
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
return true;
}
@@ -753,20 +753,20 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
const QQmlPropertyData *valueTypeProperty = 0;
QObject *bindingTarget = _bindingTarget;
- if (QQmlValueTypeFactory::isValueType(property->propType)) {
- valueType = QQmlValueTypeFactory::valueType(property->propType);
+ if (QQmlValueTypeFactory::isValueType(property->propType())) {
+ valueType = QQmlValueTypeFactory::valueType(property->propType());
if (!valueType) {
recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
return false;
}
- valueType->read(_qobject, property->coreIndex);
+ valueType->read(_qobject, property->coreIndex());
groupObject = valueType;
valueTypeProperty = property;
} else {
void *argv[1] = { &groupObject };
- QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::ReadProperty, property->coreIndex(), argv);
if (!groupObject) {
recordError(binding->location, tr("Cannot set properties on %1 as it is null").arg(stringAt(binding->propertyNameIndex)));
return false;
@@ -779,16 +779,16 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return false;
if (valueType)
- valueType->write(_qobject, property->coreIndex, QQmlPropertyData::BypassInterceptor);
+ valueType->write(_qobject, property->coreIndex(), QQmlPropertyData::BypassInterceptor);
return true;
}
}
- if (_ddata->hasBindingBit(property->coreIndex) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
+ if (_ddata->hasBindingBit(property->coreIndex()) && !(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression)
&& !(binding->flags & QV4::CompiledData::Binding::IsOnAssignment)
&& !_valueTypeProperty)
- QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(property->coreIndex));
+ QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(property->coreIndex()));
if (binding->type == QV4::CompiledData::Binding::Type_Script) {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
@@ -798,7 +798,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction, /*createProto*/ false));
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
- int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex);
+ int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex());
QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
context, _scopeObject, function);
@@ -810,16 +810,18 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
// the point property (_qobjectForBindings) and after evaluating the expression,
// the result is written to a value type virtual property, that contains the sub-index
// of the "x" property.
- QQmlPropertyData targetCorePropertyData = *property;
- if (_valueTypeProperty)
- targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
+ QQmlBinding *qmlBinding;
+ if (_valueTypeProperty) {
+ qmlBinding = QQmlBinding::create(_valueTypeProperty, function, _scopeObject, context);
+ qmlBinding->setTarget(_bindingTarget, *_valueTypeProperty, property);
+ } else {
+ qmlBinding = QQmlBinding::create(property, function, _scopeObject, context);
+ qmlBinding->setTarget(_bindingTarget, *property, nullptr);
+ }
- QQmlBinding *qmlBinding = QQmlBinding::create(&targetCorePropertyData, function, _scopeObject, context);
sharedState->allCreatedBindings.push(QQmlAbstractBinding::Ptr(qmlBinding));
- qmlBinding->setTarget(_bindingTarget, targetCorePropertyData);
-
- if (targetCorePropertyData.isAlias()) {
+ if (property->isAlias()) {
QQmlPropertyPrivate::setBinding(qmlBinding, QQmlPropertyPrivate::DontEnable);
} else {
qmlBinding->addToObject();
@@ -827,7 +829,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
if (!_valueTypeProperty) {
QQmlData *targetDeclarativeData = QQmlData::get(_bindingTarget);
Q_ASSERT(targetDeclarativeData);
- targetDeclarativeData->setPendingBindingBit(_bindingTarget, property->coreIndex);
+ targetDeclarativeData->setPendingBindingBit(_bindingTarget, property->coreIndex());
}
}
}
@@ -840,15 +842,16 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlType *type = qmlTypeForObject(createdSubObject);
Q_ASSERT(type);
- QQmlPropertyData targetCorePropertyData = *property;
- if (_valueTypeProperty)
- targetCorePropertyData = QQmlPropertyPrivate::saveValueType(*_valueTypeProperty, _qobject->metaObject(), property->coreIndex, engine);
-
int valueSourceCast = type->propertyValueSourceCast();
if (valueSourceCast != -1) {
QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
QObject *target = createdSubObject->parent();
- vs->setTarget(QQmlPropertyPrivate::restore(target, targetCorePropertyData, context));
+ QQmlProperty prop;
+ if (_valueTypeProperty)
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, property, context);
+ else
+ prop = QQmlPropertyPrivate::restore(target, *property, nullptr, context);
+ vs->setTarget(prop);
return true;
}
int valueInterceptorCast = type->propertyValueInterceptorCast();
@@ -856,9 +859,11 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
QQmlPropertyValueInterceptor *vi = reinterpret_cast<QQmlPropertyValueInterceptor *>(reinterpret_cast<char *>(createdSubObject) + valueInterceptorCast);
QObject *target = createdSubObject->parent();
- if (targetCorePropertyData.isAlias()) {
+ QQmlPropertyIndex propertyIndex;
+ if (property->isAlias()) {
+ QQmlPropertyIndex originalIndex(property->coreIndex(), _valueTypeProperty ? _valueTypeProperty->coreIndex() : -1);
QQmlPropertyIndex propIndex;
- QQmlPropertyPrivate::findAliasTarget(target, QQmlPropertyIndex(targetCorePropertyData.coreIndex), &target, &propIndex);
+ QQmlPropertyPrivate::findAliasTarget(target, originalIndex, &target, &propIndex);
QQmlData *data = QQmlData::get(target);
if (!data || !data->propertyCache) {
qWarning() << "can't resolve property alias for 'on' assignment";
@@ -866,17 +871,24 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
}
// we can't have aliasses on subproperties of value types, so:
- targetCorePropertyData = *data->propertyCache->property(propIndex.coreIndex());
+ QQmlPropertyData targetPropertyData = *data->propertyCache->property(propIndex.coreIndex());
+ auto prop = QQmlPropertyPrivate::restore(target, targetPropertyData, nullptr, context);
+ vi->setTarget(prop);
+ propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
+ } else {
+ QQmlProperty prop;
+ if (_valueTypeProperty)
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, property, context);
+ else
+ prop = QQmlPropertyPrivate::restore(target, *property, nullptr, context);
+ vi->setTarget(prop);
+ propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
}
- QQmlProperty prop =
- QQmlPropertyPrivate::restore(target, targetCorePropertyData, context);
-
- vi->setTarget(prop);
QQmlInterceptorMetaObject *mo = QQmlInterceptorMetaObject::get(target);
if (!mo)
mo = new QQmlInterceptorMetaObject(target, QQmlData::get(target)->propertyCache);
- mo->registerInterceptor(QQmlPropertyPrivate::propertyIndex(prop), vi);
+ mo->registerInterceptor(propertyIndex, vi);
return true;
}
return false;
@@ -894,7 +906,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return false;
}
- QMetaMethod signalMethod = _qobject->metaObject()->method(property->coreIndex);
+ QMetaMethod signalMethod = _qobject->metaObject()->method(property->coreIndex());
if (!QMetaObject::checkConnectArgs(signalMethod, method)) {
recordError(binding->valueLocation,
tr("Cannot connect mismatched signal/slot %1 %vs. %2")
@@ -903,7 +915,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
return false;
}
- QQmlPropertyPrivate::connect(_qobject, property->coreIndex, createdSubObject, method.methodIndex());
+ QQmlPropertyPrivate::connect(_qobject, property->coreIndex(), createdSubObject, method.methodIndex());
return true;
}
@@ -912,24 +924,24 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
int propertyWriteStatus = -1;
void *argv[] = { 0, 0, &propertyWriteStatus, &propertyWriteFlags };
- if (const char *iid = QQmlMetaType::interfaceIId(property->propType)) {
+ if (const char *iid = QQmlMetaType::interfaceIId(property->propType())) {
void *ptr = createdSubObject->qt_metacast(iid);
if (ptr) {
argv[0] = &ptr;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
} else {
recordError(binding->location, tr("Cannot assign object to interface property"));
return false;
}
- } else if (property->propType == QMetaType::QVariant) {
+ } else if (property->propType() == QMetaType::QVariant) {
if (property->isVarProperty()) {
QV4::Scope scope(v4);
QV4::ScopedValue wrappedObject(scope, QV4::QObjectWrapper::wrap(QV8Engine::getV4(engine), createdSubObject));
- _vmeMetaObject->setVMEProperty(property->coreIndex, wrappedObject);
+ _vmeMetaObject->setVMEProperty(property->coreIndex(), wrappedObject);
} else {
QVariant value = QVariant::fromValue(createdSubObject);
argv[0] = &value;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
}
} else if (property->isQList()) {
Q_ASSERT(_currentList.object);
@@ -937,7 +949,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
void *itemToAdd = createdSubObject;
const char *iid = 0;
- int listItemType = QQmlEnginePrivate::get(engine)->listType(property->propType);
+ int listItemType = QQmlEnginePrivate::get(engine)->listType(property->propType());
if (listItemType != -1)
iid = QQmlMetaType::interfaceIId(listItemType);
if (iid)
@@ -953,7 +965,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *property, con
} else {
// pointer compatibility was tested in QQmlPropertyValidator at type compile time
argv[0] = &createdSubObject;
- QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex, argv);
+ QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, property->coreIndex(), argv);
}
return true;
}
@@ -983,7 +995,7 @@ void QQmlObjectCreator::setupFunctions()
continue;
function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction);
- _vmeMetaObject->setVmeMethod(property->coreIndex, function);
+ _vmeMetaObject->setVmeMethod(property->coreIndex(), function);
}
}
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 0fd9e63bde..49f02476a2 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -278,7 +278,7 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void *
propertyRead(propId);
*reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
} else if (c == QMetaObject::WriteProperty) {
- if (propId >= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ if (propId >= d->data.count() || d->data.at(propId).first != *reinterpret_cast<QVariant *>(a[0])) {
propertyWrite(propId);
QPair<QVariant, bool> &prop = d->getDataRef(propId);
prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 33f3b96389..7b1e2ec4f6 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -291,9 +291,9 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (property->isFunction())
return; // Not an object property
- if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType)) {
+ if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType())) {
// We're now at a value type property
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType());
if (!valueTypeMetaObject) return; // Not a value type
int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
@@ -306,10 +306,9 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
object = currentObject;
core = *property;
- core.setAsValueTypeVirtual();
- core.valueTypeFlags = QQmlPropertyData::flagsForProperty(vtProp);
- core.valueTypePropType = vtProp.userType();
- core.valueTypeCoreIndex = idx;
+ valueTypeData.setFlags(QQmlPropertyData::flagsForProperty(vtProp));
+ valueTypeData.setPropType(vtProp.userType());
+ valueTypeData.setCoreIndex(idx);
return;
} else {
@@ -356,9 +355,9 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
while (d && d->isFunction())
d = ddata->propertyCache->overrideData(d);
- if (d && d->notifyIndex != -1) {
+ if (d && d->notifyIndex() != -1) {
object = currentObject;
- core = *ddata->propertyCache->signal(d->notifyIndex);
+ core = *ddata->propertyCache->signal(d->notifyIndex());
return;
}
}
@@ -395,7 +394,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
int QQmlPropertyPrivate::signalIndex() const
{
Q_ASSERT(type() == QQmlProperty::SignalProperty);
- QMetaMethod m = object->metaObject()->method(core.coreIndex);
+ QMetaMethod m = object->metaObject()->method(core.coreIndex());
return QMetaObjectPrivate::signalIndex(m);
}
@@ -471,11 +470,11 @@ const char *QQmlProperty::propertyTypeName() const
if (!d)
return 0;
if (d->isValueType()) {
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType());
Q_ASSERT(valueTypeMetaObject);
- return valueTypeMetaObject->property(d->core.valueTypeCoreIndex).typeName();
+ return valueTypeMetaObject->property(d->valueTypeData.coreIndex()).typeName();
} else if (d->object && type() & Property && d->core.isValid()) {
- return d->object->metaObject()->property(d->core.coreIndex).typeName();
+ return d->object->metaObject()->property(d->core.coreIndex()).typeName();
} else {
return 0;
}
@@ -492,11 +491,8 @@ bool QQmlProperty::operator==(const QQmlProperty &other) const
// category is intentially omitted here as it is generated
// from the other members
return d->object == other.d->object &&
- d->core.coreIndex == other.d->core.coreIndex &&
- d->core.isValueTypeVirtual() == other.d->core.isValueTypeVirtual() &&
- (!d->core.isValueTypeVirtual() ||
- (d->core.valueTypeCoreIndex == other.d->core.valueTypeCoreIndex &&
- d->core.valueTypePropType == other.d->core.valueTypePropType));
+ d->core.coreIndex() == other.d->core.coreIndex() &&
+ d->valueTypeData.coreIndex() == other.d->valueTypeData.coreIndex();
}
/*!
@@ -510,16 +506,16 @@ int QQmlProperty::propertyType() const
bool QQmlPropertyPrivate::isValueType() const
{
- return core.isValueTypeVirtual();
+ return valueTypeData.isValid();
}
int QQmlPropertyPrivate::propertyType() const
{
uint type = this->type();
if (isValueType()) {
- return core.valueTypePropType;
+ return valueTypeData.propType();
} else if (type & QQmlProperty::Property) {
- return core.propType;
+ return core.propType();
} else {
return QVariant::Invalid;
}
@@ -608,7 +604,7 @@ bool QQmlProperty::isDesignable() const
if (!d)
return false;
if (type() & Property && d->core.isValid() && d->object)
- return d->object->metaObject()->property(d->core.coreIndex).isDesignable();
+ return d->object->metaObject()->property(d->core.coreIndex()).isDesignable();
else
return false;
}
@@ -648,15 +644,11 @@ QString QQmlProperty::name() const
// ###
if (!d->object) {
} else if (d->isValueType()) {
- QString rv = d->core.name(d->object) + QLatin1Char('.');
-
- const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType());
Q_ASSERT(valueTypeMetaObject);
- const char *vtName = valueTypeMetaObject->property(d->core.valueTypeCoreIndex).name();
- rv += QString::fromUtf8(vtName);
-
- d->nameCache = rv;
+ const char *vtName = valueTypeMetaObject->property(d->valueTypeData.coreIndex()).name();
+ d->nameCache = d->core.name(d->object) + QLatin1Char('.') + QString::fromUtf8(vtName);
} else if (type() & SignalProperty) {
QString name = QLatin1String("on") + d->core.name(d->object);
name[2] = name.at(2).toUpper();
@@ -679,7 +671,7 @@ QMetaProperty QQmlProperty::property() const
if (!d)
return QMetaProperty();
if (type() & Property && d->core.isValid() && d->object)
- return d->object->metaObject()->property(d->core.coreIndex);
+ return d->object->metaObject()->property(d->core.coreIndex());
else
return QMetaProperty();
}
@@ -693,7 +685,7 @@ QMetaMethod QQmlProperty::method() const
if (!d)
return QMetaMethod();
if (type() & SignalProperty && d->object)
- return d->object->metaObject()->method(d->core.coreIndex);
+ return d->object->metaObject()->method(d->core.coreIndex());
else
return QMetaMethod();
}
@@ -708,7 +700,8 @@ QQmlPropertyPrivate::binding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return 0;
- return binding(that.d->object, that.d->core.encodedIndex());
+ QQmlPropertyIndex thatIndex(that.d->core.coreIndex(), that.d->valueTypeData.coreIndex());
+ return binding(that.d->object, thatIndex);
}
/*!
@@ -791,7 +784,7 @@ void QQmlPropertyPrivate::removeBinding(const QQmlProperty &that)
if (!that.d || !that.isProperty() || !that.d->object)
return;
- removeBinding(that.d->object, that.d->core.encodedIndex());
+ removeBinding(that.d->object, that.d->encodedIndex());
}
QQmlAbstractBinding *
@@ -1027,16 +1020,16 @@ QVariant QQmlPropertyPrivate::readValueProperty()
{
if (isValueType()) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType);
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(core.propType());
Q_ASSERT(valueType);
- valueType->read(object, core.coreIndex);
- return valueType->metaObject()->property(core.valueTypeCoreIndex).read(valueType);
+ valueType->read(object, core.coreIndex());
+ return valueType->metaObject()->property(valueTypeData.coreIndex()).read(valueType);
} else if (core.isQList()) {
QQmlListProperty<QObject> prop;
core.readProperty(object, &prop);
- return QVariant::fromValue(QQmlListReferencePrivate::init(prop, core.propType, engine));
+ return QVariant::fromValue(QQmlListReferencePrivate::init(prop, core.propType(), engine));
} else if (core.isQObject()) {
@@ -1046,21 +1039,21 @@ QVariant QQmlPropertyPrivate::readValueProperty()
} else {
- if (!core.propType) // Unregistered type
- return object->metaObject()->property(core.coreIndex).read(object);
+ if (!core.propType()) // Unregistered type
+ return object->metaObject()->property(core.coreIndex()).read(object);
QVariant value;
int status = -1;
void *args[] = { 0, &value, &status };
- if (core.propType == QMetaType::QVariant) {
+ if (core.propType() == QMetaType::QVariant) {
args[0] = &value;
} else {
- value = QVariant(core.propType, (void*)0);
+ value = QVariant(core.propType(), (void*)0);
args[0] = value.data();
}
core.readPropertyWithArgs(object, args);
- if (core.propType != QMetaType::QVariant && args[0] != value.data())
- return QVariant((QVariant::Type)core.propType, args[0]);
+ if (core.propType() != QMetaType::QVariant && args[0] != value.data())
+ return QVariant((QVariant::Type)core.propType(), args[0]);
return value;
}
@@ -1148,38 +1141,28 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
bool QQmlPropertyPrivate::writeValueProperty(const QVariant &value, QQmlPropertyData::WriteFlags flags)
{
- return writeValueProperty(object, core, value, effectiveContext(), flags);
+ return writeValueProperty(object, core, valueTypeData, value, effectiveContext(), flags);
}
bool
QQmlPropertyPrivate::writeValueProperty(QObject *object,
const QQmlPropertyData &core,
+ const QQmlPropertyData &valueTypeData,
const QVariant &value,
QQmlContextData *context,QQmlPropertyData::WriteFlags flags)
{
// Remove any existing bindings on this property
if (!(flags & QQmlPropertyData::DontRemoveBinding) && object)
- removeBinding(object, core.encodedIndex());
+ removeBinding(object, encodedIndex(core, valueTypeData));
bool rv = false;
- if (core.isValueTypeVirtual()) {
-
- QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType);
- writeBack->read(object, core.coreIndex);
-
- QQmlPropertyData data = core;
- data.setFlags(core.valueTypeFlags);
- data.coreIndex = core.valueTypeCoreIndex;
- data.propType = core.valueTypePropType;
-
- rv = write(writeBack, data, value, context, flags);
-
- writeBack->write(object, core.coreIndex, flags);
-
+ if (valueTypeData.isValid()) {
+ QQmlValueType *writeBack = QQmlValueTypeFactory::valueType(core.propType());
+ writeBack->read(object, core.coreIndex());
+ rv = write(writeBack, valueTypeData, value, context, flags);
+ writeBack->write(object, core.coreIndex(), flags);
} else {
-
rv = write(object, core, value, context, flags);
-
}
return rv;
@@ -1190,11 +1173,11 @@ bool QQmlPropertyPrivate::write(QObject *object,
const QVariant &value, QQmlContextData *context,
QQmlPropertyData::WriteFlags flags)
{
- const int propertyType = property.propType;
+ const int propertyType = property.propType();
const int variantType = value.userType();
if (property.isEnum()) {
- QMetaProperty prop = object->metaObject()->property(property.coreIndex);
+ QMetaProperty prop = object->metaObject()->property(property.coreIndex());
QVariant v = value;
// Enum values come through the script engine as doubles
if (variantType == QVariant::Double) {
@@ -1203,7 +1186,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
if (qFuzzyIsNull(fractional))
v.convert(QVariant::Int);
}
- return writeEnumProperty(prop, property.coreIndex, object, v, flags);
+ return writeEnumProperty(prop, property.coreIndex(), object, v, flags);
}
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(context);
@@ -1291,9 +1274,9 @@ bool QQmlPropertyPrivate::write(QObject *object,
QQmlMetaObject listType;
if (enginePriv) {
- listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType));
+ listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType()));
} else {
- QQmlType *type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType));
+ QQmlType *type = QQmlMetaType::qmlType(QQmlMetaType::listType(property.propType()));
if (!type)
return false;
listType = type->baseMetaObject();
@@ -1508,7 +1491,7 @@ bool QQmlProperty::reset() const
{
if (isResettable()) {
void *args[] = { 0 };
- QMetaObject::metacall(d->object, QMetaObject::ResetProperty, d->core.coreIndex, args);
+ QMetaObject::metacall(d->object, QMetaObject::ResetProperty, d->core.coreIndex(), args);
return true;
} else {
return false;
@@ -1533,7 +1516,7 @@ bool QQmlPropertyPrivate::write(const QQmlProperty &that,
bool QQmlProperty::hasNotifySignal() const
{
if (type() & Property && d->object) {
- return d->object->metaObject()->property(d->core.coreIndex).hasNotifySignal();
+ return d->object->metaObject()->property(d->core.coreIndex()).hasNotifySignal();
}
return false;
}
@@ -1563,7 +1546,7 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, int method) const
if (!(type() & Property) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex());
if (prop.hasNotifySignal()) {
return QQmlPropertyPrivate::connect(d->object, prop.notifySignalIndex(), dest, method, Qt::DirectConnection);
} else {
@@ -1584,7 +1567,7 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, const char *slot) const
if (!(type() & Property) || !d->object)
return false;
- QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
+ QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex());
if (prop.hasNotifySignal()) {
QByteArray signal('2' + prop.notifySignal().methodSignature());
return QObject::connect(d->object, signal.constData(), dest, slot);
@@ -1598,61 +1581,28 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, const char *slot) const
*/
int QQmlProperty::index() const
{
- return d ? d->core.coreIndex : -1;
+ return d ? d->core.coreIndex() : -1;
}
QQmlPropertyIndex QQmlPropertyPrivate::propertyIndex(const QQmlProperty &that)
{
- return that.d ? that.d->core.encodedIndex() : QQmlPropertyIndex();
-}
-
-/*!
- Returns the "property index" for use in bindings. The top 16 bits are the value type
- offset, and 0 otherwise. The bottom 16 bits are the regular property index.
-*/
-int QQmlPropertyPrivate::bindingIndex(const QQmlProperty &that)
-{
- if (!that.d)
- return -1;
- return bindingIndex(that.d->core);
-}
-
-int QQmlPropertyPrivate::bindingIndex(const QQmlPropertyData &that)
-{
- int rv = that.coreIndex;
- if (rv != -1 && that.isValueTypeVirtual())
- rv = rv | (that.valueTypeCoreIndex << 16);
- return rv;
-}
-
-QQmlPropertyData
-QQmlPropertyPrivate::saveValueType(const QQmlPropertyData &base,
- const QMetaObject *subObject, int subIndex,
- QQmlEngine *)
-{
- QMetaProperty subProp = subObject->property(subIndex);
-
- QQmlPropertyData core = base;
- core.setAsValueTypeVirtual();
- core.valueTypeFlags = QQmlPropertyData::flagsForProperty(subProp);
- core.valueTypeCoreIndex = subIndex;
- core.valueTypePropType = subProp.userType();
-
- return core;
+ return that.d ? that.d->encodedIndex() : QQmlPropertyIndex();
}
QQmlProperty
QQmlPropertyPrivate::restore(QObject *object, const QQmlPropertyData &data,
- QQmlContextData *ctxt)
+ const QQmlPropertyData *valueTypeData, QQmlContextData *ctxt)
{
QQmlProperty prop;
prop.d = new QQmlPropertyPrivate;
prop.d->object = object;
prop.d->context = ctxt;
- prop.d->engine = ctxt?ctxt->engine:0;
+ prop.d->engine = ctxt ? ctxt->engine : nullptr;
prop.d->core = data;
+ if (valueTypeData)
+ prop.d->valueTypeData = *valueTypeData;
return prop;
}
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index f23426f45c..2565ec0ce6 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -73,12 +73,18 @@ public:
QPointer<QObject> object;
QQmlPropertyData core;
+ QQmlPropertyData valueTypeData;
bool isNameCached:1;
QString nameCache;
QQmlPropertyPrivate();
+ QQmlPropertyIndex encodedIndex() const
+ { return encodedIndex(core, valueTypeData); }
+ static QQmlPropertyIndex encodedIndex(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData)
+ { return QQmlPropertyIndex(core.coreIndex(), valueTypeData.coreIndex()); }
+
inline QQmlContextData *effectiveContext() const;
void initProperty(QObject *obj, const QString &name);
@@ -96,7 +102,7 @@ public:
static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object,
const QVariant &value, int flags);
static bool writeValueProperty(QObject *,
- const QQmlPropertyData &,
+ const QQmlPropertyData &, const QQmlPropertyData &valueTypeData,
const QVariant &, QQmlContextData *,
QQmlPropertyData::WriteFlags flags = 0);
static bool write(QObject *, const QQmlPropertyData &, const QVariant &,
@@ -116,12 +122,8 @@ public:
static void removeBinding(QQmlAbstractBinding *b);
static QQmlAbstractBinding *binding(QObject *, QQmlPropertyIndex index);
- static QQmlPropertyData saveValueType(const QQmlPropertyData &,
- const QMetaObject *, int,
- QQmlEngine *);
- static QQmlProperty restore(QObject *,
- const QQmlPropertyData &,
- QQmlContextData *);
+ static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *,
+ QQmlContextData *);
int signalIndex() const;
@@ -139,8 +141,6 @@ public:
QQmlBoundSignalExpression *);
static bool write(const QQmlProperty &that, const QVariant &, QQmlPropertyData::WriteFlags);
static QQmlPropertyIndex propertyIndex(const QQmlProperty &that);
- static int bindingIndex(const QQmlProperty &that);
- static int bindingIndex(const QQmlPropertyData &that);
static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &);
static bool connect(const QObject *sender, int signal_index,
const QObject *receiver, int method_index,
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 9ac137a315..af9b8cc045 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -145,102 +145,102 @@ QQmlPropertyData::flagsForProperty(const QMetaProperty &p, QQmlEngine *engine)
void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
{
- coreIndex = p.propertyIndex();
- notifyIndex = QMetaObjectPrivate::signalIndex(p.notifySignal());
+ setCoreIndex(p.propertyIndex());
+ setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
Q_ASSERT(p.revision() <= Q_INT16_MAX);
- revision = p.revision();
+ setRevision(p.revision());
- flags = fastFlagsForProperty(p);
+ _flags = fastFlagsForProperty(p);
int type = static_cast<int>(p.type());
if (type == QMetaType::QObjectStar) {
- propType = type;
- flags.type = Flags::QObjectDerivedType;
+ setPropType(type);
+ _flags.type = Flags::QObjectDerivedType;
} else if (type == QMetaType::QVariant) {
- propType = type;
- flags.type = Flags::QVariantType;
+ setPropType(type);
+ _flags.type = Flags::QVariantType;
} else if (type == QVariant::UserType || type == -1) {
- propTypeName = p.typeName();
- flags.notFullyResolved = true;
+ _flags.notFullyResolved = true;
+ setPropTypeName(p.typeName());
} else {
- propType = type;
+ setPropType(type);
}
}
void QQmlPropertyData::load(const QMetaProperty &p, QQmlEngine *engine)
{
- propType = p.userType();
- coreIndex = p.propertyIndex();
- notifyIndex = QMetaObjectPrivate::signalIndex(p.notifySignal());
- flags = fastFlagsForProperty(p);
- flagsForPropertyType(propType, engine, flags);
+ setPropType(p.userType());
+ setCoreIndex(p.propertyIndex());
+ setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
+ _flags = fastFlagsForProperty(p);
+ flagsForPropertyType(propType(), engine, _flags);
Q_ASSERT(p.revision() <= Q_INT16_MAX);
- revision = p.revision();
+ setRevision(p.revision());
}
void QQmlPropertyData::load(const QMetaMethod &m)
{
- coreIndex = m.methodIndex();
- arguments = 0;
+ setCoreIndex(m.methodIndex());
+ setArguments(nullptr);
- propType = m.returnType();
+ setPropType(m.returnType());
- flags.type = Flags::FunctionType;
+ _flags.type = Flags::FunctionType;
if (m.methodType() == QMetaMethod::Signal)
- flags.isSignal = true;
+ _flags.isSignal = true;
else if (m.methodType() == QMetaMethod::Constructor) {
- flags.isConstructor = true;
- propType = QMetaType::QObjectStar;
+ _flags.isConstructor = true;
+ setPropType(QMetaType::QObjectStar);
}
if (m.parameterCount()) {
- flags.hasArguments = true;
+ _flags.hasArguments = true;
if ((m.parameterCount() == 1) && (m.parameterTypes().first() == "QQmlV4Function*")) {
- flags.isV4Function = true;
+ _flags.isV4Function = true;
}
}
if (m.attributes() & QMetaMethod::Cloned)
- flags.isCloned = true;
+ _flags.isCloned = true;
Q_ASSERT(m.revision() <= Q_INT16_MAX);
- revision = m.revision();
+ setRevision(m.revision());
}
void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
{
- coreIndex = m.methodIndex();
- propType = QMetaType::Void;
- arguments = 0;
- flags.type = Flags::FunctionType;
+ setCoreIndex(m.methodIndex());
+ setPropType(QMetaType::Void);
+ setArguments(nullptr);
+ _flags.type = Flags::FunctionType;
if (m.methodType() == QMetaMethod::Signal)
- flags.isSignal = true;
+ _flags.isSignal = true;
else if (m.methodType() == QMetaMethod::Constructor) {
- flags.isConstructor = true;
- propType = QMetaType::QObjectStar;
+ _flags.isConstructor = true;
+ setPropType(QMetaType::QObjectStar);
}
const char *returnType = m.typeName();
if (!returnType)
returnType = "\0";
if ((*returnType != 'v') || (qstrcmp(returnType+1, "oid") != 0)) {
- propTypeName = returnType;
- flags.notFullyResolved = true;
+ setPropTypeName(returnType);
+ _flags.notFullyResolved = true;
}
const int paramCount = m.parameterCount();
if (paramCount) {
- flags.hasArguments = true;
+ _flags.hasArguments = true;
if ((paramCount == 1) && (m.parameterTypes().first() == "QQmlV4Function*")) {
- flags.isV4Function = true;
+ _flags.isV4Function = true;
}
}
if (m.attributes() & QMetaMethod::Cloned)
- flags.isCloned = true;
+ _flags.isCloned = true;
Q_ASSERT(m.revision() <= Q_INT16_MAX);
- revision = m.revision();
+ setRevision(m.revision());
}
/*!
@@ -343,10 +343,10 @@ void QQmlPropertyCache::appendProperty(const QString &name, QQmlPropertyData::Fl
int coreIndex, int propType, int notifyIndex)
{
QQmlPropertyData data;
- data.propType = propType;
- data.coreIndex = coreIndex;
- data.notifyIndex = notifyIndex;
- data.flags = flags;
+ data.setPropType(propType);
+ data.setCoreIndex(coreIndex);
+ data.setNotifyIndex(notifyIndex);
+ data._flags = flags;
QQmlPropertyData *old = findNamedProperty(name);
if (old)
@@ -363,20 +363,20 @@ void QQmlPropertyCache::appendSignal(const QString &name, QQmlPropertyData::Flag
const QList<QByteArray> &names)
{
QQmlPropertyData data;
- data.propType = QVariant::Invalid;
- data.coreIndex = coreIndex;
- data.flags = flags;
- data.arguments = 0;
+ data.setPropType(QVariant::Invalid);
+ data.setCoreIndex(coreIndex);
+ data._flags = flags;
+ data.setArguments(nullptr);
QQmlPropertyData handler = data;
- handler.flags.isSignalHandler = true;
+ handler._flags.isSignalHandler = true;
if (types) {
int argumentCount = *types;
QQmlPropertyCacheMethodArguments *args = createArgumentsObject(argumentCount, names);
::memcpy(args->arguments, types, (argumentCount + 1) * sizeof(int));
args->argumentsValid = true;
- data.arguments = args;
+ data.setArguments(args);
}
QQmlPropertyData *old = findNamedProperty(name);
@@ -390,7 +390,7 @@ void QQmlPropertyCache::appendSignal(const QString &name, QQmlPropertyData::Flag
signalHandlerIndexCache.append(handler);
QString handlerName = QLatin1String("on") + name;
- handlerName[2] = handlerName[2].toUpper();
+ handlerName[2] = handlerName.at(2).toUpper();
setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
setNamedProperty(handlerName, signalHandlerIndex + signalOffset(), signalHandlerIndexCache.data() + signalHandlerIndex, (old != 0));
@@ -402,16 +402,16 @@ void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flag
int argumentCount = names.count();
QQmlPropertyData data;
- data.propType = QMetaType::QVariant;
- data.coreIndex = coreIndex;
+ data.setPropType(QMetaType::QVariant);
+ data.setCoreIndex(coreIndex);
QQmlPropertyCacheMethodArguments *args = createArgumentsObject(argumentCount, names);
for (int ii = 0; ii < argumentCount; ++ii)
args->arguments[ii + 1] = QMetaType::QVariant;
args->argumentsValid = true;
- data.arguments = args;
+ data.setArguments(args);
- data.flags = flags;
+ data._flags = flags;
QQmlPropertyData *old = findNamedProperty(name);
if (old)
@@ -570,20 +570,20 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
QQmlPropertyData *sigdata = 0;
if (m.methodType() == QMetaMethod::Signal)
- data->flags = signalFlags;
+ data->_flags = signalFlags;
else
- data->flags = methodFlags;
+ data->_flags = methodFlags;
data->lazyLoad(m);
- data->flags.isDirect = !dynamicMetaObject;
+ data->_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
- data->metaObjectOffset = allowedRevisionCache.count() - 1;
+ data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
if (data->isSignal()) {
sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHandlerIndexCacheStart];
*sigdata = *data;
- sigdata->flags.isSignalHandler = true;
+ sigdata->_flags.isSignalHandler = true;
}
QQmlPropertyData *old = 0;
@@ -624,8 +624,8 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
if (old) {
// We only overload methods in the same class, exactly like C++
- if (old->isFunction() && old->coreIndex >= methodOffset)
- data->flags.isOverload = true;
+ if (old->isFunction() && old->coreIndex() >= methodOffset)
+ data->_flags.isOverload = true;
data->markAsOverrideOf(old);
}
@@ -652,13 +652,13 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
QQmlPropertyData *data = &propertyIndexCache[ii - propertyIndexCacheStart];
- data->flags = propertyFlags;
+ data->_flags = propertyFlags;
data->lazyLoad(p);
- data->flags.isDirect = !dynamicMetaObject;
+ data->_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
- data->metaObjectOffset = allowedRevisionCache.count() - 1;
+ data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
QQmlPropertyData *old = 0;
@@ -677,11 +677,11 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
QQmlAccessorProperties::Property *accessorProperty = accessorProperties.property(str);
// Fast properties may not be overrides or revisioned
- Q_ASSERT(accessorProperty == 0 || (old == 0 && data->revision == 0));
+ Q_ASSERT(accessorProperty == 0 || (old == 0 && data->revision() == 0));
if (accessorProperty) {
- data->flags.hasAccessors = true;
- data->accessors = accessorProperty->accessors;
+ data->_flags.hasAccessors = true;
+ data->setAccessors(accessorProperty->accessors);
} else if (old) {
data->markAsOverrideOf(old);
}
@@ -692,10 +692,11 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
{
Q_ASSERT(data->notFullyResolved());
- data->propType = QMetaType::type(data->propTypeName);
+ data->setPropType(QMetaType::type(data->propTypeName()));
+ data->_flags.notFullyResolved = false;
if (!data->isFunction()) {
- if (data->propType == QMetaType::UnknownType) {
+ if (data->propType() == QMetaType::UnknownType) {
const QMetaObject *mo = _metaObject;
QQmlPropertyCache *p = _parent;
while (p && (!mo || _ownMetaObject)) {
@@ -704,22 +705,20 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
}
int propOffset = mo->propertyOffset();
- if (mo && data->coreIndex < propOffset + mo->propertyCount()) {
- while (data->coreIndex < propOffset) {
+ if (mo && data->coreIndex() < propOffset + mo->propertyCount()) {
+ while (data->coreIndex() < propOffset) {
mo = mo->superClass();
propOffset = mo->propertyOffset();
}
int registerResult = -1;
void *argv[] = { &registerResult };
- mo->static_metacall(QMetaObject::RegisterPropertyMetaType, data->coreIndex - propOffset, argv);
- data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
+ mo->static_metacall(QMetaObject::RegisterPropertyMetaType, data->coreIndex() - propOffset, argv);
+ data->setPropType(registerResult == -1 ? QMetaType::UnknownType : registerResult);
}
}
- flagsForPropertyType(data->propType, engine->qmlEngine(), data->flags);
+ flagsForPropertyType(data->propType(), engine->qmlEngine(), data->_flags);
}
-
- data->flags.notFullyResolved = false;
}
void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject)
@@ -873,33 +872,25 @@ QString QQmlPropertyData::name(QObject *object) const
QString QQmlPropertyData::name(const QMetaObject *metaObject) const
{
- if (!metaObject || coreIndex == -1)
+ if (!metaObject || coreIndex() == -1)
return QString();
if (isFunction()) {
- QMetaMethod m = metaObject->method(coreIndex);
+ QMetaMethod m = metaObject->method(coreIndex());
return QString::fromUtf8(m.name().constData());
} else {
- QMetaProperty p = metaObject->property(coreIndex);
+ QMetaProperty p = metaObject->property(coreIndex());
return QString::fromUtf8(p.name());
}
}
void QQmlPropertyData::markAsOverrideOf(QQmlPropertyData *predecessor)
{
- overrideIndexIsProperty = !predecessor->isFunction();
- overrideIndex = predecessor->coreIndex;
-
- predecessor->flags.isOverridden = true;
-}
+ setOverrideIndexIsProperty(!predecessor->isFunction());
+ setOverrideIndex(predecessor->coreIndex());
-QStringList QQmlPropertyCache::propertyNames() const
-{
- QStringList keys;
- for (StringCache::ConstIterator iter = stringCache.begin(), cend = stringCache.end(); iter != cend; ++iter)
- keys.append(iter.key());
- return keys;
+ predecessor->_flags.isOverridden = true;
}
struct StaticQtMetaObject : public QObject
@@ -950,7 +941,6 @@ QString QQmlPropertyCache::signalParameterStringForJS(QV4::ExecutionEngine *engi
{
bool unnamedParameter = false;
const QSet<QString> &illegalNames = engine->v8Engine->illegalNames();
- QString error;
QString parameters;
for (int i = 0; i < parameterNameList.count(); ++i) {
@@ -1133,7 +1123,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
{
struct Sort { static bool lt(const QPair<QString, QQmlPropertyData *> &lhs,
const QPair<QString, QQmlPropertyData *> &rhs) {
- return lhs.second->coreIndex < rhs.second->coreIndex;
+ return lhs.second->coreIndex() < rhs.second->coreIndex();
} };
struct Insert { static void in(QQmlPropertyCache *This,
@@ -1144,7 +1134,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
return;
if (data->isFunction()) {
- if (data->coreIndex < This->methodIndexCacheStart)
+ if (data->coreIndex() < This->methodIndexCacheStart)
return;
QPair<QString, QQmlPropertyData *> entry = qMakePair((QString)iter.key(), data);
@@ -1154,7 +1144,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
data = This->overrideData(data);
if (data && !data->isFunction()) Insert::in(This, properties, methods, iter, data);
} else {
- if (data->coreIndex < This->propertyIndexCacheStart)
+ if (data->coreIndex() < This->propertyIndexCacheStart)
return;
QPair<QString, QQmlPropertyData *> entry = qMakePair((QString)iter.key(), data);
@@ -1185,11 +1175,11 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
QQmlPropertyData *data = properties.at(ii).second;
int notifierId = -1;
- if (data->notifyIndex != -1)
- notifierId = data->notifyIndex - signalHandlerIndexCacheStart;
+ if (data->notifyIndex() != -1)
+ notifierId = data->notifyIndex() - signalHandlerIndexCacheStart;
QMetaPropertyBuilder property = builder.addProperty(properties.at(ii).first.toUtf8(),
- QMetaType::typeName(data->propType),
+ QMetaType::typeName(data->propType()),
notifierId);
property.setReadable(true);
@@ -1201,14 +1191,16 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
QQmlPropertyData *data = methods.at(ii).second;
QByteArray returnType;
- if (data->propType != 0)
- returnType = QMetaType::typeName(data->propType);
+ if (data->propType() != 0)
+ returnType = QMetaType::typeName(data->propType());
- QByteArray signature = methods.at(ii).first.toUtf8() + '(';
+ QByteArray signature;
+ // '+=' reserves extra capacity. Follow-up appending will be probably free.
+ signature += methods.at(ii).first.toUtf8() + '(';
QQmlPropertyCacheMethodArguments *arguments = 0;
if (data->hasArguments()) {
- arguments = (QQmlPropertyCacheMethodArguments *)data->arguments;
+ arguments = (QQmlPropertyCacheMethodArguments *)data->arguments();
Q_ASSERT(arguments->argumentsValid);
for (int ii = 0; ii < arguments->arguments[0]; ++ii) {
if (ii != 0) signature.append(',');
@@ -1235,7 +1227,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
if (!_defaultPropertyName.isEmpty()) {
QQmlPropertyData *dp = property(_defaultPropertyName, 0, 0);
- if (dp && dp->coreIndex >= propertyIndexCacheStart) {
+ if (dp && dp->coreIndex() >= propertyIndexCacheStart) {
Q_ASSERT(!dp->isFunction());
builder.addClassInfo("DefaultProperty", _defaultPropertyName.toUtf8());
}
@@ -1459,7 +1451,7 @@ QList<QByteArray> QQmlPropertyCache::signalParameterNames(int index) const
{
QQmlPropertyData *signalData = signal(index);
if (signalData && signalData->hasArguments()) {
- QQmlPropertyCacheMethodArguments *args = (QQmlPropertyCacheMethodArguments *)signalData->arguments;
+ QQmlPropertyCacheMethodArguments *args = (QQmlPropertyCacheMethodArguments *)signalData->arguments();
if (args && args->names)
return *args->names;
const QMetaMethod &method = QMetaObjectPrivate::signal(firstCppMetaObject(), index);
@@ -1561,9 +1553,9 @@ QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const
int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const
{
- Q_ASSERT(!_m.isNull() && data.coreIndex >= 0);
+ Q_ASSERT(!_m.isNull() && data.coreIndex() >= 0);
- int type = data.propType;
+ int type = data.propType();
const char *propTypeName = 0;
@@ -1573,16 +1565,16 @@ int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *u
if (_m.isT1()) {
QQmlPropertyCache *c = _m.asT1();
- Q_ASSERT(data.coreIndex < c->methodIndexCacheStart + c->methodIndexCache.count());
+ Q_ASSERT(data.coreIndex() < c->methodIndexCacheStart + c->methodIndexCache.count());
- while (data.coreIndex < c->methodIndexCacheStart)
+ while (data.coreIndex() < c->methodIndexCacheStart)
c = c->_parent;
const QMetaObject *metaObject = c->createMetaObject();
Q_ASSERT(metaObject);
- m = metaObject->method(data.coreIndex);
+ m = metaObject->method(data.coreIndex());
} else {
- m = _m.asT2()->method(data.coreIndex);
+ m = _m.asT2()->method(data.coreIndex());
}
type = m.returnType();
@@ -1622,19 +1614,19 @@ int *QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage,
QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
- if (rv->arguments && static_cast<A *>(rv->arguments)->argumentsValid)
- return static_cast<A *>(rv->arguments)->arguments;
+ if (rv->arguments() && static_cast<A *>(rv->arguments())->argumentsValid)
+ return static_cast<A *>(rv->arguments())->arguments;
const QMetaObject *metaObject = c->createMetaObject();
Q_ASSERT(metaObject);
QMetaMethod m = metaObject->method(index);
int argc = m.parameterCount();
- if (!rv->arguments) {
+ if (!rv->arguments()) {
A *args = c->createArgumentsObject(argc, m.parameterNames());
- rv->arguments = args;
+ rv->setArguments(args);
}
- A *args = static_cast<A *>(rv->arguments);
+ A *args = static_cast<A *>(rv->arguments());
QList<QByteArray> argTypeNames; // Only loaded if needed
@@ -1658,7 +1650,7 @@ int *QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage,
args->arguments[ii + 1] = type;
}
args->argumentsValid = true;
- return static_cast<A *>(rv->arguments)->arguments;
+ return static_cast<A *>(rv->arguments())->arguments;
} else {
QMetaMethod m = _m.asT2()->method(index);
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index bc2e338348..6d3c4a8a7e 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -64,6 +64,8 @@
#include <private/qv4value_p.h>
#include <private/qqmlaccessors_p.h>
+#include <limits>
+
QT_BEGIN_NAMESPACE
class QCryptographicHash;
@@ -95,8 +97,7 @@ public:
QJSValueType = 6, // Property type is a QScriptValue
V4HandleType = 7, // Property type is a QQmlV4Handle
VarPropertyType = 8, // Property type is a "var" property of VMEMO
- ValueTypeVirtualType = 9, // Property is a value type "virtual" property
- QVariantType = 10 // Property is a QVariant
+ QVariantType = 9 // Property is a QVariant
};
// Can apply to all properties, except IsFunction
@@ -124,106 +125,129 @@ public:
// Internal QQmlPropertyCache flags
unsigned notFullyResolved : 1; // True if the type data is to be lazily resolved
+ unsigned overrideIndexIsProperty: 1;
- unsigned _padding : 10; // align to 32 bits
+ unsigned _padding : 9; // align to 32 bits
inline Flags();
inline bool operator==(const Flags &other) const;
inline void copyPropertyTypeFlags(Flags from);
};
- Flags getFlags() const { return flags; }
- void setFlags(Flags f) { flags = f; }
-
- bool isValid() const { return coreIndex != -1; }
-
- bool isConstant() const { return flags.isConstant; }
- bool isWritable() const { return flags.isWritable; }
- void setWritable(bool onoff) { flags.isWritable = onoff; }
- bool isResettable() const { return flags.isResettable; }
- bool isAlias() const { return flags.isAlias; }
- bool isFinal() const { return flags.isFinal; }
- bool isOverridden() const { return flags.isOverridden; }
- bool isDirect() const { return flags.isDirect; }
- bool hasAccessors() const { return flags.hasAccessors; }
- bool isFunction() const { return flags.type == Flags::FunctionType; }
- bool isQObject() const { return flags.type == Flags::QObjectDerivedType; }
- bool isEnum() const { return flags.type == Flags::EnumType; }
- bool isQList() const { return flags.type == Flags::QListType; }
- bool isQmlBinding() const { return flags.type == Flags::QmlBindingType; }
- bool isQJSValue() const { return flags.type == Flags::QJSValueType; }
- bool isV4Handle() const { return flags.type == Flags::V4HandleType; }
- bool isVarProperty() const { return flags.type == Flags::VarPropertyType; }
- bool isValueTypeVirtual() const { return flags.type == Flags::ValueTypeVirtualType; }
- void setAsValueTypeVirtual() { flags.type = Flags::ValueTypeVirtualType; }
- bool isQVariant() const { return flags.type == Flags::QVariantType; }
- bool isVMEFunction() const { return flags.isVMEFunction; }
- bool hasArguments() const { return flags.hasArguments; }
- bool isSignal() const { return flags.isSignal; }
- bool isVMESignal() const { return flags.isVMESignal; }
- bool isV4Function() const { return flags.isV4Function; }
- bool isSignalHandler() const { return flags.isSignalHandler; }
- bool isOverload() const { return flags.isOverload; }
- void setOverload(bool onoff) { flags.isOverload = onoff; }
- bool isCloned() const { return flags.isCloned; }
- bool isConstructor() const { return flags.isConstructor; }
-
- bool hasOverride() const { return flags.type != Flags::ValueTypeVirtualType &&
- !(flags.hasAccessors) &&
- overrideIndex >= 0; }
- bool hasRevision() const { return !(flags.hasAccessors) && revision != 0; }
-
- bool isFullyResolved() const { return !flags.notFullyResolved; }
-
- // Returns -1 if not a value type virtual property
- inline int getValueTypeCoreIndex() const;
-
- // Returns the "encoded" index for use with bindings. Encoding is:
- // coreIndex | ((valueTypeCoreIndex + 1) << 16)
- inline QQmlPropertyIndex encodedIndex() const;
+ Flags flags() const { return _flags; }
+ void setFlags(Flags f) { _flags = f; }
+
+ bool isValid() const { return coreIndex() != -1; }
+
+ bool isConstant() const { return _flags.isConstant; }
+ bool isWritable() const { return _flags.isWritable; }
+ void setWritable(bool onoff) { _flags.isWritable = onoff; }
+ bool isResettable() const { return _flags.isResettable; }
+ bool isAlias() const { return _flags.isAlias; }
+ bool isFinal() const { return _flags.isFinal; }
+ bool isOverridden() const { return _flags.isOverridden; }
+ bool isDirect() const { return _flags.isDirect; }
+ bool hasAccessors() const { return _flags.hasAccessors; }
+ bool isFunction() const { return _flags.type == Flags::FunctionType; }
+ bool isQObject() const { return _flags.type == Flags::QObjectDerivedType; }
+ bool isEnum() const { return _flags.type == Flags::EnumType; }
+ bool isQList() const { return _flags.type == Flags::QListType; }
+ bool isQmlBinding() const { return _flags.type == Flags::QmlBindingType; }
+ bool isQJSValue() const { return _flags.type == Flags::QJSValueType; }
+ bool isV4Handle() const { return _flags.type == Flags::V4HandleType; }
+ bool isVarProperty() const { return _flags.type == Flags::VarPropertyType; }
+ bool isQVariant() const { return _flags.type == Flags::QVariantType; }
+ bool isVMEFunction() const { return _flags.isVMEFunction; }
+ bool hasArguments() const { return _flags.hasArguments; }
+ bool isSignal() const { return _flags.isSignal; }
+ bool isVMESignal() const { return _flags.isVMESignal; }
+ bool isV4Function() const { return _flags.isV4Function; }
+ bool isSignalHandler() const { return _flags.isSignalHandler; }
+ bool isOverload() const { return _flags.isOverload; }
+ void setOverload(bool onoff) { _flags.isOverload = onoff; }
+ bool isCloned() const { return _flags.isCloned; }
+ bool isConstructor() const { return _flags.isConstructor; }
+
+ bool hasOverride() const { return !(_flags.hasAccessors) &&
+ overrideIndex() >= 0; }
+ bool hasRevision() const { return !(_flags.hasAccessors) && revision() != 0; }
+
+ bool isFullyResolved() const { return !_flags.notFullyResolved; }
+
+ int propType() const { Q_ASSERT(isFullyResolved()); return _propType; }
+ void setPropType(int pt) { _propType = pt; }
+
+ const char *propTypeName() const { Q_ASSERT(!isFullyResolved()); return _propTypeName; }
+ void setPropTypeName(const char *ptn) { _propTypeName = ptn; }
+
+ int notifyIndex() const { return _notifyIndex; }
+ void setNotifyIndex(int idx) { _notifyIndex = idx; }
+
+ QQmlPropertyCacheMethodArguments *arguments() const { return _arguments; }
+ void setArguments(QQmlPropertyCacheMethodArguments *args) { _arguments = args; }
+
+ int revision() const { return _revision; }
+ void setRevision(int rev)
+ {
+ Q_ASSERT(rev >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(rev <= std::numeric_limits<qint16>::max());
+ _revision = qint16(rev);
+ }
+
+ int metaObjectOffset() const { return _metaObjectOffset; }
+ void setMetaObjectOffset(int off)
+ {
+ Q_ASSERT(off >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(off <= std::numeric_limits<qint16>::max());
+ _metaObjectOffset = qint16(off);
+ }
+
+ bool overrideIndexIsProperty() const { return _flags.overrideIndexIsProperty; }
+ void setOverrideIndexIsProperty(bool onoff) { _flags.overrideIndexIsProperty = onoff; }
+
+ int overrideIndex() const { return _overrideIndex; }
+ void setOverrideIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ _overrideIndex = idx;
+ }
+
+ QQmlAccessors *accessors() const { return _accessors; }
+ void setAccessors(QQmlAccessors *acc) { _accessors = acc; }
+ int coreIndex() const { return _coreIndex; }
+ void setCoreIndex(int idx) { _coreIndex = idx; }
+
+private:
union {
- int propType; // When !NotFullyResolved
- const char *propTypeName; // When NotFullyResolved
+ int _propType; // When !NotFullyResolved
+ const char *_propTypeName; // When NotFullyResolved
};
union {
// The notify index is in the range returned by QObjectPrivate::signalIndex().
// This is different from QMetaMethod::methodIndex().
- int notifyIndex; // When !IsFunction
- void *arguments; // When IsFunction && HasArguments
+ int _notifyIndex; // When !IsFunction
+ QQmlPropertyCacheMethodArguments *_arguments; // When IsFunction && HasArguments
};
union {
struct { // When !HasAccessors
- qint16 revision;
- qint16 metaObjectOffset;
-
- union {
- struct { // When IsValueTypeVirtual
- quint16 valueTypePropType; // The QVariant::Type of access property on the value
- // type proxy object
- quint16 valueTypeCoreIndex; // The prop index of the access property on the value
- // type proxy object
- };
-
- struct { // When !IsValueTypeVirtual
- uint overrideIndexIsProperty : 1;
- signed int overrideIndex : 31;
- };
- };
+ qint16 _revision;
+ qint16 _metaObjectOffset;
+
+ signed int _overrideIndex; // When !IsValueTypeVirtual
};
struct { // When HasAccessors
- QQmlAccessors *accessors;
+ QQmlAccessors *_accessors;
};
};
- int coreIndex;
- Flags valueTypeFlags; // flags of the access property on the value type proxy
- // object
-private:
+ int _coreIndex;
+ Flags _flags;
+
friend class QQmlPropertyData;
friend class QQmlPropertyCache;
- Flags flags;
};
class QQmlPropertyData : public QQmlPropertyRawData
@@ -258,20 +282,20 @@ public:
inline void readPropertyWithArgs(QObject *target, void *args[]) const
{
if (hasAccessors()) {
- accessors->read(target, args[0]);
+ accessors()->read(target, args[0]);
} else {
- QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex, args);
+ QMetaObject::metacall(target, QMetaObject::ReadProperty, coreIndex(), args);
}
}
bool writeProperty(QObject *target, void *value, WriteFlags flags) const
{
- if (flags.testFlag(BypassInterceptor) && hasAccessors() && accessors->write) {
- accessors->write(target, value);
+ if (flags.testFlag(BypassInterceptor) && hasAccessors() && accessors()->write) {
+ accessors()->write(target, value);
} else {
int status = -1;
void *argv[] = { value, 0, &status, &flags };
- QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex, argv);
+ QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIndex(), argv);
}
return true;
}
@@ -297,7 +321,7 @@ private:
friend class QQmlPropertyCache;
void lazyLoad(const QMetaProperty &);
void lazyLoad(const QMetaMethod &);
- bool notFullyResolved() const { return flags.notFullyResolved; }
+ bool notFullyResolved() const { return _flags.notFullyResolved; }
};
class QQmlPropertyCacheMethodArguments;
@@ -347,7 +371,6 @@ public:
QQmlPropertyData *method(int) const;
QQmlPropertyData *signal(int index) const;
int methodIndexToSignalIndex(int) const;
- QStringList propertyNames() const;
QString defaultPropertyName() const;
QQmlPropertyData *defaultProperty() const;
@@ -559,6 +582,7 @@ QQmlPropertyRawData::Flags::Flags()
, isCloned(false)
, isConstructor(false)
, notFullyResolved(false)
+ , overrideIndexIsProperty(false)
, _padding(0)
{}
@@ -581,7 +605,8 @@ bool QQmlPropertyRawData::Flags::operator==(const QQmlPropertyRawData::Flags &ot
isOverload == other.isOverload &&
isCloned == other.isCloned &&
isConstructor == other.isConstructor &&
- notFullyResolved == other.notFullyResolved;
+ notFullyResolved == other.notFullyResolved &&
+ overrideIndexIsProperty == other.overrideIndexIsProperty;
}
void QQmlPropertyRawData::Flags::copyPropertyTypeFlags(QQmlPropertyRawData::Flags from)
@@ -600,13 +625,12 @@ void QQmlPropertyRawData::Flags::copyPropertyTypeFlags(QQmlPropertyRawData::Flag
QQmlPropertyData::QQmlPropertyData()
{
- propType = 0;
- coreIndex = -1;
- notifyIndex = -1;
- overrideIndexIsProperty = false;
- overrideIndex = -1;
- revision = 0;
- metaObjectOffset = -1;
+ setPropType(0);
+ setNotifyIndex(-1);
+ setOverrideIndex(-1);
+ setRevision(0);
+ setMetaObjectOffset(-1);
+ setCoreIndex(-1);
}
QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
@@ -616,25 +640,11 @@ QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
{
- return flags == other.flags &&
- propType == other.propType &&
- coreIndex == other.coreIndex &&
- notifyIndex == other.notifyIndex &&
- revision == other.revision &&
- (!isValueTypeVirtual() ||
- (valueTypeCoreIndex == other.valueTypeCoreIndex &&
- valueTypePropType == other.valueTypePropType));
-}
-
-int QQmlPropertyRawData::getValueTypeCoreIndex() const
-{
- return isValueTypeVirtual()?valueTypeCoreIndex:-1;
-}
-
-QQmlPropertyIndex QQmlPropertyRawData::encodedIndex() const
-{
- return isValueTypeVirtual() ? QQmlPropertyIndex(coreIndex, valueTypeCoreIndex)
- : QQmlPropertyIndex(coreIndex);
+ return _flags == other._flags &&
+ propType() == other.propType() &&
+ coreIndex() == other.coreIndex() &&
+ notifyIndex() == other.notifyIndex() &&
+ revision() == other.revision();
}
inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
@@ -697,7 +707,7 @@ inline QQmlPropertyData *QQmlPropertyCache::signal(int index) const
return _parent->signal(index);
QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&methodIndexCache.at(index - signalHandlerIndexCacheStart));
- Q_ASSERT(rv->isSignal() || rv->coreIndex == -1);
+ Q_ASSERT(rv->isSignal() || rv->coreIndex() == -1);
return ensureResolved(rv);
}
@@ -729,16 +739,16 @@ QQmlPropertyCache::overrideData(QQmlPropertyData *data) const
if (!data->hasOverride())
return 0;
- if (data->overrideIndexIsProperty)
- return property(data->overrideIndex);
+ if (data->overrideIndexIsProperty())
+ return property(data->overrideIndex());
else
- return method(data->overrideIndex);
+ return method(data->overrideIndex());
}
bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const
{
- return (data->hasAccessors() || (data->metaObjectOffset == -1 && data->revision == 0)) ||
- (allowedRevisionCache[data->metaObjectOffset] >= data->revision);
+ return (data->hasAccessors() || (data->metaObjectOffset() == -1 && data->revision() == 0)) ||
+ (allowedRevisionCache[data->metaObjectOffset()] >= data->revision());
}
int QQmlPropertyCache::propertyCount() const
diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp
index bbaab1e155..27e3c13ff8 100644
--- a/src/qml/qml/qqmlproxymetaobject.cpp
+++ b/src/qml/qml/qqmlproxymetaobject.cpp
@@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
QQmlProxyMetaObject::QQmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
: metaObjects(mList), proxies(0), parent(0), object(obj)
{
- *static_cast<QMetaObject *>(this) = *metaObjects->first().metaObject;
+ *static_cast<QMetaObject *>(this) = *metaObjects->constFirst().metaObject;
QObjectPrivate *op = QObjectPrivate::get(obj);
if (op->metaObject)
@@ -71,7 +71,7 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void
if ((c == QMetaObject::ReadProperty ||
c == QMetaObject::WriteProperty) &&
- id >= metaObjects->last().propertyOffset) {
+ id >= metaObjects->constLast().propertyOffset) {
for (int ii = 0; ii < metaObjects->count(); ++ii) {
const ProxyData &data = metaObjects->at(ii);
@@ -107,7 +107,7 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void
}
}
} else if (c == QMetaObject::InvokeMetaMethod &&
- id >= metaObjects->last().methodOffset) {
+ id >= metaObjects->constLast().methodOffset) {
QMetaMethod m = object->metaObject()->method(id);
if (m.methodType() == QMetaMethod::Signal) {
QMetaObject::activate(object, id, a);
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 40a2c596e3..f7846f333b 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -51,6 +51,7 @@
#include <private/qqmltypecompiler_p.h>
#include <private/qqmlpropertyvalidator_p.h>
#include <private/qqmlpropertycachecreator_p.h>
+#include <private/qdeferredcleanup_p.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
@@ -103,22 +104,12 @@
#endif
DEFINE_BOOL_CONFIG_OPTION(dumpErrors, QML_DUMP_ERRORS);
-DEFINE_BOOL_CONFIG_OPTION(_disableDiskCache, QML_DISABLE_DISK_CACHE);
+DEFINE_BOOL_CONFIG_OPTION(disableDiskCache, QML_DISABLE_DISK_CACHE);
DEFINE_BOOL_CONFIG_OPTION(forceDiskCache, QML_FORCE_DISK_CACHE);
Q_DECLARE_LOGGING_CATEGORY(DBG_DISK_CACHE)
Q_LOGGING_CATEGORY(DBG_DISK_CACHE, "qt.qml.diskcache")
-static bool disableDiskCache()
-{
- return _disableDiskCache()
- // ### FIXME: Fix crashes on Windows with mmap'ed code.
-#if defined(Q_OS_WIN)
- || true
-#endif
- ;
-}
-
QT_BEGIN_NAMESPACE
namespace {
@@ -130,18 +121,6 @@ namespace {
LockHolder(LockType *l) : lock(*l) { lock.lock(); }
~LockHolder() { lock.unlock(); }
};
-
- struct Defer
- {
- std::function<void()> callback;
- template <typename Callback>
- Defer(Callback &&cb)
- : callback(cb)
- {}
- ~Defer() { callback(); }
- Defer(const Defer &) = delete;
- Defer &operator=(const Defer &) = delete;
- };
}
#ifndef QT_NO_NETWORK
@@ -1473,13 +1452,10 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
bool incomplete = false;
- QUrl qmldirUrl;
- if (importQualifier.isEmpty()) {
- qmldirUrl = finalUrl().resolved(QUrl(importUri + QLatin1String("/qmldir")));
- if (!QQmlImports::isLocal(qmldirUrl)) {
- // This is a remote file; the import is currently incomplete
- incomplete = true;
- }
+ QUrl qmldirUrl = finalUrl().resolved(QUrl(importUri + QLatin1String("/qmldir")));
+ if (!QQmlImports::isLocal(qmldirUrl)) {
+ // This is a remote file; the import is currently incomplete
+ incomplete = true;
}
if (!m_importCache.addFileImport(importDatabase, importUri, importQualifier, import->majorVersion,
@@ -2002,8 +1978,7 @@ void QQmlTypeLoader::trimCache()
break;
while (!unneededTypes.isEmpty()) {
- TypeCache::Iterator iter = unneededTypes.last();
- unneededTypes.removeLast();
+ TypeCache::Iterator iter = unneededTypes.takeLast();
iter.value()->release();
m_typeCache.erase(iter);
@@ -2173,7 +2148,7 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeName
void QQmlTypeData::done()
{
- Defer cleanup([this]{
+ QDeferredCleanup cleanup([this]{
m_document.reset();
m_typeReferences.clear();
if (isError())
@@ -2546,13 +2521,13 @@ void QQmlTypeData::resolveTypes()
ScriptReference ref;
//ref.location = ...
- ref.qualifier = script.nameSpace;
if (!script.qualifier.isEmpty())
{
- ref.qualifier.prepend(script.qualifier + QLatin1Char('.'));
-
+ ref.qualifier = script.qualifier + QLatin1Char('.') + script.nameSpace;
// Add a reference to the enclosing namespace
m_namespaces.insert(script.qualifier);
+ } else {
+ ref.qualifier = script.nameSpace;
}
ref.script = blob;
@@ -2562,12 +2537,13 @@ void QQmlTypeData::resolveTypes()
// Lets handle resolved composite singleton types
foreach (const QQmlImports::CompositeSingletonReference &csRef, m_importCache.resolvedCompositeSingletons()) {
TypeReference ref;
- QString typeName = csRef.typeName;
-
+ QString typeName;
if (!csRef.prefix.isEmpty()) {
- typeName.prepend(csRef.prefix + QLatin1Char('.'));
+ typeName = csRef.prefix + QLatin1Char('.') + csRef.typeName;
// Add a reference to the enclosing namespace
m_namespaces.insert(csRef.prefix);
+ } else {
+ typeName = csRef.typeName;
}
int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1;
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 8e87ec7f63..bcefad0ee3 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -88,6 +88,7 @@ bool QQmlValueTypeFactoryImpl::isValueType(int idx)
&& idx != QVariant::StringList
&& idx != QMetaType::QObjectStar
&& idx != QMetaType::VoidStar
+ && idx != QMetaType::Nullptr
&& idx != QMetaType::QVariant
&& idx != QMetaType::QLocale) {
return true;
@@ -259,7 +260,7 @@ int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **a
QString QQmlPointFValueType::toString() const
{
- return QString(QLatin1String("QPointF(%1, %2)")).arg(v.x()).arg(v.y());
+ return QString::asprintf("QPointF(%g, %g)", v.x(), v.y());
}
qreal QQmlPointFValueType::x() const
@@ -306,7 +307,7 @@ void QQmlPointValueType::setY(int y)
QString QQmlSizeFValueType::toString() const
{
- return QString(QLatin1String("QSizeF(%1, %2)")).arg(v.width()).arg(v.height());
+ return QString::asprintf("QSizeF(%g, %g)", v.width(), v.height());
}
qreal QQmlSizeFValueType::width() const
@@ -352,7 +353,7 @@ void QQmlSizeValueType::setHeight(int h)
QString QQmlRectFValueType::toString() const
{
- return QString(QLatin1String("QRectF(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height());
+ return QString::asprintf("QRectF(%g, %g, %g, %g)", v.x(), v.y(), v.width(), v.height());
}
qreal QQmlRectFValueType::x() const
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index a1bf692f19..2566ab06b5 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -332,7 +332,8 @@ 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)) + 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) {
@@ -369,10 +370,10 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
if (result->isFunction())
// calling a Q_INVOKABLE function of a value type
- return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex);
+ return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex());
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
- if (result->propType == metatype) { \
+ if (result->propType() == metatype) { \
cpptype v; \
void *args[] = { &v, 0 }; \
metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); \
@@ -381,7 +382,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
- int index = result->coreIndex;
+ int index = result->coreIndex();
QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index);
void *gadget = r->d()->gadgetPtr;
@@ -394,10 +395,10 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
QVariant v;
void *args[] = { Q_NULLPTR, Q_NULLPTR };
- if (result->propType == QMetaType::QVariant) {
+ if (result->propType() == QMetaType::QVariant) {
args[0] = &v;
} else {
- v = QVariant(result->propType, static_cast<void *>(Q_NULLPTR));
+ v = QVariant(result->propType(), static_cast<void *>(Q_NULLPTR));
args[0] = v.data();
}
metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args);
@@ -431,8 +432,6 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0);
if (!pd)
return;
- QMetaProperty property = metaObject->property(pd->coreIndex);
- Q_ASSERT(property.isValid());
if (reference) {
QV4::ScopedFunctionObject f(scope, value);
@@ -449,25 +448,23 @@ void QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
QQmlPropertyData cacheData;
cacheData.setWritable(true);
- cacheData.setAsValueTypeVirtual();
- cacheData.propType = writeBackPropertyType;
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeCoreIndex = pd->coreIndex;
- cacheData.valueTypePropType = property.userType();
+ cacheData.setPropType(writeBackPropertyType);
+ cacheData.setCoreIndex(reference->d()->property);
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
bindingFunction->initBindingLocation();
QQmlBinding *newBinding = QQmlBinding::create(&cacheData, value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData);
+ newBinding->setTarget(reference->d()->object, cacheData, pd);
QQmlPropertyPrivate::setBinding(newBinding);
return;
} else {
- QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex));
-
+ QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex()));
}
}
+ QMetaProperty property = metaObject->property(pd->coreIndex());
+ Q_ASSERT(property.isValid());
QVariant v = v4->toVariant(value, property.userType());
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 81bc6846e6..c8281f02c0 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -164,8 +164,8 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
if (!pd)
return;
- if (pd->notifyIndex != -1)
- connect(target, pd->notifyIndex, ctxt->engine);
+ if (pd->notifyIndex() != -1)
+ connect(target, pd->notifyIndex(), ctxt->engine);
}
metaObject.setFlag();
@@ -225,7 +225,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
continue;
const int valueIndex = vi->m_propertyIndex.valueTypeIndex();
- int type = QQmlData::get(object)->propertyCache->property(id)->propType;
+ int type = QQmlData::get(object)->propertyCache->property(id)->propType();
if (type != QVariant::Invalid) {
if (valueIndex != -1) {
@@ -883,7 +883,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
return -1;
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
// Value type property
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType);
+ QQmlValueType *valueType = QQmlValueTypeFactory::valueType(pd->propType());
Q_ASSERT(valueType);
valueType->read(target, coreIndex);
@@ -932,10 +932,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
// are not rewritten correctly but this bug is deemed out-of-scope to fix for
// performance reasons; see QTBUG-24064) and thus compilation will have failed.
QQmlError e;
- e.setDescription(QString::fromLatin1("Exception occurred during compilation of "
- "function: %1")
- .arg(QString::fromUtf8(QMetaObject::method(_id)
- .methodSignature())));
+ e.setDescription(QLatin1String("Exception occurred during compilation of "
+ "function: ")
+ + QString::fromUtf8(QMetaObject::method(_id)
+ .methodSignature()));
ep->warning(e);
return -1; // The dynamic method with that id is not available.
}
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 201d634411..85e17525a5 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -502,7 +502,7 @@ ReturnedValue NodePrototype::method_get_firstChild(CallContext *ctx)
if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(scope.engine, r->d()->d->children.first());
+ return Node::create(scope.engine, r->d()->d->children.constFirst());
}
ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
@@ -515,7 +515,7 @@ ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(scope.engine, r->d()->d->children.last());
+ return Node::create(scope.engine, r->d()->d->children.constLast());
}
ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
@@ -1016,8 +1016,8 @@ public:
ReturnedValue abort(Object *thisObject, QQmlContextData *context);
void addHeader(const QString &, const QString &);
- QString header(const QString &name);
- QString headers();
+ QString header(const QString &name) const;
+ QString headers() const;
QString responseBody();
const QByteArray & rawResponseBody() const;
@@ -1144,26 +1144,27 @@ void QQmlXMLHttpRequest::addHeader(const QString &name, const QString &value)
}
}
-QString QQmlXMLHttpRequest::header(const QString &name)
+QString QQmlXMLHttpRequest::header(const QString &name) const
{
- QByteArray utfname = name.toLower().toUtf8();
-
- foreach (const HeaderPair &header, m_headersList) {
- if (header.first == utfname)
- return QString::fromUtf8(header.second);
+ if (!m_headersList.isEmpty()) {
+ const QByteArray utfname = name.toLower().toUtf8();
+ for (const HeaderPair &header : m_headersList) {
+ if (header.first == utfname)
+ return QString::fromUtf8(header.second);
+ }
}
return QString();
}
-QString QQmlXMLHttpRequest::headers()
+QString QQmlXMLHttpRequest::headers() const
{
QString ret;
- foreach (const HeaderPair &header, m_headersList) {
+ for (const HeaderPair &header : m_headersList) {
if (ret.length())
ret.append(QLatin1String("\r\n"));
- ret = ret % QString::fromUtf8(header.first) % QLatin1String(": ")
- % QString::fromUtf8(header.second);
+ ret += QString::fromUtf8(header.first) + QLatin1String(": ")
+ + QString::fromUtf8(header.second);
}
return ret;
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index edc83b3bf1..5d70b17ece 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -140,6 +140,7 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
o->defineDefaultProperty(QStringLiteral("darker"), QV4::QtObject::method_darker);
o->defineDefaultProperty(QStringLiteral("tint"), QV4::QtObject::method_tint);
o->defineDefaultProperty(QStringLiteral("quit"), QV4::QtObject::method_quit);
+ o->defineDefaultProperty(QStringLiteral("exit"), QV4::QtObject::method_exit);
o->defineDefaultProperty(QStringLiteral("createQmlObject"), QV4::QtObject::method_createQmlObject);
o->defineDefaultProperty(QStringLiteral("createComponent"), QV4::QtObject::method_createComponent);
}
@@ -995,6 +996,8 @@ This function causes the QQmlEngine::quit() signal to be emitted.
Within the \l {Prototyping with qmlscene}, this causes the launcher application to exit;
to quit a C++ application when this method is called, connect the
QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
+
+\sa exit()
*/
ReturnedValue QtObject::method_quit(CallContext *ctx)
{
@@ -1003,6 +1006,28 @@ ReturnedValue QtObject::method_quit(CallContext *ctx)
}
/*!
+ \qmlmethod Qt::exit(int retCode)
+
+ This function causes the QQmlEngine::exit(int) signal to be emitted.
+ Within the \l {Prototyping with qmlscene}, this causes the launcher application to exit
+ the specified return code. To exit from the event loop with a specified return code when this
+ method is called, a C++ application can connect the QQmlEngine::exit(int) signal
+ to the QCoreApplication::exit(int) slot.
+
+ \sa quit()
+*/
+ReturnedValue QtObject::method_exit(CallContext *ctx)
+{
+ if (ctx->argc() != 1)
+ V4THROW_ERROR("Qt.exit(): Invalid arguments");
+
+ int retCode = ctx->args()[0].toNumber();
+
+ QQmlEnginePrivate::get(ctx->engine()->qmlEngine())->sendExit(retCode);
+ return QV4::Encode::undefined();
+}
+
+/*!
\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
Returns a new object created from the given \a string of QML which will have the specified \a parent,
@@ -1035,7 +1060,9 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
struct Error {
static ReturnedValue create(QV4::ExecutionEngine *v4, const QList<QQmlError> &errors) {
Scope scope(v4);
- QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
+ QString errorstr;
+ // '+=' reserves extra capacity. Follow-up appending will be probably free.
+ errorstr += QLatin1String("Qt.createQmlObject(): failed to create object: ");
QV4::ScopedArrayObject qmlerrors(scope, v4->newArrayObject());
QV4::ScopedObject qmlerror(scope);
@@ -1490,15 +1517,13 @@ static QV4::ReturnedValue writeToConsole(ConsoleLogTypes logType, CallContext *c
result.append(QLatin1Char(' '));
if (ctx->args()[i].as<ArrayObject>())
- result.append(QLatin1Char('[') + ctx->args()[i].toQStringNoThrow() + QLatin1Char(']'));
+ result += QLatin1Char('[') + ctx->args()[i].toQStringNoThrow() + QLatin1Char(']');
else
result.append(ctx->args()[i].toQStringNoThrow());
}
- if (printStack) {
- result.append(QLatin1Char('\n'));
- result.append(jsStack(v4));
- }
+ if (printStack)
+ result += QLatin1Char('\n') + jsStack(v4);
static QLoggingCategory qmlLoggingCategory("qml");
static QLoggingCategory jsLoggingCategory("js");
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index d29983c476..8c0759679a 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -122,6 +122,7 @@ struct QtObject : Object
static ReturnedValue method_btoa(CallContext *ctx);
static ReturnedValue method_atob(CallContext *ctx);
static ReturnedValue method_quit(CallContext *ctx);
+ static ReturnedValue method_exit(CallContext *ctx);
static ReturnedValue method_resolvedUrl(CallContext *ctx);
static ReturnedValue method_createQmlObject(CallContext *ctx);
static ReturnedValue method_createComponent(CallContext *ctx);
diff --git a/src/qmltest/qmltest.pro b/src/qmltest/qmltest.pro
index ebbcbcd1eb..9852861334 100644
--- a/src/qmltest/qmltest.pro
+++ b/src/qmltest/qmltest.pro
@@ -1,6 +1,6 @@
TARGET = QtQuickTest
-DEFINES += QT_NO_URL_CAST_FROM_STRING
+DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_FOREACH
QT = core testlib-private
QT_PRIVATE = quick qml-private gui core-private
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index bc26a19033..0e348eee11 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -144,7 +144,7 @@ void handleCompileErrors(const QFileInfo &fi, QQuickView *view)
QTextStream str(&message);
str << "\n " << QDir::toNativeSeparators(fi.absoluteFilePath()) << " produced "
<< errors.size() << " error(s):\n";
- foreach (const QQmlError &e, errors) {
+ for (const QQmlError &e : errors) {
str << " ";
if (e.url().isLocalFile()) {
str << QDir::toNativeSeparators(e.url().toLocalFile());
@@ -158,11 +158,12 @@ void handleCompileErrors(const QFileInfo &fi, QQuickView *view)
str << " Working directory: " << QDir::toNativeSeparators(QDir::current().absolutePath()) << '\n';
if (QQmlEngine *engine = view->engine()) {
str << " View: " << view->metaObject()->className() << ", import paths:\n";
- foreach (const QString &i, engine->importPathList())
+ const auto importPaths = engine->importPathList();
+ for (const QString &i : importPaths)
str << " '" << QDir::toNativeSeparators(i) << "'\n";
const QStringList pluginPaths = engine->pluginPathList();
str << " Plugin paths:\n";
- foreach (const QString &p, pluginPaths)
+ for (const QString &p : pluginPaths)
str << " '" << QDir::toNativeSeparators(p) << "'\n";
}
qWarning("%s", qPrintable(message));
@@ -338,11 +339,11 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
&eventLoop, SLOT(quit()));
view->rootContext()->setContextProperty
(QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead
- foreach (const QString &path, imports)
+ for (const QString &path : qAsConst(imports))
view->engine()->addImportPath(path);
- foreach (const QString &path, pluginPaths)
+ for (const QString &path : qAsConst(pluginPaths))
view->engine()->addPluginPath(path);
- foreach (const QString &file, files) {
+ for (const QString &file : qAsConst(files)) {
const QFileInfo fi(file);
if (!fi.exists())
continue;
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index b924701f2b..c26f641754 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -794,7 +794,7 @@ static QPainter::CompositionMode qt_composite_mode_from_string(const QString &co
} else if (compositeOperator == QLatin1String("destination-over")) {
return QPainter::CompositionMode_DestinationOver;
} else if (compositeOperator == QLatin1String("lighter")) {
- return QPainter::CompositionMode_Lighten;
+ return QPainter::CompositionMode_Plus;
} else if (compositeOperator == QLatin1String("copy")) {
return QPainter::CompositionMode_Source;
} else if (compositeOperator == QLatin1String("xor")) {
@@ -857,7 +857,7 @@ static QString qt_composite_mode_to_string(QPainter::CompositionMode op)
case QPainter::CompositionMode_Xor:
return QStringLiteral("xor");
case QPainter::CompositionMode_Plus:
- return QStringLiteral("plus");
+ return QStringLiteral("lighter");
case QPainter::CompositionMode_Multiply:
return QStringLiteral("qt-multiply");
case QPainter::CompositionMode_Screen:
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
index a82b88f36f..f281cec2d5 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer_p.h
@@ -70,7 +70,7 @@ public:
inline int size() {return commands.size();}
inline bool isEmpty() const {return commands.isEmpty(); }
inline bool hasNext() const {return cmdIdx < commands.size(); }
- inline QQuickContext2D::PaintCommand takeNextCommand() { return commands[cmdIdx++]; }
+ inline QQuickContext2D::PaintCommand takeNextCommand() { return commands.at(cmdIdx++); }
inline qreal takeGlobalAlpha() { return takeReal(); }
inline QPainter::CompositionMode takeGlobalCompositeOperation(){ return static_cast<QPainter::CompositionMode>(takeInt()); }
@@ -227,20 +227,20 @@ public:
colors << color;
}
- inline QTransform takeMatrix() { return matrixes[matrixIdx++]; }
+ inline QTransform takeMatrix() { return matrixes.at(matrixIdx++); }
- inline QRectF takeRect() { return rects[rectIdx++]; }
+ inline QRectF takeRect() { return rects.at(rectIdx++); }
- inline QPainterPath takePath() { return pathes[pathIdx++]; }
+ inline QPainterPath takePath() { return pathes.at(pathIdx++); }
- inline const QImage& takeImage() { return images[imageIdx++]; }
- inline QQmlRefPointer<QQuickCanvasPixmap> takePixmap() { return pixmaps[pixmapIdx++]; }
+ inline const QImage& takeImage() { return images.at(imageIdx++); }
+ inline QQmlRefPointer<QQuickCanvasPixmap> takePixmap() { return pixmaps.at(pixmapIdx++); }
- inline int takeInt() { return ints[intIdx++]; }
- inline bool takeBool() {return bools[boolIdx++]; }
- inline qreal takeReal() { return reals[realIdx++]; }
- inline QColor takeColor() { return colors[colorIdx++]; }
- inline QBrush takeBrush() { return brushes[brushIdx++]; }
+ inline int takeInt() { return ints.at(intIdx++); }
+ inline bool takeBool() {return bools.at(boolIdx++); }
+ inline qreal takeReal() { return reals.at(realIdx++); }
+ inline QColor takeColor() { return colors.at(colorIdx++); }
+ inline QBrush takeBrush() { return brushes.at(brushIdx++); }
void replay(QPainter* painter, QQuickContext2D::State& state, const QVector2D &scaleFactor);
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 14c0adf393..59faafa023 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -38,9 +38,15 @@
****************************************************************************/
#include "qquickevents_p_p.h"
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <private/qdebug_p.h>
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcPointerEvents, "qt.quick.pointer.events")
+
/*!
\qmltype KeyEvent
\instantiates QQuickKeyEvent
@@ -437,4 +443,500 @@ Item {
\l inverted always returns false.
*/
+typedef QHash<QTouchDevice *, QQuickPointerDevice *> PointerDeviceForTouchDeviceHash;
+Q_GLOBAL_STATIC(PointerDeviceForTouchDeviceHash, g_touchDevices)
+
+Q_GLOBAL_STATIC_WITH_ARGS(QQuickPointerDevice, g_genericMouseDevice,
+ (QQuickPointerDevice::Mouse,
+ QQuickPointerDevice::GenericPointer,
+ QQuickPointerDevice::Position | QQuickPointerDevice::Scroll | QQuickPointerDevice::Hover,
+ 1, 3, QLatin1String("core pointer"), 0))
+
+typedef QHash<qint64, QQuickPointerDevice *> PointerDeviceForDeviceIdHash;
+Q_GLOBAL_STATIC(PointerDeviceForDeviceIdHash, g_tabletDevices)
+
+QQuickPointerDevice *QQuickPointerDevice::touchDevice(QTouchDevice *d)
+{
+ if (g_touchDevices->contains(d))
+ return g_touchDevices->value(d);
+
+ QQuickPointerDevice::DeviceType type = QQuickPointerDevice::TouchScreen;
+ QString name;
+ int maximumTouchPoints = 10;
+ QQuickPointerDevice::Capabilities caps = QQuickPointerDevice::Capabilities(QTouchDevice::Position);
+ if (d) {
+ QQuickPointerDevice::Capabilities caps =
+ static_cast<QQuickPointerDevice::Capabilities>(static_cast<int>(d->capabilities()) & 0x0F);
+ if (d->type() == QTouchDevice::TouchPad) {
+ type = QQuickPointerDevice::TouchPad;
+ caps |= QQuickPointerDevice::Scroll;
+ }
+ name = d->name();
+ maximumTouchPoints = d->maximumTouchPoints();
+ } else {
+ qWarning() << "QQuickWindowPrivate::touchDevice: creating touch device from nullptr device in QTouchEvent";
+ }
+
+ QQuickPointerDevice *dev = new QQuickPointerDevice(type, QQuickPointerDevice::Finger,
+ caps, maximumTouchPoints, 0, name, 0);
+ g_touchDevices->insert(d, dev);
+ return dev;
+}
+
+QList<QQuickPointerDevice*> QQuickPointerDevice::touchDevices()
+{
+ return g_touchDevices->values();
+}
+
+QQuickPointerDevice *QQuickPointerDevice::genericMouseDevice()
+{
+ return g_genericMouseDevice;
+}
+
+QQuickPointerDevice *QQuickPointerDevice::tabletDevice(qint64 id)
+{
+ auto it = g_tabletDevices->find(id);
+ if (it != g_tabletDevices->end())
+ return it.value();
+
+ // ### Figure out how to populate the tablet devices
+ return nullptr;
+}
+
+void QQuickEventPoint::reset(Qt::TouchPointState state, QPointF scenePos, quint64 pointId, ulong timestamp)
+{
+ m_scenePos = scenePos;
+ m_pointId = pointId;
+ m_valid = true;
+ m_accept = false;
+ m_state = static_cast<QQuickEventPoint::State>(state);
+ m_timestamp = timestamp;
+ if (state == Qt::TouchPointPressed)
+ m_pressTimestamp = timestamp;
+ // TODO calculate velocity
+}
+
+QQuickItem *QQuickEventPoint::grabber() const
+{
+ return m_grabber.data();
+}
+
+void QQuickEventPoint::setGrabber(QQuickItem *grabber)
+{
+ m_grabber = QPointer<QQuickItem>(grabber);
+}
+
+void QQuickEventPoint::setAccepted(bool accepted)
+{
+ if (m_accept != accepted) {
+ qCDebug(lcPointerEvents) << this << m_accept << "->" << accepted;
+ m_accept = accepted;
+ }
+}
+
+QQuickEventTouchPoint::QQuickEventTouchPoint(QQuickPointerTouchEvent *parent)
+ : QQuickEventPoint(parent), m_rotation(0), m_pressure(0)
+{}
+
+void QQuickEventTouchPoint::reset(const QTouchEvent::TouchPoint &tp, ulong timestamp)
+{
+ QQuickEventPoint::reset(tp.state(), tp.scenePos(), tp.id(), timestamp);
+ m_rotation = tp.rotation();
+ m_pressure = tp.pressure();
+ m_uniqueId = tp.uniqueId();
+}
+
+/*!
+ \internal
+ \class QQuickPointerEvent
+
+ QQuickPointerEvent is used as a long-lived object to store data related to
+ an event from a pointing device, such as a mouse, touch or tablet event,
+ during event delivery. It also provides properties which may be used later
+ to expose the event to QML, the same as is done with QQuickMouseEvent,
+ QQuickTouchPoint, QQuickKeyEvent, etc. Since only one event can be
+ delivered at a time, this class is effectively a singleton. We don't worry
+ about the QObject overhead because the instances are long-lived: we don't
+ dynamically create and destroy objects of this type for each event.
+*/
+
+QQuickPointerEvent::~QQuickPointerEvent()
+{}
+
+QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event)
+{
+ auto ev = static_cast<QMouseEvent*>(event);
+ m_event = ev;
+ if (!event)
+ return this;
+
+ m_device = QQuickPointerDevice::genericMouseDevice();
+ m_button = ev->button();
+ m_pressedButtons = ev->buttons();
+ Qt::TouchPointState state = Qt::TouchPointStationary;
+ switch (ev->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ state = Qt::TouchPointPressed;
+ break;
+ case QEvent::MouseButtonRelease:
+ state = Qt::TouchPointReleased;
+ break;
+ case QEvent::MouseMove:
+ state = Qt::TouchPointMoved;
+ break;
+ default:
+ break;
+ }
+ m_mousePoint->reset(state, ev->windowPos(), 0, ev->timestamp()); // mouse is 0
+ return this;
+}
+
+QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event)
+{
+ auto ev = static_cast<QTouchEvent*>(event);
+ m_event = ev;
+ if (!event)
+ return this;
+
+ m_device = QQuickPointerDevice::touchDevice(ev->device());
+ m_button = Qt::NoButton;
+ m_pressedButtons = Qt::NoButton;
+
+ const QList<QTouchEvent::TouchPoint> &tps = ev->touchPoints();
+ int newPointCount = tps.count();
+ m_touchPoints.reserve(newPointCount);
+
+ for (int i = m_touchPoints.size(); i < newPointCount; ++i)
+ m_touchPoints.insert(i, new QQuickEventTouchPoint(this));
+
+ // Make sure the grabbers are right from one event to the next
+ QVector<QQuickItem*> grabbers;
+ // Copy all grabbers, because the order of points might have changed in the event.
+ // The ID is all that we can rely on (release might remove the first point etc).
+ for (int i = 0; i < newPointCount; ++i) {
+ QQuickItem *grabber = nullptr;
+ if (auto point = pointById(tps.at(i).id()))
+ grabber = point->grabber();
+ grabbers.append(grabber);
+ }
+
+ for (int i = 0; i < newPointCount; ++i) {
+ auto point = m_touchPoints.at(i);
+ point->reset(tps.at(i), ev->timestamp());
+ if (point->state() == QQuickEventPoint::Pressed) {
+ if (grabbers.at(i))
+ qWarning() << "TouchPointPressed without previous release event" << point;
+ point->setGrabber(nullptr);
+ } else {
+ point->setGrabber(grabbers.at(i));
+ }
+ }
+ m_pointCount = newPointCount;
+ return this;
+}
+
+QQuickEventPoint *QQuickPointerMouseEvent::point(int i) const {
+ if (i == 0)
+ return m_mousePoint;
+ return nullptr;
+}
+
+QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const {
+ if (i >= 0 && i < m_pointCount)
+ return m_touchPoints.at(i);
+ return nullptr;
+}
+
+QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent)
+ : QObject(parent), m_pointId(0), m_grabber(nullptr), m_timestamp(0), m_pressTimestamp(0),
+ m_state(QQuickEventPoint::Released), m_valid(false), m_accept(false)
+{
+ Q_UNUSED(m_reserved);
+}
+
+QQuickPointerEvent *QQuickEventPoint::pointerEvent() const
+{
+ return static_cast<QQuickPointerEvent *>(parent());
+}
+
+bool QQuickPointerMouseEvent::allPointsAccepted() const {
+ return m_mousePoint->isAccepted();
+}
+
+QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const
+{
+ auto event = static_cast<QMouseEvent *>(m_event);
+ event->setLocalPos(localPos);
+ return event;
+}
+
+QVector<QQuickItem *> QQuickPointerMouseEvent::grabbers() const
+{
+ QVector<QQuickItem *> result;
+ if (QQuickItem *grabber = m_mousePoint->grabber())
+ result << grabber;
+ return result;
+}
+
+void QQuickPointerMouseEvent::clearGrabbers() const {
+ m_mousePoint->setGrabber(nullptr);
+}
+
+bool QQuickPointerMouseEvent::isPressEvent() const
+{
+ auto me = static_cast<QMouseEvent*>(m_event);
+ return ((me->type() == QEvent::MouseButtonPress || me->type() == QEvent::MouseButtonDblClick) &&
+ (me->buttons() & me->button()) == me->buttons());
+}
+
+bool QQuickPointerTouchEvent::allPointsAccepted() const {
+ for (int i = 0; i < m_pointCount; ++i) {
+ if (!m_touchPoints.at(i)->isAccepted())
+ return false;
+ }
+ return true;
+}
+
+QVector<QQuickItem *> QQuickPointerTouchEvent::grabbers() const
+{
+ QVector<QQuickItem *> result;
+ for (int i = 0; i < m_pointCount; ++i) {
+ auto point = m_touchPoints.at(i);
+ if (QQuickItem *grabber = point->grabber()) {
+ if (!result.contains(grabber))
+ result << grabber;
+ }
+ }
+ return result;
+}
+
+void QQuickPointerTouchEvent::clearGrabbers() const {
+ for (auto point: m_touchPoints)
+ point->setGrabber(nullptr);
+}
+
+bool QQuickPointerTouchEvent::isPressEvent() const
+{
+ return static_cast<QTouchEvent*>(m_event)->touchPointStates() & Qt::TouchPointPressed;
+}
+
+QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() const
+{
+ QVector<QPointF> points;
+ for (int i = 0; i < pointCount(); ++i) {
+ if (!point(i)->isAccepted() && point(i)->state() == QQuickEventPoint::Pressed)
+ points << point(i)->scenePos();
+ }
+ return points;
+}
+
+/*!
+ \internal
+ Populate the reusable synth-mouse event from one touchpoint.
+ It's required that isTouchEvent() be true when this is called.
+ If the touchpoint cannot be found, this returns nullptr.
+ Ownership of the event is NOT transferred to the caller.
+*/
+QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const {
+ const QTouchEvent::TouchPoint *p = touchPointById(pointID);
+ if (!p)
+ return nullptr;
+ QEvent::Type type;
+ Qt::MouseButton buttons = Qt::LeftButton;
+ switch (p->state()) {
+ case Qt::TouchPointPressed:
+ type = QEvent::MouseButtonPress;
+ break;
+ case Qt::TouchPointMoved:
+ case Qt::TouchPointStationary:
+ type = QEvent::MouseMove;
+ break;
+ case Qt::TouchPointReleased:
+ type = QEvent::MouseButtonRelease;
+ buttons = Qt::NoButton;
+ break;
+ default:
+ Q_ASSERT(false);
+ return nullptr;
+ }
+ m_synthMouseEvent = QMouseEvent(type, relativeTo->mapFromScene(p->scenePos()),
+ p->scenePos(), p->screenPos(), Qt::LeftButton, buttons, m_event->modifiers());
+ m_synthMouseEvent.setAccepted(true);
+ m_synthMouseEvent.setTimestamp(m_event->timestamp());
+ // In the future we will try to always have valid velocity in every QQuickEventPoint.
+ // QQuickFlickablePrivate::handleMouseMoveEvent() checks for QTouchDevice::Velocity
+ // and if it is set, then it does not need to do its own velocity calculations.
+ // That's probably the only usecase for this, so far. Some day Flickable should handle
+ // pointer events, and then passing touchpoint velocity via QMouseEvent will be obsolete.
+ // Conveniently (by design), QTouchDevice::Velocity == QQuickPointerDevice.Velocity
+ // so that we don't need to convert m_device->capabilities().
+ if (m_device)
+ QGuiApplicationPrivate::setMouseEventCapsAndVelocity(&m_synthMouseEvent, m_device->capabilities(), p->velocity());
+ QGuiApplicationPrivate::setMouseEventSource(&m_synthMouseEvent, Qt::MouseEventSynthesizedByQt);
+ return &m_synthMouseEvent;
+}
+
+/*!
+ \internal
+ Returns a pointer to the QQuickEventPoint which has the \a pointId as
+ \l {QQuickEventPoint::pointId}{pointId}.
+ Returns nullptr if there is no point with that ID.
+
+ \fn QQuickPointerEvent::pointById(quint64 pointId) const
+*/
+QQuickEventPoint *QQuickPointerMouseEvent::pointById(quint64 pointId) const {
+ if (m_mousePoint && pointId == m_mousePoint->pointId())
+ return m_mousePoint;
+ return nullptr;
+}
+
+QQuickEventPoint *QQuickPointerTouchEvent::pointById(quint64 pointId) const {
+ auto it = std::find_if(m_touchPoints.constBegin(), m_touchPoints.constEnd(),
+ [pointId](const QQuickEventTouchPoint *tp) { return tp->pointId() == pointId; } );
+ if (it != m_touchPoints.constEnd())
+ return *it;
+ return nullptr;
+}
+
+
+/*!
+ \internal
+ Returns a pointer to the original TouchPoint which has the same
+ \l {QTouchEvent::TouchPoint::id}{id} as \a pointId, if the original event is a
+ QTouchEvent, and if that point is found. Otherwise, returns nullptr.
+*/
+const QTouchEvent::TouchPoint *QQuickPointerTouchEvent::touchPointById(int pointId) const {
+ const QTouchEvent *ev = asTouchEvent();
+ if (!ev)
+ return nullptr;
+ const QList<QTouchEvent::TouchPoint> &tps = ev->touchPoints();
+ auto it = std::find_if(tps.constBegin(), tps.constEnd(),
+ [pointId](QTouchEvent::TouchPoint const& tp) { return tp.id() == pointId; } );
+ // return the pointer to the actual TP in QTouchEvent::_touchPoints
+ return (it == tps.constEnd() ? nullptr : it.operator->());
+}
+
+/*!
+ \internal
+ Make a new QTouchEvent, giving it a subset of the original touch points.
+
+ Returns a nullptr if all points are stationary or there are no points inside the item.
+*/
+QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool isFiltering) const
+{
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ Qt::TouchPointStates eventStates;
+ // TODO maybe add QQuickItem::mapVector2DFromScene(QVector2D) to avoid needing QQuickItemPrivate here
+ // Or else just document that velocity is always scene-relative and is not scaled and rotated with the item
+ // but that would require changing tst_qquickwindow::touchEvent_velocity(): it expects transformed velocity
+
+ QMatrix4x4 transformMatrix(QQuickItemPrivate::get(item)->windowToItemTransform());
+ for (int i = 0; i < m_pointCount; ++i) {
+ auto p = m_touchPoints.at(i);
+ if (p->isAccepted())
+ continue;
+ bool isGrabber = p->grabber() == item;
+ bool isPressInside = p->state() == QQuickEventPoint::Pressed && item->contains(item->mapFromScene(p->scenePos()));
+ if (!(isGrabber || isPressInside || isFiltering))
+ continue;
+
+ const QTouchEvent::TouchPoint *tp = touchPointById(p->pointId());
+ if (tp) {
+ eventStates |= tp->state();
+ QTouchEvent::TouchPoint tpCopy = *tp;
+ tpCopy.setPos(item->mapFromScene(tpCopy.scenePos()));
+ tpCopy.setLastPos(item->mapFromScene(tpCopy.lastScenePos()));
+ tpCopy.setStartPos(item->mapFromScene(tpCopy.startScenePos()));
+ tpCopy.setRect(item->mapRectFromScene(tpCopy.sceneRect()));
+ tpCopy.setVelocity(transformMatrix.mapVector(tpCopy.velocity()).toVector2D());
+ touchPoints << tpCopy;
+ }
+ }
+
+ if (eventStates == Qt::TouchPointStationary || touchPoints.isEmpty())
+ return nullptr;
+
+ // if all points have the same state, set the event type accordingly
+ const QTouchEvent &event = *asTouchEvent();
+ QEvent::Type eventType = event.type();
+ switch (eventStates) {
+ case Qt::TouchPointPressed:
+ eventType = QEvent::TouchBegin;
+ break;
+ case Qt::TouchPointReleased:
+ eventType = QEvent::TouchEnd;
+ break;
+ default:
+ eventType = QEvent::TouchUpdate;
+ break;
+ }
+
+ QTouchEvent *touchEvent = new QTouchEvent(eventType);
+ touchEvent->setWindow(event.window());
+ touchEvent->setTarget(item);
+ touchEvent->setDevice(event.device());
+ touchEvent->setModifiers(event.modifiers());
+ touchEvent->setTouchPoints(touchPoints);
+ touchEvent->setTouchPointStates(eventStates);
+ touchEvent->setTimestamp(event.timestamp());
+ touchEvent->accept();
+ return touchEvent;
+}
+
+QTouchEvent *QQuickPointerTouchEvent::asTouchEvent() const
+{
+ return static_cast<QTouchEvent *>(m_event);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerDevice *dev) {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg << "QQuickPointerDevice("<< dev->name() << ' ';
+ QtDebugUtils::formatQEnum(dbg, dev->type());
+ dbg << ' ';
+ QtDebugUtils::formatQEnum(dbg, dev->pointerType());
+ dbg << " caps:";
+ QtDebugUtils::formatQFlags(dbg, dev->capabilities());
+ if (dev->type() == QQuickPointerDevice::TouchScreen ||
+ dev->type() == QQuickPointerDevice::TouchPad)
+ dbg << " maxTouchPoints:" << dev->maximumTouchPoints();
+ else
+ dbg << " buttonCount:" << dev->buttonCount();
+ dbg << ')';
+ return dbg;
+}
+
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerEvent *event) {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg << "QQuickPointerEvent(dev:";
+ QtDebugUtils::formatQEnum(dbg, event->device()->type());
+ if (event->buttons() != Qt::NoButton) {
+ dbg << " buttons:";
+ QtDebugUtils::formatQEnum(dbg, event->buttons());
+ }
+ dbg << " [";
+ int c = event->pointCount();
+ for (int i = 0; i < c; ++i)
+ dbg << event->point(i) << ' ';
+ dbg << "])";
+ return dbg;
+}
+
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *event) {
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg << "QQuickEventPoint(valid:" << event->isValid() << " accepted:" << event->isAccepted()
+ << " state:";
+ QtDebugUtils::formatQEnum(dbg, event->state());
+ dbg << " scenePos:" << event->scenePos() << " id:" << event->pointId()
+ << " timeHeld:" << event->timeHeld() << ')';
+ return dbg;
+}
+
+#endif
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index 065e025152..61bbb4ecda 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -55,12 +55,20 @@
#include <qqml.h>
#include <QtCore/qobject.h>
+#include <QtCore/qpointer.h>
#include <QtGui/qvector2d.h>
#include <QtGui/qevent.h>
#include <QtGui/qkeysequence.h>
+#include <QtQuick/qquickitem.h>
QT_BEGIN_NAMESPACE
+class QQuickPointerDevice;
+class QQuickPointerEvent;
+class QQuickPointerMouseEvent;
+class QQuickPointerTabletEvent;
+class QQuickPointerTouchEvent;
+
class QQuickKeyEvent : public QObject
{
Q_OBJECT
@@ -238,11 +246,315 @@ private:
bool _accepted;
};
+class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF scenePos READ scenePos)
+ Q_PROPERTY(State state READ state)
+ Q_PROPERTY(quint64 pointId READ pointId)
+ Q_PROPERTY(qreal timeHeld READ timeHeld)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ Q_PROPERTY(QQuickItem *grabber READ grabber WRITE setGrabber)
+
+public:
+ enum State {
+ Pressed = Qt::TouchPointPressed,
+ Updated = Qt::TouchPointMoved,
+ Stationary = Qt::TouchPointStationary,
+ Released = Qt::TouchPointReleased
+ // Canceled = Qt::TouchPointReleased << 1 // 0x10 // TODO maybe
+ };
+ Q_ENUM(State)
+
+ QQuickEventPoint(QQuickPointerEvent *parent);
+
+ void reset(Qt::TouchPointState state, QPointF scenePos, quint64 pointId, ulong timestamp);
+
+ void invalidate() { m_valid = false; }
+
+ QQuickPointerEvent *pointerEvent() const;
+ QPointF scenePos() const { return m_scenePos; }
+ State state() const { return m_state; }
+ quint64 pointId() const { return m_pointId; }
+ bool isValid() const { return m_valid; }
+ qreal timeHeld() const { return (m_timestamp - m_pressTimestamp) / 1000.0; }
+ bool isAccepted() const { return m_accept; }
+ void setAccepted(bool accepted = true);
+ QQuickItem *grabber() const;
+ void setGrabber(QQuickItem *grabber);
+
+private:
+ QPointF m_scenePos;
+ quint64 m_pointId;
+ QPointer<QQuickItem> m_grabber;
+ ulong m_timestamp;
+ ulong m_pressTimestamp;
+ State m_state;
+ bool m_valid : 1;
+ bool m_accept : 1;
+ int m_reserved : 30;
+
+ Q_DISABLE_COPY(QQuickEventPoint)
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickEventTouchPoint : public QQuickEventPoint
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal rotation READ rotation)
+ Q_PROPERTY(qreal pressure READ pressure)
+ Q_PROPERTY(QPointerUniqueId uniqueId READ uniqueId)
+
+public:
+ QQuickEventTouchPoint(QQuickPointerTouchEvent *parent);
+
+ void reset(const QTouchEvent::TouchPoint &tp, ulong timestamp);
+
+ qreal rotation() const { return m_rotation; }
+ qreal pressure() const { return m_pressure; }
+ QPointerUniqueId uniqueId() const { return m_uniqueId; }
+
+private:
+ qreal m_rotation;
+ qreal m_pressure;
+ QPointerUniqueId m_uniqueId;
+
+ Q_DISABLE_COPY(QQuickEventTouchPoint)
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerEvent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(const QQuickPointerDevice *device READ device)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers)
+ Q_PROPERTY(Qt::MouseButtons button READ button)
+ Q_PROPERTY(Qt::MouseButtons buttons READ buttons)
+
+public:
+ QQuickPointerEvent(QObject *parent = nullptr)
+ : QObject(parent)
+ , m_device(nullptr)
+ , m_event(nullptr)
+ , m_button(Qt::NoButton)
+ , m_pressedButtons(Qt::NoButton)
+ { }
+
+ virtual ~QQuickPointerEvent();
+
+public: // property accessors
+ QQuickPointerDevice *device() const { return m_device; }
+ Qt::KeyboardModifiers modifiers() const { return m_event ? m_event->modifiers() : Qt::NoModifier; }
+ Qt::MouseButton button() const { return m_button; }
+ Qt::MouseButtons buttons() const { return m_pressedButtons; }
+
+public: // helpers for C++ only (during event delivery)
+ virtual QQuickPointerEvent *reset(QEvent *ev) = 0;
+
+ virtual bool isPressEvent() const = 0;
+ virtual QQuickPointerMouseEvent *asPointerMouseEvent() { return nullptr; }
+ virtual QQuickPointerTouchEvent *asPointerTouchEvent() { return nullptr; }
+ virtual QQuickPointerTabletEvent *asPointerTabletEvent() { return nullptr; }
+ virtual const QQuickPointerMouseEvent *asPointerMouseEvent() const { return nullptr; }
+ virtual const QQuickPointerTouchEvent *asPointerTouchEvent() const { return nullptr; }
+ virtual const QQuickPointerTabletEvent *asPointerTabletEvent() const { return nullptr; }
+ bool isValid() const { return m_event != nullptr; }
+ virtual bool allPointsAccepted() const = 0;
+ bool isAccepted() { return m_event->isAccepted(); }
+ void setAccepted(bool accepted) { m_event->setAccepted(accepted); }
+ QVector<QPointF> unacceptedPressedPointScenePositions() const;
+
+ virtual int pointCount() const = 0;
+ virtual QQuickEventPoint *point(int i) const = 0;
+ virtual QQuickEventPoint *pointById(quint64 pointId) const = 0;
+ virtual QVector<QQuickItem *> grabbers() const = 0;
+ virtual void clearGrabbers() const = 0;
+
+ ulong timestamp() const { return m_event->timestamp(); }
+
+protected:
+ QQuickPointerDevice *m_device;
+ QInputEvent *m_event; // original event as received by QQuickWindow
+ Qt::MouseButton m_button;
+ Qt::MouseButtons m_pressedButtons;
+
+ Q_DISABLE_COPY(QQuickPointerEvent)
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerMouseEvent : public QQuickPointerEvent
+{
+ Q_OBJECT
+public:
+ QQuickPointerMouseEvent(QObject *parent = nullptr)
+ : QQuickPointerEvent(parent), m_mousePoint(new QQuickEventPoint(this)) { }
+
+ QQuickPointerEvent *reset(QEvent *) override;
+ bool isPressEvent() const override;
+ QQuickPointerMouseEvent *asPointerMouseEvent() override { return this; }
+ const QQuickPointerMouseEvent *asPointerMouseEvent() const override { return this; }
+ int pointCount() const override { return 1; }
+ QQuickEventPoint *point(int i) const override;
+ QQuickEventPoint *pointById(quint64 pointId) const override;
+ bool allPointsAccepted() const override;
+ QVector<QQuickItem *> grabbers() const override;
+ void clearGrabbers() const override;
+
+ QMouseEvent *asMouseEvent(const QPointF& localPos) const;
+
+private:
+ QQuickEventPoint *m_mousePoint;
+
+ Q_DISABLE_COPY(QQuickPointerMouseEvent)
+};
+
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerTouchEvent : public QQuickPointerEvent
+{
+ Q_OBJECT
+public:
+ QQuickPointerTouchEvent(QObject *parent = nullptr)
+ : QQuickPointerEvent(parent)
+ , m_pointCount(0)
+ , m_synthMouseEvent(QEvent::MouseMove, QPointF(), Qt::NoButton, Qt::NoButton, Qt::NoModifier)
+ { }
+
+ QQuickPointerEvent *reset(QEvent *) override;
+ bool isPressEvent() const override;
+ QQuickPointerTouchEvent *asPointerTouchEvent() override { return this; }
+ const QQuickPointerTouchEvent *asPointerTouchEvent() const override { return this; }
+ int pointCount() const override { return m_pointCount; }
+ QQuickEventPoint *point(int i) const override;
+ QQuickEventPoint *pointById(quint64 pointId) const override;
+ const QTouchEvent::TouchPoint *touchPointById(int pointId) const;
+ bool allPointsAccepted() const override;
+ QVector<QQuickItem *> grabbers() const override;
+ void clearGrabbers() const override;
+
+ QMouseEvent *syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const;
+ QTouchEvent *touchEventForItem(QQuickItem *item, bool isFiltering = false) const;
+
+ QTouchEvent *asTouchEvent() const;
+
+private:
+ int m_pointCount;
+ QVector<QQuickEventTouchPoint *> m_touchPoints;
+ mutable QMouseEvent m_synthMouseEvent;
+
+ Q_DISABLE_COPY(QQuickPointerTouchEvent)
+};
+
+// ### Qt 6: move this to qtbase, replace QTouchDevice and the enums in QTabletEvent
+class Q_QUICK_PRIVATE_EXPORT QQuickPointerDevice : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(DeviceType type READ type CONSTANT)
+ Q_PROPERTY(PointerType pointerType READ pointerType CONSTANT)
+ Q_PROPERTY(Capabilities capabilities READ capabilities CONSTANT)
+ Q_PROPERTY(int maximumTouchPoints READ maximumTouchPoints CONSTANT)
+ Q_PROPERTY(int buttonCount READ buttonCount CONSTANT)
+ Q_PROPERTY(QString name READ name CONSTANT)
+ Q_PROPERTY(qint64 uniqueId READ uniqueId CONSTANT)
+
+public:
+ enum DeviceType {
+ UnknownDevice = 0x0000,
+ Mouse = 0x0001,
+ TouchScreen = 0x0002,
+ TouchPad = 0x0004,
+ Puck = 0x0008,
+ Stylus = 0x0010,
+ Airbrush = 0x0020,
+ AllDevices = 0x003F
+ };
+ Q_DECLARE_FLAGS(DeviceTypes, DeviceType)
+ Q_ENUM(DeviceType)
+ Q_FLAG(DeviceTypes)
+
+ enum PointerType {
+ GenericPointer = 0x0001,
+ Finger = 0x0002,
+ Pen = 0x0004,
+ Eraser = 0x0008,
+ Cursor = 0x0010,
+ AllPointerTypes = 0x001F
+ };
+ Q_DECLARE_FLAGS(PointerTypes, PointerType)
+ Q_ENUM(PointerType)
+ Q_FLAG(PointerTypes)
+
+ enum CapabilityFlag {
+ Position = QTouchDevice::Position,
+ Area = QTouchDevice::Area,
+ Pressure = QTouchDevice::Pressure,
+ Velocity = QTouchDevice::Velocity,
+ // some bits reserved in case we need more of QTouchDevice::Capabilities
+ Scroll = 0x0100, // mouse has a wheel, or there is OS-level scroll gesture recognition (dubious?)
+ Hover = 0x0200,
+ Rotation = 0x0400,
+ XTilt = 0x0800,
+ YTilt = 0x1000
+ };
+ Q_DECLARE_FLAGS(Capabilities, CapabilityFlag)
+ Q_ENUM(CapabilityFlag)
+ Q_FLAG(Capabilities)
+
+ QQuickPointerDevice(DeviceType devType, PointerType pType, Capabilities caps, int maxPoints, int buttonCount, const QString &name, qint64 uniqueId = 0)
+ : m_deviceType(devType), m_pointerType(pType), m_capabilities(caps)
+ , m_maximumTouchPoints(maxPoints), m_buttonCount(buttonCount), m_name(name), m_uniqueId(uniqueId), m_event(nullptr)
+ {
+ if (m_deviceType == Mouse) {
+ m_event = new QQuickPointerMouseEvent;
+ } else if (m_deviceType == TouchScreen || m_deviceType == TouchPad) {
+ m_event = new QQuickPointerTouchEvent;
+ } else {
+ Q_ASSERT(false);
+ }
+ }
+
+ ~QQuickPointerDevice() { delete m_event; }
+ DeviceType type() const { return m_deviceType; }
+ PointerType pointerType() const { return m_pointerType; }
+ Capabilities capabilities() const { return m_capabilities; }
+ bool hasCapability(CapabilityFlag cap) { return m_capabilities & cap; }
+ int maximumTouchPoints() const { return m_maximumTouchPoints; }
+ int buttonCount() const { return m_buttonCount; }
+ QString name() const { return m_name; }
+ qint64 uniqueId() const { return m_uniqueId; }
+ QQuickPointerEvent *pointerEvent() const { return m_event; }
+
+ static QQuickPointerDevice *touchDevice(QTouchDevice *d);
+ static QList<QQuickPointerDevice *> touchDevices();
+ static QQuickPointerDevice *genericMouseDevice();
+ static QQuickPointerDevice *tabletDevice(qint64);
+
+private:
+ DeviceType m_deviceType;
+ PointerType m_pointerType;
+ Capabilities m_capabilities;
+ int m_maximumTouchPoints;
+ int m_buttonCount;
+ QString m_name;
+ qint64 m_uniqueId;
+ // the device-specific event instance which is reused during event delivery
+ QQuickPointerEvent *m_event;
+
+ Q_DISABLE_COPY(QQuickPointerDevice)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPointerDevice::DeviceTypes)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPointerDevice::PointerTypes)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPointerDevice::Capabilities)
+
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug, const QQuickPointerDevice *);
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug, const QQuickPointerEvent *);
+Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug, const QQuickEventPoint *);
+//Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug, const QQuickEventTouchPoint *); TODO maybe
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickKeyEvent)
QML_DECLARE_TYPE(QQuickMouseEvent)
QML_DECLARE_TYPE(QQuickWheelEvent)
QML_DECLARE_TYPE(QQuickCloseEvent)
+QML_DECLARE_TYPE(QQuickPointerDevice)
+QML_DECLARE_TYPE(QPointerUniqueId)
+QML_DECLARE_TYPE(QQuickPointerEvent)
#endif // QQUICKEVENTS_P_P_H
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index cb2611199e..b5d5e43f7a 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -478,7 +478,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
qreal colPos = colPosAt(visibleIndex);
qreal rowPos = rowPosAt(visibleIndex);
if (visibleItems.count()) {
- FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
+ FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.constLast());
rowPos = lastItem->rowPos();
int colNum = qFloor((lastItem->colPos()+colSize()/2) / colSize());
if (++colNum >= columns) {
@@ -536,7 +536,7 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal
// Find first column
if (visibleItems.count()) {
- FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+ FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.constFirst());
rowPos = firstItem->rowPos();
colNum = qFloor((firstItem->colPos()+colSize()/2) / colSize());
if (--colNum < 0) {
@@ -586,7 +586,7 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
bool changed = false;
while (visibleItems.count() > 1
- && (item = static_cast<FxGridItemSG*>(visibleItems.first()))
+ && (item = static_cast<FxGridItemSG*>(visibleItems.constFirst()))
&& item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
if (item->attached->delayRemove())
break;
@@ -598,7 +598,7 @@ bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
changed = true;
}
while (visibleItems.count() > 1
- && (item = static_cast<FxGridItemSG*>(visibleItems.last()))
+ && (item = static_cast<FxGridItemSG*>(visibleItems.constLast()))
&& item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
if (item->attached->delayRemove())
break;
@@ -623,7 +623,7 @@ void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex)
const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning;
const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd;
- FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+ FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.constFirst());
qreal rowPos = firstItem->rowPos();
qreal colPos = firstItem->colPos();
int col = visibleIndex % columns;
@@ -679,7 +679,7 @@ void QQuickGridViewPrivate::repositionPackageItemAt(QQuickItem *item, int index)
void QQuickGridViewPrivate::resetFirstItemPosition(qreal pos)
{
- FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.first());
+ FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.constFirst());
item->setPosition(0, pos);
}
@@ -692,7 +692,7 @@ void QQuickGridViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int
if (moveCount == 0 && changeBeforeVisible != 0)
moveCount += (changeBeforeVisible % columns) - (columns - 1);
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.first());
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.constFirst());
gridItem->setPosition(gridItem->colPos(), gridItem->rowPos() + ((moveCount / columns) * rowSize()));
}
@@ -2517,7 +2517,7 @@ void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
int markerItemIndex = -1;
for (int i=0; i<visibleItems.count(); i++) {
- if (visibleItems[i]->index == afterModelIndex) {
+ if (visibleItems.at(i)->index == afterModelIndex) {
markerItemIndex = i;
break;
}
@@ -2536,7 +2536,7 @@ void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
countItemsRemoved -= removalResult.countChangeAfterVisibleItems;
for (int i=markerItemIndex+1; i<visibleItems.count() && visibleItems.at(i)->position() < viewEndPos; i++) {
- FxGridItemSG *gridItem = static_cast<FxGridItemSG *>(visibleItems[i]);
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG *>(visibleItems.at(i));
if (!gridItem->transitionScheduledOrRunning()) {
qreal origRowPos = gridItem->colPos();
qreal origColPos = gridItem->rowPos();
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 60e31631c0..a2b99b6395 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -355,7 +355,7 @@ void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixe
if (disable2xImageLoading)
return;
- QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
+ const QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
// Non-local file path: @2x loading is not supported.
if (localFile.isEmpty())
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 8905faf973..84f9b0f169 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -1426,7 +1426,7 @@ void QQuickKeysAttached::inputMethodEvent(QInputMethodEvent *event, bool post)
d->inIM = true;
for (QQuickItem *targetItem : qAsConst(d->targets)) {
if (targetItem && targetItem->isVisible() && (targetItem->flags() & QQuickItem::ItemAcceptsInputMethod)) {
- d->item->window()->sendEvent(targetItem, event);
+ QCoreApplication::sendEvent(targetItem, event);
if (event->isAccepted()) {
d->imeItem = targetItem;
d->inIM = false;
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index 027c07ec07..5c0caf5ca2 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -339,9 +339,9 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
qreal w = target->width();
qreal h = target->height();
if (pc->widthIsSet() && i < actions.size() - 1)
- w = actions[++i].toValue.toReal();
+ w = actions.at(++i).toValue.toReal();
if (pc->heightIsSet() && i < actions.size() - 1)
- h = actions[++i].toValue.toReal();
+ h = actions.at(++i).toValue.toReal();
const QPointF &transformOrigin
= d->computeTransformOrigin(target->transformOrigin(), w,h);
qreal tempxt = transformOrigin.x();
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 3c1a5a6ebe..d3f045f35c 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1199,9 +1199,9 @@ void QQuickItemViewPrivate::showVisibleItems() const
{
qDebug() << "Visible items:";
for (int i = 0; i < visibleItems.count(); ++i) {
- qDebug() << "\t" << visibleItems[i]->index
- << visibleItems[i]->item->objectName()
- << visibleItems[i]->position();
+ qDebug() << "\t" << visibleItems.at(i)->index
+ << visibleItems.at(i)->item->objectName()
+ << visibleItems.at(i)->position();
}
}
@@ -1998,7 +1998,7 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
prevViewPos = prevFirstVisible->position();
prevFirstVisibleIndex = prevFirstVisible->index;
}
- qreal prevVisibleItemsFirstPos = visibleItems.count() ? visibleItems.first()->position() : 0.0;
+ qreal prevVisibleItemsFirstPos = visibleItems.count() ? visibleItems.constFirst()->position() : 0.0;
totalInsertionResult->visiblePos = prevViewPos;
totalRemovalResult->visiblePos = prevViewPos;
@@ -2077,13 +2077,13 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
// can transition it from this "original" position to its new position in the view
if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true)) {
for (int i=0; i<movingIntoView.count(); i++) {
- int fromIndex = findMoveKeyIndex(movingIntoView[i].moveKey, removals);
+ int fromIndex = findMoveKeyIndex(movingIntoView.at(i).moveKey, removals);
if (fromIndex >= 0) {
if (prevFirstVisibleIndex >= 0 && fromIndex < prevFirstVisibleIndex)
- repositionItemAt(movingIntoView[i].item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
+ repositionItemAt(movingIntoView.at(i).item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
else
- repositionItemAt(movingIntoView[i].item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
- movingIntoView[i].item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true);
+ repositionItemAt(movingIntoView.at(i).item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
+ movingIntoView.at(i).item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true);
}
}
}
@@ -2129,11 +2129,11 @@ bool QQuickItemViewPrivate::applyRemovalChange(const QQmlChangeSet::Change &remo
Q_Q(QQuickItemView);
bool visibleAffected = false;
- if (visibleItems.count() && removal.index + removal.count > visibleItems.last()->index) {
- if (removal.index > visibleItems.last()->index)
+ if (visibleItems.count() && removal.index + removal.count > visibleItems.constLast()->index) {
+ if (removal.index > visibleItems.constLast()->index)
removeResult->countChangeAfterVisibleItems += removal.count;
else
- removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.last()->index);
+ removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.constLast()->index);
}
QList<FxViewItem*>::Iterator it = visibleItems.begin();
@@ -2223,10 +2223,11 @@ void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirs
qreal moveBackwardsBy = 0;
// shift visibleItems.first() relative to the number of added/removed items
- if (visibleItems.first()->position() > prevViewPos) {
+ const auto pos = visibleItems.constFirst()->position();
+ if (pos > prevViewPos) {
moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
- } else if (visibleItems.first()->position() < prevViewPos) {
+ } else if (pos < prevViewPos) {
moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
}
@@ -2304,7 +2305,7 @@ bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item, co
void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *item)
{
for (int i=0; i<releasePendingTransition.count(); i++) {
- if (releasePendingTransition[i]->transitionableItem == item) {
+ if (releasePendingTransition.at(i)->transitionableItem == item) {
releaseItem(releasePendingTransition.takeAt(i));
return;
}
@@ -2324,8 +2325,8 @@ FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
return 0;
for (int i=0; i<releasePendingTransition.count(); i++) {
- if (releasePendingTransition[i]->index == modelIndex
- && !releasePendingTransition[i]->isPendingRemoval()) {
+ if (releasePendingTransition.at(i)->index == modelIndex
+ && !releasePendingTransition.at(i)->isPendingRemoval()) {
releasePendingTransition[i]->releaseAfterTransition = false;
return releasePendingTransition.takeAt(i);
}
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 7bbc6dc9ba..50d75d3dab 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -400,7 +400,7 @@ FxViewItem *QQuickListViewPrivate::itemBefore(int modelIndex) const
++idx;
}
if (lastIndex == modelIndex-1)
- return visibleItems.last();
+ return visibleItems.constLast();
return 0;
}
@@ -752,7 +752,7 @@ bool QQuickListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal buffer
}
}
- while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
+ while (visibleItems.count() > 1 && (item = visibleItems.constLast()) && item->position() > bufferTo) {
if (item->attached->delayRemove())
break;
qCDebug(lcItemViewDelegateLifecycle) << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position() << (QObject *)(item->item);
@@ -839,7 +839,7 @@ void QQuickListViewPrivate::repositionPackageItemAt(QQuickItem *item, int index)
void QQuickListViewPrivate::resetFirstItemPosition(qreal pos)
{
- FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.first());
+ FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.constFirst());
item->setPosition(pos);
}
@@ -848,12 +848,12 @@ void QQuickListViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int
if (!visibleItems.count())
return;
qreal diff = forwards - backwards;
- static_cast<FxListItemSG*>(visibleItems.first())->setPosition(visibleItems.first()->position() + diff);
+ static_cast<FxListItemSG*>(visibleItems.constFirst())->setPosition(visibleItems.constFirst()->position() + diff);
}
void QQuickListViewPrivate::updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult)
{
- if (item != visibleItems.first())
+ if (item != visibleItems.constFirst())
QQuickItemViewPrivate::updateSizeChangesBeforeVisiblePos(item, removeResult);
}
@@ -1270,7 +1270,7 @@ void QQuickListViewPrivate::initializeCurrentItem()
if (!actualItem) {
if (currentIndex == visibleIndex - 1 && visibleItems.count()) {
// We can calculate exact postion in this case
- listItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
+ listItem->setPosition(visibleItems.constFirst()->position() - currentItem->size() - spacing);
} else {
// Create current item now and position as best we can.
// Its position will be corrected when it becomes visible.
@@ -1424,8 +1424,8 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometry
// if visibleItems.first() has resized, adjust its pos since it is used to
// position all subsequent items
- if (visibleItems.count() && item == visibleItems.first()->item) {
- FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.first());
+ if (visibleItems.count() && item == visibleItems.constFirst()->item) {
+ FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.constFirst());
const QRectF oldGeometry(item->x() - diff.x(),
item->y() - diff.y(),
item->width() - diff.width(),
@@ -3111,7 +3111,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
int i = visibleItems.count() - 1;
while (i > 0 && visibleItems.at(i)->index == -1)
--i;
- if (i == 0 && visibleItems.first()->index == -1) {
+ if (i == 0 && visibleItems.constFirst()->index == -1) {
// there are no visible items except items marked for removal
index = visibleItems.count();
} else if (visibleItems.at(i)->index + 1 == modelIndex
@@ -3136,7 +3136,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Change &ch
qreal pos = 0;
if (visibleItems.count()) {
pos = index < visibleItems.count() ? visibleItems.at(index)->position()
- : visibleItems.last()->endPosition()+spacing;
+ : visibleItems.constLast()->endPosition() + spacing;
}
// Update the indexes of the following visible items.
@@ -3271,7 +3271,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
int markerItemIndex = -1;
for (int i=0; i<visibleItems.count(); i++) {
- if (visibleItems[i]->index == afterModelIndex) {
+ if (visibleItems.at(i)->index == afterModelIndex) {
markerItemIndex = i;
break;
}
@@ -3284,7 +3284,7 @@ void QQuickListViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex
- (removalResult.countChangeAfterVisibleItems * (averageSize + spacing));
for (int i=markerItemIndex+1; i<visibleItems.count() && visibleItems.at(i)->position() < viewEndPos; i++) {
- FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems[i]);
+ FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(i));
if (!listItem->transitionScheduledOrRunning()) {
qreal pos = listItem->position();
listItem->setPosition(pos - sizeRemoved);
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 33cc6c9a63..0118d882af 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -405,8 +405,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
/*!
\qmlsignal QtQuick::MouseArea::canceled()
- This signal is emitted when mouse events have been canceled, either because an event was not accepted, or
- because another item stole the mouse event handling.
+ This signal is emitted when mouse events have been canceled, because another item stole the mouse event handling.
This signal is for advanced use: it is useful when there is more than one MouseArea
that is handling input, or when there is a MouseArea inside a \l Flickable. In the latter
@@ -1198,6 +1197,11 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
emit mouseXChanged(&me);
me.setPosition(d->lastPos);
emit mouseYChanged(&me);
+
+ if (!me.isAccepted()) {
+ d->pressed = Qt::NoButton;
+ }
+
if (!oldPressed) {
emit pressedChanged();
emit containsPressChanged();
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index ac5598767a..d31807de7f 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -448,20 +448,12 @@ void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
}
}
updateTouchData(event);
- if (event->type() == QEvent::TouchEnd) {
- //TODO: move to window
- _stealMouse = false;
- setKeepMouseGrab(false);
- setKeepTouchGrab(false);
- ungrabTouchPoints();
- }
+ if (event->type() == QEvent::TouchEnd)
+ ungrab();
break;
}
case QEvent::TouchCancel:
- _stealMouse = false;
- setKeepMouseGrab(false);
- setKeepTouchGrab(false);
- ungrabTouchPoints();
+ ungrab();
break;
default:
QQuickItem::touchEvent(event);
@@ -557,13 +549,13 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
addTouchPoint(&p);
started = true;
} else if (touchPointState & Qt::TouchPointMoved) {
- QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
Q_ASSERT(dtp);
_movedTouchPoints.append(dtp);
updateTouchPoint(dtp,&p);
moved = true;
} else {
- QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
Q_ASSERT(dtp);
updateTouchPoint(dtp,&p);
}
@@ -784,13 +776,12 @@ void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
void QQuickMultiPointTouchArea::ungrab()
{
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ setKeepTouchGrab(false);
+ ungrabTouchPoints();
+
if (_touchPoints.count()) {
- QQuickWindow *c = window();
- if (c && c->mouseGrabberItem() == this) {
- _stealMouse = false;
- setKeepMouseGrab(false);
- }
- setKeepTouchGrab(false);
foreach (QObject *obj, _touchPoints)
static_cast<QQuickTouchPoint*>(obj)->setPressed(false);
emit canceled(_touchPoints.values());
@@ -881,11 +872,7 @@ bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *i, QEvent *eve
if (!shouldFilter(event))
return false;
updateTouchData(event);
- //TODO: verify this behavior
- _stealMouse = false;
- setKeepMouseGrab(false);
- setKeepTouchGrab(false);
- ungrabTouchPoints();
+ ungrab();
}
break;
default:
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index 52913f53f6..b9ef7816e0 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -231,7 +231,7 @@ public:
static QQuickTouchPoint* touchPoint_at(QQmlListProperty<QQuickTouchPoint> *list, int index) {
QQuickMultiPointTouchArea *q = static_cast<QQuickMultiPointTouchArea*>(list->object);
- return q->_touchPrototypes[index];
+ return q->_touchPrototypes.value(index);
}
Q_SIGNALS:
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index 9d24a6c511..b974641cca 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -252,11 +252,11 @@ void QQuickOpenGLShaderEffectCommon::connectPropertySignals(QQuickItem *item,
const UniformData &d = uniformData[shaderType].at(i);
QQmlPropertyData *pd = propCache->property(QString::fromUtf8(d.name), nullptr, nullptr);
if (pd && !pd->isFunction()) {
- if (pd->notifyIndex == -1) {
+ if (pd->notifyIndex() == -1) {
qWarning("QQuickOpenGLShaderEffect: property '%s' does not have notification method!", d.name.constData());
} else {
auto *mapper = signalMappers[shaderType].at(i);
- mapper->setSignalIndex(pd->notifyIndex);
+ mapper->setSignalIndex(pd->notifyIndex());
Q_ASSERT(item->metaObject() == itemMetaObject);
QObjectPrivate::connectImpl(item, mapper->signalIndex(), item, nullptr, mapper,
Qt::AutoConnection, nullptr, itemMetaObject);
@@ -347,7 +347,7 @@ void QQuickOpenGLShaderEffectCommon::lookThroughShaderCode(QQuickItem *item,
} else {
if (QQmlPropertyData *pd = propCache->property(QString::fromUtf8(d.name), nullptr, nullptr)) {
if (!pd->isFunction())
- d.propertyIndex = pd->coreIndex;
+ d.propertyIndex = pd->coreIndex();
}
const int mappedId = uniformData[shaderType].size() | (shaderType << 16);
mapper = new QtPrivate::MappedSlotObject([this, mappedId](){
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index c7e476c4b5..1de20ed5b9 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -245,7 +245,7 @@ void QQuickPathViewPrivate::clear()
currentItem = 0;
}
for (int i=0; i<items.count(); i++){
- QQuickItem *p = items[i];
+ QQuickItem *p = items.at(i);
releaseItem(p);
}
if (requestedIndex >= 0) {
@@ -1993,8 +1993,8 @@ void QQuickPathView::refill()
endPos = -1.0;
startPos = 2.0;
- for (int i = 0; i < d->items.count(); i++) {
- int idx = d->model->indexOf(d->items[i], 0);
+ for (QQuickItem * item : qAsConst(d->items)) {
+ int idx = d->model->indexOf(item, 0);
qreal curPos = d->positionOfIndex(idx);
if (curPos > endPos) {
endPos = curPos;
@@ -2084,7 +2084,7 @@ void QQuickPathView::refill()
if (!waiting && d->items.count() < count+d->cacheSize) {
qCDebug(lcItemViewDelegateLifecycle) << "Checking for pathview middle inserts, items count was" << d->items.count();
idx = startIdx;
- QQuickItem *lastItem = d->items[0];
+ QQuickItem *lastItem = d->items.at(0);
while (idx != endIdx) {
//This gets the reference from the delegate model, and will not re-create
QQuickItem *item = d->getItem(idx, idx+1, nextPos >= 1.0);
@@ -2300,8 +2300,8 @@ void QQuickPathViewPrivate::createCurrentItem()
return;
bool inItems = false;
- for (int i = 0; i < items.count(); i++) {
- if (model->indexOf(items[i], 0) == currentIndex) {
+ for (QQuickItem *item : qAsConst(items)) {
+ if (model->indexOf(item, 0) == currentIndex) {
inItems = true;
break;
}
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index 083e02fe3f..db04a83afc 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -94,7 +94,7 @@ QQuickStochasticEngine::QQuickStochasticEngine(QObject *parent) :
setCount(1);
}
-QQuickStochasticEngine::QQuickStochasticEngine(QList<QQuickStochasticState*> states, QObject *parent) :
+QQuickStochasticEngine::QQuickStochasticEngine(const QList<QQuickStochasticState *> &states, QObject *parent) :
QObject(parent), m_states(states), m_timeOffset(0), m_addAdvance(false)
{
//Default size 1
@@ -122,7 +122,7 @@ QQuickSpriteEngine::~QQuickSpriteEngine()
}
-int QQuickSpriteEngine::maxFrames()
+int QQuickSpriteEngine::maxFrames() const
{
return m_maxFrames;
}
@@ -140,7 +140,7 @@ TODO: Above idea needs to have the varying duration offset added to it
m_startTimes will be set in advance/restart to 0->(m_framesPerRow-1) and can be used directly as extra.
This makes it 'frame' instead, but is more memory efficient than two arrays and less hideous than a vector of unions.
*/
-int QQuickSpriteEngine::pseudospriteProgress(int sprite, int state, int* rowDuration)
+int QQuickSpriteEngine::pseudospriteProgress(int sprite, int state, int* rowDuration) const
{
int myRowDuration = m_duration[sprite] * m_sprites[state]->m_framesPerRow / m_sprites[state]->m_frames;
if (rowDuration)
@@ -153,7 +153,7 @@ int QQuickSpriteEngine::pseudospriteProgress(int sprite, int state, int* rowDura
return (m_timeOffset - m_startTimes[sprite]) / myRowDuration;
}
-int QQuickSpriteEngine::spriteState(int sprite)
+int QQuickSpriteEngine::spriteState(int sprite) const
{
if (!m_loaded)
return 0;
@@ -174,7 +174,7 @@ int QQuickSpriteEngine::spriteState(int sprite)
return state + extra;
}
-int QQuickSpriteEngine::spriteStart(int sprite)
+int QQuickSpriteEngine::spriteStart(int sprite) const
{
if (!m_duration[sprite] || !m_loaded)
return m_timeOffset;
@@ -188,7 +188,7 @@ int QQuickSpriteEngine::spriteStart(int sprite)
return m_startTimes[sprite] + extra*rowDuration;
}
-int QQuickSpriteEngine::spriteFrames(int sprite)
+int QQuickSpriteEngine::spriteFrames(int sprite) const
{
if (!m_loaded)
return 1;
@@ -215,7 +215,7 @@ int QQuickSpriteEngine::spriteFrames(int sprite)
return m_sprites[state]->m_framesPerRow;
}
-int QQuickSpriteEngine::spriteDuration(int sprite)//Full duration, not per frame
+int QQuickSpriteEngine::spriteDuration(int sprite) const //Full duration, not per frame
{
if (!m_duration[sprite] || !m_loaded)
return m_duration[sprite];
@@ -235,7 +235,7 @@ int QQuickSpriteEngine::spriteDuration(int sprite)//Full duration, not per frame
return rowDuration;
}
-int QQuickSpriteEngine::spriteY(int sprite)
+int QQuickSpriteEngine::spriteY(int sprite) const
{
if (!m_loaded)
return 0;
@@ -257,7 +257,7 @@ int QQuickSpriteEngine::spriteY(int sprite)
return m_sprites[state]->m_rowY + m_sprites[state]->m_frameHeight * extra;
}
-int QQuickSpriteEngine::spriteX(int sprite)
+int QQuickSpriteEngine::spriteX(int sprite) const
{
if (!m_loaded)
return 0;
@@ -280,24 +280,24 @@ int QQuickSpriteEngine::spriteX(int sprite)
return m_sprites[state]->m_rowStartX;
}
-QQuickSprite* QQuickSpriteEngine::sprite(int sprite)
+QQuickSprite* QQuickSpriteEngine::sprite(int sprite) const
{
return m_sprites[m_things[sprite]];
}
-int QQuickSpriteEngine::spriteWidth(int sprite)
+int QQuickSpriteEngine::spriteWidth(int sprite) const
{
int state = m_things[sprite];
return m_sprites[state]->m_frameWidth;
}
-int QQuickSpriteEngine::spriteHeight(int sprite)
+int QQuickSpriteEngine::spriteHeight(int sprite) const
{
int state = m_things[sprite];
return m_sprites[state]->m_frameHeight;
}
-int QQuickSpriteEngine::spriteCount()//TODO: Actually image state count, need to rename these things to make sense together
+int QQuickSpriteEngine::spriteCount() const //TODO: Actually image state count, need to rename these things to make sense together
{
return m_imageStateCount;
}
@@ -312,14 +312,14 @@ void QQuickStochasticEngine::setGoal(int state, int sprite, bool jump)
return;
}
- if (m_things[sprite] == state)
+ if (m_things.at(sprite) == state)
return;//Already there
m_things[sprite] = state;
- m_duration[sprite] = m_states[state]->variedDuration();
+ m_duration[sprite] = m_states.at(state)->variedDuration();
m_goals[sprite] = -1;
restart(sprite);
emit stateChanged(sprite);
- emit m_states[state]->entered();
+ emit m_states.at(state)->entered();
return;
}
@@ -516,8 +516,8 @@ void QQuickStochasticEngine::start(int index, int state)
if (index >= m_things.count())
return;
m_things[index] = state;
- m_duration[index] = m_states[state]->variedDuration();
- if (m_states[state]->randomStart())
+ m_duration[index] = m_states.at(state)->variedDuration();
+ if (m_states.at(state)->randomStart())
m_startTimes[index] = NINF;
else
m_startTimes[index] = 0;
@@ -538,33 +538,33 @@ void QQuickStochasticEngine::stop(int index)
void QQuickStochasticEngine::restart(int index)
{
- bool randomStart = (m_startTimes[index] == NINF);
+ bool randomStart = (m_startTimes.at(index) == NINF);
m_startTimes[index] = m_timeOffset;
if (m_addAdvance)
m_startTimes[index] += m_advanceTime.elapsed();
if (randomStart)
- m_startTimes[index] -= qrand() % m_duration[index];
- int time = m_duration[index] + m_startTimes[index];
+ m_startTimes[index] -= qrand() % m_duration.at(index);
+ int time = m_duration.at(index) + m_startTimes.at(index);
for (int i=0; i<m_stateUpdates.count(); i++)
m_stateUpdates[i].second.removeAll(index);
- if (m_duration[index] >= 0)
+ if (m_duration.at(index) >= 0)
addToUpdateList(time, index);
}
void QQuickSpriteEngine::restart(int index) //Reimplemented to recognize and handle pseudostates
{
- bool randomStart = (m_startTimes[index] == NINF);
- if (m_loaded && m_sprites[m_things[index]]->frameSync()) {//Manually advanced
+ bool randomStart = (m_startTimes.at(index) == NINF);
+ if (m_loaded && m_sprites.at(m_things.at(index))->frameSync()) {//Manually advanced
m_startTimes[index] = 0;
- if (randomStart && m_sprites[m_things[index]]->m_generatedCount)
- m_startTimes[index] += qrand() % m_sprites[m_things[index]]->m_generatedCount;
+ if (randomStart && m_sprites.at(m_things.at(index))->m_generatedCount)
+ m_startTimes[index] += qrand() % m_sprites.at(m_things.at(index))->m_generatedCount;
} else {
m_startTimes[index] = m_timeOffset;
if (m_addAdvance)
m_startTimes[index] += m_advanceTime.elapsed();
if (randomStart)
- m_startTimes[index] -= qrand() % m_duration[index];
- int time = spriteDuration(index) + m_startTimes[index];
+ m_startTimes[index] -= qrand() % m_duration.at(index);
+ int time = spriteDuration(index) + m_startTimes.at(index);
if (randomStart) {
int curTime = m_timeOffset + (m_addAdvance ? m_advanceTime.elapsed() : 0);
while (time < curTime) //Fast forward through psuedostates as needed
@@ -581,11 +581,11 @@ void QQuickStochasticEngine::advance(int idx)
{
if (idx >= m_things.count())
return;//TODO: Proper fix(because this has happened and I just ignored it)
- int nextIdx = nextState(m_things[idx],idx);
+ int nextIdx = nextState(m_things.at(idx), idx);
m_things[idx] = nextIdx;
- m_duration[idx] = m_states[nextIdx]->variedDuration();
+ m_duration[idx] = m_states.at(nextIdx)->variedDuration();
restart(idx);
- emit m_states[nextIdx]->entered();
+ emit m_states.at(nextIdx)->entered();
emit stateChanged(idx);
}
@@ -598,29 +598,29 @@ void QQuickSpriteEngine::advance(int idx) //Reimplemented to recognize and handl
if (idx >= m_things.count())
return;//TODO: Proper fix(because this has happened and I just ignored it)
- if (m_duration[idx] == 0) {
- if (m_sprites[m_things[idx]]->frameSync()) {
+ if (m_duration.at(idx) == 0) {
+ if (m_sprites.at(m_things.at(idx))->frameSync()) {
//Manually called, advance inner substate count
m_startTimes[idx]++;
- if (m_startTimes[idx] < m_sprites[m_things[idx]]->m_generatedCount) {
+ if (m_startTimes.at(idx) < m_sprites.at(m_things.at(idx))->m_generatedCount) {
//only a pseudostate ended
emit stateChanged(idx);
return;
}
}
//just go past the pseudostate logic
- } else if (m_startTimes[idx] + m_duration[idx]
+ } else if (m_startTimes.at(idx) + m_duration.at(idx)
> int(m_timeOffset + (m_addAdvance ? m_advanceTime.elapsed() : 0))) {
//only a pseduostate ended
emit stateChanged(idx);
addToUpdateList(spriteStart(idx) + spriteDuration(idx) + (m_addAdvance ? m_advanceTime.elapsed() : 0), idx);
return;
}
- int nextIdx = nextState(m_things[idx],idx);
+ int nextIdx = nextState(m_things.at(idx), idx);
m_things[idx] = nextIdx;
- m_duration[idx] = m_states[nextIdx]->variedDuration();
+ m_duration[idx] = m_states.at(nextIdx)->variedDuration();
restart(idx);
- emit m_states[nextIdx]->entered();
+ emit m_states.at(nextIdx)->entered();
emit stateChanged(idx);
}
@@ -631,16 +631,16 @@ int QQuickStochasticEngine::nextState(int curState, int curThing)
if (goalPath == -1){//Random
qreal r =(qreal) qrand() / (qreal) RAND_MAX;
qreal total = 0.0;
- for (QVariantMap::const_iterator iter=m_states[curState]->m_to.constBegin();
- iter!=m_states[curState]->m_to.constEnd(); ++iter)
+ for (QVariantMap::const_iterator iter=m_states.at(curState)->m_to.constBegin();
+ iter!=m_states.at(curState)->m_to.constEnd(); ++iter)
total += (*iter).toReal();
r*=total;
- for (QVariantMap::const_iterator iter= m_states[curState]->m_to.constBegin();
- iter!=m_states[curState]->m_to.constEnd(); ++iter){
+ for (QVariantMap::const_iterator iter= m_states.at(curState)->m_to.constBegin();
+ iter!=m_states.at(curState)->m_to.constEnd(); ++iter){
if (r < (*iter).toReal()){
bool superBreak = false;
for (int i=0; i<m_states.count(); i++){
- if (m_states[i]->name() == iter.key()){
+ if (m_states.at(i)->name() == iter.key()){
nextIdx = i;
superBreak = true;
break;
@@ -664,8 +664,8 @@ uint QQuickStochasticEngine::updateSprites(uint time)//### would returning a lis
//Sprite State Update;
m_timeOffset = time;
m_addAdvance = false;
- while (!m_stateUpdates.isEmpty() && time >= m_stateUpdates.first().first){
- foreach (int idx, m_stateUpdates.first().second)
+ while (!m_stateUpdates.isEmpty() && time >= m_stateUpdates.constFirst().first){
+ foreach (int idx, m_stateUpdates.constFirst().second)
advance(idx);
m_stateUpdates.pop_front();
}
@@ -674,14 +674,14 @@ uint QQuickStochasticEngine::updateSprites(uint time)//### would returning a lis
m_addAdvance = true;
if (m_stateUpdates.isEmpty())
return uint(-1);
- return m_stateUpdates.first().first;
+ return m_stateUpdates.constFirst().first;
}
int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
{
QString goalName;
- if (m_goals[spriteIdx] != -1)
- goalName = m_states[m_goals[spriteIdx]]->name();
+ if (m_goals.at(spriteIdx) != -1)
+ goalName = m_states.at(m_goals.at(spriteIdx))->name();
else
goalName = m_globalGoal;
if (goalName.isEmpty())
@@ -689,16 +689,16 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
//TODO: caching instead of excessively redoing iterative deepening (which was chosen arbitrarily anyways)
// Paraphrased - implement in an *efficient* manner
for (int i=0; i<m_states.count(); i++)
- if (m_states[curIdx]->name() == goalName)
+ if (m_states.at(curIdx)->name() == goalName)
return curIdx;
if (dist < 0)
dist = m_states.count();
- QQuickStochasticState* curState = m_states[curIdx];
+ QQuickStochasticState* curState = m_states.at(curIdx);
for (QVariantMap::const_iterator iter = curState->m_to.constBegin();
iter!=curState->m_to.constEnd(); ++iter){
if (iter.key() == goalName)
for (int i=0; i<m_states.count(); i++)
- if (m_states[i]->name() == goalName)
+ if (m_states.at(i)->name() == goalName)
return i;
}
QSet<int> options;
@@ -707,7 +707,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
iter!=curState->m_to.constEnd(); ++iter){
int option = -1;
for (int j=0; j<m_states.count(); j++)//One place that could be a lot more efficient...
- if (m_states[j]->name() == iter.key())
+ if (m_states.at(j)->name() == iter.key())
if (goalSeek(j, spriteIdx, i) != -1)
option = j;
if (option != -1)
@@ -721,13 +721,13 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
qreal total = 0;
for (QSet<int>::const_iterator iter=options.constBegin();
iter!=options.constEnd(); ++iter)
- total += curState->m_to.value(m_states[(*iter)]->name()).toReal();
+ total += curState->m_to.value(m_states.at((*iter))->name()).toReal();
r *= total;
for (QVariantMap::const_iterator iter = curState->m_to.constBegin();
iter!=curState->m_to.constEnd(); ++iter){
bool superContinue = true;
for (int j=0; j<m_states.count(); j++)
- if (m_states[j]->name() == iter.key())
+ if (m_states.at(j)->name() == iter.key())
if (options.contains(j))
superContinue = false;
if (superContinue)
@@ -735,7 +735,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
if (r < (*iter).toReal()){
bool superBreak = false;
for (int j=0; j<m_states.count(); j++){
- if (m_states[j]->name() == iter.key()){
+ if (m_states.at(j)->name() == iter.key()){
option = j;
superBreak = true;
break;
@@ -755,10 +755,10 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist)
void QQuickStochasticEngine::addToUpdateList(uint t, int idx)
{
for (int i=0; i<m_stateUpdates.count(); i++){
- if (m_stateUpdates[i].first==t){
+ if (m_stateUpdates.at(i).first == t){
m_stateUpdates[i].second << idx;
return;
- }else if (m_stateUpdates[i].first > t){
+ } else if (m_stateUpdates.at(i).first > t) {
QList<int> tmpList;
tmpList << idx;
m_stateUpdates.insert(i, qMakePair(t, tmpList));
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
index 1bdcc9a741..424fa18a54 100644
--- a/src/quick/items/qquickspriteengine_p.h
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -189,7 +189,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickStochasticEngine : public QObject
Q_PROPERTY(QQmlListProperty<QQuickStochasticState> states READ states)
public:
explicit QQuickStochasticEngine(QObject *parent = 0);
- QQuickStochasticEngine(QList<QQuickStochasticState*> states, QObject *parent=0);
+ QQuickStochasticEngine(const QList<QQuickStochasticState*> &states, QObject *parent = 0);
~QQuickStochasticEngine();
QQmlListProperty<QQuickStochasticState> states()
@@ -210,11 +210,11 @@ public:
virtual void restart(int index=0);
virtual void advance(int index=0);//Sends state to the next chosen state, unlike goal.
void stop(int index=0);
- int curState(int index=0) {return m_things[index];}
+ int curState(int index=0) const {return m_things[index];}
- QQuickStochasticState* state(int idx){return m_states[idx];}
- int stateIndex(QQuickStochasticState* s){return m_states.indexOf(s);}
- int stateIndex(const QString& s) {
+ QQuickStochasticState* state(int idx) const {return m_states[idx];}
+ int stateIndex(QQuickStochasticState* s) const {return m_states.indexOf(s);}
+ int stateIndex(const QString& s) const {
for (int i=0; i<m_states.count(); i++)
if (m_states[i]->name() == s)
return i;
@@ -273,17 +273,17 @@ public:
return QQmlListProperty<QQuickSprite>(this, m_sprites);
}
- QQuickSprite* sprite(int sprite=0);
- int spriteState(int sprite=0);
- int spriteStart(int sprite=0);
- int spriteFrames(int sprite=0);
- int spriteDuration(int sprite=0);
- int spriteX(int sprite=0);
- int spriteY(int sprite=0);
- int spriteWidth(int sprite=0);
- int spriteHeight(int sprite=0);
- int spriteCount();//Like state count
- int maxFrames();
+ QQuickSprite* sprite(int sprite = 0) const;
+ int spriteState(int sprite = 0) const;
+ int spriteStart(int sprite = 0) const;
+ int spriteFrames(int sprite = 0) const;
+ int spriteDuration(int sprite = 0) const;
+ int spriteX(int sprite = 0) const;
+ int spriteY(int sprite = 0) const;
+ int spriteWidth(int sprite = 0) const;
+ int spriteHeight(int sprite = 0) const;
+ int spriteCount() const;//Like state count
+ int maxFrames() const;
void restart(int index=0) Q_DECL_OVERRIDE;
void advance(int index=0) Q_DECL_OVERRIDE;
@@ -298,7 +298,7 @@ public:
QImage assembledImage(int maxSize = 2048);
private:
- int pseudospriteProgress(int,int,int*rd=0);
+ int pseudospriteProgress(int, int, int *rd = 0) const;
QList<QQuickSprite*> m_sprites;
bool m_startedImageAssembly;
bool m_loaded;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index a2c82c30a0..f958d1a087 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -471,7 +471,6 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
QQuickWindowPrivate::QQuickWindowPrivate()
: contentItem(0)
, activeFocusItem(0)
- , mouseGrabberItem(0)
#ifndef QT_NO_CURSOR
, cursorItem(0)
#endif
@@ -479,6 +478,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, dragGrabber(0)
#endif
, touchMouseId(-1)
+ , touchMouseDevice(nullptr)
, touchMousePressTimestamp(0)
, dirtyItemList(0)
, devicePixelRatio(0)
@@ -486,7 +486,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, renderer(0)
, windowManager(0)
, renderControl(0)
- , touchRecursionGuard(0)
+ , pointerEventRecursionGuard(0)
, customRenderStage(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
@@ -622,8 +622,15 @@ bool QQuickWindowPrivate::checkIfDoubleClicked(ulong newPressEventTimestamp)
return doubleClicked;
}
-bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *event)
+bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent)
{
+ Q_Q(QQuickWindow);
+ auto device = pointerEvent->device();
+
+ // FIXME: make this work for mouse events too and get rid of the asTouchEvent in here.
+ Q_ASSERT(pointerEvent->asPointerTouchEvent());
+ QTouchEvent *event = pointerEvent->asPointerTouchEvent()->touchEventForItem(item);
+
// For each point, check if it is accepted, if not, try the next point.
// Any of the fingers can become the mouse one.
// This can happen because a mouse area might not accept an event at some point but another.
@@ -637,65 +644,45 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
if (!item->contains(pos))
break;
- // Store the id already here and restore it to -1 if the event does not get
- // accepted. Cannot defer setting the new value because otherwise if the event
- // handler spins the event loop all subsequent moves and releases get lost.
- touchMouseId = p.id();
- itemForTouchPointId[touchMouseId] = item;
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << p.id() << "->" << item;
QScopedPointer<QMouseEvent> mousePress(touchToMouseEvent(QEvent::MouseButtonPress, p, event, item, false));
// Send a single press and see if that's accepted
- if (!mouseGrabberItem)
- item->grabMouse();
- item->grabTouchPoints(QVector<int>() << touchMouseId);
-
QCoreApplication::sendEvent(item, mousePress.data());
event->setAccepted(mousePress->isAccepted());
- if (!mousePress->isAccepted()) {
- touchMouseId = -1;
- if (itemForTouchPointId.value(p.id()) == item) {
- qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << p.id() << "disassociated";
- itemForTouchPointId.remove(p.id());
+ if (mousePress->isAccepted()) {
+ touchMouseDevice = device;
+ touchMouseId = p.id();
+ if (!q->mouseGrabberItem())
+ item->grabMouse();
+ auto pointerEventPoint = pointerEvent->pointById(p.id());
+ pointerEventPoint->setGrabber(item);
+
+ if (checkIfDoubleClicked(event->timestamp())) {
+ QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item, false));
+ QCoreApplication::sendEvent(item, mouseDoubleClick.data());
+ event->setAccepted(mouseDoubleClick->isAccepted());
+ if (!mouseDoubleClick->isAccepted()) {
+ touchMouseId = -1;
+ touchMouseDevice = nullptr;
+ }
}
- if (mouseGrabberItem == item)
- item->ungrabMouse();
- }
-
- if (mousePress->isAccepted() && checkIfDoubleClicked(event->timestamp())) {
- QScopedPointer<QMouseEvent> mouseDoubleClick(touchToMouseEvent(QEvent::MouseButtonDblClick, p, event, item, false));
- QCoreApplication::sendEvent(item, mouseDoubleClick.data());
- event->setAccepted(mouseDoubleClick->isAccepted());
- if (mouseDoubleClick->isAccepted()) {
- touchMouseIdCandidates.clear();
- return true;
- } else {
- touchMouseId = -1;
- }
- }
- // The event was accepted, we are done.
- if (mousePress->isAccepted()) {
- touchMouseIdCandidates.clear();
return true;
}
- // The event was not accepted but touchMouseId was set.
- if (touchMouseId != -1)
- return false;
// try the next point
// Touch point was there before and moved
- } else if (p.id() == touchMouseId) {
+ } else if (touchMouseDevice == device && p.id() == touchMouseId) {
if (p.state() & Qt::TouchPointMoved) {
- if (mouseGrabberItem) {
+ if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseMove, p, event, mouseGrabberItem, false));
QCoreApplication::sendEvent(item, me.data());
event->setAccepted(me->isAccepted());
if (me->isAccepted()) {
qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << p.id() << "->" << mouseGrabberItem;
- itemForTouchPointId[p.id()] = mouseGrabberItem; // N.B. the mouseGrabberItem may be different after returning from sendEvent()
- return true;
}
+ return event->isAccepted();
} else {
// no grabber, check if we care about mouse hover
// FIXME: this should only happen once, not recursively... I'll ignore it just ignore hover now.
@@ -718,7 +705,8 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
} else if (p.state() & Qt::TouchPointReleased) {
// currently handled point was released
touchMouseId = -1;
- if (mouseGrabberItem) {
+ touchMouseDevice = nullptr;
+ if (QQuickItem *mouseGrabberItem = q->mouseGrabberItem()) {
QScopedPointer<QMouseEvent> me(touchToMouseEvent(QEvent::MouseButtonRelease, p, event, mouseGrabberItem, false));
QCoreApplication::sendEvent(item, me.data());
@@ -730,8 +718,8 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
Qt::NoButton, Qt::NoButton, event->modifiers());
QCoreApplication::sendEvent(item, &mm);
}
- if (mouseGrabberItem) // might have ungrabbed due to event
- mouseGrabberItem->ungrabMouse();
+ if (q->mouseGrabberItem()) // might have ungrabbed due to event
+ q->mouseGrabberItem()->ungrabMouse();
return me->isAccepted();
}
}
@@ -744,25 +732,29 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e
void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
{
Q_Q(QQuickWindow);
- if (mouseGrabberItem == grabber)
+ if (q->mouseGrabberItem() == grabber)
return;
- qCDebug(DBG_MOUSE_TARGET) << "grabber" << mouseGrabberItem << "->" << grabber;
- QQuickItem *oldGrabber = mouseGrabberItem;
- mouseGrabberItem = grabber;
+ qCDebug(DBG_MOUSE_TARGET) << "grabber" << q->mouseGrabberItem() << "->" << grabber;
+ QQuickItem *oldGrabber = q->mouseGrabberItem();
+
+ QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent();
+ Q_ASSERT(event->pointCount() == 1);
+ event->point(0)->setGrabber(grabber);
- if (touchMouseId != -1) {
+ if (grabber && touchMouseId != -1 && touchMouseDevice) {
// update the touch item for mouse touch id to the new grabber
- itemForTouchPointId.remove(touchMouseId);
- if (grabber) {
- qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << touchMouseId << "->" << mouseGrabberItem;
- itemForTouchPointId[touchMouseId] = grabber;
- }
+ qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << touchMouseId << "->" << q->mouseGrabberItem();
+ auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId);
+ if (point)
+ point->setGrabber(grabber);
}
if (oldGrabber) {
- QEvent ev(QEvent::UngrabMouse);
- q->sendEvent(oldGrabber, &ev);
+ QEvent e(QEvent::UngrabMouse);
+ QSet<QQuickItem *> hasFiltered;
+ if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered))
+ oldGrabber->mouseUngrabEvent();
}
}
@@ -771,20 +763,24 @@ void QQuickWindowPrivate::grabTouchPoints(QQuickItem *grabber, const QVector<int
Q_Q(QQuickWindow);
QSet<QQuickItem*> ungrab;
for (int i = 0; i < ids.count(); ++i) {
- QQuickItem *oldGrabber = itemForTouchPointId.value(ids.at(i));
- if (oldGrabber == grabber)
- continue;
+ // FIXME: deprecate this function, we need a device
+ for (auto device: QQuickPointerDevice::touchDevices()) {
+ auto point = device->pointerEvent()->pointById(ids.at(i));
+ if (!point)
+ continue;
+ QQuickItem *oldGrabber = point->grabber();
+ if (oldGrabber == grabber)
+ continue;
- itemForTouchPointId[ids.at(i)] = grabber;
- if (oldGrabber)
- ungrab.insert(oldGrabber);
+ point->setGrabber(grabber);
+ if (oldGrabber)
+ ungrab.insert(oldGrabber);
+ }
- QQuickItem *originalMouseGrabberItem = mouseGrabberItem;
+ QQuickItem *mouseGrabberItem = q->mouseGrabberItem();
if (touchMouseId == ids.at(i) && mouseGrabberItem && mouseGrabberItem != grabber) {
qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: grabber" << mouseGrabberItem << "-> null";
- mouseGrabberItem = 0;
- QEvent ev(QEvent::UngrabMouse);
- q->sendEvent(originalMouseGrabberItem, &ev);
+ setMouseGrabber(nullptr);
}
}
foreach (QQuickItem *oldGrabber, ungrab)
@@ -795,35 +791,23 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
{
Q_Q(QQuickWindow);
if (Q_LIKELY(touch)) {
- QMutableHashIterator<int, QQuickItem *> itemTouchMapIt(itemForTouchPointId);
- while (itemTouchMapIt.hasNext()) {
- if (itemTouchMapIt.next().value() == grabber) {
- itemTouchMapIt.remove();
- grabber->touchUngrabEvent();
+ for (auto device: QQuickPointerDevice::touchDevices()) {
+ auto pointerEvent = device->pointerEvent();
+ for (int i = 0; i < pointerEvent->pointCount(); ++i) {
+ if (pointerEvent->point(i)->grabber() == grabber) {
+ pointerEvent->point(i)->setGrabber(nullptr);
+ // FIXME send ungrab event only once
+ grabber->touchUngrabEvent();
+ }
}
}
}
- if (Q_LIKELY(mouse) && mouseGrabberItem == grabber) {
- qCDebug(DBG_MOUSE_TARGET) << "removeGrabber" << mouseGrabberItem << "-> null";
- mouseGrabberItem = 0;
- QEvent ev(QEvent::UngrabMouse);
- q->sendEvent(grabber, &ev);
- }
-}
-
-void QQuickWindowPrivate::transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform)
-{
- QMatrix4x4 transformMatrix(transform);
- for (int i=0; i<touchPoints.count(); i++) {
- QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
- touchPoint.setRect(transform.mapRect(touchPoint.sceneRect()));
- touchPoint.setStartPos(transform.map(touchPoint.startScenePos()));
- touchPoint.setLastPos(transform.map(touchPoint.lastScenePos()));
- touchPoint.setVelocity(transformMatrix.mapVector(touchPoint.velocity()).toVector2D());
+ if (Q_LIKELY(mouse) && q->mouseGrabberItem() == grabber) {
+ qCDebug(DBG_MOUSE_TARGET) << "removeGrabber" << q->mouseGrabberItem() << "-> null";
+ setMouseGrabber(nullptr);
}
}
-
/*!
Translates the data in \a touchEvent to this window. This method leaves the item local positions in
\a touchEvent untouched (these are filled in later).
@@ -837,9 +821,6 @@ void QQuickWindowPrivate::translateTouchEvent(QTouchEvent *touchEvent)
touchPoint.setSceneRect(touchPoint.rect());
touchPoint.setStartScenePos(touchPoint.startPos());
touchPoint.setLastScenePos(touchPoint.lastPos());
-
- if (i == 0)
- lastMousePosition = touchPoint.pos().toPoint();
}
touchEvent->setTouchPoints(touchPoints);
}
@@ -950,17 +931,16 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
}
// Now that all the state is changed, emit signals & events
- // We must do this last, as this process may result in further changes to
- // focus.
+ // We must do this last, as this process may result in further changes to focus.
if (oldActiveFocusItem) {
QFocusEvent event(QEvent::FocusOut, reason);
- q->sendEvent(oldActiveFocusItem, &event);
+ QCoreApplication::sendEvent(oldActiveFocusItem, &event);
}
// Make sure that the FocusOut didn't result in another focus change.
if (sendFocusIn && activeFocusItem == newActiveFocusItem) {
QFocusEvent event(QEvent::FocusIn, reason);
- q->sendEvent(newActiveFocusItem, &event);
+ QCoreApplication::sendEvent(newActiveFocusItem, &event);
}
if (activeFocusItem != currentActiveFocusItem)
@@ -1047,13 +1027,13 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
// focus.
if (oldActiveFocusItem) {
QFocusEvent event(QEvent::FocusOut, reason);
- q->sendEvent(oldActiveFocusItem, &event);
+ QCoreApplication::sendEvent(oldActiveFocusItem, &event);
}
// Make sure that the FocusOut didn't result in another focus change.
if (newActiveFocusItem && activeFocusItem == newActiveFocusItem) {
QFocusEvent event(QEvent::FocusIn, reason);
- q->sendEvent(newActiveFocusItem, &event);
+ QCoreApplication::sendEvent(newActiveFocusItem, &event);
}
if (activeFocusItem != currentActiveFocusItem)
@@ -1482,9 +1462,9 @@ QObject *QQuickWindow::focusObject() const
*/
QQuickItem *QQuickWindow::mouseGrabberItem() const
{
- Q_D(const QQuickWindow);
-
- return d->mouseGrabberItem;
+ QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent();
+ Q_ASSERT(event->pointCount());
+ return event->point(0)->grabber();
}
@@ -1529,7 +1509,7 @@ bool QQuickWindow::event(QEvent *e)
break;
case QEvent::Leave:
d->clearHover();
- d->lastMousePosition = QPoint();
+ d->lastMousePosition = QPointF();
break;
#ifndef QT_NO_DRAGANDDROP
case QEvent::DragEnter:
@@ -1555,8 +1535,8 @@ bool QQuickWindow::event(QEvent *e)
if (d->activeFocusItem)
qGuiApp->inputMethod()->commit();
#endif
- if (d->mouseGrabberItem)
- d->mouseGrabberItem->ungrabMouse();
+ if (mouseGrabberItem())
+ mouseGrabberItem()->ungrabMouse();
break;
case QEvent::UpdateRequest: {
if (d->windowManager)
@@ -1570,7 +1550,7 @@ bool QQuickWindow::event(QEvent *e)
#endif
case QEvent::ShortcutOverride:
if (d->activeFocusItem)
- sendEvent(d->activeFocusItem, static_cast<QKeyEvent *>(e));
+ QCoreApplication::sendEvent(d->activeFocusItem, e);
return true;
default:
break;
@@ -1622,78 +1602,44 @@ QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *t
return me;
}
-bool QQuickWindowPrivate::deliverInitialMousePressEvent(QQuickItem *item, QMouseEvent *event)
+void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent)
{
Q_Q(QQuickWindow);
-
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
- if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- QPointF p = item->mapFromScene(event->windowPos());
- if (!item->contains(p))
- return false;
- }
-
- QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
- for (int ii = children.count() - 1; ii >= 0; --ii) {
- QQuickItem *child = children.at(ii);
- if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
- continue;
- if (deliverInitialMousePressEvent(child, event))
- return true;
- }
-
- if (itemPrivate->acceptedMouseButtons() & event->button()) {
- QPointF localPos = item->mapFromScene(event->windowPos());
- if (item->contains(localPos)) {
- QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
- me->accept();
- item->grabMouse();
- q->sendEvent(item, me.data());
- event->setAccepted(me->isAccepted());
- if (me->isAccepted())
- return true;
- if (mouseGrabberItem)
- mouseGrabberItem->ungrabMouse();
+ auto point = pointerEvent->point(0);
+ lastMousePosition = point->scenePos();
+ QQuickItem *grabber = point->grabber();
+ if (grabber) {
+ // if the update consists of changing button state, then don't accept it
+ // unless the button is one in which the item is interested
+ if (pointerEvent->button() != Qt::NoButton
+ && grabber->acceptedMouseButtons()
+ && !(grabber->acceptedMouseButtons() & pointerEvent->button())) {
+ pointerEvent->setAccepted(false);
+ return;
}
- }
- return false;
-}
-
-bool QQuickWindowPrivate::deliverMouseEvent(QMouseEvent *event)
-{
- Q_Q(QQuickWindow);
-
- lastMousePosition = event->windowPos();
-
- if (!mouseGrabberItem &&
- event->type() == QEvent::MouseButtonPress &&
- (event->buttons() & event->button()) == event->buttons()) {
- if (deliverInitialMousePressEvent(contentItem, event))
- event->accept();
- else
- event->ignore();
- return event->isAccepted();
- }
+ // send update
+ QPointF localPos = grabber->mapFromScene(lastMousePosition);
+ auto me = pointerEvent->asMouseEvent(localPos);
+ me->accept();
+ q->sendEvent(grabber, me);
+ point->setAccepted(me->isAccepted());
- if (mouseGrabberItem) {
- if (event->button() != Qt::NoButton
- && mouseGrabberItem->acceptedMouseButtons()
- && !(mouseGrabberItem->acceptedMouseButtons() & event->button())) {
- event->ignore();
- return false;
+ // release event, make sure to ungrab if there still is a grabber
+ if (me->type() == QEvent::MouseButtonRelease && !me->buttons() && q->mouseGrabberItem())
+ q->mouseGrabberItem()->ungrabMouse();
+ } else {
+ // send initial press
+ bool delivered = false;
+ if (pointerEvent->isPressEvent()) {
+ QSet<QQuickItem*> hasFiltered;
+ delivered = deliverPressEvent(pointerEvent, &hasFiltered);
}
- QPointF localPos = mouseGrabberItem->mapFromScene(event->windowPos());
- QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
- me->accept();
- q->sendEvent(mouseGrabberItem, me.data());
- event->setAccepted(me->isAccepted());
- if (me->isAccepted())
- return true;
- }
- return false;
+ if (!delivered)
+ // make sure not to accept unhandled events
+ pointerEvent->setAccepted(false);
+ }
}
bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
@@ -1701,7 +1647,6 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
Qt::KeyboardModifiers modifiers, ulong timestamp,
bool accepted)
{
- Q_Q(QQuickWindow);
const QTransform transform = QQuickItemPrivate::get(item)->windowToItemTransform();
//create copy of event
@@ -1714,7 +1659,7 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
return true;
}
- q->sendEvent(item, &hoverEvent);
+ QCoreApplication::sendEvent(item, &hoverEvent);
return hoverEvent.isAccepted();
}
@@ -1746,7 +1691,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
if (itemPrivate->hoverEnabled) {
QPointF p = item->mapFromScene(scenePos);
if (item->contains(p)) {
- if (!hoverItems.isEmpty() && hoverItems[0] == item) {
+ if (!hoverItems.isEmpty() && hoverItems.at(0) == item) {
//move
accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted);
} else {
@@ -1757,24 +1702,24 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
itemsToHover << parent;
// Leaving from previous hovered items until we reach the item or one of its ancestors.
- while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) {
+ while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems.at(0))) {
QQuickItem *hoverLeaveItem = hoverItems.takeFirst();
sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, timestamp, accepted);
}
- if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item
+ if (!hoverItems.isEmpty() && hoverItems.at(0) == item) {//Not entering a new Item
// ### Shouldn't we send moves for the parent items as well?
accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted);
} else {
// Enter items that are not entered yet.
int startIdx = -1;
if (!hoverItems.isEmpty())
- startIdx = itemsToHover.indexOf(hoverItems[0]) - 1;
+ startIdx = itemsToHover.indexOf(hoverItems.at(0)) - 1;
if (startIdx == -1)
startIdx = itemsToHover.count() - 1;
for (int i = startIdx; i >= 0; i--) {
- QQuickItem *itemToHover = itemsToHover[i];
+ QQuickItem *itemToHover = itemsToHover.at(i);
QQuickItemPrivate *itemToHoverPrivate = QQuickItemPrivate::get(itemToHover);
// The item may be about to be deleted or reparented to another window
// due to another hover event delivered in this function. If that is the
@@ -1798,7 +1743,6 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce
#ifndef QT_NO_WHEELEVENT
bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event)
{
- Q_Q(QQuickWindow);
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
@@ -1822,7 +1766,7 @@ bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event
QWheelEvent wheel(p, p, event->pixelDelta(), event->angleDelta(), event->delta(),
event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted());
wheel.accept();
- q->sendEvent(item, &wheel);
+ QCoreApplication::sendEvent(item, &wheel);
if (wheel.isAccepted()) {
event->accept();
return true;
@@ -1889,20 +1833,22 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
{
qCDebug(DBG_TOUCH) << event;
Q_Q(QQuickWindow);
+
// A TouchCancel event will typically not contain any points.
// Deliver it to all items that have active touches.
- QSet<QQuickItem *> cancelDelivered;
- foreach (QQuickItem *item, itemForTouchPointId) {
- if (cancelDelivered.contains(item))
- continue;
- cancelDelivered.insert(item);
- q->sendEvent(item, event);
+ QQuickPointerEvent *pointerEvent = QQuickPointerDevice::touchDevice(event->device())->pointerEvent();
+ QVector<QQuickItem *> grabbers = pointerEvent->grabbers();
+
+ for (QQuickItem *grabber: qAsConst(grabbers)) {
+ q->sendEvent(grabber, event);
}
touchMouseId = -1;
- if (mouseGrabberItem)
- mouseGrabberItem->ungrabMouse();
+ touchMouseDevice = nullptr;
+ if (q->mouseGrabberItem())
+ q->mouseGrabberItem()->ungrabMouse();
+
// The next touch event can only be a TouchBegin so clean up.
- itemForTouchPointId.clear();
+ pointerEvent->clearGrabbers();
return true;
}
@@ -1912,7 +1858,7 @@ void QQuickWindowPrivate::deliverDelayedTouchEvent()
// Set delayedTouch to 0 before delivery to avoid redelivery in case of
// event loop recursions (e.g if it the touch starts a dnd session).
QScopedPointer<QTouchEvent> e(delayedTouch.take());
- deliverTouchEvent(e.data());
+ deliverPointerEvent(pointerEventInstance(e.data()));
}
static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION");
@@ -1988,17 +1934,20 @@ bool QQuickWindowPrivate::compressTouchEvent(QTouchEvent *event)
void QQuickWindowPrivate::handleTouchEvent(QTouchEvent *event)
{
translateTouchEvent(event);
+ if (event->touchPoints().size())
+ lastMousePosition = event->touchPoints().at(0).pos();
+
qCDebug(DBG_TOUCH) << event;
- if (qquickwindow_no_touch_compression || touchRecursionGuard) {
- deliverTouchEvent(event);
+ if (qquickwindow_no_touch_compression || pointerEventRecursionGuard) {
+ deliverPointerEvent(pointerEventInstance(event));
return;
}
if (!compressTouchEvent(event)) {
if (delayedTouch)
deliverDelayedTouchEvent();
- deliverTouchEvent(event);
+ deliverPointerEvent(pointerEventInstance(event));
}
}
@@ -2029,6 +1978,8 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event)
void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
{
+ Q_Q(QQuickWindow);
+
if (event->source() == Qt::MouseEventSynthesizedBySystem) {
event->accept();
return;
@@ -2039,33 +1990,17 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
case QEvent::MouseButtonPress:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMousePress, event->button(),
event->buttons());
- deliverMouseEvent(event);
+ deliverPointerEvent(pointerEventInstance(event));
break;
case QEvent::MouseButtonRelease:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseRelease, event->button(),
event->buttons());
- if (!mouseGrabberItem) {
- event->ignore();
- return;
- }
-
- deliverMouseEvent(event);
- if (mouseGrabberItem && !event->buttons())
- mouseGrabberItem->ungrabMouse();
+ deliverPointerEvent(pointerEventInstance(event));
break;
case QEvent::MouseButtonDblClick:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseDoubleClick,
event->button(), event->buttons());
-
- if (!mouseGrabberItem && (event->buttons() & event->button()) == event->buttons()) {
- if (deliverInitialMousePressEvent(contentItem, event))
- event->accept();
- else
- event->ignore();
- return;
- }
-
- deliverMouseEvent(event);
+ deliverPointerEvent(pointerEventInstance(event));
break;
case QEvent::MouseMove:
Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseMove,
@@ -2077,10 +2012,8 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
updateCursor(event->windowPos());
#endif
- if (!mouseGrabberItem) {
- if (lastMousePosition.isNull())
- lastMousePosition = event->windowPos();
- QPointF last = lastMousePosition;
+ if (!q->mouseGrabberItem()) {
+ QPointF last = lastMousePosition.isNull() ? event->windowPos() : lastMousePosition;
lastMousePosition = event->windowPos();
bool accepted = event->isAccepted();
@@ -2092,7 +2025,7 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
event->setAccepted(accepted);
return;
}
- deliverMouseEvent(event);
+ deliverPointerEvent(pointerEventInstance(event));
break;
default:
Q_ASSERT(false);
@@ -2102,6 +2035,8 @@ void QQuickWindowPrivate::handleMouseEvent(QMouseEvent *event)
void QQuickWindowPrivate::flushFrameSynchronousEvents()
{
+ Q_Q(QQuickWindow);
+
if (delayedTouch) {
deliverDelayedTouchEvent();
@@ -2116,7 +2051,7 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
// For instance, during animation (including the case of a ListView
// whose delegates contain MouseAreas), a MouseArea needs to know
// whether it has moved into a position where it is now under the cursor.
- if (!mouseGrabberItem && !lastMousePosition.isNull()) {
+ if (!q->mouseGrabberItem() && !lastMousePosition.isNull()) {
bool accepted = false;
bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0, accepted);
if (!delivered)
@@ -2124,167 +2059,211 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
}
}
-void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
-{
- qCDebug(DBG_TOUCH) << " - delivering" << event;
+/*!
+ \internal
+ Returns a QQuickPointerEvent instance suitable for wrapping and delivering \a event.
- // If users spin the eventloop as a result of touch delivery, we disable
- // touch compression and send events directly. This is because we consider
- // the usecase a bit evil, but we at least don't want to lose events.
- ++touchRecursionGuard;
-
- // List of all items that received an event before
- // When we have TouchBegin this is and will stay empty
- QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > updatedPoints;
-
- // Figure out who accepted a touch point last and put it in updatedPoints
- // Add additional item to newPoints
- const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
- QList<QTouchEvent::TouchPoint> newPoints;
- for (int i=0; i<touchPoints.count(); i++) {
- const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
- if (touchPoint.state() == Qt::TouchPointPressed) {
- newPoints << touchPoint;
- } else {
- // TouchPointStationary is relevant only to items which
- // are also receiving touch points with some other state.
- // But we have not yet decided which points go to which item,
- // so for now we must include all non-new points in updatedPoints.
- if (itemForTouchPointId.contains(touchPoint.id())) {
- QQuickItem *item = itemForTouchPointId.value(touchPoint.id());
- if (item)
- updatedPoints[item].append(touchPoint);
- }
- }
+ There is a unique instance per QQuickPointerDevice, which is determined
+ from \a event's device.
+*/
+QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event)
+{
+ QQuickPointerDevice *dev = nullptr;
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ dev = QQuickPointerDevice::genericMouseDevice();
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ case QEvent::TouchCancel:
+ dev = QQuickPointerDevice::touchDevice(static_cast<QTouchEvent *>(event)->device());
+ break;
+ // TODO tablet event types
+ default:
+ break;
}
+ Q_ASSERT(dev);
+ return dev->pointerEvent()->reset(event);
+}
- // Deliver the event, but only if there is at least one new point
- // or some item accepted a point and should receive an update
- if (newPoints.count() > 0 || updatedPoints.count() > 0) {
- QSet<int> acceptedNewPoints;
- QSet<QQuickItem *> hasFiltered;
- event->setAccepted(deliverTouchPoints(contentItem, event, newPoints, &acceptedNewPoints, &updatedPoints, &hasFiltered));
- } else
- event->ignore();
+void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
+{
+ // If users spin the eventloop as a result of event delivery, we disable
+ // event compression and send events directly. This is because we consider
+ // the usecase a bit evil, but we at least don't want to lose events.
+ ++pointerEventRecursionGuard;
- // Remove released points from itemForTouchPointId
- if (event->touchPointStates() & Qt::TouchPointReleased) {
- for (int i=0; i<touchPoints.count(); i++) {
- if (touchPoints[i].state() == Qt::TouchPointReleased) {
- qCDebug(DBG_TOUCH_TARGET) << "TP" << touchPoints[i].id() << "released";
- itemForTouchPointId.remove(touchPoints[i].id());
- if (touchPoints[i].id() == touchMouseId)
- touchMouseId = -1;
- touchMouseIdCandidates.remove(touchPoints[i].id());
- }
- }
+ if (event->asPointerMouseEvent()) {
+ deliverMouseEvent(event->asPointerMouseEvent());
+ } else if (event->asPointerTouchEvent()) {
+ deliverTouchEvent(event->asPointerTouchEvent());
+ } else {
+ Q_ASSERT(false);
}
- if (event->type() == QEvent::TouchEnd) {
- if (!itemForTouchPointId.isEmpty()) {
- qWarning() << "No release received for" << itemForTouchPointId.size()
- << "touch points over" << itemForTouchPointId.begin().value()
- << "on touch end.";
- itemForTouchPointId.clear();
- }
- }
+ event->reset(nullptr);
- --touchRecursionGuard;
+ --pointerEventRecursionGuard;
}
-// This function recurses and sends the events to the individual items
-bool QQuickWindowPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *event, const QList<QTouchEvent::TouchPoint> &newPoints,
- QSet<int> *acceptedNewPoints, QHash<QQuickItem *,
- QList<QTouchEvent::TouchPoint> > *updatedPoints, QSet<QQuickItem *> *hasFiltered)
+// check if item or any of its child items contain the point
+// FIXME: should this be iterative instead of recursive?
+QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, const QPointF &scenePos, bool checkMouseButtons) const
{
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
-
+ QVector<QQuickItem *> targets;
+ auto itemPrivate = QQuickItemPrivate::get(item);
+ QPointF itemPos = item->mapFromScene(scenePos);
+ // if the item clips, we can potentially return early
if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
- for (int i=0; i<newPoints.count(); i++) {
- QPointF p = item->mapFromScene(newPoints[i].scenePos());
- if (!item->contains(p))
- return false;
- }
+ if (!item->contains(itemPos))
+ return targets;
}
- // Check if our children want the event (or parts of it)
- // This is the only point where touch event delivery recurses!
+ // recurse for children
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
for (int ii = children.count() - 1; ii >= 0; --ii) {
QQuickItem *child = children.at(ii);
- if (!child->isEnabled() || !child->isVisible() || QQuickItemPrivate::get(child)->culled)
+ auto childPrivate = QQuickItemPrivate::get(child);
+ if (!child->isVisible() || !child->isEnabled() || childPrivate->culled)
continue;
- if (deliverTouchPoints(child, event, newPoints, acceptedNewPoints, updatedPoints, hasFiltered))
- return true;
+ targets << pointerTargets(child, scenePos, false);
}
- // None of the children accepted the event, so check the given item itself.
- // First, construct matchingPoints as a list of TouchPoints which the
- // given item might be interested in. Any newly-pressed point which is
- // inside the item's bounds will be interesting, and also any updated point
- // which was already accepted by that item when it was first pressed.
- // (A point which was already accepted is effectively "grabbed" by the item.)
-
- // set of IDs of "interesting" new points
- QSet<int> matchingNewPoints;
- // set of points which this item has previously accepted, for starters
- QList<QTouchEvent::TouchPoint> matchingPoints = (*updatedPoints)[item];
- // now add the new points which are inside this item's bounds
- if (newPoints.count() > 0 && acceptedNewPoints->count() < newPoints.count()) {
- for (int i = 0; i < newPoints.count(); i++) {
- if (acceptedNewPoints->contains(newPoints[i].id()))
- continue;
- QPointF p = item->mapFromScene(newPoints[i].scenePos());
- if (item->contains(p)) {
- matchingNewPoints.insert(newPoints[i].id());
- matchingPoints << newPoints[i];
- }
+ if (item->contains(itemPos) && (!checkMouseButtons || itemPrivate->acceptedMouseButtons())) {
+ // add this item last - children take precedence
+ targets << item;
+ }
+ return targets;
+}
+
+// return the joined lists
+// list1 has priority, common items come last
+QVector<QQuickItem *> QQuickWindowPrivate::mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const
+{
+ QVector<QQuickItem *> targets = list1;
+ // start at the end of list2
+ // if item not in list, append it
+ // if item found, move to next one, inserting before the last found one
+ int insertPosition = targets.length();
+ for (int i = list2.length() - 1; i >= 0; --i) {
+ int newInsertPosition = targets.lastIndexOf(list2.at(i), insertPosition);
+ if (newInsertPosition >= 0) {
+ Q_ASSERT(newInsertPosition <= insertPosition);
+ insertPosition = newInsertPosition;
}
+ // check for duplicates, only insert if the item isn't there already
+ if (insertPosition == targets.size() || list2.at(i) != targets.at(insertPosition))
+ targets.insert(insertPosition, list2.at(i));
}
- // If there are no matching new points, and the existing points are all stationary,
- // there's no need to send an event to this item. This is required by a test in
- // tst_qquickwindow::touchEvent_basic:
- // a single stationary press on an item shouldn't cause an event
- if (matchingNewPoints.isEmpty()) {
- bool stationaryOnly = true;
-
- foreach (const QTouchEvent::TouchPoint &tp, matchingPoints) {
- if (tp.state() != Qt::TouchPointStationary) {
- stationaryOnly = false;
- break;
+ return targets;
+}
+
+void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event)
+{
+ qCDebug(DBG_TOUCH) << " - delivering" << event->asTouchEvent();
+
+ QSet<QQuickItem *> hasFiltered;
+ if (event->isPressEvent())
+ deliverPressEvent(event, &hasFiltered);
+ if (!event->allPointsAccepted())
+ deliverUpdatedTouchPoints(event, &hasFiltered);
+
+ // Remove released points from itemForTouchPointId
+ bool allReleased = true;
+ int pointCount = event->pointCount();
+ for (int i = 0; i < pointCount; ++i) {
+ QQuickEventPoint *point = event->point(i);
+ if (point->state() == QQuickEventPoint::Released) {
+ int id = point->pointId();
+ qCDebug(DBG_TOUCH_TARGET) << "TP" << id << "released";
+ point->setGrabber(nullptr);
+ if (id == touchMouseId) {
+ touchMouseId = -1;
+ touchMouseDevice = nullptr;
}
+ } else {
+ allReleased = false;
}
+ }
- if (stationaryOnly)
- matchingPoints.clear();
+ if (allReleased && !event->grabbers().isEmpty()) {
+ qWarning() << "No release received for some grabbers" << event->grabbers();
+ event->clearGrabbers();
}
+}
- if (!matchingPoints.isEmpty()) {
- // Now we know this item might be interested in the event. Copy and send it, but
- // with only the subset of TouchPoints which are relevant to that item: that's matchingPoints.
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- transformTouchPoints(matchingPoints, itemPrivate->windowToItemTransform());
- deliverMatchingPointsToItem(item, event, acceptedNewPoints, matchingNewPoints, matchingPoints, hasFiltered);
+// Deliver touch points to existing grabbers
+bool QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event, QSet<QQuickItem *> *hasFiltered)
+{
+ for (auto grabber: event->grabbers()) {
+ deliverMatchingPointsToItem(grabber, event, hasFiltered);
+ }
+
+ return false;
+}
+
+// Deliver newly pressed touch points
+bool QQuickWindowPrivate::deliverPressEvent(QQuickPointerEvent *event, QSet<QQuickItem *> *hasFiltered)
+{
+ const QVector<QPointF> points = event->unacceptedPressedPointScenePositions();
+ QVector<QQuickItem *> targetItems;
+ for (QPointF point: points) {
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, false);
+ if (targetItems.count()) {
+ targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
+ } else {
+ targetItems = targetItemsForPoint;
+ }
}
- // record the fact that this item has been visited already
- updatedPoints->remove(item);
+ for (QQuickItem *item: targetItems) {
+ deliverMatchingPointsToItem(item, event, hasFiltered);
+ if (event->allPointsAccepted())
+ break;
+ }
- // recursion is done only if ALL touch points have been delivered
- return (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty());
+ return event->allPointsAccepted();
}
-// touchEventForItem has no means to generate a touch event that contains
-// only the points that are relevant for this item. Thus the need for
-// matchingPoints to already be that set of interesting points.
-// They are all pre-transformed, too.
-bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem *> *hasFiltered)
+bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, QSet<QQuickItem *> *hasFiltered)
{
- QScopedPointer<QTouchEvent> touchEvent(touchEventWithPoints(*event, matchingPoints));
- touchEvent.data()->setTarget(item);
- bool touchEventAccepted = false;
+ Q_Q(QQuickWindow);
+
+ // TODO: unite this mouse point delivery with the synthetic mouse event below
+ if (auto event = pointerEvent->asPointerMouseEvent()) {
+ if (item->acceptedMouseButtons() & event->button()) {
+ auto point = event->point(0);
+ if (point->isAccepted())
+ return false;
+ QPointF localPos = item->mapFromScene(point->scenePos());
+ Q_ASSERT(item->contains(localPos)); // transform is checked already
+ QMouseEvent *me = event->asMouseEvent(localPos);
+ me->accept();
+ q->sendEvent(item, me);
+ if (me->isAccepted()) {
+ if (!q->mouseGrabberItem())
+ item->grabMouse();
+ point->setAccepted(true);
+ }
+ return me->isAccepted();
+ }
+ return false;
+ }
+
+ QQuickPointerTouchEvent *event = pointerEvent->asPointerTouchEvent();
+ if (!event)
+ return false;
+
+ QScopedPointer<QTouchEvent> touchEvent(event->touchEventForItem(item));
+ if (!touchEvent)
+ return false;
qCDebug(DBG_TOUCH) << " - considering delivering " << touchEvent.data() << " to " << item;
+ bool eventAccepted = false;
// First check whether the parent wants to be a filter,
// and if the parent accepts the event we are done.
@@ -2292,114 +2271,53 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv
// If the touch was accepted (regardless by whom or in what form),
// update acceptedNewPoints
qCDebug(DBG_TOUCH) << " - can't. intercepted " << touchEvent.data() << " to " << item->parentItem() << " instead of " << item;
- foreach (int id, matchingNewPoints)
- acceptedNewPoints->insert(id);
+ for (auto point: qAsConst(touchEvent->touchPoints())) {
+ event->pointById(point.id())->setAccepted();
+ }
return true;
}
- // Since it can change in sendEvent, update itemForTouchPointId now
- foreach (int id, matchingNewPoints) {
- qCDebug(DBG_TOUCH_TARGET) << "TP" << id << "->" << item;
- itemForTouchPointId[id] = item;
- }
-
// Deliver the touch event to the given item
qCDebug(DBG_TOUCH) << " - actually delivering " << touchEvent.data() << " to " << item;
QCoreApplication::sendEvent(item, touchEvent.data());
- touchEventAccepted = touchEvent->isAccepted();
+ eventAccepted = touchEvent->isAccepted();
// If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it.
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if (!touchEventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) {
+ if (!eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) {
// send mouse event
- event->setAccepted(translateTouchToMouse(item, touchEvent.data()));
- if (event->isAccepted()) {
- touchEventAccepted = true;
- }
+ if (deliverTouchAsMouse(item, event))
+ eventAccepted = true;
}
- if (touchEventAccepted) {
+ if (eventAccepted) {
// If the touch was accepted (regardless by whom or in what form),
- // update acceptedNewPoints.
- foreach (int id, matchingNewPoints)
- acceptedNewPoints->insert(id);
+ // update accepted new points.
+ for (auto point: qAsConst(touchEvent->touchPoints())) {
+ auto pointerEventPoint = event->pointById(point.id());
+ pointerEventPoint->setAccepted();
+ if (point.state() == Qt::TouchPointPressed)
+ pointerEventPoint->setGrabber(item);
+ }
} else {
// But if the event was not accepted then we know this item
// will not be interested in further updates for those touchpoint IDs either.
- foreach (int id, matchingNewPoints)
- if (itemForTouchPointId[id] == item) {
- qCDebug(DBG_TOUCH_TARGET) << "TP" << id << "disassociated";
- itemForTouchPointId.remove(id);
- }
- }
-
- return touchEventAccepted;
-}
-
-// create touch event containing only points inside the target item
-QTouchEvent *QQuickWindowPrivate::touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds)
-{
- const QList<QTouchEvent::TouchPoint> &touchPoints = originalEvent.touchPoints();
- QList<QTouchEvent::TouchPoint> pointsInBounds;
- // if all points are stationary, the list of points should be empty to signal a no-op
- if (originalEvent.touchPointStates() != Qt::TouchPointStationary) {
- for (int i = 0; i < touchPoints.count(); ++i) {
- const QTouchEvent::TouchPoint &tp = touchPoints.at(i);
- // Touch presses are relevant to the target item only if they occur inside its bounds.
- // Touch updates and releases are relevant if they occur inside, or if we want to
- // finish the sequence because the press occurred inside.
- if (tp.state() == Qt::TouchPointPressed || alwaysCheckBounds) {
- QPointF p = target->mapFromScene(tp.scenePos());
- if (target->contains(p))
- pointsInBounds.append(tp);
- } else {
- pointsInBounds.append(tp);
+ for (auto point: qAsConst(touchEvent->touchPoints())) {
+ if (point.state() == Qt::TouchPointPressed) {
+ if (event->pointById(point.id())->grabber() == item) {
+ qCDebug(DBG_TOUCH_TARGET) << "TP" << point.id() << "disassociated";
+ event->pointById(point.id())->setGrabber(nullptr);
+ }
}
}
- transformTouchPoints(pointsInBounds, QQuickItemPrivate::get(target)->windowToItemTransform());
- }
-
- QTouchEvent* touchEvent = touchEventWithPoints(originalEvent, pointsInBounds);
- touchEvent->setTarget(target);
- return touchEvent;
-}
-
-// copy a touch event's basic properties but give it new touch points
-QTouchEvent *QQuickWindowPrivate::touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints)
-{
- Qt::TouchPointStates eventStates;
- for (int i=0; i<newPoints.count(); i++)
- eventStates |= newPoints[i].state();
- // if all points have the same state, set the event type accordingly
- QEvent::Type eventType = event.type();
- switch (eventStates) {
- case Qt::TouchPointPressed:
- eventType = QEvent::TouchBegin;
- break;
- case Qt::TouchPointReleased:
- eventType = QEvent::TouchEnd;
- break;
- default:
- eventType = QEvent::TouchUpdate;
- break;
}
- QTouchEvent *touchEvent = new QTouchEvent(eventType);
- touchEvent->setWindow(event.window());
- touchEvent->setTarget(event.target());
- touchEvent->setDevice(event.device());
- touchEvent->setModifiers(event.modifiers());
- touchEvent->setTouchPoints(newPoints);
- touchEvent->setTouchPointStates(eventStates);
- touchEvent->setTimestamp(event.timestamp());
- touchEvent->accept();
- return touchEvent;
+ return eventAccepted;
}
#ifndef QT_NO_DRAGANDDROP
void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *event)
{
- Q_Q(QQuickWindow);
grabber->resetTarget();
QQuickDragGrabber::iterator grabItem = grabber->begin();
if (grabItem != grabber->end()) {
@@ -2415,7 +2333,7 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e
e->mouseButtons(),
e->keyboardModifiers());
QQuickDropEventEx::copyActions(&translatedEvent, *e);
- q->sendEvent(**grabItem, &translatedEvent);
+ QCoreApplication::sendEvent(**grabItem, &translatedEvent);
e->setAccepted(translatedEvent.isAccepted());
e->setDropAction(translatedEvent.dropAction());
grabber->setTarget(**grabItem);
@@ -2424,7 +2342,7 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e
if (event->type() != QEvent::DragMove) { // Either an accepted drop or a leave.
QDragLeaveEvent leaveEvent;
for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem))
- q->sendEvent(**grabItem, &leaveEvent);
+ QCoreApplication::sendEvent(**grabItem, &leaveEvent);
return;
} else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
@@ -2440,18 +2358,18 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e
moveEvent->mouseButtons(),
moveEvent->keyboardModifiers());
QQuickDropEventEx::copyActions(&translatedEvent, *moveEvent);
- q->sendEvent(**grabItem, &translatedEvent);
+ QCoreApplication::sendEvent(**grabItem, &translatedEvent);
++grabItem;
} else {
QDragLeaveEvent leaveEvent;
- q->sendEvent(**grabItem, &leaveEvent);
+ QCoreApplication::sendEvent(**grabItem, &leaveEvent);
grabItem = grabber->release(grabItem);
}
}
return;
} else {
QDragLeaveEvent leaveEvent;
- q->sendEvent(**grabItem, &leaveEvent);
+ QCoreApplication::sendEvent(**grabItem, &leaveEvent);
}
}
}
@@ -2470,7 +2388,6 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e
bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickItem *item, QDragMoveEvent *event)
{
- Q_Q(QQuickWindow);
bool accepted = false;
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
if (!item->isVisible() || !item->isEnabled() || QQuickItemPrivate::get(item)->culled)
@@ -2505,7 +2422,7 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte
event->keyboardModifiers(),
event->type());
QQuickDropEventEx::copyActions(&translatedEvent, *event);
- q->sendEvent(item, &translatedEvent);
+ QCoreApplication::sendEvent(item, &translatedEvent);
if (event->type() == QEvent::DragEnter) {
if (translatedEvent.isAccepted()) {
grabber->grab(item);
@@ -2568,8 +2485,10 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF
}
#endif
-bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event, QSet<QQuickItem *> *hasFiltered)
+bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QQuickPointerTouchEvent *event, QSet<QQuickItem *> *hasFiltered)
{
+ Q_Q(QQuickWindow);
+
if (!target)
return false;
@@ -2578,8 +2497,8 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) {
hasFiltered->insert(target);
- QScopedPointer<QTouchEvent> targetEvent(touchEventForItem(target, *event));
- if (!targetEvent->touchPoints().isEmpty()) {
+ QScopedPointer<QTouchEvent> targetEvent(event->touchEventForItem(target, true));
+ if (targetEvent) {
if (target->childMouseEventFilter(item, targetEvent.data())) {
qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target;
QVector<int> touchIds;
@@ -2588,9 +2507,10 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
for (int i = 0; i < touchPointCount; ++i)
touchIds.append(targetEvent->touchPoints().at(i).id());
target->grabTouchPoints(touchIds);
- if (mouseGrabberItem) {
- mouseGrabberItem->ungrabMouse();
+ if (q->mouseGrabberItem()) {
+ q->mouseGrabberItem()->ungrabMouse();
touchMouseId = -1;
+ touchMouseDevice = nullptr;
}
filtered = true;
}
@@ -2602,12 +2522,6 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
switch (tp.state()) {
case Qt::TouchPointPressed:
t = QEvent::MouseButtonPress;
- if (touchMouseId == -1) {
- // We don't want to later filter touches as a mouse event if they were pressed
- // while a touchMouseId was already active.
- // Remember this touch as a potential to become the touchMouseId.
- touchMouseIdCandidates.insert(tp.id());
- }
break;
case Qt::TouchPointReleased:
t = QEvent::MouseButtonRelease;
@@ -2620,18 +2534,20 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
}
// Only deliver mouse event if it is the touchMouseId or it could become the touchMouseId
- if ((touchMouseIdCandidates.contains(tp.id()) && touchMouseId == -1) || touchMouseId == tp.id()) {
+ if (touchMouseId == -1 || touchMouseId == tp.id()) {
// targetEvent is already transformed wrt local position, velocity, etc.
- QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, event, item, false));
+
+ // FIXME: remove asTouchEvent!!!
+ QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, event->asTouchEvent(), item, false));
if (target->childMouseEventFilter(item, mouseEvent.data())) {
qCDebug(DBG_TOUCH) << " - second chance intercepted on childMouseEventFilter by " << target;
if (t != QEvent::MouseButtonRelease) {
qCDebug(DBG_TOUCH_TARGET) << "TP" << tp.id() << "->" << target;
- itemForTouchPointId[tp.id()] = target;
touchMouseId = tp.id();
+ touchMouseDevice = event->device();
+ touchMouseDevice->pointerEvent()->pointById(tp.id())->setGrabber(target);
target->grabMouse();
}
- touchMouseIdCandidates.clear();
filtered = true;
}
// Only one event can be filtered as a mouse event.
@@ -2785,8 +2701,13 @@ void QQuickWindowPrivate::contextCreationFailureMessage(const QSurfaceFormat &fo
/*!
Propagates an event \a e to a QQuickItem \a item on the window.
+ Use \l QCoreApplication::sendEvent() directly instead.
+
The return value is currently not used.
+
+ \deprecated
*/
+// ### Qt6: remove
bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
{
Q_D(QQuickWindow);
@@ -2808,9 +2729,6 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
QCoreApplication::sendEvent(item, e);
}
break;
- case QEvent::ShortcutOverride:
- QCoreApplication::sendEvent(item, e);
- break;
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
@@ -2824,41 +2742,8 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
}
}
break;
- case QEvent::UngrabMouse: {
- QSet<QQuickItem *> hasFiltered;
- if (!d->sendFilteredMouseEvent(item->parentItem(), item, e, &hasFiltered)) {
- e->accept();
- item->mouseUngrabEvent();
- }
- }
- break;
-#ifndef QT_NO_WHEELEVENT
- case QEvent::Wheel:
-#endif
-#ifndef QT_NO_DRAGANDDROP
- case QEvent::DragEnter:
- case QEvent::DragMove:
- case QEvent::DragLeave:
- case QEvent::Drop:
-#endif
- case QEvent::FocusIn:
- case QEvent::FocusOut:
- case QEvent::HoverEnter:
- case QEvent::HoverLeave:
- case QEvent::HoverMove:
- case QEvent::TouchCancel:
- QCoreApplication::sendEvent(item, e);
- break;
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd: {
- QSet<QQuickItem*> hasFiltered;
- QTouchEvent *ev = static_cast<QTouchEvent *>(e);
- qCDebug(DBG_TOUCH) << " - sendEvent for " << ev << " to " << item->parentItem() << " and " << item;
- d->sendFilteredTouchEvent(item->parentItem(), item, ev, &hasFiltered);
- }
- break;
default:
+ QCoreApplication::sendEvent(item, e);
break;
}
@@ -3219,7 +3104,7 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
<< itemPriv->paintNode;
nodes.removeAll(0);
- Q_ASSERT(nodes.first() == itemPriv->itemNodeInstance);
+ Q_ASSERT(nodes.constFirst() == itemPriv->itemNodeInstance);
for (int i=1; i<nodes.size(); ++i) {
QSGNode *n = nodes.at(i);
// Failing this means we messed up reparenting
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 40a361a897..3328eb65c4 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -53,6 +53,7 @@
#include "qquickitem.h"
#include "qquickwindow.h"
+#include "qquickevents_p_p.h"
#include <QtQuick/private/qsgcontext_p.h>
@@ -68,13 +69,19 @@
QT_BEGIN_NAMESPACE
-//Make it easy to identify and customize the root item if needed
-
+class QOpenGLVertexArrayObjectHelper;
class QQuickAnimatorController;
-class QSGRenderLoop;
-class QQuickRenderControl;
class QQuickDragGrabber;
+class QQuickItemPrivate;
+class QQuickPointerDevice;
+class QQuickRenderControl;
+class QQuickWindowIncubationController;
+class QQuickWindowPrivate;
+class QQuickWindowRenderLoop;
+class QSGRenderLoop;
+class QTouchEvent;
+//Make it easy to identify and customize the root item if needed
class QQuickRootItem : public QQuickItem
{
Q_OBJECT
@@ -85,15 +92,6 @@ public Q_SLOTS:
void setHeight(int h) {QQuickItem::setHeight(qreal(h));}
};
-class QQuickItemPrivate;
-class QQuickWindowPrivate;
-
-class QTouchEvent;
-class QQuickWindowRenderLoop;
-class QQuickWindowIncubationController;
-
-class QOpenGLVertexArrayObjectHelper;
-
class Q_QUICK_PRIVATE_EXPORT QQuickCustomRenderStage
{
public:
@@ -127,7 +125,6 @@ public:
void deliverKeyEvent(QKeyEvent *e);
// Keeps track of the item currently receiving mouse events
- QQuickItem *mouseGrabberItem;
#ifndef QT_NO_CURSOR
QQuickItem *cursorItem;
#endif
@@ -135,20 +132,19 @@ public:
QQuickDragGrabber *dragGrabber;
#endif
int touchMouseId;
+ QQuickPointerDevice *touchMouseDevice;
bool checkIfDoubleClicked(ulong newPressEventTimestamp);
ulong touchMousePressTimestamp;
// Mouse positions are saved in widget coordinates
QPointF lastMousePosition;
- bool translateTouchToMouse(QQuickItem *item, QTouchEvent *event);
+ bool deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent);
void translateTouchEvent(QTouchEvent *touchEvent);
void setMouseGrabber(QQuickItem *grabber);
void grabTouchPoints(QQuickItem *grabber, const QVector<int> &ids);
void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
- static void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform);
static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0);
- bool deliverInitialMousePressEvent(QQuickItem *, QMouseEvent *);
- bool deliverMouseEvent(QMouseEvent *);
+ void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);
bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *, QSet<QQuickItem *> *);
#ifndef QT_NO_WHEELEVENT
bool deliverWheelEvent(QQuickItem *, QWheelEvent *);
@@ -156,23 +152,33 @@ public:
#ifndef QT_NO_GESTURES
bool deliverNativeGestureEvent(QQuickItem *, QNativeGestureEvent *);
#endif
- bool deliverTouchPoints(QQuickItem *, QTouchEvent *, const QList<QTouchEvent::TouchPoint> &, QSet<int> *,
- QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > *, QSet<QQuickItem*> *filtered);
+
+ // entry point of events to the window
void handleTouchEvent(QTouchEvent *);
void handleMouseEvent(QMouseEvent *);
- void deliverTouchEvent(QTouchEvent *);
bool compressTouchEvent(QTouchEvent *);
- bool deliverTouchCancelEvent(QTouchEvent *);
- void deliverDelayedTouchEvent();
void flushFrameSynchronousEvents();
+ void deliverDelayedTouchEvent();
+
+ // delivery of pointer events:
+ QQuickPointerEvent *pointerEventInstance(QEvent *ev);
+ void deliverPointerEvent(QQuickPointerEvent *);
+ void deliverTouchEvent(QQuickPointerTouchEvent *);
+ bool deliverTouchCancelEvent(QTouchEvent *);
+ bool deliverPressEvent(QQuickPointerEvent *, QSet<QQuickItem *> *);
+ bool deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event, QSet<QQuickItem *> *hasFiltered);
+ bool deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, QSet<QQuickItem*> *filtered);
+ bool sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QQuickPointerTouchEvent *event, QSet<QQuickItem*> *filtered);
+
+ QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointF &, bool checkMouseButtons) const;
+ QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
+
+ // hover delivery
bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted);
- bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered);
- static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false);
- static QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints);
- bool sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event, QSet<QQuickItem*> *filtered);
bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos,
Qt::KeyboardModifiers modifiers, ulong timestamp, bool accepted);
bool clearHover(ulong timestamp = 0);
+
#ifndef QT_NO_DRAGANDDROP
void deliverDragEvent(QQuickDragGrabber *, QEvent *);
bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *);
@@ -237,7 +243,8 @@ public:
QQuickRenderControl *renderControl;
QQuickAnimatorController *animationController;
QScopedPointer<QTouchEvent> delayedTouch;
- int touchRecursionGuard;
+
+ int pointerEventRecursionGuard;
QQuickCustomRenderStage *customRenderStage;
QColor clearColor;
@@ -258,10 +265,6 @@ public:
QOpenGLVertexArrayObjectHelper *vaoHelper;
- // Keeps track of which touch point (int) was last accepted by which item
- QHash<int, QQuickItem *> itemForTouchPointId;
- QSet<int> touchMouseIdCandidates;
-
mutable QQuickWindowIncubationController *incubationController;
static bool defaultAlphaBuffer;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
index d900688173..7b9e749532 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp
@@ -218,11 +218,11 @@ void QSGSoftwareRenderableNode::update()
struct RenderNodeState : public QSGRenderNode::RenderState
{
const QMatrix4x4 *projectionMatrix() const override { return &ident; }
- QRect scissorRect() const { return QRect(); }
- bool scissorEnabled() const { return false; }
- int stencilValue() const { return 0; }
- bool stencilEnabled() const { return false; }
- const QRegion *clipRegion() const { return &cr; }
+ QRect scissorRect() const override { return QRect(); }
+ bool scissorEnabled() const override { return false; }
+ int stencilValue() const override { return 0; }
+ bool stencilEnabled() const override { return false; }
+ const QRegion *clipRegion() const override { return &cr; }
QMatrix4x4 ident;
QRegion cr;
};
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
index c0967bcb09..2211f88973 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -1268,7 +1268,7 @@ QSGRootNode::QSGRootNode()
QSGRootNode::~QSGRootNode()
{
while (!m_renderers.isEmpty())
- m_renderers.last()->setRootNode(0);
+ m_renderers.constLast()->setRootNode(0);
destroy(); // Must call destroy() here because markDirty() casts this to QSGRootNode.
}
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index 3fc7d87840..eb902b2972 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -265,7 +265,7 @@ void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job)
* needed in any case.
*/
if (!m_deleting.contains(job)) {
- QQuickAnimatorProxyJob *proxy = m_animatorRoots[job];
+ QQuickAnimatorProxyJob *proxy = m_animatorRoots.value(job);
if (proxy) {
m_window->update();
m_proxiesToStop << proxy;
diff --git a/src/quick/util/qquickfontloader.cpp b/src/quick/util/qquickfontloader.cpp
index b7367f3934..6e23d99f7e 100644
--- a/src/quick/util/qquickfontloader.cpp
+++ b/src/quick/util/qquickfontloader.cpp
@@ -264,7 +264,7 @@ void QQuickFontLoader::setSource(const QUrl &url)
updateFontInfo(QString(), Error);
}
} else {
- updateFontInfo(QFontDatabase::applicationFontFamilies(fontLoaderFonts()->map[d->url]->id).at(0), Ready);
+ updateFontInfo(QFontDatabase::applicationFontFamilies(fontLoaderFonts()->map.value(d->url)->id).at(0), Ready);
}
} else {
if (!fontLoaderFonts()->map.contains(d->url)) {
@@ -280,7 +280,7 @@ void QQuickFontLoader::setSource(const QUrl &url)
// Silently fail if compiled with no_network
#endif
} else {
- QQuickFontObject *fo = fontLoaderFonts()->map[d->url];
+ QQuickFontObject *fo = fontLoaderFonts()->map.value(d->url);
if (fo->id == -1) {
#ifndef QT_NO_NETWORK
d->status = Loading;
diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp
index 6b491a433c..dfed4c1885 100644
--- a/src/quick/util/qquickpath.cpp
+++ b/src/quick/util/qquickpath.cpp
@@ -382,7 +382,7 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
}
// Fixup end points
- const AttributePoint &last = attributePoints.last();
+ const AttributePoint &last = attributePoints.constLast();
for (int ii = 0; ii < attributes.count(); ++ii) {
if (!last.values.contains(attributes.at(ii)))
endpoint(attributePoints, attributes.at(ii));
@@ -407,11 +407,11 @@ QPainterPath QQuickPath::createPath(const QPointF &startPoint, const QPointF &en
}
attributePoints[ii].origpercent /= length;
attributePoints[ii].percent = point.values.value(percentString);
- prevorigpercent = attributePoints[ii].origpercent;
- prevpercent = attributePoints[ii].percent;
+ prevorigpercent = attributePoints.at(ii).origpercent;
+ prevpercent = attributePoints.at(ii).percent;
} else {
attributePoints[ii].origpercent /= length;
- attributePoints[ii].percent = attributePoints[ii].origpercent;
+ attributePoints[ii].percent = attributePoints.at(ii).origpercent;
}
}
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index dc4b27d738..49956de822 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -629,7 +629,7 @@ void QQuickPixmapReader::processJobs()
// Find a job we can use
bool usableJob = false;
for (int i = jobs.count() - 1; !usableJob && i >= 0; i--) {
- QQuickPixmapReply *job = jobs[i];
+ QQuickPixmapReply *job = jobs.at(i);
const QUrl url = job->url;
QString localFile;
QQuickImageProvider::ImageType imageType = QQuickImageProvider::Invalid;
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index c4be68cd31..555533a44e 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -287,7 +287,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler;
handler->property = prop;
handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(),
- QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]));
+ QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex)));
signalReplacements << handler;
return;
}
@@ -455,7 +455,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
QQmlBinding *newBinding = 0;
if (e.id != QQmlBinding::Invalid) {
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
- QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->compilationUnit->runtimeFunctions[e.id]));
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->compilationUnit->runtimeFunctions.at(e.id)));
newBinding = QQmlBinding::create(&QQmlPropertyPrivate::get(prop)->core,
function, object(), context);
}
diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp
index a992589040..e7beee8ed3 100644
--- a/src/quick/util/qquicksmoothedanimation.cpp
+++ b/src/quick/util/qquicksmoothedanimation.cpp
@@ -409,7 +409,7 @@ QAbstractAnimationJob* QQuickSmoothedAnimation::transition(QQuickStateActions &a
Q_UNUSED(direction);
Q_D(QQuickSmoothedAnimation);
- QQuickStateActions dataActions = QQuickPropertyAnimation::createTransitionActions(actions, modified, defaultTarget);
+ const QQuickStateActions dataActions = QQuickPropertyAnimation::createTransitionActions(actions, modified, defaultTarget);
QContinuingAnimationGroupJob *wrapperGroup = new QContinuingAnimationGroupJob();
diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp
index 74baa3bfda..b3f0caa2b3 100644
--- a/src/quick/util/qquicktimeline.cpp
+++ b/src/quick/util/qquicktimeline.cpp
@@ -154,7 +154,7 @@ void QQuickTimeLinePrivate::add(QQuickTimeLineObject &g, const Op &o)
}
if (!iter->ops.isEmpty() &&
o.type == Op::Pause &&
- iter->ops.last().type == Op::Pause) {
+ iter->ops.constLast().type == Op::Pause) {
iter->ops.last().length += o.length;
iter->length += o.length;
} else {
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index ad04c76783..b8c5b900c9 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -575,8 +575,8 @@ void QQuickWidget::setContent(const QUrl& url, QQmlComponent *component, QObject
d->component = component;
if (d->component && d->component->isError()) {
- QList<QQmlError> errorList = d->component->errors();
- foreach (const QQmlError &error, errorList) {
+ const QList<QQmlError> errorList = d->component->errors();
+ for (const QQmlError &error : errorList) {
QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
<< error;
}
@@ -1018,8 +1018,8 @@ void QQuickWidget::continueExecute()
disconnect(d->component, SIGNAL(statusChanged(QQmlComponent::Status)), this, SLOT(continueExecute()));
if (d->component->isError()) {
- QList<QQmlError> errorList = d->component->errors();
- foreach (const QQmlError &error, errorList) {
+ const QList<QQmlError> errorList = d->component->errors();
+ for (const QQmlError &error : errorList) {
QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
<< error;
}
@@ -1030,8 +1030,8 @@ void QQuickWidget::continueExecute()
QObject *obj = d->component->create();
if (d->component->isError()) {
- QList<QQmlError> errorList = d->component->errors();
- foreach (const QQmlError &error, errorList) {
+ const QList<QQmlError> errorList = d->component->errors();
+ for (const QQmlError &error : errorList) {
QMessageLogger(error.url().toString().toLatin1().constData(), error.line(), 0).warning()
<< error;
}
diff --git a/src/quickwidgets/quickwidgets.pro b/src/quickwidgets/quickwidgets.pro
index 87409e31c5..2438e577ae 100644
--- a/src/quickwidgets/quickwidgets.pro
+++ b/src/quickwidgets/quickwidgets.pro
@@ -2,7 +2,7 @@ TARGET = QtQuickWidgets
QT = core-private gui-private qml-private quick-private widgets-private
-DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES
+DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES QT_NO_FOREACH
HEADERS += \
qquickwidget.h \
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 3ceeb97718..cd55ae191d 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -1444,6 +1444,7 @@ void tst_QJSEngine::valueConversion_QVariant()
QCOMPARE(qjsvalue_cast<QVariant>(QJSValue(123)), QVariant(123));
QVERIFY(eng.toScriptValue(QVariant(QMetaType::VoidStar, 0)).isNull());
+ QVERIFY(eng.toScriptValue(QVariant::fromValue(nullptr)).isNull());
{
QVariantMap map;
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 859caf72c7..28b9adea38 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -978,8 +978,8 @@ void tst_QJSValue::toVariant()
QCOMPARE(qjsvalue_cast<QVariant>(undefined), QVariant());
QJSValue null = eng.evaluate("null");
- QCOMPARE(null.toVariant(), QVariant(QMetaType::VoidStar, 0));
- QCOMPARE(qjsvalue_cast<QVariant>(null), QVariant(QMetaType::VoidStar, 0));
+ QCOMPARE(null.toVariant(), QVariant::fromValue(nullptr));
+ QCOMPARE(qjsvalue_cast<QVariant>(null), QVariant::fromValue(nullptr));
{
QJSValue number = eng.toScriptValue(123.0);
@@ -1055,8 +1055,8 @@ void tst_QJSValue::toVariant()
QCOMPARE(qjsvalue_cast<QVariant>(undef), QVariant());
QJSValue nil = QJSValue(QJSValue::NullValue);
- QCOMPARE(nil.toVariant(), QVariant(QMetaType::VoidStar, 0));
- QCOMPARE(qjsvalue_cast<QVariant>(nil), QVariant(QMetaType::VoidStar, 0));
+ QCOMPARE(nil.toVariant(), QVariant::fromValue(nullptr));
+ QCOMPARE(qjsvalue_cast<QVariant>(nil), QVariant::fromValue(nullptr));
}
// array
diff --git a/tests/auto/qml/qmldiskcache/qmldiskcache.pro b/tests/auto/qml/qmldiskcache/qmldiskcache.pro
index f2d1a04780..f98a157b6a 100644
--- a/tests/auto/qml/qmldiskcache/qmldiskcache.pro
+++ b/tests/auto/qml/qmldiskcache/qmldiskcache.pro
@@ -4,4 +4,6 @@ osx:CONFIG -= app_bundle
SOURCES += tst_qmldiskcache.cpp
+RESOURCES += test.qml
+
QT += core-private qml-private testlib
diff --git a/tests/auto/qml/qmldiskcache/test.qml b/tests/auto/qml/qmldiskcache/test.qml
new file mode 100644
index 0000000000..d632422616
--- /dev/null
+++ b/tests/auto/qml/qmldiskcache/test.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ property int value: 20
+}
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index dd23dfca07..8ccf4714ba 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -38,6 +38,9 @@
#include <QQmlEngine>
#include <QQmlFileSelector>
#include <QThread>
+#include <QCryptographicHash>
+#include <QStandardPaths>
+#include <QDirIterator>
class tst_qmldiskcache: public QObject
{
@@ -52,6 +55,7 @@ private slots:
void recompileAfterChange();
void fileSelectors();
void localAliases();
+ void cacheResources();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -529,6 +533,30 @@ void tst_qmldiskcache::localAliases()
}
}
+void tst_qmldiskcache::cacheResources()
+{
+ const QString cacheDirectory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
+ QVERIFY(QDir::root().mkpath(cacheDirectory));
+
+ const QString qmlCacheDirectory = cacheDirectory + QLatin1String("/qmlcache/");
+ QVERIFY(QDir(qmlCacheDirectory).removeRecursively());
+ QVERIFY(QDir::root().mkpath(qmlCacheDirectory));
+ QVERIFY(QDir(qmlCacheDirectory).entryList(QDir::NoDotAndDotDot).isEmpty());
+
+
+ QQmlEngine engine;
+
+ {
+ CleanlyLoadingComponent component(&engine, QUrl("qrc:/test.qml"));
+ qDebug() << component.errorString();
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("value").toInt(), 20);
+ }
+
+ QCOMPARE(QDir(qmlCacheDirectory).entryList(QDir::NoDotAndDotDot | QDir::Files).count(), 1);
+}
+
QTEST_MAIN(tst_qmldiskcache)
#include "tst_qmldiskcache.moc"
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index de3ead917f..30ecfa7d96 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -5814,7 +5814,7 @@ void tst_qqmlecmascript::variants()
QVERIFY(object != 0);
QCOMPARE(object->property("undefinedVariant").type(), QVariant::Invalid);
- QCOMPARE(int(object->property("nullVariant").type()), int(QMetaType::VoidStar));
+ QCOMPARE(int(object->property("nullVariant").type()), int(QMetaType::Nullptr));
QCOMPARE(object->property("intVariant").type(), QVariant::Int);
QCOMPARE(object->property("doubleVariant").type(), QVariant::Double);
@@ -7470,8 +7470,11 @@ void tst_qqmlecmascript::negativeYear()
QVariant q;
QMetaObject::invokeMethod(object, "check_negative_tostring", Q_RETURN_ARG(QVariant, q));
- // Strip the timezone. It should be irrelevant as the date was created with the same one.
- QCOMPARE(q.toString().left(32), QStringLiteral("result: Sat Jan 1 00:00:00 -2001"));
+
+ // Only check for the year. We hope that every language writes the year in arabic numerals and
+ // in relation to a specific dude's date of birth. We also hope that no language adds a "-2001"
+ // junk string somewhere in the middle.
+ QVERIFY(q.toString().indexOf(QStringLiteral("-2001")) != -1);
QMetaObject::invokeMethod(object, "check_negative_toisostring", Q_RETURN_ARG(QVariant, q));
QCOMPARE(q.toString().left(16), QStringLiteral("result: -002000-"));
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index f32051a26a..ad06946b0b 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -2601,7 +2601,7 @@ void tst_qqmllanguage::basicRemote_data()
QTest::newRow("no need for qmldir") << QUrl(serverdir+"Test.qml") << "" << "";
QTest::newRow("absent qmldir") << QUrl(serverdir+"/noqmldir/Test.qml") << "" << "";
- QTest::newRow("need qmldir") << QUrl(serverdir+"TestLocal.qml") << "" << "";
+ QTest::newRow("need qmldir") << QUrl(serverdir+"TestNamed.qml") << "" << "";
}
void tst_qqmllanguage::basicRemote()
@@ -2641,6 +2641,8 @@ void tst_qqmllanguage::importsRemote_data()
<< "";
QTest::newRow("remote import with local") << "import \""+serverdir+"\"\nTestLocal {}" << "QQuickImage"
<< "";
+ QTest::newRow("remote import with qualifier") << "import \""+serverdir+"\" as NS\nNS.NamedLocal {}" << "QQuickImage"
+ << "";
QTest::newRow("wrong remote import with undeclared local") << "import \""+serverdir+"\"\nWrongTestLocal {}" << ""
<< "WrongTestLocal is not a type";
QTest::newRow("wrong remote import of internal local") << "import \""+serverdir+"\"\nLocalInternal {}" << ""
@@ -4126,7 +4128,7 @@ void tst_qqmllanguage::preservePropertyCacheOnGroupObjects()
QVERIFY(subCache);
QQmlPropertyData *pd = subCache->property(QStringLiteral("newProperty"), /*object*/0, /*context*/0);
QVERIFY(pd);
- QCOMPARE(pd->propType, qMetaTypeId<int>());
+ QCOMPARE(pd->propType(), qMetaTypeId<int>());
}
void tst_qqmllanguage::propertyCacheInSync()
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index 2916d8455c..824fe445c0 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -111,16 +111,16 @@ void tst_qqmlpropertycache::properties()
QQmlPropertyData *data;
QVERIFY((data = cacheProperty(cache, "propertyA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyA"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyA"));
QVERIFY((data = cacheProperty(cache, "propertyB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyB"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyB"));
QVERIFY((data = cacheProperty(cache, "propertyC")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyC"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyC"));
QVERIFY((data = cacheProperty(cache, "propertyD")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyD"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyD"));
}
void tst_qqmlpropertycache::propertiesDerived()
@@ -135,16 +135,16 @@ void tst_qqmlpropertycache::propertiesDerived()
QQmlPropertyData *data;
QVERIFY((data = cacheProperty(cache, "propertyA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyA"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyA"));
QVERIFY((data = cacheProperty(cache, "propertyB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyB"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyB"));
QVERIFY((data = cacheProperty(cache, "propertyC")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyC"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyC"));
QVERIFY((data = cacheProperty(cache, "propertyD")));
- QCOMPARE(data->coreIndex, metaObject->indexOfProperty("propertyD"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfProperty("propertyD"));
}
void tst_qqmlpropertycache::methods()
@@ -158,28 +158,28 @@ void tst_qqmlpropertycache::methods()
QQmlPropertyData *data;
QVERIFY((data = cacheProperty(cache, "slotA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotA()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("slotA()"));
QVERIFY((data = cacheProperty(cache, "slotB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotB()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("slotB()"));
QVERIFY((data = cacheProperty(cache, "signalA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalA()"));
QVERIFY((data = cacheProperty(cache, "signalB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalB()"));
QVERIFY((data = cacheProperty(cache, "propertyAChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyAChanged()"));
QVERIFY((data = cacheProperty(cache, "propertyBChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyBChanged()"));
QVERIFY((data = cacheProperty(cache, "propertyCChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyCChanged()"));
QVERIFY((data = cacheProperty(cache, "propertyDChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyDChanged()"));
}
void tst_qqmlpropertycache::methodsDerived()
@@ -194,28 +194,28 @@ void tst_qqmlpropertycache::methodsDerived()
QQmlPropertyData *data;
QVERIFY((data = cacheProperty(cache, "slotA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotA()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("slotA()"));
QVERIFY((data = cacheProperty(cache, "slotB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("slotB()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("slotB()"));
QVERIFY((data = cacheProperty(cache, "signalA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalA()"));
QVERIFY((data = cacheProperty(cache, "signalB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalB()"));
QVERIFY((data = cacheProperty(cache, "propertyAChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyAChanged()"));
QVERIFY((data = cacheProperty(cache, "propertyBChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyBChanged()"));
QVERIFY((data = cacheProperty(cache, "propertyCChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyCChanged()"));
QVERIFY((data = cacheProperty(cache, "propertyDChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyDChanged()"));
}
void tst_qqmlpropertycache::signalHandlers()
@@ -229,22 +229,22 @@ void tst_qqmlpropertycache::signalHandlers()
QQmlPropertyData *data;
QVERIFY((data = cacheProperty(cache, "onSignalA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalA()"));
QVERIFY((data = cacheProperty(cache, "onSignalB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalB()"));
QVERIFY((data = cacheProperty(cache, "onPropertyAChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyAChanged()"));
QVERIFY((data = cacheProperty(cache, "onPropertyBChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyBChanged()"));
QVERIFY((data = cacheProperty(cache, "onPropertyCChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyCChanged()"));
QVERIFY((data = cacheProperty(cache, "onPropertyDChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyDChanged()"));
}
void tst_qqmlpropertycache::signalHandlersDerived()
@@ -259,22 +259,22 @@ void tst_qqmlpropertycache::signalHandlersDerived()
QQmlPropertyData *data;
QVERIFY((data = cacheProperty(cache, "onSignalA")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalA()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalA()"));
QVERIFY((data = cacheProperty(cache, "onSignalB")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("signalB()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("signalB()"));
QVERIFY((data = cacheProperty(cache, "onPropertyAChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyAChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyAChanged()"));
QVERIFY((data = cacheProperty(cache, "onPropertyBChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyBChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyBChanged()"));
QVERIFY((data = cacheProperty(cache, "onPropertyCChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyCChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyCChanged()"));
QVERIFY((data = cacheProperty(cache, "onPropertyDChanged")));
- QCOMPARE(data->coreIndex, metaObject->indexOfMethod("propertyDChanged()"));
+ QCOMPARE(data->coreIndex(), metaObject->indexOfMethod("propertyDChanged()"));
}
class TestClass : public QObject
diff --git a/tests/auto/qml/qqmlqt/data/exit.qml b/tests/auto/qml/qqmlqt/data/exit.qml
new file mode 100644
index 0000000000..12727d9f04
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/exit.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+QtObject {
+ property int returnCode: -1
+ Component.onCompleted: Qt.exit(returnCode)
+}
+
diff --git a/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml b/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml
new file mode 100644
index 0000000000..9d73640c87
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/timeRoundtrip.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+QtObject {
+ Component.onCompleted: {
+ var t = tp.time;
+ tp.time = t;
+ }
+}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 8150241e4a..0576650d01 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -46,6 +46,15 @@
#include <QFont>
#include "../../shared/util.h"
+// Copied from tst_qdatetime.cpp
+#ifdef Q_OS_WIN
+# include <qt_windows.h>
+# include <time.h>
+# if defined(Q_OS_WINRT)
+# define tzset()
+# endif
+#endif
+
class tst_qqmlqt : public QQmlDataTest
{
Q_OBJECT
@@ -87,11 +96,15 @@ private slots:
void atob();
void fontFamilies();
void quit();
+ void exit();
void resolvedUrl();
void later_data();
void later();
void qtObjectContents();
+ void timeRoundtrip_data();
+ void timeRoundtrip();
+
private:
QQmlEngine engine;
};
@@ -872,8 +885,6 @@ void tst_qqmlqt::dateTimeFormattingVariants_data()
QTime time(11, 16, 39, 755);
temporary = QDateTime(QDate(1970,1,1), time);
- QTest::newRow("formatDate, qtime") << "formatDate" << QVariant::fromValue(time) << (QStringList() << temporary.date().toString(Qt::DefaultLocaleShortDate) << temporary.date().toString(Qt::DefaultLocaleLongDate) << temporary.date().toString("ddd MMMM d yy"));
- QTest::newRow("formatDateTime, qtime") << "formatDateTime" << QVariant::fromValue(time) << (QStringList() << temporary.toString(Qt::DefaultLocaleShortDate) << temporary.toString(Qt::DefaultLocaleLongDate) << temporary.toString("M/d/yy H:m:s a"));
QTest::newRow("formatTime, qtime") << "formatTime" << QVariant::fromValue(time) << (QStringList() << temporary.time().toString(Qt::DefaultLocaleShortDate) << temporary.time().toString(Qt::DefaultLocaleLongDate) << temporary.time().toString("H:m:s a") << temporary.time().toString("hh:mm:ss.zzz"));
QDate date(2011,5,31);
@@ -980,6 +991,20 @@ void tst_qqmlqt::quit()
delete object;
}
+void tst_qqmlqt::exit()
+{
+ QQmlComponent component(&engine, testFileUrl("exit.qml"));
+
+ QSignalSpy spy(&engine, &QQmlEngine::exit);
+ QObject *object = component.create();
+ QVERIFY(object != Q_NULLPTR);
+ QCOMPARE(spy.count(), 1);
+ QList<QVariant> arguments = spy.takeFirst();
+ QVERIFY(arguments.at(0).toInt() == object->property("returnCode").toInt());
+
+ delete object;
+}
+
void tst_qqmlqt::resolvedUrl()
{
QQmlComponent component(&engine, testFileUrl("resolvedUrl.qml"));
@@ -1139,6 +1164,104 @@ void tst_qqmlqt::qtObjectContents()
delete object;
}
+class TimeProvider: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QTime time READ time WRITE setTime NOTIFY timeChanged)
+
+public:
+ TimeProvider(const QTime &t)
+ : m_getTime(t)
+ {}
+
+ QTime time() const { return m_getTime; }
+ void setTime(const QTime &t) { m_putTime = t; emit timeChanged(); }
+
+signals:
+ void timeChanged();
+
+public:
+ QTime m_getTime, m_putTime;
+};
+
+class TimeZoneSwitch
+{
+public:
+ TimeZoneSwitch(const char *newZone)
+ : doChangeZone(qstrcmp(newZone, "localtime") == 0)
+ {
+ if (!doChangeZone)
+ return;
+
+ hadOldZone = qEnvironmentVariableIsSet("TZ");
+ if (hadOldZone) {
+ oldZone = qgetenv("TZ");
+ }
+ qputenv("TZ", newZone);
+ tzset();
+ }
+
+ ~TimeZoneSwitch()
+ {
+ if (!doChangeZone)
+ return;
+
+ if (hadOldZone)
+ qputenv("TZ", oldZone);
+ else
+ qunsetenv("TZ");
+ tzset();
+ }
+
+private:
+ bool doChangeZone;
+ bool hadOldZone;
+ QByteArray oldZone;
+};
+
+void tst_qqmlqt::timeRoundtrip_data()
+{
+ QTest::addColumn<QTime>("time");
+
+ // Local timezone:
+ QTest::newRow("localtime") << QTime(0, 0, 0);
+
+ // No DST:
+ QTest::newRow("UTC") << QTime(0, 0, 0);
+ QTest::newRow("Europe/Amsterdam") << QTime(1, 0, 0);
+ QTest::newRow("Asia/Jakarta") << QTime(7, 0, 0);
+
+ // DST:
+ QTest::newRow("Namibia/Windhoek") << QTime(1, 0, 0);
+ QTest::newRow("Australia/Adelaide") << QTime(10, 0, 0);
+ QTest::newRow("Australia/Hobart") << QTime(10, 0, 0);
+ QTest::newRow("Pacific/Auckland") << QTime(12, 0, 0);
+ QTest::newRow("Pacific/Samoa") << QTime(13, 0, 0);
+}
+
+void tst_qqmlqt::timeRoundtrip()
+{
+#ifdef Q_OS_WIN
+ QSKIP("On Windows, the DateObject doesn't handle DST transitions correctly when the timezone is not localtime."); // I.e.: for this test.
+#endif
+
+ TimeZoneSwitch tzs(QTest::currentDataTag());
+ QFETCH(QTime, time);
+
+ TimeProvider tp(time);
+
+ QQmlEngine eng;
+ eng.rootContext()->setContextProperty(QLatin1String("tp"), &tp);
+ QQmlComponent component(&eng, testFileUrl("timeRoundtrip.qml"));
+ QObject *obj = component.create();
+ QVERIFY(obj != 0);
+
+ // QML reads m_getTime and saves the result as m_putTime; this should come out the same, without
+ // any perturbation (e.g. by DST effects) from converting from QTime to V4's Date and back
+ // again.
+ QCOMPARE(tp.m_getTime, tp.m_putTime);
+}
+
QTEST_MAIN(tst_qqmlqt)
#include "tst_qqmlqt.moc"
diff --git a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
index ea988bb50d..d4922599be 100644
--- a/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
+++ b/tests/auto/quick/qquickframebufferobject/tst_qquickframebufferobject.cpp
@@ -180,7 +180,7 @@ void tst_QQuickFramebufferObject::testThatStuffWorks()
qmlRegisterType<FBOItem>("FBOItem", 1, 0, "FBOItem");
QQuickView view;
- view.setSource(QUrl::fromLocalFile("data/testStuff.qml"));
+ view.setSource(testFileUrl("testStuff.qml"));
FBOItem *item = view.rootObject()->findChild<FBOItem *>("fbo");
@@ -224,7 +224,7 @@ void tst_QQuickFramebufferObject::testInvalidate()
qmlRegisterType<FBOItem>("FBOItem", 1, 0, "FBOItem");
QQuickView view;
- view.setSource(QUrl::fromLocalFile("data/testStuff.qml"));
+ view.setSource(testFileUrl("testStuff.qml"));
FBOItem *item = view.rootObject()->findChild<FBOItem *>("fbo");
item->setTextureFollowsItemSize(false);
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index bf9df7850d..b0d903908f 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -250,6 +250,7 @@ private slots:
void QTBUG_50105();
void keyNavigationEnabled();
void QTBUG_50097_stickyHeader_positionViewAtIndex();
+ void itemFiltered();
private:
template <class T> void items(const QUrl &source);
@@ -8343,6 +8344,37 @@ void tst_QQuickListView::QTBUG_50097_stickyHeader_positionViewAtIndex()
QTRY_COMPARE(listview->contentY(), -100.0); // back to the same position: header visible, items not under the header.
}
+void tst_QQuickListView::itemFiltered()
+{
+ QStringListModel model(QStringList() << "one" << "two" << "three" << "four" << "five" << "six");
+ QSortFilterProxyModel proxy1;
+ proxy1.setSourceModel(&model);
+ proxy1.setSortRole(Qt::DisplayRole);
+ proxy1.setDynamicSortFilter(true);
+ proxy1.sort(0);
+
+ QSortFilterProxyModel proxy2;
+ proxy2.setSourceModel(&proxy1);
+ proxy2.setFilterRole(Qt::DisplayRole);
+ proxy2.setFilterRegExp("^[^ ]*$");
+ proxy2.setDynamicSortFilter(true);
+
+ QScopedPointer<QQuickView> window(createView());
+ window->engine()->rootContext()->setContextProperty("_model", &proxy2);
+ QQmlComponent component(window->engine());
+ component.setData("import QtQuick 2.4; ListView { "
+ "anchors.fill: parent; model: _model; delegate: Text { width: parent.width;"
+ "text: model.display; } }",
+ QUrl());
+ window->setContent(QUrl(), &component, component.create());
+
+ window->show();
+ QTest::qWaitForWindowExposed(window.data());
+
+ // this should not crash
+ model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole);
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickloader/data/qmldir b/tests/auto/quick/qquickloader/data/qmldir
deleted file mode 100644
index bf42b507c0..0000000000
--- a/tests/auto/quick/qquickloader/data/qmldir
+++ /dev/null
@@ -1 +0,0 @@
-# For tst_QDeclarativeLoader::networkRequestUrl; no types needed though.
diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
index 9c627ad69c..adf0d282c5 100644
--- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
+++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp
@@ -769,7 +769,7 @@ void tst_QQuickMouseArea::onMousePressRejected()
QVERIFY(!window.rootObject()->property("mr1_canceled").toBool());
QVERIFY(window.rootObject()->property("mr2_pressed").toBool());
QVERIFY(!window.rootObject()->property("mr2_released").toBool());
- QVERIFY(window.rootObject()->property("mr2_canceled").toBool());
+ QVERIFY(!window.rootObject()->property("mr2_canceled").toBool());
QTest::qWait(200);
@@ -1904,9 +1904,9 @@ void tst_QQuickMouseArea::ignoreBySource()
// MouseArea should grab the press because it's interested in non-synthesized mouse events
QPoint p = QPoint(80, 80);
QTest::mousePress(&window, Qt::LeftButton, 0, p);
- QVERIFY(window.mouseGrabberItem() == mouseArea);
+ QCOMPARE(window.mouseGrabberItem(), mouseArea);
// That was a real mouse event
- QVERIFY(root->property("lastEventSource").toInt() == Qt::MouseEventNotSynthesized);
+ QCOMPARE(root->property("lastEventSource").toInt(), int(Qt::MouseEventNotSynthesized));
// Flickable content should not move
p -= QPoint(startDragDistance() + 1, startDragDistance() + 1);
@@ -1919,12 +1919,14 @@ void tst_QQuickMouseArea::ignoreBySource()
QCOMPARE(flickable->contentY(), 0.);
QTest::mouseRelease(&window, Qt::LeftButton, 0, p);
+ QCOMPARE(window.mouseGrabberItem(), nullptr);
// Now try touch events and confirm that MouseArea ignores them, while Flickable does its thing
p = QPoint(80, 80);
QTest::touchEvent(&window, device).press(0, p, &window);
QQuickTouchUtils::flush(&window);
- QVERIFY(window.mouseGrabberItem() != mouseArea);
+ QCOMPARE(window.mouseGrabberItem(), flickable);
+
// That was a fake mouse event
QCOMPARE(root->property("lastEventSource").toInt(), int(Qt::MouseEventSynthesizedByQt));
p -= QPoint(startDragDistance() + 1, startDragDistance() + 1);
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index c3981c466f..2872556a94 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -915,13 +915,13 @@ void tst_QQuickMultiPointTouchArea::mouseAsTouchpoint()
// Touch both, release one, manipulate other touchpoint with mouse
QTest::touchEvent(window.data(), device).press(1, touch1);
QQuickTouchUtils::flush(window.data());
- QTest::touchEvent(window.data(), device).press(2, touch2);
+ QTest::touchEvent(window.data(), device).move(1, touch1).press(2, touch2);
QQuickTouchUtils::flush(window.data());
QCOMPARE(touch1rect->property("x").toInt(), touch1.x());
QCOMPARE(touch1rect->property("y").toInt(), touch1.y());
QCOMPARE(touch2rect->property("x").toInt(), touch2.x());
QCOMPARE(touch2rect->property("y").toInt(), touch2.y());
- QTest::touchEvent(window.data(), device).release(1, touch1);
+ QTest::touchEvent(window.data(), device).release(1, touch1).move(2, touch2);
touch1.setY(20);
QTest::mousePress(window.data(), Qt::LeftButton, 0, touch1);
QQuickTouchUtils::flush(window.data());
diff --git a/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp b/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp
index 355301878d..3bf61e8f17 100644
--- a/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp
+++ b/tests/auto/quick/qquickopenglinfo/tst_qquickopenglinfo.cpp
@@ -48,7 +48,7 @@ private slots:
void tst_QQuickOpenGLInfo::testProperties()
{
QQuickView view;
- view.setSource(QUrl::fromLocalFile("data/basic.qml"));
+ view.setSource(testFileUrl("basic.qml"));
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
index 1d7273f6df..c1a51fd659 100644
--- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
+++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp
@@ -511,6 +511,7 @@ void tst_QQuickPinchArea::cancel()
QCOMPARE(blackRect->scale(), 1.5);
QTouchEvent cancelEvent(QEvent::TouchCancel);
+ cancelEvent.setDevice(device);
QCoreApplication::sendEvent(window, &cancelEvent);
QQuickTouchUtils::flush(window);
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index d9bdf47041..acccac8eca 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -157,6 +157,7 @@ public:
lastVelocity = lastVelocityFromMouseMove = QVector2D();
lastMousePos = QPointF();
lastMouseCapabilityFlags = 0;
+ touchEventCount = 0;
}
static void clearMousePressCounter()
@@ -302,6 +303,9 @@ private slots:
void touchEvent_reentrant();
void touchEvent_velocity();
+ void mergeTouchPointLists_data();
+ void mergeTouchPointLists();
+
void mouseFromTouch_basic();
void clearWindow();
@@ -362,6 +366,9 @@ private slots:
void testHoverChildMouseEventFilter();
void testHoverTimestamp();
+
+ void pointerEventTypeAndPointCount();
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -521,9 +528,8 @@ void tst_qquickwindow::touchEvent_basic()
// press single point
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window);
- QTest::qWait(50);
-
- QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
+ QQuickTouchUtils::flush(window);
+ QTRY_COMPARE(topItem->lastEvent.touchPoints.count(), 1);
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
@@ -531,9 +537,10 @@ void tst_qquickwindow::touchEvent_basic()
// would put the decorated window at that position rather than the window itself.
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(topItem, pos)));
topItem->reset();
+ QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window);
// press multiple points
- QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),window)
+ QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window)
.press(1, bottomItem->mapToScene(pos).toPoint(), window);
QQuickTouchUtils::flush(window);
QCOMPARE(topItem->lastEvent.touchPoints.count(), 1);
@@ -543,6 +550,7 @@ void tst_qquickwindow::touchEvent_basic()
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos)));
topItem->reset();
bottomItem->reset();
+ QTest::touchEvent(window, touchDevice).release(0, topItem->mapToScene(pos).toPoint(), window).release(1, bottomItem->mapToScene(pos).toPoint(), window);
// touch point on top item moves to bottom item, but top item should still receive the event
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
@@ -553,6 +561,7 @@ void tst_qquickwindow::touchEvent_basic()
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(topItem, topItem->mapFromItem(bottomItem, pos), pos)));
topItem->reset();
+ QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window);
// touch point on bottom item moves to top item, but bottom item should still receive the event
QTest::touchEvent(window, touchDevice).press(0, bottomItem->mapToScene(pos).toPoint(), window);
@@ -563,6 +572,7 @@ void tst_qquickwindow::touchEvent_basic()
COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchUpdate, window, Qt::TouchPointMoved,
makeTouchPoint(bottomItem, bottomItem->mapFromItem(topItem, pos), pos)));
bottomItem->reset();
+ QTest::touchEvent(window, touchDevice).release(0, bottomItem->mapToScene(pos).toPoint(), window);
// a single stationary press on an item shouldn't cause an event
QTest::touchEvent(window, touchDevice).press(0, topItem->mapToScene(pos).toPoint(), window);
@@ -667,6 +677,7 @@ void tst_qquickwindow::touchEvent_propagation()
QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))));
+ QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window);
// touch top and middle items, middle item should get both events
QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window)
@@ -678,6 +689,8 @@ void tst_qquickwindow::touchEvent_propagation()
COMPARE_TOUCH_DATA(middleItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
(QList<QTouchEvent::TouchPoint>() << makeTouchPoint(middleItem, middleItem->mapFromItem(topItem, pos))
<< makeTouchPoint(middleItem, pos) )));
+ QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window)
+ .release(1, pointInMiddleItem, window);
middleItem->reset();
// disable middleItem as well
@@ -702,6 +715,8 @@ void tst_qquickwindow::touchEvent_propagation()
bottomItem->acceptTouchEvents = acceptTouchEvents;
bottomItem->setEnabled(enableItem);
bottomItem->setVisible(showItem);
+ QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window)
+ .release(1, pointInMiddleItem, window);
// no events should be received
QTest::touchEvent(window, touchDevice).press(0, pointInTopItem, window)
@@ -711,7 +726,9 @@ void tst_qquickwindow::touchEvent_propagation()
QVERIFY(topItem->lastEvent.touchPoints.isEmpty());
QVERIFY(middleItem->lastEvent.touchPoints.isEmpty());
QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty());
-
+ QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window)
+ .release(1, pointInMiddleItem, window)
+ .release(2, pointInBottomItem, window);
topItem->reset();
middleItem->reset();
bottomItem->reset();
@@ -737,6 +754,7 @@ void tst_qquickwindow::touchEvent_propagation()
COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, window, Qt::TouchPointPressed,
makeTouchPoint(topItem, pos)));
}
+ QTest::touchEvent(window, touchDevice).release(0, pointInTopItem, window);
delete topItem;
delete middleItem;
@@ -855,6 +873,8 @@ void tst_qquickwindow::touchEvent_velocity()
QWindowSystemInterface::handleTouchEvent(window, touchDeviceWithVelocity, points);
QGuiApplication::processEvents();
QQuickTouchUtils::flush(window);
+ QCOMPARE(item->touchEventCount, 1);
+
points[0].state = Qt::TouchPointMoved;
points[0].area.adjust(5, 5, 5, 5);
QVector2D velocity(1.5, 2.5);
@@ -887,6 +907,67 @@ void tst_qquickwindow::touchEvent_velocity()
delete item;
}
+void tst_qquickwindow::mergeTouchPointLists_data()
+{
+ QTest::addColumn<QVector<QQuickItem*>>("list1");
+ QTest::addColumn<QVector<QQuickItem*>>("list2");
+ QTest::addColumn<QVector<QQuickItem*>>("expected");
+ QTest::addColumn<bool>("showItem");
+
+ // FIXME: do not leak all these items
+ auto item1 = new QQuickItem();
+ auto item2 = new QQuickItem();
+ auto item3 = new QQuickItem();
+ auto item4 = new QQuickItem();
+ auto item5 = new QQuickItem();
+
+ QTest::newRow("empty") << QVector<QQuickItem*>() << QVector<QQuickItem*>() << QVector<QQuickItem*>();
+ QTest::newRow("single list left")
+ << (QVector<QQuickItem*>() << item1 << item2 << item3)
+ << QVector<QQuickItem*>()
+ << (QVector<QQuickItem*>() << item1 << item2 << item3);
+ QTest::newRow("single list right")
+ << QVector<QQuickItem*>()
+ << (QVector<QQuickItem*>() << item1 << item2 << item3)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3);
+ QTest::newRow("two lists identical")
+ << (QVector<QQuickItem*>() << item1 << item2 << item3)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3);
+ QTest::newRow("two lists 1")
+ << (QVector<QQuickItem*>() << item1 << item2 << item5)
+ << (QVector<QQuickItem*>() << item3 << item4 << item5)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5);
+ QTest::newRow("two lists 2")
+ << (QVector<QQuickItem*>() << item1 << item2 << item5)
+ << (QVector<QQuickItem*>() << item3 << item4 << item5)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5);
+ QTest::newRow("two lists 3")
+ << (QVector<QQuickItem*>() << item1 << item2 << item3)
+ << (QVector<QQuickItem*>() << item1 << item4 << item5)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5);
+ QTest::newRow("two lists 4")
+ << (QVector<QQuickItem*>() << item1 << item3 << item4)
+ << (QVector<QQuickItem*>() << item2 << item3 << item5)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4 << item5);
+ QTest::newRow("two lists 5")
+ << (QVector<QQuickItem*>() << item1 << item2 << item4)
+ << (QVector<QQuickItem*>() << item1 << item3 << item4)
+ << (QVector<QQuickItem*>() << item1 << item2 << item3 << item4);
+}
+
+void tst_qquickwindow::mergeTouchPointLists()
+{
+ QFETCH(QVector<QQuickItem*>, list1);
+ QFETCH(QVector<QQuickItem*>, list2);
+ QFETCH(QVector<QQuickItem*>, expected);
+
+ QQuickWindow win;
+ auto windowPrivate = QQuickWindowPrivate::get(&win);
+ auto targetList = windowPrivate->mergePointerTargets(list1, list2);
+ QCOMPARE(targetList, expected);
+}
+
void tst_qquickwindow::mouseFromTouch_basic()
{
// Turn off accepting touch events with acceptTouchEvents. This
@@ -2402,6 +2483,58 @@ void tst_qquickwindow::testHoverTimestamp()
QCOMPARE(hoverConsumer->hoverTimestamps.last(), 5UL);
}
+void tst_qquickwindow::pointerEventTypeAndPointCount()
+{
+ QPointF localPosition(33, 66);
+ QPointF scenePosition(133, 166);
+ QPointF screenPosition(333, 366);
+ QMouseEvent me(QEvent::MouseButtonPress, localPosition, scenePosition, screenPosition,
+ Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ QTouchEvent te(QEvent::TouchBegin, touchDevice, Qt::NoModifier, Qt::TouchPointPressed,
+ QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1));
+
+
+ QQuickPointerMouseEvent pme;
+ pme.reset(&me);
+ QVERIFY(pme.isValid());
+ QCOMPARE(pme.asMouseEvent(localPosition), &me);
+ QVERIFY(pme.asPointerMouseEvent());
+ QVERIFY(!pme.asPointerTouchEvent());
+ QVERIFY(!pme.asPointerTabletEvent());
+// QVERIFY(!pe->asTabletEvent()); // TODO
+ QCOMPARE(pme.pointCount(), 1);
+ QCOMPARE(pme.point(0)->scenePos(), scenePosition);
+ QCOMPARE(pme.asMouseEvent(localPosition)->localPos(), localPosition);
+ QCOMPARE(pme.asMouseEvent(localPosition)->screenPos(), screenPosition);
+
+ QQuickPointerTouchEvent pte;
+ pte.reset(&te);
+ QVERIFY(pte.isValid());
+ QCOMPARE(pte.asTouchEvent(), &te);
+ QVERIFY(!pte.asPointerMouseEvent());
+ QVERIFY(pte.asPointerTouchEvent());
+ QVERIFY(!pte.asPointerTabletEvent());
+ QVERIFY(pte.asTouchEvent());
+// QVERIFY(!pte.asTabletEvent()); // TODO
+ QCOMPARE(pte.pointCount(), 1);
+ QCOMPARE(pte.touchPointById(1)->id(), 1);
+ QVERIFY(!pte.touchPointById(0));
+
+ te.setTouchPoints(QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1) << QTouchEvent::TouchPoint(2));
+ pte.reset(&te);
+ QCOMPARE(pte.pointCount(), 2);
+ QCOMPARE(pte.touchPointById(1)->id(), 1);
+ QCOMPARE(pte.touchPointById(2)->id(), 2);
+ QVERIFY(!pte.touchPointById(0));
+
+ te.setTouchPoints(QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(2));
+ pte.reset(&te);
+ QCOMPARE(pte.pointCount(), 1);
+ QCOMPARE(pte.touchPointById(2)->id(), 2);
+ QVERIFY(!pte.touchPointById(1));
+ QVERIFY(!pte.touchPointById(0));
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
index 791bcb215a..f6d624d871 100644
--- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp
+++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp
@@ -44,6 +44,7 @@
#include <private/qsgcontext_p.h>
#include <private/qsgrenderloop_p.h>
+#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
using namespace QQuickVisualTestUtil;
@@ -92,7 +93,7 @@ private:
QColor m_color;
};
-class tst_SceneGraph : public QObject
+class tst_SceneGraph : public QQmlDataTest
{
Q_OBJECT
@@ -112,6 +113,7 @@ private slots:
private:
bool m_brokenMipmapSupport;
+ QQuickView *createView(const QString &file, QWindow *parent = 0, int x = -1, int y = -1, int w = -1, int h = -1);
};
template <typename T> class ScopedList : public QList<T> {
@@ -123,6 +125,8 @@ void tst_SceneGraph::initTestCase()
{
qmlRegisterType<PerPixelRect>("SceneGraphTest", 1, 0, "PerPixelRect");
+ QQmlDataTest::initTestCase();
+
QSGRenderLoop *loop = QSGRenderLoop::instance();
qDebug() << "RenderLoop: " << loop;
@@ -162,26 +166,16 @@ void tst_SceneGraph::initTestCase()
#endif
}
-QQuickView *createView(const QString &file, QWindow *parent = 0, int x = -1, int y = -1, int w = -1, int h = -1)
+QQuickView *tst_SceneGraph::createView(const QString &file, QWindow *parent, int x, int y, int w, int h)
{
QQuickView *view = new QQuickView(parent);
- view->setSource(QUrl::fromLocalFile("data/" + file));
+ view->setSource(testFileUrl(file));
if (x >= 0 && y >= 0) view->setPosition(x, y);
if (w >= 0 && h >= 0) view->resize(w, h);
view->show();
return view;
}
-QImage showAndGrab(const QString &file, int w, int h)
-{
- QQuickView view;
- view.setSource(QUrl::fromLocalFile(QStringLiteral("data/") + file));
- if (w >= 0 && h >= 0)
- view.resize(w, h);
- view.create();
- return view.grabWindow();
-}
-
// Assumes the images are opaque white...
bool containsSomethingOtherThanWhite(const QImage &image)
{
@@ -384,17 +378,17 @@ void tst_SceneGraph::render_data()
QTest::addColumn<QList<Sample> >("finalStage");
QList<QString> files;
- files << "data/render_DrawSets.qml"
- << "data/render_Overlap.qml"
- << "data/render_MovingOverlap.qml"
- << "data/render_BreakOpacityBatch.qml"
- << "data/render_OutOfFloatRange.qml"
- << "data/render_StackingOrder.qml"
- << "data/render_ImageFiltering.qml"
- << "data/render_bug37422.qml"
- << "data/render_OpacityThroughBatchRoot.qml";
+ files << "render_DrawSets.qml"
+ << "render_Overlap.qml"
+ << "render_MovingOverlap.qml"
+ << "render_BreakOpacityBatch.qml"
+ << "render_OutOfFloatRange.qml"
+ << "render_StackingOrder.qml"
+ << "render_ImageFiltering.qml"
+ << "render_bug37422.qml"
+ << "render_OpacityThroughBatchRoot.qml";
if (!m_brokenMipmapSupport)
- files << "data/render_Mipmap.qml";
+ files << "render_Mipmap.qml";
QRegExp sampleCount("#samples: *(\\d+)");
// X:int Y:int R:float G:float B:float Error:float
@@ -402,7 +396,7 @@ void tst_SceneGraph::render_data()
QRegExp finalSamples("#final: *(\\d+) *(\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+) *(\\d\\.\\d+)");
foreach (QString fileName, files) {
- QFile file(fileName);
+ QFile file(testFile(fileName));
if (!file.open(QFile::ReadOnly)) {
qFatal("render_data: QFile::open failed! file=%s, error=%s",
qPrintable(fileName), qPrintable(file.errorString()));
@@ -452,7 +446,7 @@ void tst_SceneGraph::render()
QQuickView view;
view.rootContext()->setContextProperty("suite", &suite);
- view.setSource(QUrl::fromLocalFile(file));
+ view.setSource(testFileUrl(file));
view.setResizeMode(QQuickView::SizeViewToRootObject);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
@@ -501,7 +495,7 @@ void tst_SceneGraph::hideWithOtherContext()
{
QQuickView view;
- view.setSource(QUrl::fromLocalFile("data/simple.qml"));
+ view.setSource(testFileUrl("simple.qml"));
view.setResizeMode(QQuickView::SizeViewToRootObject);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
diff --git a/tests/auto/quick/touchmouse/data/touchpointdeliveryorder.qml b/tests/auto/quick/touchmouse/data/touchpointdeliveryorder.qml
new file mode 100644
index 0000000000..9f67c226a0
--- /dev/null
+++ b/tests/auto/quick/touchmouse/data/touchpointdeliveryorder.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.0
+import Qt.test 1.0
+
+Rectangle {
+ id: root
+
+ width: 600
+ height: 400
+
+ EventItem {
+ objectName: "background"
+ width: 600
+ height: 400
+ Rectangle { anchors.fill: parent; color: "lightsteelblue" }
+
+ EventItem {
+ objectName: "left"
+ width: 300
+ height: 300
+ Rectangle { anchors.fill: parent; color: "yellow" }
+ }
+
+ EventItem {
+ objectName: "right"
+ x: 300
+ width: 300
+ height: 300
+ Rectangle { anchors.fill: parent; color: "green" }
+ }
+
+ EventItem {
+ objectName: "middle"
+ x: 150
+ width: 300
+ height: 300
+ Rectangle { anchors.fill: parent; color: "blue" }
+ }
+ }
+}
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index dc70081f09..1ec24e35d5 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -33,12 +33,12 @@
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
+#include <QtQuick/private/qquickevents_p_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquickmultipointtoucharea_p.h>
#include <QtQuick/private/qquickpincharea_p.h>
#include <QtQuick/private/qquickflickable_p.h>
-
-#include <private/qquickwindow_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
@@ -65,15 +65,22 @@ struct Event
class EventItem : public QQuickItem
{
Q_OBJECT
+
+Q_SIGNALS:
+ void onTouchEvent(QQuickItem *receiver);
+
public:
EventItem(QQuickItem *parent = 0)
: QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false)
- {}
+ {
+ setAcceptedMouseButtons(Qt::LeftButton);
+ }
void touchEvent(QTouchEvent *event)
{
eventList.append(Event(event->type(), event->touchPoints()));
event->setAccepted(acceptTouch);
+ emit onTouchEvent(this);
}
void mousePressEvent(QMouseEvent *event)
{
@@ -154,6 +161,7 @@ private slots:
void tapOnDismissiveTopMouseAreaClicksBottomOne();
void touchGrabCausesMouseUngrab();
+ void touchPointDeliveryOrder();
void hoverEnabled();
@@ -211,15 +219,17 @@ void tst_TouchMouse::simpleTouchEvent()
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
QQuickTouchUtils::flush(window);
- QCOMPARE(eventItem1->eventList.size(), 1);
+ // Get a touch and then mouse event offered
+ QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
QQuickTouchUtils::flush(window);
- QCOMPARE(eventItem1->eventList.size(), 1);
+ // Not accepted, no updates
+ QCOMPARE(eventItem1->eventList.size(), 2);
QTest::touchEvent(window, device).release(0, p1, window);
QQuickTouchUtils::flush(window);
- QCOMPARE(eventItem1->eventList.size(), 1);
+ QCOMPARE(eventItem1->eventList.size(), 2);
eventItem1->eventList.clear();
// Accept touch
@@ -285,17 +295,16 @@ void tst_TouchMouse::simpleTouchEvent()
p1 = QPoint(20, 20);
QTest::touchEvent(window, device).press(0, p1, window);
QQuickTouchUtils::flush(window);
- QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE(eventItem1->eventList.size(), 2);
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
- QCOMPARE(eventItem1->eventList.at(2).type, QEvent::UngrabMouse);
p1 += QPoint(10, 0);
QTest::touchEvent(window, device).move(0, p1, window);
QQuickTouchUtils::flush(window);
- QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE(eventItem1->eventList.size(), 2);
QTest::touchEvent(window, device).release(0, p1, window);
QQuickTouchUtils::flush(window);
- QCOMPARE(eventItem1->eventList.size(), 3);
+ QCOMPARE(eventItem1->eventList.size(), 2);
eventItem1->eventList.clear();
// wait to avoid getting a double click event
@@ -572,7 +581,8 @@ void tst_TouchMouse::buttonOnFlickable()
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
QCOMPARE(windowPriv->touchMouseId, 0);
- QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1);
+ auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent();
+ QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1);
QCOMPARE(window->mouseGrabberItem(), eventItem1);
p1 += QPoint(0, -10);
@@ -593,7 +603,7 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(window->mouseGrabberItem(), flickable);
QCOMPARE(windowPriv->touchMouseId, 0);
- QCOMPARE(windowPriv->itemForTouchPointId[0], flickable);
+ QCOMPARE(pointerEvent->point(0)->grabber(), flickable);
QVERIFY(flickable->isMovingVertically());
QTest::touchEvent(window, device).release(0, p3, window);
@@ -653,11 +663,12 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
QCOMPARE(filteredEventList.count(), 1);
- // eventItem1 should have the mouse grab, and have moved the itemForTouchPointId
+ // eventItem1 should have the mouse grab, and have moved the grab
// for the touchMouseId to the new grabber.
QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
QCOMPARE(windowPriv->touchMouseId, 0);
- QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1);
+ auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent();
+ QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1);
QCOMPARE(window->mouseGrabberItem(), eventItem1);
p1 += QPoint(0, -10);
@@ -676,7 +687,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable()
// for the touchMouseId to the new grabber.
QCOMPARE(window->mouseGrabberItem(), flickable);
QCOMPARE(windowPriv->touchMouseId, 0);
- QCOMPARE(windowPriv->itemForTouchPointId[0], flickable);
+ QCOMPARE(pointerEvent->point(0)->grabber(), flickable);
QTest::touchEvent(window, device).release(0, p3, window);
QQuickTouchUtils::flush(window);
@@ -1090,8 +1101,6 @@ void tst_TouchMouse::mouseOnFlickableOnPinch()
pinchSequence.move(0, p, window).commit();
QQuickTouchUtils::flush(window);
- QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
- qDebug() << "Mouse Grabber: " << window->mouseGrabberItem() << " itemForTouchPointId: " << windowPriv->itemForTouchPointId;
QCOMPARE(window->mouseGrabberItem(), flickable);
// Add a second finger, this should lead to stealing
@@ -1222,6 +1231,105 @@ void tst_TouchMouse::touchGrabCausesMouseUngrab()
delete window;
}
+void tst_TouchMouse::touchPointDeliveryOrder()
+{
+ // Touch points should be first delivered to the item under the primary finger
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("touchpointdeliveryorder.qml"));
+ /*
+ The items are positioned from left to right:
+ | background |
+ | left |
+ | | right |
+ | middle |
+ 0 150 300 450 600
+ */
+ QPoint pLeft = QPoint(100, 100);
+ QPoint pRight = QPoint(500, 100);
+ QPoint pLeftMiddle = QPoint(200, 100);
+ QPoint pRightMiddle = QPoint(350, 100);
+
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QVector<QQuickItem*> events;
+ EventItem *background = window->rootObject()->findChild<EventItem*>("background");
+ EventItem *left = window->rootObject()->findChild<EventItem*>("left");
+ EventItem *middle = window->rootObject()->findChild<EventItem*>("middle");
+ EventItem *right = window->rootObject()->findChild<EventItem*>("right");
+ QVERIFY(background);
+ QVERIFY(left);
+ QVERIFY(middle);
+ QVERIFY(right);
+ connect(background, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
+ connect(left, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
+ connect(middle, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
+ connect(right, &EventItem::onTouchEvent, [&events](QQuickItem* receiver){ events.append(receiver); });
+
+ QTest::touchEvent(window.data(), device).press(0, pLeft, window.data());
+ QQuickTouchUtils::flush(window.data());
+
+ // Touch on left, then background
+ QCOMPARE(events.size(), 2);
+ QCOMPARE(events.at(0), left);
+ QCOMPARE(events.at(1), background);
+ events.clear();
+
+ // New press events are deliverd first, the stationary point was not accepted, thus it doesn't get delivered
+ QTest::touchEvent(window.data(), device).stationary(0).press(1, pRightMiddle, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QCOMPARE(events.size(), 3);
+ QCOMPARE(events.at(0), middle);
+ QCOMPARE(events.at(1), right);
+ QCOMPARE(events.at(2), background);
+ events.clear();
+
+ QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRightMiddle, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QCOMPARE(events.size(), 0); // no accepted events
+
+ // Two presses, the first point should come first
+ QTest::touchEvent(window.data(), device).press(0, pLeft, window.data()).press(1, pRight, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QCOMPARE(events.size(), 3);
+ QCOMPARE(events.at(0), left);
+ QCOMPARE(events.at(1), right);
+ QCOMPARE(events.at(2), background);
+ QTest::touchEvent(window.data(), device).release(0, pLeft, window.data()).release(1, pRight, window.data());
+ events.clear();
+
+ // Again, pressing right first
+ QTest::touchEvent(window.data(), device).press(0, pRight, window.data()).press(1, pLeft, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QCOMPARE(events.size(), 3);
+ QCOMPARE(events.at(0), right);
+ QCOMPARE(events.at(1), left);
+ QCOMPARE(events.at(2), background);
+ QTest::touchEvent(window.data(), device).release(0, pRight, window.data()).release(1, pLeft, window.data());
+ events.clear();
+
+ // Two presses, both hitting the middle item on top, then branching left and right, then bottom
+ // Each target should be offered the events exactly once, middle first, left must come before right (id 0)
+ QTest::touchEvent(window.data(), device).press(0, pLeftMiddle, window.data()).press(1, pRightMiddle, window.data());
+ QCOMPARE(events.size(), 4);
+ QCOMPARE(events.at(0), middle);
+ QCOMPARE(events.at(1), left);
+ QCOMPARE(events.at(2), right);
+ QCOMPARE(events.at(3), background);
+ QTest::touchEvent(window.data(), device).release(0, pLeftMiddle, window.data()).release(1, pRightMiddle, window.data());
+ events.clear();
+
+ QTest::touchEvent(window.data(), device).press(0, pRightMiddle, window.data()).press(1, pLeftMiddle, window.data());
+ qDebug() << events;
+ QCOMPARE(events.size(), 4);
+ QCOMPARE(events.at(0), middle);
+ QCOMPARE(events.at(1), right);
+ QCOMPARE(events.at(2), left);
+ QCOMPARE(events.at(3), background);
+ QTest::touchEvent(window.data(), device).release(0, pRightMiddle, window.data()).release(1, pLeftMiddle, window.data());
+}
+
void tst_TouchMouse::hoverEnabled()
{
// QTouchDevice *device = new QTouchDevice;
diff --git a/tools/fdegen/fdegen.pro b/tools/fdegen/fdegen.pro
deleted file mode 100644
index a52533280e..0000000000
--- a/tools/fdegen/fdegen.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = app
-TARGET = fdegen
-INCLUDEPATH += .
-
-# Input
-SOURCES += main.cpp
-
-LIBS += -ldwarf -lelf
diff --git a/tools/fdegen/main.cpp b/tools/fdegen/main.cpp
deleted file mode 100644
index 53ee9dec2a..0000000000
--- a/tools/fdegen/main.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the V4VM module 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 <libdwarf.h>
-#include <dwarf.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#define DEBUG
-
-#ifdef DEBUG
-#include <libelf.h>
-#endif
-
-#include <qglobal.h>
-
-enum DwarfRegs {
-#if defined(Q_PROCESSOR_X86_64)
- // X86-64
- RAX = 0,
- RDX = 1,
- RCX = 2,
- RBX = 3,
- RSI = 4,
- RDI = 5,
- RBP = 6,
- RSP = 7,
- R8 = 8,
- R9 = 9,
- R10 = 10,
- R11 = 11,
- R12 = 12,
- R13 = 13,
- R14 = 14,
- R15 = 15,
- RIP = 16,
-
- InstructionPointerRegister = RIP,
- StackPointerRegister = RSP,
- StackFrameRegister = RBP
-#elif defined(Q_PROCESSOR_X86)
- // x86
- EAX = 0,
- EDX = 1,
- ECX = 2,
- EBX = 3,
- ESP = 4,
- EBP = 5,
- ESI = 6,
- EDI = 7,
- EIP = 8,
-
- InstructionPointerRegister = EIP,
- StackPointerRegister = ESP,
- StackFrameRegister = EBP
-#else
-#error Not ported yet
-#endif
-};
-
-static const DwarfRegs calleeSavedRegisters[] = {
-#if defined(Q_PROCESSOR_X86_64)
- R12,
- R14
-#elif defined(Q_PROCESSOR_X86)
- ESI,
- EDI
-#endif
-};
-static const int calleeSavedRegisterCount = sizeof(calleeSavedRegisters) / sizeof(calleeSavedRegisters[0]);
-
-#if QT_POINTER_SIZE == 8
-#define Elf_Ehdr Elf64_Ehdr
-#define elf_newehdr elf64_newehdr
-#define Elf_Shdr Elf64_Shdr
-#define elf_getshdr elf64_getshdr
-#else
-#define Elf_Ehdr Elf32_Ehdr
-#define elf_newehdr elf32_newehdr
-#define Elf_Shdr Elf32_Shdr
-#define elf_getshdr elf32_getshdr
-#endif
-
-static void die(const char *msg)
-{
- fprintf(stderr, "error: %s\n", msg);
- exit(1);
-}
-
-static int createSectionCallback(
- char *name,
- int size,
- Dwarf_Unsigned /*type*/,
- Dwarf_Unsigned /*flags*/,
- Dwarf_Unsigned /*link*/,
- Dwarf_Unsigned /*info*/,
- Dwarf_Unsigned* /*sect_name_index*/,
- void * /*user_data*/,
- int* /*error*/)
-{
- if (strcmp(name, ".debug_frame"))
- return 0;
- fprintf(stderr, "createsection called with %s and size %d\n", name, size);
- return 1;
-}
-
-static unsigned char cie_init_instructions[] = {
- DW_CFA_def_cfa, StackPointerRegister, /*offset in bytes */sizeof(void*),
- DW_CFA_offset | InstructionPointerRegister, 1,
-};
-
-int main()
-{
- Dwarf_Error error = 0;
- Dwarf_P_Debug dw = dwarf_producer_init_c(DW_DLC_WRITE | DW_DLC_SIZE_64,
- createSectionCallback,
- /* error handler */0,
- /* error arg */0,
- /* user data */0,
- &error);
- if (error != 0)
- die("dwarf_producer_init_c failed");
-
- Dwarf_Unsigned cie = dwarf_add_frame_cie(dw,
- "",
- /* code alignment factor */sizeof(void*),
- /* data alignment factor */-sizeof(void*),
- /* return address reg*/InstructionPointerRegister,
- cie_init_instructions,
- sizeof(cie_init_instructions),
- &error);
- if (error != 0)
- die("dwarf_add_frame_cie failed");
-
- Dwarf_P_Fde fde = dwarf_new_fde(dw, &error);
- if (error != 0)
- die("dwarf_new_fde failed");
-
- /* New entry in state machine for code offset 1 after push rbp instruction */
- dwarf_add_fde_inst(fde,
- DW_CFA_advance_loc,
- /*offset in code alignment units*/ 1,
- /* unused*/ 0,
- &error);
-
- /* After "push rbp" the offset to the CFA is now 2 instead of 1 */
- dwarf_add_fde_inst(fde,
- DW_CFA_def_cfa_offset_sf,
- /*offset in code alignment units*/ -2,
- /* unused*/ 0,
- &error);
-
- /* After "push rbp" the value of rbp is now stored at offset 1 from CFA */
- dwarf_add_fde_inst(fde,
- DW_CFA_offset,
- StackFrameRegister,
- 2,
- &error);
-
- /* New entry in state machine for code offset 3 for mov rbp, rsp instruction */
- dwarf_add_fde_inst(fde,
- DW_CFA_advance_loc,
- /*offset in code alignment units*/ 3,
- /* unused */ 0,
- &error);
-
- /* After "mov rbp, rsp" the cfa is reachable via rbp */
- dwarf_add_fde_inst(fde,
- DW_CFA_def_cfa_register,
- StackFrameRegister,
- /* unused */0,
- &error);
-
- /* Callee saved registers */
- for (int i = 0; i < calleeSavedRegisterCount; ++i) {
- dwarf_add_fde_inst(fde,
- DW_CFA_offset,
- calleeSavedRegisters[i],
- i + 3,
- &error);
- }
-
- dwarf_add_frame_fde(dw, fde,
- /* die */0,
- cie,
- /*virt addr */0,
- /* length of code */0,
- /* symbol index */0,
- &error);
- if (error != 0)
- die("dwarf_add_frame_fde failed");
-
- dwarf_transform_to_disk_form(dw, &error);
- if (error != 0)
- die("dwarf_transform_to_disk_form failed");
-
- Dwarf_Unsigned len = 0;
- Dwarf_Signed elfIdx = 0;
- unsigned char *bytes = (unsigned char *)dwarf_get_section_bytes(dw, /* section */1,
- &elfIdx, &len, &error);
- if (error != 0)
- die("dwarf_get_section_bytes failed");
-
- // libdwarf doesn't add a terminating FDE with zero length, so let's add one
- // ourselves.
- unsigned char *newBytes = (unsigned char *)alloca(len + 4);
- memcpy(newBytes, bytes, len);
- newBytes[len] = 0;
- newBytes[len + 1] = 0;
- newBytes[len + 2] = 0;
- newBytes[len + 3] = 0;
- newBytes[len + 4] = 0;
- bytes = newBytes;
- len += 4;
-
- // Reset CIE-ID back to 0 as expected for .eh_frames
- bytes[4] = 0;
- bytes[5] = 0;
- bytes[6] = 0;
- bytes[7] = 0;
-
- unsigned fde_offset = bytes[0] + 4;
-
- bytes[fde_offset + 4] = fde_offset + 4;
-
- printf("static const unsigned char cie_fde_data[] = {\n");
- int i = 0;
- while (i < len) {
- printf(" ");
- for (int j = 0; i < len && j < 8; ++j, ++i)
- printf("0x%x, ", bytes[i]);
- printf("\n");
- }
- printf("};\n");
-
- printf("static const int fde_offset = %d;\n", fde_offset);
- printf("static const int initial_location_offset = %d;\n", fde_offset + 8);
- printf("static const int address_range_offset = %d;\n", fde_offset + 8 + sizeof(void*));
-
-#ifdef DEBUG
- {
- if (elf_version(EV_CURRENT) == EV_NONE)
- die("wrong elf version");
- int fd = open("debug.o", O_WRONLY | O_CREAT, 0777);
- if (fd < 0)
- die("cannot create debug.o");
-
- Elf *e = elf_begin(fd, ELF_C_WRITE, 0);
- if (!e)
- die("elf_begin failed");
-
- Elf_Ehdr *ehdr = elf_newehdr(e);
- if (!ehdr)
- die(elf_errmsg(-1));
-
- ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
-#if defined(Q_PROCESSOR_X86_64)
- ehdr->e_machine = EM_X86_64;
-#elif defined(Q_PROCESSOR_X86)
- ehdr->e_machine = EM_386;
-#else
-#error port me :)
-#endif
- ehdr->e_type = ET_EXEC;
- ehdr->e_version = EV_CURRENT;
-
- Elf_Scn *section = elf_newscn(e);
- if (!section)
- die("elf_newscn failed");
-
- Elf_Data *data = elf_newdata(section);
- if (!data)
- die(elf_errmsg(-1));
- data->d_align = 4;
- data->d_off = 0;
- data->d_buf = bytes;
- data->d_size = len;
- data->d_type = ELF_T_BYTE;
- data->d_version = EV_CURRENT;
-
- Elf_Shdr *shdr = elf_getshdr(section);
- if (!shdr)
- die(elf_errmsg(-1));
-
- shdr->sh_name = 1;
- shdr->sh_type = SHT_PROGBITS;
- shdr->sh_entsize = 0;
-
- char stringTable[] = {
- 0,
- '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0,
- '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0
- };
-
- section = elf_newscn(e);
- if (!section)
- die("elf_newscn failed");
-
- data = elf_newdata(section);
- if (!data)
- die(elf_errmsg(-1));
- data->d_align = 1;
- data->d_off = 0;
- data->d_buf = stringTable;
- data->d_size = sizeof(stringTable);
- data->d_type = ELF_T_BYTE;
- data->d_version = EV_CURRENT;
-
- shdr = elf_getshdr(section);
- if (!shdr)
- die(elf_errmsg(-1));
-
- shdr->sh_name = 11;
- shdr->sh_type = SHT_STRTAB;
- shdr->sh_flags = SHF_STRINGS | SHF_ALLOC;
- shdr->sh_entsize = 0;
-
- ehdr->e_shstrndx = elf_ndxscn(section);
-
- if (elf_update(e, ELF_C_WRITE) < 0)
- die(elf_errmsg(-1));
-
- elf_end(e);
- close(fd);
- }
-#endif
-
- dwarf_producer_finish(dw, &error);
- if (error != 0)
- die("dwarf_producer_finish failed");
- return 0;
-}
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index a795144984..d718067616 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -160,18 +160,23 @@ public:
LoadWatcher(QQmlApplicationEngine *e, int expected)
: QObject(e)
, earlyExit(false)
+ , returnCode(0)
, expect(expected)
, haveOne(false)
{
connect(e, SIGNAL(objectCreated(QObject*,QUrl)),
this, SLOT(checkFinished(QObject*)));
// QQmlApplicationEngine also connects quit() to QCoreApplication::quit
- // but if called before exec() then QCoreApplication::quit does nothing
+ // and exit() to QCoreApplication::exit but if called before exec()
+ // then QCoreApplication::quit or QCoreApplication::exit does nothing
connect(e, SIGNAL(quit()),
this, SLOT(quit()));
+ connect(e, &QQmlEngine::exit,
+ this, &LoadWatcher::exit);
}
bool earlyExit;
+ int returnCode;
private:
void contain(QObject *o, const QUrl &containPath);
@@ -196,14 +201,20 @@ public Q_SLOTS:
if (! --expect) {
printf("qml: Did not load any objects, exiting.\n");
- exit(2);//Different return code from qFatal
+ std::exit(2);//Different return code from qFatal
}
}
void quit() {
//Will be checked before calling exec()
earlyExit = true;
+ returnCode = 0;
}
+ void exit(int retCode) {
+ earlyExit = true;
+ returnCode = retCode;
+ }
+
#if defined(QT_GUI_LIB) && !defined(QT_NO_OPENGL)
void onOpenGlContextCreated(QOpenGLContext *context);
#endif
@@ -582,7 +593,7 @@ int main(int argc, char *argv[])
}
if (lw->earlyExit)
- return 0;
+ return lw->returnCode;
return app->exec();
}
diff --git a/tools/qmleasing/splineeditor.cpp b/tools/qmleasing/splineeditor.cpp
index 78ed9606db..ee55931a46 100644
--- a/tools/qmleasing/splineeditor.cpp
+++ b/tools/qmleasing/splineeditor.cpp
@@ -34,6 +34,7 @@
#include <QContextMenuEvent>
#include <QDebug>
#include <QApplication>
+#include <QVector>
const int canvasWidth = 640;
const int canvasHeight = 320;
@@ -672,25 +673,23 @@ void SplineEditor::setEasingCurve(const QString &code)
if (m_block)
return;
if (code.startsWith(QLatin1Char('[')) && code.endsWith(QLatin1Char(']'))) {
- QString cleanCode = code;
- cleanCode.remove(0, 1);
- cleanCode.chop(1);
- const QStringList stringList = cleanCode.split(QLatin1Char(','), QString::SkipEmptyParts);
+ const QStringRef cleanCode(&code, 1, code.size() - 2);
+ const auto stringList = cleanCode.split(QLatin1Char(','), QString::SkipEmptyParts);
if (stringList.count() >= 6 && (stringList.count() % 6 == 0)) {
- QList<qreal> realList;
+ QVector<qreal> realList;
realList.reserve(stringList.count());
- foreach (const QString &string, stringList) {
+ for (const QStringRef &string : stringList) {
bool ok;
realList.append(string.toDouble(&ok));
if (!ok)
return;
}
- QList<QPointF> points;
+ QVector<QPointF> points;
const int count = realList.count() / 2;
points.reserve(count);
for (int i = 0; i < count; ++i)
points.append(QPointF(realList.at(i * 2), realList.at(i * 2 + 1)));
- if (points.last() == QPointF(1.0, 1.0)) {
+ if (points.constLast() == QPointF(1.0, 1.0)) {
QEasingCurve easingCurve(QEasingCurve::BezierSpline);
for (int i = 0; i < points.count() / 3; ++i) {
diff --git a/tools/qmlimportscanner/main.cpp b/tools/qmlimportscanner/main.cpp
index 2569d78c63..2371057878 100644
--- a/tools/qmlimportscanner/main.cpp
+++ b/tools/qmlimportscanner/main.cpp
@@ -224,11 +224,11 @@ QVariantList findPathsForModuleImports(const QVariantList &imports)
if (plugininfo.contains(QStringLiteral("dependencies"))) {
QStringList dependencies = plugininfo.value(QStringLiteral("dependencies")).toStringList();
foreach (const QString &line, dependencies) {
- QList<QString> dep = line.split(QLatin1Char(' '));
+ const auto dep = line.splitRef(QLatin1Char(' '));
QVariantMap depImport;
depImport[QStringLiteral("type")] = QStringLiteral("module");
- depImport[QStringLiteral("name")] = dep[0];
- depImport[QStringLiteral("version")] = dep[1];
+ depImport[QStringLiteral("name")] = dep[0].toString();
+ depImport[QStringLiteral("version")] = dep[1].toString();
importsCopy.append(depImport);
}
}
diff --git a/tools/qmlprofiler/qmlprofilerapplication.cpp b/tools/qmlprofiler/qmlprofilerapplication.cpp
index 063e5e2961..45c32487a2 100644
--- a/tools/qmlprofiler/qmlprofilerapplication.cpp
+++ b/tools/qmlprofiler/qmlprofilerapplication.cpp
@@ -347,7 +347,7 @@ bool QmlProfilerApplication::checkOutputFile(PendingRequest pending)
void QmlProfilerApplication::userCommand(const QString &command)
{
- QStringList args = command.split(QChar::Space, QString::SkipEmptyParts);
+ auto args = command.splitRef(QChar::Space, QString::SkipEmptyParts);
if (args.isEmpty()) {
prompt();
return;
@@ -401,7 +401,7 @@ void QmlProfilerApplication::userCommand(const QString &command)
} else if (m_profilerData.isEmpty()) {
prompt(tr("No data was recorded so far."));
} else {
- m_interactiveOutputFile = args.length() > 0 ? args[0] : m_outputFile;
+ m_interactiveOutputFile = args.length() > 0 ? args.at(0).toString() : m_outputFile;
if (checkOutputFile(REQUEST_OUTPUT_FILE))
output();
}
@@ -418,7 +418,7 @@ void QmlProfilerApplication::userCommand(const QString &command)
if (!m_recording && m_profilerData.isEmpty()) {
prompt(tr("No data was recorded so far."));
} else {
- m_interactiveOutputFile = args.length() > 0 ? args[0] : m_outputFile;
+ m_interactiveOutputFile = args.length() > 0 ? args.at(0).toString() : m_outputFile;
if (checkOutputFile(REQUEST_FLUSH_FILE))
flush();
}
diff --git a/tools/qmlprofiler/qmlprofilerdata.cpp b/tools/qmlprofiler/qmlprofilerdata.cpp
index 74fa44c1d6..b651b2724f 100644
--- a/tools/qmlprofiler/qmlprofilerdata.cpp
+++ b/tools/qmlprofiler/qmlprofilerdata.cpp
@@ -248,7 +248,7 @@ void QmlProfilerData::addQmlEvent(QQmlProfilerDefinitions::RangeType type,
eventHashStr = getHashStringForQmlEvent(eventLocation, type);
} else {
const QString filePath = QUrl(eventLocation.filename).path();
- displayName = filePath.mid(
+ displayName = filePath.midRef(
filePath.lastIndexOf(QLatin1Char('/')) + 1) +
QLatin1Char(':') + QString::number(eventLocation.line);
eventHashStr = getHashStringForQmlEvent(eventLocation, type);
@@ -327,8 +327,8 @@ void QmlProfilerData::addPixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventTy
QString filePath = QUrl(location).path();
- QString eventHashStr = filePath.mid(filePath.lastIndexOf(QLatin1Char('/')) + 1) +
- QStringLiteral(":") + QString::number(type);
+ const QString eventHashStr = filePath.midRef(filePath.lastIndexOf(QLatin1Char('/')) + 1)
+ + QLatin1Char(':') + QString::number(type);
QmlRangeEventData *newEvent;
if (d->eventDescriptions.contains(eventHashStr)) {
newEvent = d->eventDescriptions[eventHashStr];
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 1185a8e7ae..0e542ab0c8 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -564,6 +564,7 @@ int main(int argc, char ** argv)
loadDummyDataFiles(engine, fi.path());
}
QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
+ QObject::connect(&engine, &QQmlEngine::exit, QCoreApplication::instance(), &QCoreApplication::exit);
component->loadUrl(options.url);
while (component->isLoading())
QCoreApplication::processEvents();