aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/imports.pro4
-rw-r--r--src/plugins/plugins.pro2
-rw-r--r--src/plugins/qmltooling/qmltooling.pro10
-rw-r--r--src/qml/animations/qabstractanimationjob.cpp5
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp48
-rw-r--r--src/qml/compiler/qv4codegen.cpp12
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp7
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h1
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp52
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions_p.h1
-rw-r--r--src/qml/configure.json6
-rw-r--r--src/qml/doc/images/cpp-qml-integration-flowchart.odgbin16080 -> 15028 bytes
-rw-r--r--src/qml/doc/images/cpp-qml-integration-flowchart.pngbin113781 -> 80498 bytes
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp8
-rw-r--r--src/qml/jsruntime/qv4engine.cpp4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp33
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h11
-rw-r--r--src/qml/jsruntime/qv4generatorobject_p.h3
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp5
-rw-r--r--src/qml/jsruntime/qv4propertykey.cpp19
-rw-r--r--src/qml/jsruntime/qv4propertykey_p.h1
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp101
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h3
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp10
-rw-r--r--src/qml/qml/qqmlengine.cpp8
-rw-r--r--src/qml/qml/qqmlengine_p.h2
-rw-r--r--src/qml/qml/qqmlimport.cpp28
-rw-r--r--src/qml/qml/qqmlimport_p.h1
-rw-r--r--src/qml/qml/qqmltypeloader.cpp62
-rw-r--r--src/qml/qml/qqmltypeloader_p.h1
-rw-r--r--src/qml/qml/v8/qv8engine.cpp2
-rw-r--r--src/qml/types/types.pri9
-rw-r--r--src/quick/configure.json2
-rw-r--r--src/quick/doc/images/9BcAYDlpuT8.jpgbin0 -> 8788 bytes
-rw-r--r--src/quick/doc/qtquick.qdocconf4
-rw-r--r--src/quick/doc/snippets/qml/tableview/reusabledelegate.qml82
-rw-r--r--src/quick/doc/snippets/qml/tableview/tablemodel.cpp103
-rw-r--r--src/quick/doc/snippets/qml/tableview/tablemodel.qml71
-rw-r--r--src/quick/doc/snippets/qml/tableview/tableviewwithheader.qml64
-rw-r--r--src/quick/doc/snippets/qml/tableview/tableviewwithprovider.qml69
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc7
-rw-r--r--src/quick/items/qquickevents_p_p.h2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp2
-rw-r--r--src/quick/items/qquicktableview.cpp369
-rw-r--r--src/quick/scenegraph/adaptations/adaptations.pri2
-rw-r--r--src/quick/scenegraph/qsgcontextplugin.cpp2
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp3
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/scenegraph.pri9
-rw-r--r--src/quick/scenegraph/util/qsgtexturereader.cpp5
-rw-r--r--src/quickwidgets/qquickwidget.cpp2
-rw-r--r--src/src.pro4
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations90
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp2
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp48
-rw-r--r--tools/tools.pro2
56 files changed, 1173 insertions, 232 deletions
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index 653c787384..eb3e336c7f 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -3,10 +3,10 @@ TEMPLATE = subdirs
SUBDIRS += \
builtins \
qtqml \
- folderlistmodel \
models \
labsmodels
+qtConfig(thread): SUBDIRS += folderlistmodel
qtHaveModule(sql): SUBDIRS += localstorage
qtConfig(settings): SUBDIRS += settings
qtConfig(statemachine): SUBDIRS += statemachine
@@ -24,7 +24,7 @@ qtHaveModule(quick) {
qtConfig(quick-particles): \
SUBDIRS += particles
- qtConfig(quick-path): SUBDIRS += shapes
+ qtConfig(quick-path):qtConfig(thread): SUBDIRS += shapes
}
qtHaveModule(xmlpatterns) : SUBDIRS += xmllistmodel
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 0afd71767e..86fdf87650 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += qml
-qtConfig(qml-debug):SUBDIRS += qmltooling
+qtConfig(thread):qtConfig(qml-debug):SUBDIRS += qmltooling
qtHaveModule(quick):SUBDIRS += scenegraph
diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro
index fd4a3eac65..30097be77b 100644
--- a/src/plugins/qmltooling/qmltooling.pro
+++ b/src/plugins/qmltooling/qmltooling.pro
@@ -6,9 +6,8 @@ SUBDIRS += \
packetprotocol
# Connectors
-SUBDIRS += \
- qmldbg_native \
- qmldbg_server
+SUBDIRS += qmldbg_native
+qtConfig(thread): SUBDIRS += qmldbg_server
qmldbg_native.depends = packetprotocol
qmldbg_server.depends = packetprotocol
@@ -35,8 +34,9 @@ qmldbg_nativedebugger.depends = packetprotocol
qtHaveModule(quick) {
SUBDIRS += \
qmldbg_inspector \
- qmldbg_quickprofiler \
- qmldbg_preview
+ qmldbg_quickprofiler
+
+ qtConfig(qml-network): SUBDIRS += qmldbg_preview
qmldbg_inspector.depends = packetprotocol
qmldbg_quickprofiler.depends = packetprotocol
diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp
index 4e82c7a062..ece2f0d692 100644
--- a/src/qml/animations/qabstractanimationjob.cpp
+++ b/src/qml/animations/qabstractanimationjob.cpp
@@ -70,17 +70,12 @@ QQmlAnimationTimer::QQmlAnimationTimer() :
QQmlAnimationTimer *QQmlAnimationTimer::instance(bool create)
{
QQmlAnimationTimer *inst;
-#ifndef QT_NO_THREAD
if (create && !animationTimer()->hasLocalData()) {
inst = new QQmlAnimationTimer;
animationTimer()->setLocalData(inst);
} else {
inst = animationTimer() ? animationTimer()->localData() : 0;
}
-#else
- static QQmlAnimationTimer unifiedTimer;
- inst = &unifiedTimer;
-#endif
return inst;
}
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 88accc2f49..883b21ab07 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -2279,42 +2279,38 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n
if (_scopeObject) {
QQmlPropertyData *data = lookupQmlCompliantProperty(_scopeObject, name);
- if (!data)
- return Reference::fromName(this, name);
-
- Reference base = Reference::fromStackSlot(this, _qmlContextSlot);
- Reference::PropertyCapturePolicy capturePolicy;
- if (!data->isConstant() && !data->isQmlBinding())
- capturePolicy = Reference::CaptureAtRuntime;
- else
- capturePolicy = data->isConstant() ? Reference::DontCapture : Reference::CaptureAheadOfTime;
- return Reference::fromQmlScopeObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy);
+ if (data) {
+ Reference base = Reference::fromStackSlot(this, _qmlContextSlot);
+ Reference::PropertyCapturePolicy capturePolicy;
+ if (!data->isConstant() && !data->isQmlBinding())
+ capturePolicy = Reference::CaptureAtRuntime;
+ else
+ capturePolicy = data->isConstant() ? Reference::DontCapture : Reference::CaptureAheadOfTime;
+ return Reference::fromQmlScopeObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy);
+ }
}
if (_contextObject) {
QQmlPropertyData *data = lookupQmlCompliantProperty(_contextObject, name);
- if (!data)
- return Reference::fromName(this, name);
-
- Reference base = Reference::fromStackSlot(this, _qmlContextSlot);
- Reference::PropertyCapturePolicy capturePolicy;
- if (!data->isConstant() && !data->isQmlBinding())
- capturePolicy = Reference::CaptureAtRuntime;
- else
- capturePolicy = data->isConstant() ? Reference::DontCapture : Reference::CaptureAheadOfTime;
- return Reference::fromQmlContextObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy);
+ if (data) {
+ Reference base = Reference::fromStackSlot(this, _qmlContextSlot);
+ Reference::PropertyCapturePolicy capturePolicy;
+ if (!data->isConstant() && !data->isQmlBinding())
+ capturePolicy = Reference::CaptureAtRuntime;
+ else
+ capturePolicy = data->isConstant() ? Reference::DontCapture : Reference::CaptureAheadOfTime;
+ return Reference::fromQmlContextObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy);
+ }
}
- if (m_globalNames.contains(name)) {
- Reference r = Reference::fromName(this, name);
+ Reference r = Reference::fromName(this, name);
+ if (m_globalNames.contains(name))
r.global = true;
- return r;
- }
+ return r;
#else
Q_UNUSED(name)
-#endif // V4_BOOTSTRAP
- // fall back to name lookup at run-time.
return Reference();
+#endif // V4_BOOTSTRAP
}
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 62dbcdaa7d..d61f79f0fc 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2300,7 +2300,7 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs, co
return fallback;
Reference r = Reference::fromName(this, name);
- r.global = (resolved.type == Context::ResolvedName::Global);
+ r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global);
return r;
}
@@ -2717,6 +2717,12 @@ bool Codegen::visit(ThisExpression *)
if (hasError)
return false;
+ if (_context->isArrowFunction) {
+ Reference r = referenceForName(QStringLiteral("this"), false);
+ r.isReadonly = true;
+ _expr.setResult(r);
+ return false;
+ }
_expr.setResult(Reference::fromThis(this));
return false;
}
@@ -3996,7 +4002,7 @@ Codegen::Reference Codegen::Reference::baseObject() const
if (rval.isAccumulator())
return Reference::fromAccumulator(codegen);
if (rval.isStackSlot())
- Reference::fromStackSlot(codegen, rval.stackSlot());
+ return Reference::fromStackSlot(codegen, rval.stackSlot());
if (rval.isConst())
return Reference::fromConst(codegen, rval.constantValue());
Q_UNREACHABLE();
@@ -4279,7 +4285,7 @@ QT_WARNING_POP
return;
}
}
- if (!disable_lookups && codegen->useFastLookups && global) {
+ if (!disable_lookups && global) {
Instruction::LoadGlobalLookup load;
load.index = codegen->registerGlobalGetterLookup(nameAsIndex());
codegen->bytecodeGenerator->addInstruction(load);
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index 4ee6d2c179..1b4c084ab4 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -241,6 +241,13 @@ void Context::emitBlockHeader(Codegen *codegen)
Instruction::ConvertThisToObject convert;
bytecodeGenerator->addInstruction(convert);
}
+ if (innerFunctionAccessesThis) {
+ Instruction::LoadReg load;
+ load.reg = CallData::This;
+ bytecodeGenerator->addInstruction(load);
+ Codegen::Reference r = codegen->referenceForName(QStringLiteral("this"), true);
+ r.storeConsumeAccumulator();
+ }
if (contextType == ContextType::Global || (contextType == ContextType::Eval && !isStrict)) {
// variables in global code are properties of the global context object, not locals as with other functions.
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 3df0aa6b3a..8713b0a188 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -201,6 +201,7 @@ struct Context {
bool isArrowFunction = false;
bool isGenerator = false;
bool usesThis = false;
+ bool innerFunctionAccessesThis = false;
bool hasTry = false;
bool returnsClosure = false;
mutable bool argumentsCanEscape = false;
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 5d3a7a6d8c..dafb1c360d 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -414,6 +414,17 @@ bool ScanFunctions::visit(TemplateLiteral *ast)
}
+bool ScanFunctions::visit(SuperLiteral *)
+{
+ Context *c = _context;
+ while (c && (c->contextType != ContextType::Function || c->isArrowFunction))
+ c = c->parent;
+
+ if (c)
+ c->requiresExecutionContext = true;
+
+ return false;
+}
bool ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName)
{
if (_context->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments")))
@@ -656,13 +667,16 @@ void ScanFunctions::calcEscapingVariables()
Module *m = _cg->_module;
for (Context *inner : qAsConst(m->contextMap)) {
- if (inner->contextType == ContextType::Block && inner->usesArgumentsObject == Context::ArgumentsObjectUsed) {
- Context *c = inner->parent;
- while (c->contextType == ContextType::Block)
- c = c->parent;
+ if (inner->usesArgumentsObject != Context::ArgumentsObjectUsed)
+ continue;
+ if (inner->contextType != ContextType::Block && !inner->isArrowFunction)
+ continue;
+ Context *c = inner->parent;
+ while (c && (c->contextType == ContextType::Block || c->isArrowFunction))
+ c = c->parent;
+ if (c)
c->usesArgumentsObject = Context::ArgumentsObjectUsed;
- inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
- }
+ inner->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
}
for (Context *inner : qAsConst(m->contextMap)) {
if (!inner->parent || inner->usesArgumentsObject == Context::ArgumentsObjectUnknown)
@@ -728,6 +742,8 @@ void ScanFunctions::calcEscapingVariables()
}
Q_ASSERT(c);
c->hasDirectEval = true;
+ if (!c->isStrict)
+ c->innerFunctionAccessesThis = true;
}
Context *c = inner;
while (c) {
@@ -737,17 +753,26 @@ void ScanFunctions::calcEscapingVariables()
}
if (inner->usesThis) {
inner->usesThis = false;
- if (!inner->isStrict) {
- Context *c = inner;
- while (c->contextType == ContextType::Block) {
- c = c->parent;
- }
- Q_ASSERT(c);
- c->usesThis = true;
+ bool innerFunctionAccessesThis = false;
+ Context *c = inner;
+ while (c->contextType == ContextType::Block || c->isArrowFunction) {
+ innerFunctionAccessesThis |= c->isArrowFunction;
+ c = c->parent;
}
+ Q_ASSERT(c);
+ if (!inner->isStrict)
+ c->usesThis = true;
+ c->innerFunctionAccessesThis |= innerFunctionAccessesThis;
}
}
for (Context *c : qAsConst(m->contextMap)) {
+ if (c->innerFunctionAccessesThis) {
+ // add an escaping 'this' variable
+ c->addLocalVar(QStringLiteral("this"), Context::VariableDefinition, VariableScope::Let);
+ c->requiresExecutionContext = true;
+ auto m = c->members.find(QStringLiteral("this"));
+ m->canEscape = true;
+ }
if (c->allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
c->allVarsEscape = false;
if (c->contextType == ContextType::Global || (!c->isStrict && c->contextType == ContextType::Eval) || m->debugMode)
@@ -787,6 +812,7 @@ void ScanFunctions::calcEscapingVariables()
qDebug() << "==== escaping variables ====";
for (Context *c : qAsConst(m->contextMap)) {
qDebug() << "Context" << c << c->name << "requiresExecutionContext" << c->requiresExecutionContext << "isStrict" << c->isStrict;
+ qDebug() << " isArrowFunction" << c->isArrowFunction << "innerFunctionAccessesThis" << c->innerFunctionAccessesThis;
qDebug() << " parent:" << c->parent;
if (c->argumentsCanEscape)
qDebug() << " Arguments escape";
diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h
index 53b2336cb1..2e016b25b1 100644
--- a/src/qml/compiler/qv4compilerscanfunctions_p.h
+++ b/src/qml/compiler/qv4compilerscanfunctions_p.h
@@ -115,6 +115,7 @@ protected:
bool visit(AST::ExpressionStatement *ast) override;
bool visit(AST::FunctionExpression *ast) override;
bool visit(AST::TemplateLiteral *ast) override;
+ bool visit(AST::SuperLiteral *) override;
bool enterFunction(AST::FunctionExpression *ast, bool enterName);
diff --git a/src/qml/configure.json b/src/qml/configure.json
index 481cc553ae..1e3ac65f2a 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -32,10 +32,8 @@
"section": "QML",
"condition": [
"features.commandlineparser",
- "features.localserver",
- "features.process",
"features.qml-debug",
- "features.qml-network",
+ "features.qml-network && features.localserver",
"features.xmlstreamwriter"
],
"output": [ "privateFeature" ]
@@ -46,7 +44,7 @@
"section": "QML",
"condition": [
"features.commandlineparser",
- "features.localserver",
+ "features.qml-network && features.localserver",
"features.process",
"features.qml-debug"
],
diff --git a/src/qml/doc/images/cpp-qml-integration-flowchart.odg b/src/qml/doc/images/cpp-qml-integration-flowchart.odg
index 8482bd4bf4..f24021635e 100644
--- a/src/qml/doc/images/cpp-qml-integration-flowchart.odg
+++ b/src/qml/doc/images/cpp-qml-integration-flowchart.odg
Binary files differ
diff --git a/src/qml/doc/images/cpp-qml-integration-flowchart.png b/src/qml/doc/images/cpp-qml-integration-flowchart.png
index 56a33205fd..3649ff9e41 100644
--- a/src/qml/doc/images/cpp-qml-integration-flowchart.png
+++ b/src/qml/doc/images/cpp-qml-integration-flowchart.png
Binary files differ
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index 9b5a983fdf..e74503e9d3 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -85,7 +85,7 @@ ReturnedValue SharedArrayBufferCtor::virtualCall(const FunctionObject *f, const
}
-ReturnedValue ArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue ArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
ExecutionEngine *v4 = f->engine();
Scope scope(v4);
@@ -99,6 +99,12 @@ ReturnedValue ArrayBufferCtor::virtualCallAsConstructor(const FunctionObject *f,
return v4->throwRangeError(QLatin1String("ArrayBuffer constructor: invalid length"));
Scoped<ArrayBuffer> a(scope, v4->newArrayBuffer(len));
+ if (newTarget->heapObject() != f->heapObject() && newTarget->isFunctionObject()) {
+ const FunctionObject *nt = static_cast<const FunctionObject *>(newTarget);
+ ScopedObject o(scope, nt->protoProperty());
+ if (o)
+ a->setPrototypeOf(o);
+ }
if (scope.engine->hasException)
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index c40d6414ff..7b1fd720a7 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -342,12 +342,8 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
uint index;
ic = newInternalClass(QV4::FunctionPrototype::staticVTable(), objectPrototype());
- ic = ic->addMember(id_prototype()->propertyKey(), Attr_NotEnumerable, &index);
- Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(ic->d());
ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype());
- ic = ic->addMember(id_prototype()->propertyKey(), Attr_NotEnumerable|Attr_NotConfigurable, &index);
- Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
classes[Class_FunctionObject] = ic->d();
ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, &index);
Q_ASSERT(index == Heap::ScriptFunction::Index_Name);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index fe1ebbd556..ec041ab064 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -96,7 +96,7 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name,
f->setName(name);
if (createProto)
- f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor);
+ f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_ProtoConstructor);
}
@@ -130,8 +130,6 @@ void Heap::FunctionObject::init()
Object::init();
this->scope.set(internalClass->engine, internalClass->engine->rootContext()->d());
- Q_ASSERT(internalClass && internalClass->find(internalClass->engine->id_prototype()->propertyKey()) == Index_Prototype);
- setProperty(internalClass->engine, Index_Prototype, Primitive::undefinedValue());
}
void Heap::FunctionObject::setFunction(Function *f)
@@ -148,16 +146,15 @@ void Heap::FunctionObject::destroy()
Object::destroy();
}
-void FunctionObject::createDefaultPrototypeProperty(uint protoSlot, uint protoConstructorSlot)
+void FunctionObject::createDefaultPrototypeProperty(uint protoConstructorSlot)
{
Scope s(this);
- Q_ASSERT(internalClass() && internalClass()->find(s.engine->id_prototype()->propertyKey()) == protoSlot);
Q_ASSERT(s.engine->internalClasses(EngineBase::Class_ObjectProto)->find(s.engine->id_constructor()->propertyKey()) == protoConstructorSlot);
ScopedObject proto(s, s.engine->newObject(s.engine->internalClasses(EngineBase::Class_ObjectProto)));
proto->setProperty(protoConstructorSlot, d());
- setProperty(protoSlot, proto);
+ defineDefaultProperty(s.engine->id_prototype(), proto, Attr_NotEnumerable|Attr_NotConfigurable);
}
ReturnedValue FunctionObject::name() const
@@ -510,7 +507,7 @@ ReturnedValue ScriptFunction::virtualCall(const FunctionObject *fo, const Value
return result;
}
-void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n)
+void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n, bool makeConstructor)
{
FunctionObject::init();
this->scope.set(scope->engine(), scope->d());
@@ -524,7 +521,8 @@ void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function
ScopedString name(s, n ? n->d() : function->name());
if (name)
f->setName(name);
- f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_Prototype, Heap::FunctionObject::Index_ProtoConstructor);
+ if (makeConstructor && !function->isArrowFunction())
+ f->createDefaultPrototypeProperty(Heap::FunctionObject::Index_ProtoConstructor);
Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()->propertyKey()) == Index_Length);
setProperty(s.engine, Index_Length, Primitive::fromInt32(int(function->compiledFunction->length)));
@@ -566,6 +564,7 @@ ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject
v4->jsStackTop += frame.requiredJSStackFrameSize();
ReturnedValue result = Moth::VME::exec(&frame, v4);
+ ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue();
frame.pop();
@@ -573,9 +572,14 @@ ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject
return Encode::undefined();
else if (Value::fromReturnedValue(result).isObject())
return result;
- else if (!Value::fromReturnedValue(result).isUndefined() || frame.jsFrame->thisObject.isEmpty())
+ else if (!Value::fromReturnedValue(result).isUndefined())
return v4->throwTypeError();
- return frame.jsFrame->thisObject.asReturnedValue();
+ else if (Primitive::fromReturnedValue(thisObject).isEmpty()) {
+ Scope scope(v4);
+ ScopedString s(scope, v4->newString(QStringLiteral("this")));
+ return v4->throwReferenceError(s);
+ }
+ return thisObject;
}
ReturnedValue ConstructorFunction::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
@@ -615,6 +619,7 @@ ReturnedValue DefaultClassConstructorFunction::virtualCallAsConstructor(const Fu
// Do a super call
ReturnedValue result = super->callAsConstructor(argv, argc, newTarget);
+ ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue();
frame.pop();
@@ -624,7 +629,13 @@ ReturnedValue DefaultClassConstructorFunction::virtualCallAsConstructor(const Fu
return result;
else if (!Value::fromReturnedValue(result).isUndefined())
return v4->throwTypeError();
- return frame.jsFrame->thisObject.asReturnedValue();
+ else if (Primitive::fromReturnedValue(thisObject).isEmpty()) {
+ Scope scope(v4);
+ ScopedString s(scope, v4->newString(QStringLiteral("this")));
+ return v4->throwReferenceError(s);
+ }
+
+ return thisObject;
}
ReturnedValue DefaultClassConstructorFunction::virtualCall(const FunctionObject *f, const Value *, const Value *, int)
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 766960d2ac..43f4921875 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -76,7 +76,6 @@ namespace Heap {
DECLARE_HEAP_OBJECT(FunctionObject, Object) {
DECLARE_MARKOBJECTS(FunctionObject);
enum {
- Index_Prototype = 0,
Index_ProtoConstructor = 0
};
@@ -116,10 +115,10 @@ struct IndexedBuiltinFunction : FunctionObject {
DECLARE_HEAP_OBJECT(ScriptFunction, FunctionObject) {
DECLARE_MARKOBJECTS(ScriptFunction)
enum {
- Index_Name = FunctionObject::Index_Prototype + 1,
+ Index_Name,
Index_Length
};
- void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr);
+ void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr, bool makeConstructor = true);
};
#define MemberFunctionMembers(class, Member) \
@@ -127,6 +126,10 @@ DECLARE_HEAP_OBJECT(ScriptFunction, FunctionObject) {
DECLARE_HEAP_OBJECT(MemberFunction, ScriptFunction) {
DECLARE_MARKOBJECTS(MemberFunction)
+
+ void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr) {
+ ScriptFunction::init(scope, function, name, false);
+ }
};
struct ConstructorFunction : MemberFunction
@@ -173,7 +176,7 @@ struct Q_QML_EXPORT FunctionObject: Object {
void setName(String *name) {
defineReadonlyConfigurableProperty(engine()->id_name(), *name);
}
- void createDefaultPrototypeProperty(uint protoSlot, uint protoConstructorSlot);
+ void createDefaultPrototypeProperty(uint protoConstructorSlot);
inline ReturnedValue callAsConstructor(const JSCallData &data) const;
ReturnedValue callAsConstructor(const Value *argv, int argc, const Value *newTarget = nullptr) const {
diff --git a/src/qml/jsruntime/qv4generatorobject_p.h b/src/qml/jsruntime/qv4generatorobject_p.h
index 55e6091ad5..c3b8e84154 100644
--- a/src/qml/jsruntime/qv4generatorobject_p.h
+++ b/src/qml/jsruntime/qv4generatorobject_p.h
@@ -73,6 +73,9 @@ struct GeneratorFunctionCtor : FunctionObject {
};
struct GeneratorFunction : ScriptFunction {
+ void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr) {
+ ScriptFunction::init(scope, function, name, false);
+ }
};
struct MemberGeneratorFunction : MemberFunction {
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 8158d8ddd9..3eaf760792 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -128,7 +128,10 @@ DEFINE_OBJECT_VTABLE(ForInIteratorObject);
void Heap::ForInIteratorObject::markObjects(Heap::Base *that, MarkStack *markStack)
{
ForInIteratorObject *o = static_cast<ForInIteratorObject *>(that);
- o->object->mark(markStack);
+ if (o->object)
+ o->object->mark(markStack);
+ if (o->current)
+ o->current->mark(markStack);
o->workArea[0].mark(markStack);
o->workArea[1].mark(markStack);
Object::markObjects(that, markStack);
diff --git a/src/qml/jsruntime/qv4propertykey.cpp b/src/qml/jsruntime/qv4propertykey.cpp
index 12a3653034..361ade17c2 100644
--- a/src/qml/jsruntime/qv4propertykey.cpp
+++ b/src/qml/jsruntime/qv4propertykey.cpp
@@ -42,6 +42,7 @@
#include <QtCore/qstring.h>
#include <qv4string_p.h>
#include <qv4engine_p.h>
+#include <qv4scopedvalue_p.h>
QV4::Heap::StringOrSymbol *QV4::PropertyKey::toStringOrSymbol(QV4::ExecutionEngine *e)
{
@@ -60,6 +61,24 @@ bool QV4::PropertyKey::isSymbol() const {
return s && !s->internalClass->vtable->isString && s->internalClass->vtable->isStringOrSymbol;
}
+bool QV4::PropertyKey::isCanonicalNumericIndexString() const
+{
+ if (isArrayIndex())
+ return true;
+ if (isSymbol())
+ return false;
+ Heap::String *s = static_cast<Heap::String *>(asStringOrSymbol());
+ Scope scope(s->internalClass->engine);
+ ScopedString str(scope, s);
+ double d = str->toNumber();
+ if (d == 0. && std::signbit(d))
+ return true;
+ ScopedString converted(scope, Primitive::fromDouble(d).toString(scope.engine));
+ if (converted->equals(str))
+ return true;
+ return false;
+}
+
QString QV4::PropertyKey::toQString() const
{
if (isArrayIndex())
diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h
index 7134b06c6d..cb2661f244 100644
--- a/src/qml/jsruntime/qv4propertykey_p.h
+++ b/src/qml/jsruntime/qv4propertykey_p.h
@@ -126,6 +126,7 @@ public:
bool isString() const;
bool isSymbol() const;
+ bool isCanonicalNumericIndexString() const;
Q_QML_EXPORT QString toQString() const;
Heap::StringOrSymbol *toStringOrSymbol(ExecutionEngine *e);
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index 7492f8872d..a07443077e 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -280,11 +280,20 @@ void Heap::TypedArrayCtor::init(QV4::ExecutionContext *scope, TypedArray::Type t
type = t;
}
-ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *)
+ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f, const Value *argv, int argc, const Value *newTarget)
{
Scope scope(f->engine());
const TypedArrayCtor *that = static_cast<const TypedArrayCtor *>(f);
+ auto updateProto = [=](Scope &scope, Scoped<TypedArray> &a) {
+ if (newTarget->heapObject() != f->heapObject() && newTarget->isFunctionObject()) {
+ const FunctionObject *nt = static_cast<const FunctionObject *>(newTarget);
+ ScopedObject o(scope, nt->protoProperty());
+ if (o)
+ a->setPrototypeOf(o);
+ }
+ };
+
if (!argc || !argv[0].isObject()) {
// ECMA 6 22.2.1.1
qint64 l = argc ? argv[0].toIndex() : 0;
@@ -306,6 +315,7 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
array->d()->byteLength = byteLength;
array->d()->byteOffset = 0;
+ updateProto(scope, array);
return array.asReturnedValue();
}
Scoped<TypedArray> typedArray(scope, argc ? argv[0] : Primitive::undefinedValue());
@@ -346,6 +356,7 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
}
}
+ updateProto(scope, array);
return array.asReturnedValue();
}
Scoped<ArrayBuffer> buffer(scope, argc ? argv[0] : Primitive::undefinedValue());
@@ -383,6 +394,8 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
array->d()->buffer.set(scope.engine, buffer->d());
array->d()->byteLength = byteLength;
array->d()->byteOffset = byteOffset;
+
+ updateProto(scope, array);
return array.asReturnedValue();
}
@@ -421,7 +434,7 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
b += elementSize;
}
-
+ updateProto(scope, array);
return array.asReturnedValue();
}
@@ -446,22 +459,26 @@ Heap::TypedArray *TypedArray::create(ExecutionEngine *e, Heap::TypedArray::Type
ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
- if (!id.isArrayIndex())
+ uint index = id.asArrayIndex();
+ if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
return Object::virtualGet(m, id, receiver, hasProperty);
+ // fall through, with index == UINT_MAX it'll do the right thing.
- uint index = id.asArrayIndex();
Scope scope(static_cast<const Object *>(m)->engine());
Scoped<TypedArray> a(scope, static_cast<const TypedArray *>(m));
if (a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- uint bytesPerElement = a->d()->type->bytesPerElement;
- uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
- if (byteOffset + bytesPerElement > (uint)a->d()->buffer->byteLength()) {
+ if (index >= a->length()) {
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
}
+
+ uint bytesPerElement = a->d()->type->bytesPerElement;
+ uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
+ Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
+
if (hasProperty)
*hasProperty = true;
return a->d()->type->read(a->d()->buffer->data->data() + byteOffset);
@@ -469,17 +486,42 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val
bool TypedArray::virtualHasProperty(const Managed *m, PropertyKey id)
{
+ uint index = id.asArrayIndex();
+ if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ return Object::virtualHasProperty(m, id);
+ // fall through, with index == UINT_MAX it'll do the right thing.
+
+ const TypedArray *a = static_cast<const TypedArray *>(m);
+ if (a->d()->buffer->isDetachedBuffer()) {
+ a->engine()->throwTypeError();
+ return false;
+ }
+ if (index >= a->length())
+ return false;
+ return true;
+}
+
+PropertyAttributes TypedArray::virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p)
+{
+ uint index = id.asArrayIndex();
+ if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ return Object::virtualGetOwnProperty(m, id, p);
+ // fall through, with index == UINT_MAX it'll do the right thing.
+
bool hasProperty = false;
- virtualGet(m, id, nullptr, &hasProperty);
- return hasProperty;
+ ReturnedValue v = virtualGet(m, id, m, &hasProperty);
+ if (p)
+ p->value = v;
+ return hasProperty ? Attr_NotConfigurable : PropertyAttributes();
}
bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
- if (!id.isArrayIndex())
+ uint index = id.asArrayIndex();
+ if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
return Object::virtualPut(m, id, value, receiver);
+ // fall through, with index == UINT_MAX it'll do the right thing.
- uint index = id.asArrayIndex();
ExecutionEngine *v4 = static_cast<Object *>(m)->engine();
if (v4->hasException)
return false;
@@ -489,10 +531,12 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
if (a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
+ if (index >= a->length())
+ return false;
+
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
- if (byteOffset + bytesPerElement > (uint)a->d()->buffer->byteLength())
- return false;
+ Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
Value v = Primitive::fromReturnedValue(value.convertedToNumber());
if (scope.hasException() || a->d()->buffer->isDetachedBuffer())
@@ -501,6 +545,37 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
return true;
}
+bool TypedArray::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs)
+{
+ uint index = id.asArrayIndex();
+ if (index == UINT_MAX && !id.isCanonicalNumericIndexString())
+ return Object::virtualDefineOwnProperty(m, id, p, attrs);
+ // fall through, with index == UINT_MAX it'll do the right thing.
+
+ TypedArray *a = static_cast<TypedArray *>(m);
+ if (index >= a->length() || attrs.isAccessor())
+ return false;
+
+ if (attrs.hasConfigurable() && attrs.isConfigurable())
+ return false;
+ if (attrs.hasEnumerable() && !attrs.isEnumerable())
+ return false;
+ if (attrs.hasWritable() && !attrs.isWritable())
+ return false;
+ if (!p->value.isEmpty()) {
+ ExecutionEngine *engine = a->engine();
+
+ Value v = Primitive::fromReturnedValue(p->value.convertedToNumber());
+ if (engine->hasException || a->d()->buffer->isDetachedBuffer())
+ return engine->throwTypeError();
+ uint bytesPerElement = a->d()->type->bytesPerElement;
+ uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
+ Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
+ a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v);
+ }
+ return true;
+}
+
void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
{
Scope scope(engine);
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 909334adb0..ad0953ed0c 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -167,7 +167,10 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static bool virtualHasProperty(const Managed *m, PropertyKey id);
+ static PropertyAttributes virtualGetOwnProperty(Managed *m, PropertyKey id, Property *p);
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
+ static bool virtualDefineOwnProperty(Managed *m, PropertyKey id, const Property *p, PropertyAttributes attrs);
+
};
struct IntrinsicTypedArrayCtor: FunctionObject
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 96313d7627..2ef1dc7e93 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -316,6 +316,12 @@ void QQmlThread::shutdownThread()
void QQmlThread::internalCallMethodInThread(Message *message)
{
+#if !QT_CONFIG(thread)
+ message->call(this);
+ delete message;
+ return;
+#endif
+
Q_ASSERT(!isThisThread());
d->lock();
Q_ASSERT(d->m_mainThreadWaiting == false);
@@ -376,6 +382,10 @@ void QQmlThread::internalCallMethodInMain(Message *message)
void QQmlThread::internalPostMethodToThread(Message *message)
{
+#if !QT_CONFIG(thread)
+ internalPostMethodToMain(message);
+ return;
+#endif
Q_ASSERT(!isThisThread());
d->lock();
bool wasEmpty = d->threadList.isEmpty();
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 26187ca086..82a3f45784 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -95,7 +95,9 @@
#include <private/qqmldelegatemodel_p.h>
#endif
#include <private/qqmlobjectmodel_p.h>
+#if QT_CONFIG(thread)
#include <private/qquickworkerscript_p.h>
+#endif
#include <private/qqmlinstantiator_p.h>
#include <private/qqmlloggingcategory_p.h>
@@ -243,7 +245,9 @@ void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor,
qmlRegisterType<QQmlListElement>(uri, versionMajor, versionMinor, "ListElement"); // Now in QtQml.Models, here for compatibility
qmlRegisterCustomType<QQmlListModel>(uri, versionMajor, versionMinor, "ListModel", new QQmlListModelParser); // Now in QtQml.Models, here for compatibility
#endif
+#if QT_CONFIG(thread)
qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
+#endif
qmlRegisterType<QQuickPackage>(uri, versionMajor, versionMinor, "Package");
#if QT_CONFIG(qml_delegate_model)
qmlRegisterType<QQmlDelegateModel>(uri, versionMajor, versionMinor, "VisualDataModel");
@@ -687,7 +691,9 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
#endif
outputWarningsToMsgLog(true),
cleanup(nullptr), erroredBindings(nullptr), inProgressCreations(0),
+#if QT_CONFIG(thread)
workerScriptEngine(nullptr),
+#endif
activeObjectCreator(nullptr),
#if QT_CONFIG(qml_network)
networkAccessManager(nullptr), networkAccessManagerFactory(nullptr),
@@ -987,6 +993,7 @@ void QQmlEnginePrivate::init()
rootContext = new QQmlContext(q,true);
}
+#if QT_CONFIG(thread)
QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
{
Q_Q(QQmlEngine);
@@ -994,6 +1001,7 @@ QQuickWorkerScriptEngine *QQmlEnginePrivate::getWorkerScriptEngine()
workerScriptEngine = new QQuickWorkerScriptEngine(q);
return workerScriptEngine;
}
+#endif
/*!
\class QQmlEngine
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index f606896953..d05f6634ec 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -153,8 +153,10 @@ public:
QV8Engine *v8engine() const { return q_func()->handle()->v8Engine; }
QV4::ExecutionEngine *v4engine() const { return q_func()->handle(); }
+#if QT_CONFIG(thread)
QQuickWorkerScriptEngine *getWorkerScriptEngine();
QQuickWorkerScriptEngine *workerScriptEngine;
+#endif
QUrl baseUrl;
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 1c37894751..ee6484f0b7 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -674,6 +674,7 @@ bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQml
{
Q_ASSERT(resolvedUrl.endsWith(Slash));
url = resolvedUrl;
+ localDirectoryPath = QQmlFile::urlToLocalFileOrQrc(url);
qmlDirComponents = qmldir.components();
@@ -811,21 +812,20 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
*type_return = returnType;
return returnType.isValid();
}
- } else if (!isLibrary) {
+ } else if (!isLibrary && !localDirectoryPath.isEmpty()) {
QString qmlUrl;
bool exists = false;
const QString urlsToTry[2] = {
- url + QString::fromRawData(type.constData(), type.length()) + dotqml_string, // Type -> Type.qml
- url + QString::fromRawData(type.constData(), type.length()) + dotuidotqml_string // Type -> Type.ui.qml
+ typeStr + dotqml_string, // Type -> Type.qml
+ typeStr + dotuidotqml_string // Type -> Type.ui.qml
};
for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) {
- const QString url = urlsToTry[i];
- const QString localPath = QQmlFile::urlToLocalFileOrQrc(url);
- exists = !typeLoader->absoluteFilePath(localPath).isEmpty();
+ exists = typeLoader->fileExists(localDirectoryPath, urlsToTry[i]);
if (exists) {
+#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)
// don't let function.qml confuse the use of "new Function(...)" for example.
- if (!QQml_isFileCaseCorrect(localPath)) {
+ if (!QQml_isFileCaseCorrect(localDirectoryPath + urlsToTry[i])) {
exists = false;
if (errors) {
QQmlError caseError;
@@ -834,7 +834,10 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
}
break;
}
- qmlUrl = url;
+#else
+ Q_UNUSED(errors);
+#endif
+ qmlUrl = url + urlsToTry[i];
break;
}
}
@@ -1433,6 +1436,7 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace
QQmlImportInstance *import = new QQmlImportInstance;
import->uri = uri;
import->url = url;
+ import->localDirectoryPath = QQmlFile::urlToLocalFileOrQrc(url);
import->majversion = vmaj;
import->minversion = vmin;
import->isLibrary = (type == QV4::CompiledData::Import::ImportLibrary);
@@ -1770,8 +1774,14 @@ QQmlImportDatabase::QQmlImportDatabase(QQmlEngine *e)
{
filePluginPath << QLatin1String(".");
// Search order is applicationDirPath(), qrc:/qt-project.org/imports, $QML2_IMPORT_PATH, QLibraryInfo::Qml2ImportsPath
+#ifndef Q_OS_WASM
+ QString installImportsPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
+#else
+ // Hardcode the qml imports to "qml/" relative to the app exe.
+ // This should perhaps be set via Qml2Imports in qt.conf.
+ QString installImportsPath = QStringLiteral("qml/");
+#endif
- QString installImportsPath = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
addImportPath(installImportsPath);
// env import paths
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 283bd40660..f8c01ed876 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -78,6 +78,7 @@ struct QQmlImportInstance
{
QString uri; // e.g. QtQuick
QString url; // the base path of the import
+ QString localDirectoryPath; // the base path of the import if it's a local file
int majversion; // the major version imported
int minversion; // the minor version imported
bool isLibrary; // true means that this is not a file import
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 739280bbfe..0b0ee9cb9a 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -865,13 +865,23 @@ void QQmlTypeLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QV4::C
void QQmlTypeLoaderThread::callCompleted(QQmlDataBlob *b)
{
b->addref();
+#if !QT_CONFIG(thread)
+ if (!isThisThread())
+ postMethodToThread(&This::callCompletedMain, b);
+#else
postMethodToMain(&This::callCompletedMain, b);
+#endif
}
void QQmlTypeLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
{
b->addref();
+#if !QT_CONFIG(thread)
+ if (!isThisThread())
+ postMethodToThread(&This::callDownloadProgressChangedMain, b, p);
+#else
postMethodToMain(&This::callDownloadProgressChangedMain, b, p);
+#endif
}
void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
@@ -1755,10 +1765,14 @@ Returns a QQmlQmldirData for \a url. The QQmlQmldirData may be cached.
*/
QQmlRefPointer<QQmlQmldirData> QQmlTypeLoader::getQmldir(const QUrl &url)
{
+#ifndef Q_OS_WASM
Q_ASSERT(!url.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
!QDir::isRelativePath(QQmlFile::urlToLocalFileOrQrc(url))));
-
+#else
+ // ### wasm asserts on urls like "qml/QtQuick.2.1/qmldir",
+ // which are relative urls we want to load over the network.
+#endif
LockHolder<QQmlTypeLoader> holder(this);
QQmlQmldirData *qmldirData = m_qmldirCache.value(url);
@@ -1848,6 +1862,52 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path)
return absoluteFilePath;
}
+bool QQmlTypeLoader::fileExists(const QString &path, const QString &file)
+{
+ if (path.isEmpty())
+ return false;
+ Q_ASSERT(path.endsWith(QLatin1Char('/')));
+ if (path.at(0) == QLatin1Char(':')) {
+ // qrc resource
+ QFileInfo fileInfo(path + file);
+ return fileInfo.isFile();
+ } else if (path.count() > 3 && path.at(3) == QLatin1Char(':') &&
+ path.startsWith(QLatin1String("qrc"), Qt::CaseInsensitive)) {
+ // qrc resource url
+ QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path + file));
+ return fileInfo.isFile();
+ }
+#if defined(Q_OS_ANDROID)
+ else if (path.count() > 7 && path.at(6) == QLatin1Char(':') && path.at(7) == QLatin1Char('/') &&
+ path.startsWith(QLatin1String("assets"), Qt::CaseInsensitive)) {
+ // assets resource url
+ QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path + file));
+ return fileInfo.isFile();
+ }
+#endif
+
+ LockHolder<QQmlTypeLoader> holder(this);
+ if (!m_importDirCache.contains(path)) {
+ bool exists = QDir(path).exists();
+ QCache<QString, bool> *entry = exists ? new QCache<QString, bool> : nullptr;
+ m_importDirCache.insert(path, entry);
+ }
+ QCache<QString, bool> *fileSet = m_importDirCache.object(path);
+ if (!fileSet)
+ return false;
+
+ QString absoluteFilePath;
+
+ bool *value = fileSet->object(file);
+ if (value) {
+ return *value;
+ } else {
+ bool exists = QFile::exists(path + file);
+ fileSet->insert(file, new bool(exists));
+ return exists;
+ }
+}
+
/*!
Returns true if the path is a directory via a directory cache. Cache is
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 5d85773be3..031554b330 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -313,6 +313,7 @@ public:
QQmlRefPointer<QQmlQmldirData> getQmldir(const QUrl &);
QString absoluteFilePath(const QString &path);
+ bool fileExists(const QString &path, const QString &file);
bool directoryExists(const QString &path);
const QQmlTypeLoaderQmldirContent qmldirContent(const QString &filePath);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 78c9fe822b..d76344b613 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -138,11 +138,13 @@ QV8Engine::QV8Engine(QV4::ExecutionEngine *v4)
, m_xmlHttpRequestData(nullptr)
#endif
{
+#ifndef Q_OS_WASM // wasm does not have working simd QTBUG-63924
#ifdef Q_PROCESSOR_X86_32
if (!qCpuHasFeature(SSE2)) {
qFatal("This program requires an X86 processor that supports SSE2 extension, at least a Pentium 4 or newer");
}
#endif
+#endif
QML_MEMORY_SCOPE_STRING("QV8Engine::QV8Engine");
qMetaTypeId<QJSValue>();
diff --git a/src/qml/types/types.pri b/src/qml/types/types.pri
index 492f408271..e0ff57a13e 100644
--- a/src/qml/types/types.pri
+++ b/src/qml/types/types.pri
@@ -5,7 +5,6 @@ SOURCES += \
$$PWD/qqmlmodelindexvaluetype.cpp \
$$PWD/qqmlobjectmodel.cpp \
$$PWD/qquickpackage.cpp \
- $$PWD/qquickworkerscript.cpp \
$$PWD/qqmlinstantiator.cpp \
$$PWD/qqmltableinstancemodel.cpp
@@ -16,11 +15,17 @@ HEADERS += \
$$PWD/qqmlmodelindexvaluetype_p.h \
$$PWD/qqmlobjectmodel_p.h \
$$PWD/qquickpackage_p.h \
- $$PWD/qquickworkerscript_p.h \
$$PWD/qqmlinstantiator_p.h \
$$PWD/qqmlinstantiator_p_p.h \
$$PWD/qqmltableinstancemodel_p.h
+qtConfig(thread) {
+ SOURCES += \
+ $$PWD/qquickworkerscript.cpp
+ HEADERS += \
+ $$PWD/qquickworkerscript_p.h
+}
+
qtConfig(qml-list-model) {
SOURCES += \
$$PWD/qqmllistmodel.cpp \
diff --git a/src/quick/configure.json b/src/quick/configure.json
index 9ec3531ef4..9d7bafcb3b 100644
--- a/src/quick/configure.json
+++ b/src/quick/configure.json
@@ -129,7 +129,7 @@
"label": "Path support",
"purpose": "Provides Path elements.",
"section": "Qt Quick",
- "condition": "features.quick-shadereffect",
+ "condition": "features.thread && features.quick-shadereffect",
"output": [
"privateFeature"
]
diff --git a/src/quick/doc/images/9BcAYDlpuT8.jpg b/src/quick/doc/images/9BcAYDlpuT8.jpg
new file mode 100644
index 0000000000..0a69ab0034
--- /dev/null
+++ b/src/quick/doc/images/9BcAYDlpuT8.jpg
Binary files differ
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index ad5e47002d..34ec66bf1d 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -89,3 +89,7 @@ navigation.qmltypespage = "Qt Quick QML Types"
# \svgcolor {#ffdead}
macro.svgcolor.HTML = "<div style=\"padding:10px;color:#fff;background:\1;\"></div>"
+
+# youtube video thumbnails that show up in offline and online docs
+HTML.extraimages += images/9BcAYDlpuT8.jpg
+qhp.QtQuick.extraFiles += images/9BcAYDlpuT8.jpg
diff --git a/src/quick/doc/snippets/qml/tableview/reusabledelegate.qml b/src/quick/doc/snippets/qml/tableview/reusabledelegate.qml
new file mode 100644
index 0000000000..4a49e809cc
--- /dev/null
+++ b/src/quick/doc/snippets/qml/tableview/reusabledelegate.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+//![0]
+Component {
+ id: tableViewDelegate
+ Rectangle {
+ implicitWidth: 100
+ implicitHeight: 50
+
+ TableView.onPooled: rotationAnimation.pause()
+ TableView.onReused: rotationAnimation.resume()
+
+ Rectangle {
+ id: rect
+ anchors.centerIn: parent
+ width: 40
+ height: 5
+ color: "green"
+
+ RotationAnimation {
+ id: rotationAnimation
+ target: rect
+ duration: (Math.random() * 2000) + 200
+ from: 0
+ to: 359
+ running: true
+ loops: Animation.Infinite
+ }
+ }
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/qml/tableview/tablemodel.cpp b/src/quick/doc/snippets/qml/tableview/tablemodel.cpp
new file mode 100644
index 0000000000..ea9f76f131
--- /dev/null
+++ b/src/quick/doc/snippets/qml/tableview/tablemodel.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2018 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the documentation of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** 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.
+ **
+ ** BSD License Usage
+ ** Alternatively, you may use this file under the terms of the BSD license
+ ** as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ ** * Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** * Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in
+ ** the documentation and/or other materials provided with the
+ ** distribution.
+ ** * Neither the name of The Qt Company Ltd nor the names of its
+ ** contributors may be used to endorse or promote products derived
+ ** from this software without specific prior written permission.
+ **
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+//![0]
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QAbstractTableModel>
+
+class TableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return 200;
+ }
+
+ int columnCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return 200;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ switch (role) {
+ case Qt::DisplayRole:
+ return QString("%1, %2").arg(index.column()).arg(index.row());
+ default:
+ break;
+ }
+
+ return QVariant();
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return { {Qt::DisplayRole, "display"} };
+ }
+};
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<TableModel>("TableModel", 0, 1, "TableModel");
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+}
+
+#include "main.moc"
+//![0]
diff --git a/src/quick/doc/snippets/qml/tableview/tablemodel.qml b/src/quick/doc/snippets/qml/tableview/tablemodel.qml
new file mode 100644
index 0000000000..8a8ec94958
--- /dev/null
+++ b/src/quick/doc/snippets/qml/tableview/tablemodel.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![0]
+import QtQuick 2.12
+import TableModel 0.1
+
+TableView {
+ anchors.fill: parent
+ columnSpacing: 1
+ rowSpacing: 1
+ clip: true
+
+ model: TableModel {}
+
+ delegate: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 50
+ Text {
+ text: display
+ }
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/qml/tableview/tableviewwithheader.qml b/src/quick/doc/snippets/qml/tableview/tableviewwithheader.qml
new file mode 100644
index 0000000000..2214328ee7
--- /dev/null
+++ b/src/quick/doc/snippets/qml/tableview/tableviewwithheader.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+//![0]
+TableView {
+ id: tableView
+
+ topMargin: header.implicitHeight
+
+ Text {
+ id: header
+ text: "A table header"
+ }
+}
+//![0]
diff --git a/src/quick/doc/snippets/qml/tableview/tableviewwithprovider.qml b/src/quick/doc/snippets/qml/tableview/tableviewwithprovider.qml
new file mode 100644
index 0000000000..028b12ca6c
--- /dev/null
+++ b/src/quick/doc/snippets/qml/tableview/tableviewwithprovider.qml
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+//![0]
+TableView {
+ id: tableView
+
+ property var columnWidths: [100, 50, 80, 150]
+ columnWidthProvider: function (column) { return columnWidths[column] }
+
+ Timer {
+ running: true
+ interval: 2000
+ onTriggered: {
+ tableView.columnWidths[2] = 150
+ tableView.forceLayout();
+ }
+ }
+}
+//![0]
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index 2705ca5e34..e8265b92d2 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -41,9 +41,10 @@ QObjectList or a \l QAbstractItemModel. The first three are useful for exposing
simpler datasets, while QAbstractItemModel provides a more flexible solution for
more complex models.
-For a video tutorial that takes you through the whole process of exposing a C++
-model to QML, see the
-\l {https://youtu.be/9BcAYDlpuT8}{Using C++ Models in QML Tutorial}.
+Here is a video tutorial that takes you through the whole process of exposing a C++
+model to QML:
+
+\youtube 9BcAYDlpuT8
\section2 QStringList-based Model
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index 3623dcdf3a..5c95a12e9a 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -134,7 +134,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseEvent : public QObject
Q_PROPERTY(bool wasHeld READ wasHeld CONSTANT)
Q_PROPERTY(bool isClick READ isClick CONSTANT)
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
- Q_REVISION(11) Q_PROPERTY(int flags READ flags CONSTANT)
+ Q_PROPERTY(int flags READ flags CONSTANT REVISION 11)
public:
QQuickMouseEvent()
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 86a64cdeeb..ec74660d96 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -391,6 +391,7 @@ QImage QQuickRenderControl::grab()
grabContent.setDevicePixelRatio(d->window->effectiveDevicePixelRatio());
}
#endif
+#if QT_CONFIG(thread)
} else if (d->window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) {
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
cd->polishItems();
@@ -408,6 +409,7 @@ QImage QQuickRenderControl::grab()
render();
softwareRenderer->setCurrentPaintDevice(prevDev);
}
+#endif
} else {
qWarning("QQuickRenderControl: grabs are not supported with the current Qt Quick backend");
}
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index a1a5520239..2e594df8dd 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -51,6 +51,359 @@
#include <QtQuick/private/qquickflickable_p_p.h>
#include <QtQuick/private/qquickitemviewfxitem_p_p.h>
+/*!
+ \qmltype TableView
+ \instantiates QQuickTableView
+ \inqmlmodule QtQuick
+ \ingroup qtquick-views
+ \inherits Flickable
+ \brief Provides a table view of items provided by the model.
+
+ A TableView has a \l model that defines the data to be displayed, and a
+ \l delegate that defines how the data should be displayed.
+
+ TableView inherits \l Flickable. This means that while the model can have
+ any number of rows and columns, only a subsection of the table is usually
+ visible inside the viewport. As soon as you flick, new rows and columns
+ enter the viewport, while old ones exit and are removed from the viewport.
+ The rows and columns that move out are reused for building the rows and columns
+ that move into the viewport. As such, the TableView support models of any
+ size without affecting performance.
+
+ A TableView displays data from models created from built-in QML types
+ such as ListModel and XmlListModel, which populates the first column only
+ in a TableView. To create models with multiple columns, create a model in
+ C++ that inherits QAbstractItemModel, and expose it to QML.
+
+ \section1 Example Usage
+
+ The following example shows how to create a model from C++ with multiple
+ columns:
+
+ \snippet qml/tableview/tablemodel.cpp 0
+
+ And then how to use it from QML:
+
+ \snippet qml/tableview/tablemodel.qml 0
+
+ \section1 Reusing items
+
+ TableView recycles delegate items by default, instead of instantiating from
+ the \l delegate whenever new rows and columns are flicked into view. This
+ can give a huge performance boost, depending on the complexity of the
+ delegate.
+
+ When an item is flicked out, it moves to the \e{reuse pool}, which is an
+ internal cache of unused items. When this happens, the \l TableView::pooled
+ signal is emitted to inform the item about it. Likewise, when the item is
+ moved back from the pool, the \l TableView::reused signal is emitted.
+
+ Any item properties that come from the model are updated when the
+ item is reused. This includes \c index, \c row, and \c column, but also
+ any model roles.
+
+ \note Avoid storing any state inside a delegate. If you do, reset it
+ manually on receiving the \l TableView::reused signal.
+
+ If an item has timers or animations, consider pausing them on receiving
+ the \l TableView::pooled signal. That way you avoid using the CPU resources
+ for items that are not visible. Likewise, if an item has resources that
+ cannot be reused, they could be freed up.
+
+ If you don't want to reuse items or if the \l delegate cannot support it,
+ you can set the \l reuseItems property to \c false.
+
+ \note While an item is in the pool, it might still be alive and respond
+ to connected signals and bindings.
+
+ The following example shows a delegate that animates a spinning rectangle. When
+ it is pooled, the animation is temporarily paused:
+
+ \snippet qml/tableview/reusabledelegate.qml 0
+
+ \section1 Row heights and column widths
+
+ When a new column is flicked into view, TableView will determine its width
+ by calling the \l columnWidthProvider function. TableView itself will never
+ store row height or column width, as it's designed to support large models
+ containing any number of rows and columns. Instead, it will ask the
+ application whenever it needs to know.
+
+ TableView uses the largest \c implicitWidth among the items as the column
+ width, unless the \l columnWidthProvider property is explicitly set. Once
+ the column width is found, all other items in the same column are resized
+ to this width, even if new items that are flicked in later have larger
+ \c implicitWidth. Setting an explicit \l width on an item is ignored and
+ overwritten.
+
+ \note The calculated width of a column is discarded when it is flicked out
+ of the viewport, and is recalculated if the column is flicked back in. The
+ calculation is always based on the items that are visible when the column
+ is flicked in. This means that it can end up different each time, depending
+ on which row you're at when the column enters. You should therefore have the
+ same \c implicitWidth for all items in a column, or set
+ \l columnWidthProvider. The same logic applies for the row height
+ calculation.
+
+ If you change the values that a \l rowHeightProvider or a
+ \l columnWidthProvider return for rows and columns inside the viewport, you
+ must call \l forceLayout. This informs TableView that it needs to use the
+ provider functions again to recalculate and update the layout.
+
+ \note The size of a row or column should be a whole number to avoid
+ sub-pixel alignment of items.
+
+ The following example shows how to set a simple \c columnWidthProvider
+ together with a timer that modifies the values the function returns. When
+ the array is modified, \l forceLayout is called to let the changes
+ take effect:
+
+ \snippet qml/tableview/tableviewwithprovider.qml 0
+
+ \section1 Overlays and underlays
+
+ Tableview inherits \l Flickable. And when new items are instantiated from the
+ delegate, it will parent them to the \l{Flickable::}{contentItem}
+ with a \c z value equal to \c 1. You can add your own items inside the
+ Tableview, as child items of the Flickable. By controlling their \c z
+ value, you can make them be on top of or underneath the table items.
+
+ Here is an example that shows how to add some text on top of the table, that
+ moves together with the table as you flick:
+
+ \snippet qml/tableview/tableviewwithheader.qml 0
+*/
+
+/*!
+ \qmlproperty int QtQuick::TableView::rows
+
+ This property holds the number of rows in the table. This is
+ equal to the number of rows in the model.
+
+ This property is read only.
+*/
+
+/*!
+ \qmlproperty int QtQuick::TableView::columns
+
+ This property holds the number of columns in the table. This is
+ equal to the number of columns in the model. If the model is
+ a list, columns will be 1.
+
+ This property is read only.
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::rowSpacing
+
+ This property holds the spacing between the rows.
+
+ The default value is 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::columnSpacing
+
+ This property holds the spacing between the columns.
+
+ The default value is 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::topMargin
+
+ This property holds the margin between the top of the table and
+ the top of the content view.
+
+ The default value is 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::bottomMargin
+
+ This property holds the margin between the bottom of the table and
+ the bottom of the content view.
+
+ The default value is 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::leftMargin
+
+ This property holds the margin between the left side of the table and
+ the left side of the content view.
+
+ The default value is 0.
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::rightMargin
+
+ This property holds the margin between the right side of the table and
+ the right side of the content view.
+
+ The default value is 0.
+*/
+
+/*!
+ \qmlproperty var QtQuick::TableView::rowHeightProvider
+
+ This property can hold a function that returns the row height for each row
+ in the model. When assigned, it will be called whenever TableView needs to
+ know the height of a specific row. The function takes one argument, \c row,
+ for which the TableView needs to know the height.
+
+ \note The height of a row must always be greater than \c 0.
+
+ \sa columnWidthProvider, {Row heights and column widths}
+*/
+
+/*!
+ \qmlproperty var QtQuick::TableView::columnWidthProvider
+
+ This property can hold a function that returns the column width for each
+ column in the model. When assigned, it is called whenever TableView needs
+ to know the width of a specific column. The function takes one argument,
+ \c column, for which the TableView needs to know the width.
+
+ \note The width of a column must always be greater than \c 0.
+
+ \sa rowHeightProvider, {Row heights and column widths}
+*/
+
+/*!
+ \qmlproperty model QtQuick::TableView::model
+ This property holds the model that provides data for the table.
+
+ The model provides the set of data that is used to create the items
+ in the view. Models can be created directly in QML using \l ListModel,
+ \l XmlListModel or \l VisualItemModel, or provided by a custom C++ model
+ class. If it is a C++ model, it must be a subclass of \l QAbstractItemModel
+ or a simple list.
+
+ \sa {qml-data-models}{Data Models}
+*/
+
+/*!
+ \qmlproperty Component QtQuick::TableView::delegate
+
+ The delegate provides a template defining each cell item instantiated by the
+ view. The model index is exposed as an accessible \c index property. The same
+ applies to \c row and \c column. Properties of the model are also available
+ depending upon the type of \l {qml-data-models}{Data Model}.
+
+ A delegate should specify its size using \l implicitWidth and \l implicitHeight.
+ The TableView lays out the items based on that information. Explicit \l width or
+ \l height settings are ignored and overwritten.
+
+ \note Delegates are instantiated as needed and may be destroyed at any time.
+ They are also reused if the \l reuseItems property is set to \c true. You
+ should therefore avoid storing state information in the delegates.
+
+ \sa {Row heights and column widths}, {Reusing items}
+*/
+
+/*!
+ \qmlproperty bool QtQuick::TableView::reuseItems
+
+ This property holds whether or not items instantiated from the \l delegate
+ should be reused. If set to \c false, any currently pooled items
+ are destroyed.
+
+ \sa {Reusing items}, TableView::pooled, TableView::reused
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::contentWidth
+
+ This property holds the width of the \l contentView, which is also
+ the width of the table (including margins). As a TableView cannot
+ always know the exact width of the table without loading all columns
+ in the model, the \c contentWidth is usually an estimated width based on
+ the columns it has seen so far. This estimate is recalculated whenever
+ new columns are flicked into view, which means that the content width
+ can change dynamically.
+
+ If you know up front what the width of the table will be, assign a value
+ to \c contentWidth explicitly, to avoid unnecessary calculations and
+ updates to the TableView.
+
+ \sa contentHeight
+*/
+
+/*!
+ \qmlproperty real QtQuick::TableView::contentHeight
+
+ This property holds the height of the \l contentView, which is also
+ the height of the table (including margins). As a TableView cannot
+ always know the exact height of the table without loading all rows
+ in the model, the \c contentHeight is usually an estimated height
+ based on the rows it has seen so far. This estimate is recalculated
+ whenever new rows are flicked into view, which means that the content height
+ can change dynamically.
+
+ If you know up front what the height of the table will be, assign a
+ value to \c contentHeight explicitly, to avoid unnecessary calculations and
+ updates to the TableView.
+
+ \sa contentWidth
+*/
+
+/*!
+ \qmlmethod real QtQuick::TableView::forceLayout
+
+ Responding to changes in the model are batched so that they are handled
+ only once per frame. This means the TableView delays showing any changes
+ while a script is being run. The same is also true when changing
+ properties such as \l rowSpacing or \l leftMargin.
+
+ This method forces the TableView to immediately update the layout so
+ that any recent changes take effect.
+
+ Calling this function re-evaluates the size and position of each visible
+ row and column. This is needed if the functions assigned to
+ \l rowHeightProvider or \l columnWidthProvider return different values than
+ what is already assigned.
+*/
+
+/*!
+ \qmlattachedproperty TableView QtQuick::TableView::view
+
+ This attached property holds the view that manages the delegate instance.
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedsignal QtQuick::TableView::pooled
+
+ This signal is emitted after an item has been added to the reuse
+ pool. You can use it to pause ongoing timers or animations inside
+ the item, or free up resources that cannot be reused.
+
+ This signal is emitted only if the \l reuseItems property is \c true.
+
+ \sa {Reusing items}, reuseItems, reused
+*/
+
+/*!
+ \qmlattachedsignal QtQuick::TableView::reused
+
+ This signal is emitted after an item has been reused. At this point, the
+ item has been taken out of the pool and placed inside the content view,
+ and the model properties such as index, row, and column have been updated.
+
+ Other properties that are not provided by the model does not change when an item
+ is reused. You should avoid storing any state inside a delegate, but if you do,
+ manually reset that state on receiving this signal.
+
+ This signal is emitted when the item is reused, and not the first time the
+ item is created.
+
+ This signal is emitted only if the \l reuseItems property is \c true.
+
+ \sa {Reusing items}, reuseItems, pooled
+*/
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcTableViewDelegateLifecycle, "qt.quick.tableview.lifecycle")
@@ -252,28 +605,30 @@ void QQuickTableViewPrivate::enforceTableAtOrigin()
bool layoutNeeded = false;
const qreal flickMargin = 50;
- if (loadedTable.x() == 0 && loadedTableOuterRect.x() != tableMargins.left()) {
+ if (loadedTable.x() == 0 && loadedTableOuterRect.x() > tableMargins.left()) {
// The table is at the beginning, but not at the edge of the
// content view. So move the table to origo.
loadedTableOuterRect.moveLeft(tableMargins.left());
layoutNeeded = true;
- } else if (loadedTableOuterRect.x() < 0) {
+ } else if (loadedTableOuterRect.x() < tableMargins.left()) {
// The table is outside the beginning of the content view. Move
// the whole table inside, and make some room for flicking.
- loadedTableOuterRect.moveLeft(tableMargins.left() + loadedTable.x() == 0 ? 0 : flickMargin);
+ loadedTableOuterRect.moveLeft(qFuzzyIsNull(tableMargins.left() + loadedTable.x()) ? 0 : flickMargin);
layoutNeeded = true;
}
- if (loadedTable.y() == 0 && loadedTableOuterRect.y() != tableMargins.top()) {
+ if (loadedTable.y() == 0 && loadedTableOuterRect.y() > tableMargins.top()) {
loadedTableOuterRect.moveTop(tableMargins.top());
layoutNeeded = true;
- } else if (loadedTableOuterRect.y() < 0) {
- loadedTableOuterRect.moveTop(tableMargins.top() + loadedTable.y() == 0 ? 0 : flickMargin);
+ } else if (loadedTableOuterRect.y() < tableMargins.top()) {
+ loadedTableOuterRect.moveTop(qFuzzyIsNull(tableMargins.top() + loadedTable.y()) ? 0 : flickMargin);
layoutNeeded = true;
}
- if (layoutNeeded)
+ if (layoutNeeded) {
+ qCDebug(lcTableViewDelegateLifecycle);
relayoutTableItems();
+ }
}
void QQuickTableViewPrivate::syncLoadedTableRectFromLoadedTable()
diff --git a/src/quick/scenegraph/adaptations/adaptations.pri b/src/quick/scenegraph/adaptations/adaptations.pri
index 40fa739e15..bfd7095718 100644
--- a/src/quick/scenegraph/adaptations/adaptations.pri
+++ b/src/quick/scenegraph/adaptations/adaptations.pri
@@ -1 +1 @@
-include(software/software.pri)
+qtConfig(thread): include(software/software.pri)
diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp
index 66add51c55..4f8b1cf332 100644
--- a/src/quick/scenegraph/qsgcontextplugin.cpp
+++ b/src/quick/scenegraph/qsgcontextplugin.cpp
@@ -89,8 +89,10 @@ struct QSGAdaptationBackendData
QSGAdaptationBackendData::QSGAdaptationBackendData()
: flags(nullptr)
{
+#if QT_CONFIG(thread)
// Fill in the table with the built-in adaptations.
builtIns.append(new QSGSoftwareAdaptation);
+#endif
}
QSGAdaptationBackendData::~QSGAdaptationBackendData()
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 22e97a2dc9..73b79c6300 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -325,7 +325,8 @@ bool QSGDefaultRenderContext::separateIndexBuffer() const
// lifetime. An attempt to bind a buffer object to the other
// target will generate an INVALID_OPERATION error, and the
// current binding will remain untouched.
- static const bool isWebGL = qGuiApp->platformName().compare(QLatin1String("webgl")) == 0;
+ static const bool isWebGL = (qGuiApp->platformName().compare(QLatin1String("webgl")) == 0
+ || qGuiApp->platformName().compare(QLatin1String("wasm")) == 0);
return isWebGL;
}
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 2eaed497ef..79bfe95e90 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -221,10 +221,12 @@ QSGRenderLoop *QSGRenderLoop::instance()
}
switch (loopType) {
+#if QT_CONFIG(thread)
case ThreadedRenderLoop:
qCDebug(QSG_LOG_INFO, "threaded render loop");
s_instance = new QSGThreadedRenderLoop();
break;
+#endif
case WindowsRenderLoop:
qCDebug(QSG_LOG_INFO, "windows render loop");
s_instance = new QSGWindowsRenderLoop();
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index f08e8b7863..ddd7fb7f4c 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -115,7 +115,6 @@ qtConfig(opengl(es1|es2)?) {
$$PWD/util/qsgdefaultimagenode.cpp \
$$PWD/util/qsgdefaultninepatchnode.cpp \
$$PWD/qsgdefaultlayer.cpp \
- $$PWD/qsgthreadedrenderloop.cpp \
$$PWD/qsgwindowsrenderloop.cpp
HEADERS += \
$$PWD/qsgdefaultglyphnode_p.h \
@@ -132,9 +131,15 @@ qtConfig(opengl(es1|es2)?) {
$$PWD/util/qsgdefaultimagenode_p.h \
$$PWD/util/qsgdefaultninepatchnode_p.h \
$$PWD/qsgdefaultlayer_p.h \
- $$PWD/qsgthreadedrenderloop_p.h \
$$PWD/qsgwindowsrenderloop_p.h
+ qtConfig(thread) {
+ SOURCES += \
+ $$PWD/qsgthreadedrenderloop.cpp
+ HEADERS += \
+ $$PWD/qsgthreadedrenderloop_p.h
+ }
+
qtConfig(quick-sprite) {
SOURCES += \
$$PWD/qsgdefaultspritenode.cpp
diff --git a/src/quick/scenegraph/util/qsgtexturereader.cpp b/src/quick/scenegraph/util/qsgtexturereader.cpp
index 27ba119f63..5e12ca4035 100644
--- a/src/quick/scenegraph/util/qsgtexturereader.cpp
+++ b/src/quick/scenegraph/util/qsgtexturereader.cpp
@@ -38,9 +38,12 @@
****************************************************************************/
#include "qsgtexturereader_p.h"
-#include <private/qsgcompressedtexture_p.h>
#include <private/qtexturefilereader_p.h>
+#if QT_CONFIG(opengl)
+#include <private/qsgcompressedtexture_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
QSGTextureReader::QSGTextureReader(QIODevice *device, const QString &fileName)
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index a098c94670..8646dd32e3 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -297,6 +297,7 @@ void QQuickWidgetPrivate::render(bool needsSync)
QOpenGLContextPrivate::get(context)->defaultFboRedirect = 0;
#endif
} else {
+#if QT_CONFIG(thread)
//Software Renderer
if (needsSync) {
renderControl->polishItems();
@@ -315,6 +316,7 @@ void QQuickWidgetPrivate::render(bool needsSync)
updateRegion += softwareRenderer->flushRegion();
}
+#endif
}
}
diff --git a/src/src.pro b/src/src.pro
index 2dc6fc2758..ba96bd09a1 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -9,7 +9,9 @@ SUBDIRS += \
qtHaveModule(gui):qtConfig(qml-animation) {
SUBDIRS += \
quick \
- quickshapes
+
+ qtConfig(thread): \
+ SUBDIRS += quickshapes
qtConfig(testlib): \
SUBDIRS += qmltest
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index bcb6729ab6..fe2e9835e1 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -112,8 +112,6 @@ built-ins/Array/prototype/unshift/length-near-integer-limit.js fails
built-ins/Array/prototype/unshift/throws-if-integer-limit-exceeded.js fails
built-ins/ArrayBuffer/data-allocation-after-object-creation.js fails
built-ins/ArrayBuffer/proto-from-ctor-realm.js fails
-built-ins/ArrayBuffer/prototype-from-newtarget.js fails
-built-ins/ArrayBuffer/prototype/slice/nonconstructor.js fails
built-ins/ArrayIteratorPrototype/next/detach-typedarray-in-progress.js fails
built-ins/AsyncFunction/AsyncFunction-construct.js fails
built-ins/AsyncFunction/AsyncFunction-is-extensible.js fails
@@ -148,7 +146,6 @@ built-ins/Atomics/wake/wake-one.js fails
built-ins/Atomics/wake/wake-two.js fails
built-ins/Atomics/wake/wake-zero.js fails
built-ins/Boolean/proto-from-ctor-realm.js fails
-built-ins/DataView/custom-proto-access-throws.js fails
built-ins/DataView/custom-proto-if-object-is-used.js fails
built-ins/DataView/proto-from-ctor-realm.js fails
built-ins/Date/UTC/infinity-make-day.js fails
@@ -177,9 +174,7 @@ built-ins/Function/internals/Construct/base-ctor-revoked-proxy-realm.js fails
built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js fails
built-ins/Function/internals/Construct/derived-return-val-realm.js fails
built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js fails
-built-ins/Function/internals/Construct/derived-this-uninitialized.js fails
built-ins/Function/proto-from-ctor-realm.js fails
-built-ins/Function/prototype/Symbol.hasInstance/this-val-poisoned-prototype.js fails
built-ins/Function/prototype/bind/BoundFunction_restricted-properties.js fails
built-ins/Function/prototype/bind/get-fn-realm.js fails
built-ins/Function/prototype/bind/instance-name-chained.js fails
@@ -231,7 +226,6 @@ built-ins/Object/getOwnPropertyDescriptors/symbols-included.js fails
built-ins/Object/keys/proxy-keys.js fails
built-ins/Object/proto-from-ctor.js fails
built-ins/Object/prototype/toLocaleString/primitive_this_value_getter.js strictFails
-built-ins/Object/prototype/toString/no-prototype-property.js fails
built-ins/Object/prototype/toString/proxy-array.js fails
built-ins/Object/prototype/toString/proxy-function.js fails
built-ins/Object/prototype/valueOf/S15.2.4.4_A14.js fails
@@ -427,9 +421,7 @@ built-ins/Proxy/ownKeys/return-not-list-object-throws-realm.js fails
built-ins/Proxy/ownKeys/trap-is-not-callable-realm.js fails
built-ins/Proxy/ownKeys/trap-is-undefined.js fails
built-ins/Proxy/preventExtensions/trap-is-not-callable-realm.js fails
-built-ins/Proxy/proxy-no-prototype.js fails
built-ins/Proxy/revocable/revocation-function-name.js fails
-built-ins/Proxy/revocable/revocation-function-nonconstructor.js fails
built-ins/Proxy/set/trap-is-not-callable-realm.js fails
built-ins/Proxy/setPrototypeOf/trap-is-not-callable-realm.js fails
built-ins/RegExp/S15.10.2.12_A2_T1.js fails
@@ -453,11 +445,9 @@ built-ins/RegExp/unicode_restricted_quantifiable_assertion.js fails
built-ins/RegExp/u180e.js fails
built-ins/Set/proto-from-ctor-realm.js fails
built-ins/Set/prototype/forEach/iterates-values-revisits-after-delete-re-add.js fails
-built-ins/Set/prototype/forEach/this-arg-explicit-cannot-override-lexical-this-arrow.js fails
built-ins/SharedArrayBuffer/data-allocation-after-object-creation.js fails
built-ins/SharedArrayBuffer/proto-from-ctor-realm.js fails
built-ins/SharedArrayBuffer/prototype-from-newtarget.js fails
-built-ins/SharedArrayBuffer/prototype/slice/nonconstructor.js fails
built-ins/String/proto-from-ctor-realm.js fails
built-ins/String/prototype/endsWith/return-abrupt-from-searchstring-regexp-test.js fails
built-ins/String/prototype/includes/return-abrupt-from-searchstring-regexp-test.js fails
@@ -520,36 +510,24 @@ built-ins/TypedArray/prototype/sort/return-same-instance.js fails
built-ins/TypedArray/prototype/sort/sortcompare-with-no-tostring.js fails
built-ins/TypedArray/prototype/sort/sorted-values-nan.js fails
built-ins/TypedArray/prototype/sort/sorted-values.js fails
-built-ins/TypedArrays/ctors/buffer-arg/custom-proto-access-throws.js fails
built-ins/TypedArrays/ctors/buffer-arg/defined-negative-length.js fails
built-ins/TypedArrays/ctors/buffer-arg/proto-from-ctor-realm.js fails
-built-ins/TypedArrays/ctors/buffer-arg/use-custom-proto-if-object.js fails
-built-ins/TypedArrays/ctors/length-arg/custom-proto-access-throws.js fails
built-ins/TypedArrays/ctors/length-arg/proto-from-ctor-realm.js fails
-built-ins/TypedArrays/ctors/length-arg/use-custom-proto-if-object.js fails
-built-ins/TypedArrays/ctors/no-args/custom-proto-access-throws.js fails
built-ins/TypedArrays/ctors/no-args/proto-from-ctor-realm.js fails
-built-ins/TypedArrays/ctors/no-args/use-custom-proto-if-object.js fails
built-ins/TypedArrays/ctors/object-arg/as-generator-iterable-returns.js fails
-built-ins/TypedArrays/ctors/object-arg/custom-proto-access-throws.js fails
built-ins/TypedArrays/ctors/object-arg/iterator-not-callable-throws.js fails
built-ins/TypedArrays/ctors/object-arg/proto-from-ctor-realm.js fails
-built-ins/TypedArrays/ctors/object-arg/use-custom-proto-if-object.js fails
-built-ins/TypedArrays/ctors/typedarray-arg/custom-proto-access-throws.js fails
built-ins/TypedArrays/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js fails
built-ins/TypedArrays/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js fails
built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js fails
built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js fails
built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js fails
built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js fails
-built-ins/TypedArrays/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js fails
built-ins/TypedArrays/ctors/typedarray-arg/proto-from-ctor-realm.js fails
built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js fails
built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js fails
built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js fails
-built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js fails
built-ins/TypedArrays/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js fails
-built-ins/TypedArrays/ctors/typedarray-arg/use-custom-proto-if-object.js fails
built-ins/TypedArrays/from/arylk-get-length-error.js fails
built-ins/TypedArrays/from/arylk-to-length-error.js fails
built-ins/TypedArrays/from/custom-ctor-returns-other-instance.js fails
@@ -573,45 +551,21 @@ built-ins/TypedArrays/from/new-instance-with-mapfn.js fails
built-ins/TypedArrays/from/new-instance-without-mapfn.js fails
built-ins/TypedArrays/from/property-abrupt-completion.js fails
built-ins/TypedArrays/from/set-value-abrupt-completion.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/conversion-operation-consistent-nan.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/conversion-operation.js fails
built-ins/TypedArrays/internals/DefineOwnProperty/detached-buffer-realm.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/detached-buffer.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-greater-than-last-index.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-lower-than-zero.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-minus-zero.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-not-integer.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-accessor-desc.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-configurable.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-not-enumerable.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-not-writable.js fails
built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/set-value.js fails
-built-ins/TypedArrays/internals/DefineOwnProperty/tonumber-value-detached-buffer.js fails
built-ins/TypedArrays/internals/Get/detached-buffer-realm.js fails
-built-ins/TypedArrays/internals/Get/detached-buffer.js fails
-built-ins/TypedArrays/internals/Get/infinity-detached-buffer.js fails
built-ins/TypedArrays/internals/Get/key-is-not-integer.js fails
built-ins/TypedArrays/internals/Get/key-is-not-minus-zero.js fails
built-ins/TypedArrays/internals/Get/key-is-out-of-bounds.js fails
built-ins/TypedArrays/internals/GetOwnProperty/detached-buffer-realm.js fails
-built-ins/TypedArrays/internals/GetOwnProperty/detached-buffer.js fails
built-ins/TypedArrays/internals/GetOwnProperty/enumerate-detached-buffer.js fails
built-ins/TypedArrays/internals/GetOwnProperty/index-prop-desc.js fails
built-ins/TypedArrays/internals/HasProperty/detached-buffer-realm.js fails
-built-ins/TypedArrays/internals/HasProperty/detached-buffer.js fails
-built-ins/TypedArrays/internals/HasProperty/infinity-with-detached-buffer.js sloppyFails
-built-ins/TypedArrays/internals/HasProperty/key-is-lower-than-zero.js fails
-built-ins/TypedArrays/internals/HasProperty/key-is-minus-zero.js fails
-built-ins/TypedArrays/internals/HasProperty/key-is-not-integer.js fails
built-ins/TypedArrays/internals/OwnPropertyKeys/integer-indexes-and-string-and-symbol-keys-.js fails
built-ins/TypedArrays/internals/OwnPropertyKeys/integer-indexes-and-string-keys.js fails
built-ins/TypedArrays/internals/OwnPropertyKeys/integer-indexes.js fails
built-ins/TypedArrays/internals/Set/detached-buffer-realm.js fails
built-ins/TypedArrays/internals/Set/detached-buffer.js fails
-built-ins/TypedArrays/internals/Set/key-is-minus-zero.js fails
-built-ins/TypedArrays/internals/Set/key-is-not-integer.js fails
-built-ins/TypedArrays/internals/Set/key-is-out-of-bounds.js fails
built-ins/TypedArrays/internals/Set/tonumber-value-throws.js strictFails
built-ins/WeakMap/proto-from-ctor-realm.js fails
built-ins/WeakSet/proto-from-ctor-realm.js fails
@@ -661,18 +615,12 @@ language/eval-code/indirect/var-env-global-lex-non-strict.js fails
language/eval-code/indirect/var-env-var-init-global-exstng.js strictFails
language/eval-code/indirect/var-env-var-init-global-new.js strictFails
language/eval-code/indirect/var-env-var-non-strict.js strictFails
-language/expressions/arrow-function/cannot-override-this-with-thisArg.js fails
language/expressions/arrow-function/dflt-params-ref-later.js fails
language/expressions/arrow-function/dflt-params-ref-self.js fails
-language/expressions/arrow-function/lexical-arguments.js fails
language/expressions/arrow-function/lexical-new.target-closure-returned.js fails
language/expressions/arrow-function/lexical-new.target.js fails
language/expressions/arrow-function/lexical-super-call-from-within-constructor.js fails
-language/expressions/arrow-function/lexical-super-property-from-within-constructor.js fails
-language/expressions/arrow-function/lexical-super-property.js fails
language/expressions/arrow-function/lexical-supercall-from-immediately-invoked-arrow.js fails
-language/expressions/arrow-function/lexical-this.js fails
-language/expressions/arrow-function/prototype-rules.js fails
language/expressions/arrow-function/scope-body-lex-distinct.js sloppyFails
language/expressions/arrow-function/scope-param-elem-var-close.js sloppyFails
language/expressions/arrow-function/scope-param-elem-var-open.js sloppyFails
@@ -887,7 +835,6 @@ language/expressions/object/method-definition/gen-yield-identifier-non-strict.js
language/expressions/object/method-definition/meth-dflt-params-ref-later.js fails
language/expressions/object/method-definition/meth-dflt-params-ref-self.js fails
language/expressions/object/method-definition/name-invoke-ctor.js fails
-language/expressions/object/method-definition/name-prototype-prop.js fails
language/expressions/object/method-definition/object-method-returns-promise.js fails
language/expressions/object/method-definition/yield-as-function-expression-binding-identifier.js sloppyFails
language/expressions/object/method-definition/yield-as-identifier-in-nested-function.js sloppyFails
@@ -934,10 +881,6 @@ language/expressions/prefix-increment/S11.4.4_A5_T3.js sloppyFails
language/expressions/prefix-increment/S11.4.4_A5_T4.js sloppyFails
language/expressions/prefix-increment/S11.4.4_A5_T5.js fails
language/expressions/prefix-increment/S11.4.4_A6_T3.js fails
-language/expressions/super/prop-dot-cls-val-from-arrow.js fails
-language/expressions/super/prop-dot-obj-val-from-arrow.js fails
-language/expressions/super/prop-expr-cls-val-from-arrow.js fails
-language/expressions/super/prop-expr-obj-val-from-arrow.js fails
language/expressions/super/realm.js fails
language/expressions/tagged-template/cache-different-functions-same-site.js fails
language/expressions/tagged-template/cache-eval-inner-function.js fails
@@ -1027,20 +970,13 @@ language/statements/block/tco-stmt-list.js strictFails
language/statements/block/tco-stmt.js strictFails
language/statements/class/constructor-inferred-observable-iteration.js fails
language/statements/class/cptn-decl.js fails
-language/statements/class/definition/accessors.js fails
language/statements/class/definition/class-method-returns-promise.js fails
-language/statements/class/definition/getters-prop-desc.js fails
language/statements/class/definition/getters-restricted-ids.js fails
-language/statements/class/definition/invalid-extends.js strictFails
language/statements/class/definition/methods-gen-yield-as-literal-property-name.js fails
language/statements/class/definition/methods-gen-yield-as-property-name.js fails
language/statements/class/definition/methods-gen-yield-star-before-newline.js fails
language/statements/class/definition/methods-named-eval-arguments.js fails
-language/statements/class/definition/methods.js fails
-language/statements/class/definition/numeric-property-names.js fails
-language/statements/class/definition/prototype-getter.js fails
language/statements/class/definition/prototype-property.js fails
-language/statements/class/definition/prototype-setter.js fails
language/statements/class/definition/setters-prop-desc.js fails
language/statements/class/definition/setters-restricted-ids.js fails
language/statements/class/definition/this-access-restriction-2.js fails
@@ -1061,34 +997,8 @@ language/statements/class/scope-static-gen-meth-paramsbody-var-open.js fails
language/statements/class/scope-static-meth-paramsbody-var-open.js fails
language/statements/class/scope-static-setter-paramsbody-var-open.js fails
language/statements/class/subclass/bound-function.js fails
-language/statements/class/subclass/builtin-objects/Array/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/ArrayBuffer/regular-subclassing.js fails
-language/statements/class/subclass/builtin-objects/ArrayBuffer/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/Boolean/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/DataView/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/Date/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/Error/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/Function/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/GeneratorFunction/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/Map/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/NativeError/EvalError-super.js fails
-language/statements/class/subclass/builtin-objects/NativeError/RangeError-super.js fails
-language/statements/class/subclass/builtin-objects/NativeError/ReferenceError-super.js fails
-language/statements/class/subclass/builtin-objects/NativeError/SyntaxError-super.js fails
-language/statements/class/subclass/builtin-objects/NativeError/TypeError-super.js fails
-language/statements/class/subclass/builtin-objects/NativeError/URIError-super.js fails
-language/statements/class/subclass/builtin-objects/Number/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/Object/constructor-return-undefined-throws.js fails
language/statements/class/subclass/builtin-objects/Promise/regular-subclassing.js fails
language/statements/class/subclass/builtin-objects/Promise/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/RegExp/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/Set/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/String/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/TypedArray/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/WeakMap/super-must-be-called.js fails
-language/statements/class/subclass/builtin-objects/WeakSet/super-must-be-called.js fails
-language/statements/class/subclass/builtins.js fails
-language/statements/class/subclass/class-definition-null-proto-this.js fails
language/statements/class/subclass/default-constructor-spread-override.js fails
language/statements/do-while/tco-body.js strictFails
language/statements/for-in/head-lhs-let.js sloppyFails
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 99306d8d15..cf3eecff6d 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -1600,7 +1600,7 @@ void tst_qqmlecmascript::aliasPropertyReset()
// test that a manual write (of undefined) to a non-resettable property fails properly
QUrl url = testFileUrl("aliasreset/aliasPropertyReset.error.1.qml");
- QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
+ QString warning1 = url.toString() + QLatin1String(": Error: Cannot assign [undefined] to int");
QQmlComponent e1(&engine, url);
object = e1.create();
QVERIFY(object != nullptr);
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index e5b06051a5..e25a7b72bb 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -717,16 +717,28 @@ void tst_QQuickTableView::checkLayoutOfEqualSizedDelegateItems()
void tst_QQuickTableView::checkTableMargins_data()
{
QTest::addColumn<QVariant>("model");
- QTest::addColumn<QSize>("tableSize");
QTest::addColumn<QSizeF>("spacing");
QTest::addColumn<QMarginsF>("margins");
- QTest::newRow("QAIM 1x1 1,1 0000") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
- QTest::newRow("QAIM 4x4 1,1 0000") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
- QTest::newRow("QAIM 1x1 1,1 5555") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(1, 1) << QMarginsF(5, 5, 5, 5);
- QTest::newRow("QAIM 4x4 0,0 3333") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(0, 0) << QMarginsF(3, 3, 3, 3);
- QTest::newRow("QAIM 4x4 2,2 1234") << TestModelAsVariant(4, 4) << QSize(4, 4) << QSizeF(2, 2) << QMarginsF(1, 2, 3, 4);
- QTest::newRow("QAIM 1x1 0,0 3210") << TestModelAsVariant(1, 1) << QSize(1, 1) << QSizeF(0, 0) << QMarginsF(3, 2, 1, 0);
+ QTest::newRow("QAIM single") << TestModelAsVariant(1, 1) << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM single, 1,1, no margins") << TestModelAsVariant(1, 1) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM single, no spacing, 1111") << TestModelAsVariant(1, 1) << QSizeF(0, 0) << QMarginsF(1, 1, 1, 1);
+
+ QTest::newRow("QAIM 4x4") << TestModelAsVariant(4, 4) << QSizeF(0, 0) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 4x4, 1,1, no margins") << TestModelAsVariant(4, 4) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 4x4, no spacing, 1111") << TestModelAsVariant(1, 1) << QSizeF(0, 0) << QMarginsF(1, 1, 1, 1);
+
+ QTest::newRow("QAIM 1,1 0000") << TestModelAsVariant(20, 20) << QSizeF(1, 1) << QMarginsF(0, 0, 0, 0);
+ QTest::newRow("QAIM 1,1 5555") << TestModelAsVariant(20, 20) << QSizeF(1, 1) << QMarginsF(5, 5, 5, 5);
+ QTest::newRow("QAIM 0,0 3333") << TestModelAsVariant(20, 20) << QSizeF(0, 0) << QMarginsF(3, 3, 3, 3);
+ QTest::newRow("QAIM 2,2 1234") << TestModelAsVariant(20, 20) << QSizeF(2, 2) << QMarginsF(1, 2, 3, 4);
+ QTest::newRow("QAIM 0,0 3210") << TestModelAsVariant(20, 20) << QSizeF(0, 0) << QMarginsF(3, 2, 1, 0);
+
+ QTest::newRow("QAIM 0,0 negative left margin") << TestModelAsVariant(20, 20) << QSizeF(0, 0) << QMarginsF(-10, 0, 0, 0);
+ QTest::newRow("QAIM 0,0 negative top margin") << TestModelAsVariant(20, 20) << QSizeF(0, 0) << QMarginsF(0, -10, 0, 0);
+ QTest::newRow("QAIM 0,0 negative right margin") << TestModelAsVariant(20, 20) << QSizeF(0, 0) << QMarginsF(0, 0, -10, 0);
+ QTest::newRow("QAIM 0,0 negative bottom margin") << TestModelAsVariant(20, 20) << QSizeF(0, 0) << QMarginsF(0, 0, 0, -10);
+ QTest::newRow("QAIM 0,0 all margins negative") << TestModelAsVariant(20, 20) << QSizeF(0, 0) << QMarginsF(-10, -10, -10, -10);
}
void tst_QQuickTableView::checkTableMargins()
@@ -734,7 +746,6 @@ void tst_QQuickTableView::checkTableMargins()
// Check that the space between the content view and
// the items matches the margins we set on the tableview.
QFETCH(QVariant, model);
- QFETCH(QSize, tableSize);
QFETCH(QSizeF, spacing);
QFETCH(QMarginsF, margins);
LOAD_TABLEVIEW("plaintableview.qml");
@@ -749,19 +760,22 @@ void tst_QQuickTableView::checkTableMargins()
WAIT_UNTIL_POLISHED;
- QCOMPARE(tableViewPrivate->loadedTable.size(), tableSize);
-
- auto const topLeftFxItem = tableViewPrivate->loadedTableItem(QPoint(0, 0));
- auto const bottomRightFxItem = tableViewPrivate->loadedTableItem(tableViewPrivate->loadedTable.bottomRight());
- auto const topLeftItem = topLeftFxItem->item;
- auto const bottomRightItem = bottomRightFxItem->item;
-
+ // Check left-, and top margins
+ auto const topLeftItem = tableViewPrivate->loadedTableItem(QPoint(0, 0))->item;
qreal leftSpace = topLeftItem->x();
qreal topSpace = topLeftItem->y();
- qreal rightSpace = tableView->contentWidth() - (bottomRightItem->x() + bottomRightItem->width());
- qreal bottomSpace = tableView->contentHeight() - (bottomRightItem->y() + bottomRightItem->height());
QCOMPARE(leftSpace, margins.left());
QCOMPARE(topSpace, margins.top());
+
+ // Flick the table to the end...
+ tableView->setContentX(tableView->contentWidth() - tableView->width());
+ tableView->setContentY(tableView->contentHeight() - tableView->height());
+ const QPoint bottomRightCell = tableViewPrivate->loadedTable.bottomRight();
+ auto const bottomRightItem = tableViewPrivate->loadedTableItem(bottomRightCell)->item;
+
+ // ...and check the right-, and bottom margins
+ qreal rightSpace = tableView->contentWidth() - (bottomRightItem->x() + bottomRightItem->width());
+ qreal bottomSpace = tableView->contentHeight() - (bottomRightItem->y() + bottomRightItem->height());
QCOMPARE(rightSpace, margins.right());
QCOMPARE(bottomSpace, margins.bottom());
}
diff --git a/tools/tools.pro b/tools/tools.pro
index 779b656198..ef4872d1a1 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -9,7 +9,7 @@ qtConfig(qml-devtools) {
qtConfig(commandlineparser):qtConfig(xmlstreamwriter): SUBDIRS += qmlcachegen
}
-!android|android_app {
+qtConfig(thread):!android|android_app {
SUBDIRS += \
qml