diff options
Diffstat (limited to 'src')
28 files changed, 326 insertions, 139 deletions
diff --git a/src/imports/imports.pro b/src/imports/imports.pro index 9973883024..e0f66838ec 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -20,8 +20,9 @@ qtHaveModule(quick) { labsanimation \ layouts \ qtquick2 \ - window \ - wavefrontmesh + window + + qtConfig(quick-shadereffect): SUBDIRS += wavefrontmesh qtHaveModule(testlib): SUBDIRS += testlib qtConfig(systemsemaphore): SUBDIRS += sharedimage diff --git a/src/imports/layouts/qquicklayout_p.h b/src/imports/layouts/qquicklayout_p.h index b31bffa290..3f076c7304 100644 --- a/src/imports/layouts/qquicklayout_p.h +++ b/src/imports/layouts/qquicklayout_p.h @@ -131,7 +131,7 @@ class QQuickLayoutPrivate : public QQuickItemPrivate { Q_DECLARE_PUBLIC(QQuickLayout) public: - QQuickLayoutPrivate() : m_isReady(false), m_disableRearrange(true) {} + QQuickLayoutPrivate() : m_isReady(false), m_disableRearrange(true), m_hasItemChangeListeners(false) {} protected: unsigned m_isReady : 1; diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 7b38bf34b1..e6f6fd1b7a 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -362,7 +362,7 @@ ReturnedValue ArrayPrototype::method_toString(const FunctionObject *builtin, con ScopedString string(scope, scope.engine->newString(QStringLiteral("join"))); ScopedFunctionObject f(scope, that->get(string)); if (f) - return f->call(that, argv, argc); + return checkedResult(scope.engine, f->call(that, argv, argc)); return ObjectPrototype::method_toString(builtin, that, argv, argc); } @@ -1211,6 +1211,7 @@ ReturnedValue ArrayPrototype::method_every(const FunctionObject *b, const Value arguments[1] = Value::fromDouble(k); arguments[2] = instance; r = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); ok = r->toBoolean(); } return Encode(ok); @@ -1278,6 +1279,7 @@ ReturnedValue ArrayPrototype::method_some(const FunctionObject *b, const Value * arguments[1] = Value::fromDouble(k); arguments[2] = instance; result = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (result->toBoolean()) return Encode(true); } @@ -1347,6 +1349,7 @@ ReturnedValue ArrayPrototype::method_map(const FunctionObject *b, const Value *t arguments[1] = Value::fromDouble(k); arguments[2] = instance; mapped = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); a->arraySet(k, mapped); } return a.asReturnedValue(); @@ -1382,6 +1385,7 @@ ReturnedValue ArrayPrototype::method_filter(const FunctionObject *b, const Value arguments[1] = Value::fromDouble(k); arguments[2] = instance; selected = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (selected->toBoolean()) { a->arraySet(to, arguments[0]); ++to; @@ -1432,6 +1436,7 @@ ReturnedValue ArrayPrototype::method_reduce(const FunctionObject *b, const Value arguments[2] = Value::fromDouble(k); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } ++k; } @@ -1485,6 +1490,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(const FunctionObject *b, const arguments[2] = Value::fromDouble(k - 1); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } --k; } diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index cc89947cec..c2f48ffeac 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -1561,7 +1561,7 @@ ReturnedValue DatePrototype::method_toJSON(const FunctionObject *b, const Value if (!toIso) return v4->throwTypeError(); - return toIso->call(O, nullptr, 0); + return checkedResult(v4, toIso->call(O, nullptr, 0)); } ReturnedValue DatePrototype::method_symbolToPrimitive(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index dfef52583e..cdb3b8942b 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -358,7 +358,7 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons return v4->throwTypeError(); thisObject = argc ? argv : nullptr; if (argc < 2 || argv[1].isNullOrUndefined()) - return f->call(thisObject, argv, 0); + return checkedResult(v4, f->call(thisObject, argv, 0)); Object *arr = argv[1].objectValue(); if (!arr) @@ -398,13 +398,14 @@ ReturnedValue FunctionPrototype::method_apply(const QV4::FunctionObject *b, cons } } - return f->call(thisObject, arguments, len); + return checkedResult(v4, f->call(thisObject, arguments, len)); } ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const Value *thisObject, const Value *argv, int argc) { + QV4::ExecutionEngine *v4 = b->engine(); if (!thisObject->isFunctionObject()) - return b->engine()->throwTypeError(); + return v4->throwTypeError(); const FunctionObject *f = static_cast<const FunctionObject *>(thisObject); @@ -413,7 +414,7 @@ ReturnedValue FunctionPrototype::method_call(const QV4::FunctionObject *b, const ++argv; --argc; } - return f->call(thisObject, argv, argc); + return checkedResult(v4, f->call(thisObject, argv, argc)); } ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc) @@ -713,12 +714,12 @@ void Heap::BoundFunction::init(QV4::ExecutionContext *scope, QV4::FunctionObject ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *, const Value *argv, int argc) { - const BoundFunction *f = static_cast<const BoundFunction *>(fo); - Scope scope(f->engine()); - - if (scope.hasException()) + QV4::ExecutionEngine *v4 = fo->engine(); + if (v4->hasException) return Encode::undefined(); + const BoundFunction *f = static_cast<const BoundFunction *>(fo); + Scope scope(v4); Scoped<MemberData> boundArgs(scope, f->boundArgs()); ScopedFunctionObject target(scope, f->target()); JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc); @@ -729,7 +730,7 @@ ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value * argp += boundArgs->size(); } memcpy(argp, argv, argc*sizeof(Value)); - return target->call(jsCallData); + return checkedResult(v4, target->call(jsCallData)); } ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *) diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index c99cad8e33..78be58c60a 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -328,6 +328,10 @@ inline bool FunctionObject::isBoundFunction() const return d()->vtable() == BoundFunction::staticVTable(); } +inline ReturnedValue checkedResult(QV4::ExecutionEngine *v4, ReturnedValue result) +{ + return v4->hasException ? QV4::Encode::undefined() : result; +} } diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 936c032fad..ce759111f4 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -703,6 +703,8 @@ QString Stringify::Str(const QString &key, const Value &v) *jsCallData->thisObject = value; jsCallData->args[0] = v4->newString(key); value = toJSON->call(jsCallData); + if (v4->hasException) + return QString(); } } @@ -714,6 +716,8 @@ QString Stringify::Str(const QString &key, const Value &v) jsCallData->args[1] = value; *jsCallData->thisObject = holder; value = replacerFunction->call(jsCallData); + if (v4->hasException) + return QString(); } o = value->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 0cda6b864a..d3ea50867a 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -309,7 +309,8 @@ ReturnedValue Lookup::getterAccessor(Lookup *l, ExecutionEngine *engine, const V if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } } l->getter = getterFallback; @@ -326,7 +327,8 @@ ReturnedValue Lookup::getterProtoAccessor(Lookup *l, ExecutionEngine *engine, co if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } return getterTwoClasses(l, engine, object); } @@ -346,7 +348,8 @@ ReturnedValue Lookup::getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine * if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } } l->getter = getterFallback; @@ -391,7 +394,8 @@ ReturnedValue Lookup::primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(&object, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + &object, nullptr, 0)); } } l->getter = getterGeneric; @@ -429,7 +433,8 @@ ReturnedValue Lookup::globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engi if (!getter->isFunctionObject()) // ### catch at resolve time return Encode::undefined(); - return static_cast<const FunctionObject *>(getter)->call(engine->globalObject, nullptr, 0); + return checkedResult(engine, static_cast<const FunctionObject *>(getter)->call( + engine->globalObject, nullptr, 0)); } l->globalGetter = globalGetterGeneric; return globalGetterGeneric(l, engine); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index 89161433ed..b723141caa 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -105,7 +105,7 @@ ReturnedValue Object::getValueAccessor(const Value *thisObject, const Value &v, JSCallData jsCallData(scope); if (thisObject) *jsCallData->thisObject = *thisObject; - return f->call(jsCallData); + return checkedResult(scope.engine, f->call(jsCallData)); } bool Object::putValue(uint memberIndex, PropertyAttributes attrs, const Value &value) diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp index 7d910a1cbc..0c8cc192fc 100644 --- a/src/qml/jsruntime/qv4objectproto.cpp +++ b/src/qml/jsruntime/qv4objectproto.cpp @@ -667,7 +667,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(const FunctionObject *b, co if (!f) THROW_TYPE_ERROR(); - return f->call(thisObject, argv, argc); + return checkedResult(scope.engine, f->call(thisObject, argv, argc)); } ReturnedValue ObjectPrototype::method_valueOf(const FunctionObject *b, const Value *thisObject, const Value *, int) diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp index 17d218a6eb..ecaff72b22 100644 --- a/src/qml/jsruntime/qv4promiseobject.cpp +++ b/src/qml/jsruntime/qv4promiseobject.cpp @@ -618,7 +618,7 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this } ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1))); - if (!nextPromise || scope.hasException()) { + if (scope.hasException() || !nextPromise) { ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue)); if (scope.hasException()) { completion = e->exceptionValue->asReturnedValue(); @@ -764,7 +764,7 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi } ScopedObject nextPromise(scope, Value::fromReturnedValue(resolve->call(thisObject, nextValue, 1))); - if (!nextPromise || scope.hasException()) { + if (scope.hasException() || !nextPromise) { ScopedValue completion(scope, Runtime::IteratorClose::call(e, iteratorObject, doneValue)); if (scope.hasException()) { completion = e->exceptionValue->asReturnedValue(); diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp index 51f96b9003..24676ffd00 100644 --- a/src/qml/jsruntime/qv4proxy.cpp +++ b/src/qml/jsruntime/qv4proxy.cpp @@ -96,6 +96,8 @@ ReturnedValue ProxyObject::virtualGet(const Managed *m, PropertyKey id, const Va cdata.args[2] = *receiver; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return Encode::undefined(); ScopedProperty targetDesc(scope); PropertyAttributes attributes = target->getOwnProperty(id, targetDesc); if (attributes != Attr_Invalid && !attributes.isConfigurable()) { @@ -136,7 +138,7 @@ bool ProxyObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Val cdata.args[3] = *receiver; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - if (!trapResult->toBoolean()) + if (scope.engine->hasException || !trapResult->toBoolean()) return false; ScopedProperty targetDesc(scope); PropertyAttributes attributes = target->getOwnProperty(id, targetDesc); @@ -176,7 +178,7 @@ bool ProxyObject::virtualDeleteProperty(Managed *m, PropertyKey id) cdata.args[2] = o->d(); // ### fix receiver handling ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - if (!trapResult->toBoolean()) + if (scope.engine->hasException || !trapResult->toBoolean()) return false; ScopedProperty targetDesc(scope); PropertyAttributes attributes = target->getOwnProperty(id, targetDesc); @@ -211,6 +213,8 @@ bool ProxyObject::virtualHasProperty(const Managed *m, PropertyKey id) cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol(); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return false; bool result = trapResult->toBoolean(); if (!result) { ScopedProperty targetDesc(scope); @@ -251,6 +255,8 @@ PropertyAttributes ProxyObject::virtualGetOwnProperty(const Managed *m, Property cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol(); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return Attr_Invalid; if (!trapResult->isObject() && !trapResult->isUndefined()) { scope.engine->throwTypeError(); return Attr_Invalid; @@ -323,7 +329,7 @@ bool ProxyObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Pro cdata.args[2] = ObjectPrototype::fromPropertyDescriptor(scope.engine, p, attrs); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - bool result = trapResult->toBoolean(); + bool result = !scope.engine->hasException && trapResult->toBoolean(); if (!result) return false; @@ -373,6 +379,8 @@ bool ProxyObject::virtualIsExtensible(const Managed *m) cdata.args[0] = target; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return false; bool result = trapResult->toBoolean(); if (result != target->isExtensible()) { scope.engine->throwTypeError(); @@ -404,6 +412,8 @@ bool ProxyObject::virtualPreventExtensions(Managed *m) cdata.args[0] = target; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return false; bool result = trapResult->toBoolean(); if (result && target->isExtensible()) { scope.engine->throwTypeError(); @@ -439,6 +449,8 @@ Heap::Object *ProxyObject::virtualGetPrototypeOf(const Managed *m) cdata.args[0] = target; ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return nullptr; if (!trapResult->isNull() && !trapResult->isObject()) { scope.engine->throwTypeError(); return nullptr; @@ -482,7 +494,7 @@ bool ProxyObject::virtualSetPrototypeOf(Managed *m, const Object *p) cdata.args[1] = p ? p->asReturnedValue() : Encode::null(); ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); - bool result = trapResult->toBoolean(); + bool result = !scope.engine->hasException && trapResult->toBoolean(); if (!result) return false; if (!target->isExtensible()) { @@ -573,6 +585,8 @@ OwnPropertyKeyIterator *ProxyObject::virtualOwnPropertyKeys(const Object *m, Val JSCallData cdata(scope, 1, nullptr, handler); cdata.args[0] = target; ScopedObject trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata)); + if (scope.engine->hasException) + return nullptr; if (!trapResult) { scope.engine->throwTypeError(); return nullptr; @@ -699,7 +713,7 @@ ReturnedValue ProxyFunctionObject::virtualCall(const FunctionObject *f, const Va if (scope.hasException()) return Encode::undefined(); if (trap->isNullOrUndefined()) - return target->call(thisObject, argv, argc); + return checkedResult(scope.engine, target->call(thisObject, argv, argc)); if (!trap->isFunctionObject()) return scope.engine->throwTypeError(); diff --git a/src/qml/jsruntime/qv4reflect.cpp b/src/qml/jsruntime/qv4reflect.cpp index 0772770d63..2a6c61f044 100644 --- a/src/qml/jsruntime/qv4reflect.cpp +++ b/src/qml/jsruntime/qv4reflect.cpp @@ -98,7 +98,8 @@ ReturnedValue Reflect::method_apply(const FunctionObject *f, const Value *, cons if (scope.hasException()) return Encode::undefined(); - return static_cast<const FunctionObject &>(argv[0]).call(&argv[1], arguments.argv, arguments.argc); + return checkedResult(scope.engine, static_cast<const FunctionObject &>(argv[0]).call( + &argv[1], arguments.argv, arguments.argc)); } ReturnedValue Reflect::method_construct(const FunctionObject *f, const Value *, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index f1375e4ca4..a8a37cda37 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -481,6 +481,8 @@ ReturnedValue RegExpPrototype::exec(ExecutionEngine *engine, const Object *o, co ScopedFunctionObject exec(scope, o->get(key)); if (exec) { ScopedValue result(scope, exec->call(o, s, 1)); + if (scope.hasException()) + RETURN_UNDEFINED(); if (!result->isNull() && !result->isObject()) return scope.engine->throwTypeError(); return result->asReturnedValue(); @@ -737,6 +739,8 @@ ReturnedValue RegExpPrototype::method_replace(const FunctionObject *f, const Val cData->args[nCaptures + 1] = Encode(position); cData->args[nCaptures + 2] = s; ScopedValue replValue(scope, replaceFunction->call(cData)); + if (scope.hasException()) + return Encode::undefined(); replacement = replValue->toQString(); } else { replacement = RegExp::getSubstitution(matchString->toQString(), s->toQString(), position, cData.args, nCaptures, replaceValue->toQString()); diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 01b5ff6611..f9e4d258fc 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -390,7 +390,7 @@ QV4::ReturnedValue Runtime::Instanceof::call(ExecutionEngine *engine, const Valu return engine->throwTypeError(); ScopedValue result(scope, fHasInstance->call(&rval, &lval, 1)); - return Encode(result->toBoolean()); + return scope.hasException() ? Encode::undefined() : Encode(result->toBoolean()); } QV4::ReturnedValue Runtime::In::call(ExecutionEngine *engine, const Value &left, const Value &right) @@ -515,6 +515,8 @@ ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const ScopedValue conv(scope, object->get(meth1)); if (FunctionObject *o = conv->as<FunctionObject>()) { result = o->call(object, nullptr, 0); + if (engine->hasException) + return Encode::undefined(); if (result->isPrimitive()) return result->asReturnedValue(); } @@ -525,6 +527,8 @@ ReturnedValue RuntimeHelpers::ordinaryToPrimitive(ExecutionEngine *engine, const conv = object->get(meth2); if (FunctionObject *o = conv->as<FunctionObject>()) { result = o->call(object, nullptr, 0); + if (engine->hasException) + return Encode::undefined(); if (result->isPrimitive()) return result->asReturnedValue(); } @@ -800,6 +804,8 @@ ReturnedValue Runtime::GetIterator::call(ExecutionEngine *engine, const Value &i return engine->throwTypeError(); JSCallData cData(scope, 0, nullptr, o); ScopedObject it(scope, f->call(cData)); + if (engine->hasException) + return Encode::undefined(); if (!it) return engine->throwTypeError(); return it->asReturnedValue(); @@ -1341,7 +1347,8 @@ ReturnedValue Runtime::CallGlobalLookup::call(ExecutionEngine *engine, uint inde engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString()); } - return static_cast<FunctionObject &>(function).call(&thisObject, argv, argc); + return checkedResult(engine, static_cast<FunctionObject &>(function).call( + &thisObject, argv, argc)); } ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engine, uint index, @@ -1356,7 +1363,8 @@ ReturnedValue Runtime::CallQmlContextPropertyLookup::call(ExecutionEngine *engin engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[l->nameIndex]->toQString()); } - return static_cast<FunctionObject &>(function).call(thisObject, argv, argc); + return checkedResult(engine, static_cast<FunctionObject &>(function).call( + thisObject, argv, argc)); } ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Value *argv, int argc) @@ -1375,7 +1383,7 @@ ReturnedValue Runtime::CallPossiblyDirectEval::call(ExecutionEngine *engine, Val if (function->d() == engine->evalFunction()->d()) return static_cast<EvalFunction *>(function.getPointer())->evalCall(thisObject, argv, argc, true); - return function->call(thisObject, argv, argc); + return checkedResult(engine, function->call(thisObject, argv, argc)); } ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Value *argv, int argc) @@ -1395,7 +1403,7 @@ ReturnedValue Runtime::CallName::call(ExecutionEngine *engine, int nameIndex, Va ->runtimeStrings[nameIndex]->toQString()); } - return f->call(thisObject, argv, argc); + return checkedResult(engine, f->call(thisObject, argv, argc)); } ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value &baseRef, int nameIndex, Value *argv, int argc) @@ -1437,7 +1445,7 @@ ReturnedValue Runtime::CallProperty::call(ExecutionEngine *engine, const Value & return engine->throwTypeError(error); } - return f->call(base, argv, argc); + return checkedResult(engine, f->call(base, argv, argc)); } ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const Value &base, uint index, Value *argv, int argc) @@ -1449,7 +1457,7 @@ ReturnedValue Runtime::CallPropertyLookup::call(ExecutionEngine *engine, const V if (!f.isFunctionObject()) return engine->throwTypeError(); - return static_cast<FunctionObject &>(f).call(&base, argv, argc); + return checkedResult(engine, static_cast<FunctionObject &>(f).call(&base, argv, argc)); } ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &baseRef, const Value &index, Value *argv, int argc) @@ -1467,7 +1475,7 @@ ReturnedValue Runtime::CallElement::call(ExecutionEngine *engine, const Value &b if (!f) return engine->throwTypeError(); - return f->call(base, argv, argc); + return checkedResult(engine, f->call(base, argv, argc)); } ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &func, Value *argv, int argc) @@ -1475,7 +1483,8 @@ ReturnedValue Runtime::CallValue::call(ExecutionEngine *engine, const Value &fun if (!func.isFunctionObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); Value undef = Value::undefinedValue(); - return static_cast<const FunctionObject &>(func).call(&undef, argv, argc); + return checkedResult(engine, static_cast<const FunctionObject &>(func).call( + &undef, argv, argc)); } ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Value &func, @@ -1483,7 +1492,8 @@ ReturnedValue Runtime::CallWithReceiver::call(ExecutionEngine *engine, const Val { if (!func.isFunctionObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); - return static_cast<const FunctionObject &>(func).call(&thisObject, argv, argc); + return checkedResult(engine, static_cast<const FunctionObject &>(func).call( + &thisObject, argv, argc)); } struct CallArgs { @@ -1537,7 +1547,8 @@ ReturnedValue Runtime::CallWithSpread::call(ExecutionEngine *engine, const Value if (engine->hasException) return Encode::undefined(); - return static_cast<const FunctionObject &>(function).call(&thisObject, arguments.argv, arguments.argc); + return checkedResult(engine, static_cast<const FunctionObject &>(function).call( + &thisObject, arguments.argv, arguments.argc)); } ReturnedValue Runtime::Construct::call(ExecutionEngine *engine, const Value &function, const Value &newTarget, Value *argv, int argc) @@ -1580,7 +1591,7 @@ ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *eng if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger() || unsigned(argc) > fo.formalParameterCount()) { // Cannot tailcall, do a normal call: - return fo.call(&thisObject, argv, argc); + return checkedResult(engine, fo.call(&thisObject, argv, argc)); } memcpy(frame->jsFrame->args, argv, argc * sizeof(Value)); diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index 9b4a2d575e..209a1b4e76 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -591,7 +591,7 @@ ReturnedValue StringPrototype::method_match(const FunctionObject *b, const Value ScopedFunctionObject match(scope, that->get(scope.engine->symbol_match())); if (!match) return scope.engine->throwTypeError(); - return match->call(that, s, 1); + return checkedResult(scope.engine, match->call(that, s, 1)); } ReturnedValue StringPrototype::method_normalize(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc) diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp index a5a720abc0..6a1b003b25 100644 --- a/src/qml/jsruntime/qv4typedarray.cpp +++ b/src/qml/jsruntime/qv4typedarray.cpp @@ -763,6 +763,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_every(const FunctionObject *b arguments[1] = Value::fromDouble(k); arguments[2] = v; r = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); ok = r->toBoolean(); } return Encode(ok); @@ -862,6 +863,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_filter(const FunctionObject * arguments[1] = Value::fromDouble(k); arguments[2] = instance; selected = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (selected->toBoolean()) { ++arguments; scope.alloc(1); @@ -1201,6 +1203,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_map(const FunctionObject *b, arguments[1] = Value::fromDouble(k); arguments[2] = instance; mapped = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); a->put(k, mapped); } return a->asReturnedValue(); @@ -1250,6 +1253,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_reduce(const FunctionObject * arguments[2] = Value::fromDouble(k); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } ++k; } @@ -1305,6 +1309,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_reduceRight(const FunctionObj arguments[2] = Value::fromDouble(k - 1); arguments[3] = instance; acc = callback->call(nullptr, arguments, 4); + CHECK_EXCEPTION(); } --k; } @@ -1366,6 +1371,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_some(const FunctionObject *b, arguments[1] = Value::fromDouble(k); arguments[2] = instance; result = callback->call(that, arguments, 3); + CHECK_EXCEPTION(); if (result->toBoolean()) return Encode(true); } diff --git a/src/qmlmodels/qqmldelegatecomponent.cpp b/src/qmlmodels/qqmldelegatecomponent.cpp index cc3b38ec93..ccd54bccec 100644 --- a/src/qmlmodels/qqmldelegatecomponent.cpp +++ b/src/qmlmodels/qqmldelegatecomponent.cpp @@ -73,7 +73,7 @@ QVariant QQmlAbstractDelegateComponent::value(QQmlAdaptorModel *adaptorModel, in */ /*! - \qmlproperty string QtQml.Models::DelegateChoice::roleValue + \qmlproperty variant QtQml.Models::DelegateChoice::roleValue This property holds the value used to match the role data for the role provided by \l DelegateChooser::role. */ QVariant QQmlDelegateChoice::roleValue() const @@ -91,7 +91,7 @@ void QQmlDelegateChoice::setRoleValue(const QVariant &value) } /*! - \qmlproperty index QtQml.Models::DelegateChoice::row + \qmlproperty int QtQml.Models::DelegateChoice::row This property holds the value used to match the row value of model elements. With models that have only the index property (and thus only one column), this property should be intended as an index, and set to the desired index value. @@ -103,7 +103,7 @@ void QQmlDelegateChoice::setRoleValue(const QVariant &value) */ /*! - \qmlproperty index QtQml.Models::DelegateChoice::index + \qmlproperty int QtQml.Models::DelegateChoice::index This property holds the value used to match the index value of model elements. This is effectively an alias for \l row. @@ -125,7 +125,7 @@ void QQmlDelegateChoice::setRow(int r) } /*! - \qmlproperty index QtQml.Models::DelegateChoice::column + \qmlproperty int QtQml.Models::DelegateChoice::column This property holds the value used to match the column value of model elements. */ int QQmlDelegateChoice::column() const diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index f79910204a..083e80a0a3 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -2802,10 +2802,12 @@ bool QQmlListModelParser::applyProperty( QV4::ScopedContext context(scope, QV4::QmlContext::create(v4->rootContext(), QQmlContextData::get(qmlContext(model->m_modelCache)), nullptr)); QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(context, compilationUnit->runtimeFunctions[id])); - QV4::ReturnedValue result = function->call(v4->globalObject, nullptr, 0); - QJSValue v; - QJSValuePrivate::setValue(&v, v4, result); + QV4::ScopedValue result(scope, function->call(v4->globalObject, nullptr, 0)); + if (v4->hasException) + v4->catchException(); + else + QJSValuePrivate::setValue(&v, v4, result->asReturnedValue()); value.setValue<QJSValue>(v); } else { QByteArray script = scriptStr.toUtf8(); diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp index 49552e1901..cddf21c7ed 100644 --- a/src/qmltest/quicktestresult.cpp +++ b/src/qmltest/quicktestresult.cpp @@ -480,7 +480,7 @@ static QString qtestFixUrl(const QUrl &location) void QuickTestResult::fail (const QString &message, const QUrl &location, int line) { - QTestResult::addFailure(message.toLatin1().constData(), + QTestResult::addFailure(message.toUtf8().constData(), qtestFixUrl(location).toLatin1().constData(), line); } @@ -493,7 +493,7 @@ bool QuickTestResult::verify qtestFixUrl(location).toLatin1().constData(), line); } else { return QTestResult::verify - (success, message.toLatin1().constData(), "", + (success, message.toUtf8().constData(), "", qtestFixUrl(location).toLatin1().constData(), line); } } @@ -601,7 +601,7 @@ bool QuickTestResult::compare const QUrl &location, int line) { return QTestResult::compare - (success, message.toLocal8Bit().constData(), + (success, message.toUtf8().constData(), QTest::toString(val1.toString().toLatin1().constData()), QTest::toString(val2.toString().toLatin1().constData()), "", "", @@ -611,7 +611,7 @@ bool QuickTestResult::compare void QuickTestResult::skip (const QString &message, const QUrl &location, int line) { - QTestResult::addSkip(message.toLatin1().constData(), + QTestResult::addSkip(message.toUtf8().constData(), qtestFixUrl(location).toLatin1().constData(), line); QTestResult::setSkipCurrentTest(true); } @@ -630,13 +630,13 @@ bool QuickTestResult::expectFailContinue { return QTestResult::expectFail (tag.toLatin1().constData(), - QTest::toString(comment.toLatin1().constData()), + QTest::toString(comment.toUtf8().constData()), QTest::Continue, qtestFixUrl(location).toLatin1().constData(), line); } void QuickTestResult::warn(const QString &message, const QUrl &location, int line) { - QTestLog::warn(message.toLatin1().constData(), qtestFixUrl(location).toLatin1().constData(), line); + QTestLog::warn(message.toUtf8().constData(), qtestFixUrl(location).toLatin1().constData(), line); } void QuickTestResult::ignoreWarning(const QJSValue &message) @@ -646,7 +646,7 @@ void QuickTestResult::ignoreWarning(const QJSValue &message) QTestLog::ignoreMessage(QtWarningMsg, message.toVariant().toRegularExpression()); #endif } else { - QTestLog::ignoreMessage(QtWarningMsg, message.toString().toLatin1()); + QTestLog::ignoreMessage(QtWarningMsg, message.toString().toUtf8()); } } diff --git a/src/quick/configure.json b/src/quick/configure.json index f8277332dc..8d1ddaea7c 100644 --- a/src/quick/configure.json +++ b/src/quick/configure.json @@ -134,7 +134,7 @@ "label": "Path support", "purpose": "Provides Path elements.", "section": "Qt Quick", - "condition": "features.quick-shadereffect", + "condition": "module.gui", "output": [ "privateFeature" ] diff --git a/src/quick/doc/images/declarative-textformat.png b/src/quick/doc/images/declarative-textformat.png Binary files differindex ade1b45429..a671fbf3d6 100644 --- a/src/quick/doc/images/declarative-textformat.png +++ b/src/quick/doc/images/declarative-textformat.png diff --git a/src/quick/doc/snippets/qml/text/textEditFormats.qml b/src/quick/doc/snippets/qml/text/textEditFormats.qml new file mode 100644 index 0000000000..9065cc6a1c --- /dev/null +++ b/src/quick/doc/snippets/qml/text/textEditFormats.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module 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.14 + +//![0] +Column { + TextEdit { + font.pointSize: 24 + textFormat: TextEdit.AutoText + text: "<b>Hello</b> <i>World!</i>" + } + TextEdit { + font.pointSize: 24 + textFormat: TextEdit.RichText + text: "<b>Hello</b> <i>World!</i>" + } + TextEdit { + font.pointSize: 24 + textFormat: TextEdit.PlainText + text: "<b>Hello</b> <i>World!</i>" + } + TextEdit { + font.pointSize: 24 + textFormat: TextEdit.MarkdownText + text: "**Hello** *World!*" + } +} +//![0] + diff --git a/src/quick/doc/snippets/qml/text/textFormats.qml b/src/quick/doc/snippets/qml/text/textFormats.qml new file mode 100644 index 0000000000..b292a3ee13 --- /dev/null +++ b/src/quick/doc/snippets/qml/text/textFormats.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module 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.14 + +//![0] +Column { + Text { + font.pointSize: 24 + text: "<b>Hello</b> <i>World!</i>" + } + Text { + font.pointSize: 24 + textFormat: Text.RichText + text: "<b>Hello</b> <i>World!</i>" + } + Text { + font.pointSize: 24 + textFormat: Text.PlainText + text: "<b>Hello</b> <i>World!</i>" + } + Text { + font.pointSize: 24 + textFormat: Text.MarkdownText + text: "**Hello** *World!*" + } +} +//![0] + diff --git a/src/quick/doc/snippets/qml/xmlrole.xml b/src/quick/doc/snippets/qml/xmlrole.xml deleted file mode 100644 index 70280e067d..0000000000 --- a/src/quick/doc/snippets/qml/xmlrole.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="iso-8859-1" ?> -<catalog> - <book type="Online" wanted="true"> - <title>Qt 5 Cadaques</title> - <year>2014</year> - <author>Juergen Bocklage-Ryannel</author> - <author>Johan Thelin</author> - </book> - <book type="Hardcover"> - <title>C++ GUI Programming with Qt 4</title> - <year>2006</year> - <author>Jasmin Blanchette</author> - <author>Mark Summerfield</author> - </book> - <book type="Paperback"> - <title>Programming with Qt</title> - <year>2002</year> - <author>Matthias Kalle Dalheimer</author> - </book> - </catalog> diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index ae849aeb4b..b95a2559ff 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -1640,6 +1640,9 @@ void QQuickText::itemChange(ItemChange change, const ItemChangeData &value) The item will try to automatically determine whether the text should be treated as styled text. This determination is made using Qt::mightBeRichText(). + However, detection of Markdown is not automatic. + + \sa textFormat */ QString QQuickText::text() const { @@ -2067,26 +2070,25 @@ void QQuickText::resetMaximumLineCount() /*! \qmlproperty enumeration QtQuick::Text::textFormat - The way the text property should be displayed. + The way the \l text property should be displayed. Supported text formats are: - \list - \li Text.AutoText (default) - \li Text.PlainText - \li Text.StyledText - \li Text.RichText - \endlist + \value Text.AutoText (default) detected via the Qt::mightBeRichText() heuristic + \value Text.PlainText all styling tags are treated as plain text + \value Text.StyledText optimized basic rich text as in HTML 3.2 + \value Text.RichText \l {Supported HTML Subset} {a subset of HTML 4} + \value Text.MarkdownText \l {https://commonmark.org/help/}{CommonMark} plus the + \l {https://guides.github.com/features/mastering-markdown/}{GitHub} + extensions for tables and task lists (since 5.14) If the text format is \c Text.AutoText the Text item will automatically determine whether the text should be treated as - styled text. This determination is made using Qt::mightBeRichText() - which uses a fast and therefore simple heuristic. It mainly checks - whether there is something that looks like a tag before the first - line break. Although the result may be correct for common cases, - there is no guarantee. + styled text. This determination is made using Qt::mightBeRichText(), + which can detect the presence of an HTML tag on the first line of text, + but cannot distinguish Markdown from plain text. - Text.StyledText is an optimized format supporting some basic text + \c Text.StyledText is an optimized format supporting some basic text styling markup, in the style of HTML 3.2: \code @@ -2112,30 +2114,21 @@ void QQuickText::resetMaximumLineCount() \table \row \li - \qml -Column { - Text { - font.pointSize: 24 - text: "<b>Hello</b> <i>World!</i>" - } - Text { - font.pointSize: 24 - textFormat: Text.RichText - text: "<b>Hello</b> <i>World!</i>" - } - Text { - font.pointSize: 24 - textFormat: Text.PlainText - text: "<b>Hello</b> <i>World!</i>" - } -} - \endqml + \snippet qml/text/textFormats.qml 0 \li \image declarative-textformat.png \endtable - Text.RichText supports a larger subset of HTML 4, as described on the - \l {Supported HTML Subset} page. You should prefer using Text.PlainText - or Text.StyledText instead, as they offer better performance. + \c Text.RichText supports a larger subset of HTML 4, as described on the + \l {Supported HTML Subset} page. You should prefer using \c Text.PlainText, + \c Text.StyledText or \c Text.MarkdownText instead, as they offer better performance. + + \note With \c Text.MarkdownText, and with the supported subset of HTML, + some decorative elements are not rendered as they would be in a web browser: + \list + \li code blocks use the \l {QFontDatabase::FixedFont}{default monospace font} but without a surrounding highlight box + \li block quotes are indented, but there is no vertical line alongside the quote + \li horizontal rules are not rendered + \endlist */ QQuickText::TextFormat QQuickText::textFormat() const { diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 7d34cc3f56..650b1961a4 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -395,6 +395,7 @@ QString QQuickTextEdit::text() const The text to display. If the text format is AutoText the text edit will automatically determine whether the text should be treated as rich text. This determination is made using Qt::mightBeRichText(). + However, detection of Markdown is not automatic. The text-property is mostly suitable for setting the initial content and handling modifications to relatively small text content. The append(), @@ -402,7 +403,7 @@ QString QQuickTextEdit::text() const remarkably better performance for modifying especially large rich text content. - \sa clear() + \sa clear(), textFormat */ void QQuickTextEdit::setText(const QString &text) { @@ -444,41 +445,43 @@ QString QQuickTextEdit::preeditText() const /*! \qmlproperty enumeration QtQuick::TextEdit::textFormat - The way the text property should be displayed. + The way the \l text property should be displayed. - \list - \li TextEdit.AutoText - \li TextEdit.PlainText - \li TextEdit.RichText - \endlist + Supported text formats are: - The default is TextEdit.PlainText. If the text format is TextEdit.AutoText the text edit - will automatically determine whether the text should be treated as - rich text. This determination is made using Qt::mightBeRichText(). + \value TextEdit.PlainText (default) all styling tags are treated as plain text + \value TextEdit.AutoText detected via the Qt::mightBeRichText() heuristic + \value TextEdit.RichText \l {Supported HTML Subset} {a subset of HTML 4} + \value TextEdit.MarkdownText \l {https://commonmark.org/help/}{CommonMark} plus the + \l {https://guides.github.com/features/mastering-markdown/}{GitHub} + extensions for tables and task lists (since 5.14) + + The default is \c TextEdit.PlainText. If the text format is set to + \c TextEdit.AutoText, the text edit will automatically determine whether + the text should be treated as rich text. This determination is made using + Qt::mightBeRichText(), which can detect the presence of an HTML tag on the + first line of text, but cannot distinguish Markdown from plain text. \table \row \li - \qml -Column { - TextEdit { - font.pointSize: 24 - text: "<b>Hello</b> <i>World!</i>" - } - TextEdit { - font.pointSize: 24 - textFormat: TextEdit.RichText - text: "<b>Hello</b> <i>World!</i>" - } - TextEdit { - font.pointSize: 24 - textFormat: TextEdit.PlainText - text: "<b>Hello</b> <i>World!</i>" - } -} - \endqml + \snippet qml/text/textEditFormats.qml 0 \li \image declarative-textformat.png \endtable + + With \c TextEdit.MarkdownText, checkboxes that result from using the + \l {https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown}{GitHub checkbox extension} + are interactively checkable. + + \note Interactively typing markup or markdown formatting is not supported. + + \note With \c Text.MarkdownText, and with the supported subset of HTML, + some decorative elements are not rendered as they would be in a web browser: + \list + \li code blocks use the \l {QFontDatabase::FixedFont}{default monospace font} but without a surrounding highlight box + \li block quotes are indented, but there is no vertical line alongside the quote + \li horizontal rules are not rendered + \endlist */ QQuickTextEdit::TextFormat QQuickTextEdit::textFormat() const { diff --git a/src/quickshapes/qquickshapegenericrenderer_p.h b/src/quickshapes/qquickshapegenericrenderer_p.h index 4590c662c1..75c4277383 100644 --- a/src/quickshapes/qquickshapegenericrenderer_p.h +++ b/src/quickshapes/qquickshapegenericrenderer_p.h @@ -57,6 +57,7 @@ #include <qsggeometry.h> #include <qsgmaterial.h> #include <qsgrendererinterface.h> +#include <qsgtexture.h> #include <QtCore/qrunnable.h> QT_BEGIN_NAMESPACE |