aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-02-15 21:05:45 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-02-15 21:05:45 +0100
commitcf142cd637620e2af6ede46c4f2cefe0206d6159 (patch)
tree10ec6455b795a45152999e74335e5ae7f592903a /src
parent70f35501da4d1bbb36703dcc7b121c454f8d57a9 (diff)
parent238cc098d785b4fe76fbc8422b340d98ff8c1a1b (diff)
Merge remote-tracking branch 'origin/5.11' into dev
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/yarr/YarrPattern.cpp2
-rw-r--r--src/imports/shapes/qquickshape.cpp7
-rw-r--r--src/imports/shapes/qquickshape_p_p.h1
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp3
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp1
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp3
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h27
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp6
-rw-r--r--src/qml/doc/snippets/code/src_script_qjsengine.cpp20
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc25
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/basics.qdoc2
-rw-r--r--src/qml/doc/src/qmllanguageref/typesystem/objecttypes.qdoc2
-rw-r--r--src/qml/jsapi/qjsengine.cpp24
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp3
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp34
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp8
-rw-r--r--src/qml/jsruntime/qv4value_p.h4
-rw-r--r--src/qml/memory/qv4mm.cpp15
-rw-r--r--src/qml/qml/qqmldata_p.h10
-rw-r--r--src/qml/qml/qqmlengine.cpp24
-rw-r--r--src/qml/qml/qqmlerror.cpp2
-rw-r--r--src/qml/qml/qqmlimport.cpp150
-rw-r--r--src/qml/qml/qqmlmetatype.cpp9
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp3
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp22
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp2
-rw-r--r--src/qmldebug/qqmlprofilereventreceiver_p.h11
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc4
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp18
-rw-r--r--src/quick/items/qquickitem.cpp37
-rw-r--r--src/quick/items/qquickitem_p.h4
-rw-r--r--src/quick/items/qquickitemview.cpp4
-rw-r--r--src/quick/items/qquickloader.cpp19
-rw-r--r--src/quick/items/qquickloader_p.h1
-rw-r--r--src/quick/items/qquicktextinput.cpp36
-rw-r--r--src/quick/items/qquickwindow.cpp8
-rw-r--r--src/quick/items/qquickwindowmodule.cpp15
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp1
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp35
-rw-r--r--src/quick/scenegraph/coreapi/qsggeometry.cpp13
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp5
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp8
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.h7
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp18
-rw-r--r--src/quick/scenegraph/util/qsgimagenode.cpp11
-rw-r--r--src/quick/scenegraph/util/qsgsimplematerial.h2
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp10
-rw-r--r--src/quick/util/qquickimageprovider.cpp8
49 files changed, 480 insertions, 206 deletions
diff --git a/src/3rdparty/masm/yarr/YarrPattern.cpp b/src/3rdparty/masm/yarr/YarrPattern.cpp
index ae527f065f..c7e5b6b09b 100644
--- a/src/3rdparty/masm/yarr/YarrPattern.cpp
+++ b/src/3rdparty/masm/yarr/YarrPattern.cpp
@@ -233,7 +233,7 @@ private:
ranges.insert(i, CharacterRange(lo, hi));
return;
}
- // Okay, since we didn't hit the last case, the end of the new range is definitely at or after the begining
+ // Okay, since we didn't hit the last case, the end of the new range is definitely at or after the beginning
// If the new range start at or before the end of the last range, then the overlap (if it starts one after the
// end of the last range they concatenate, which is just as good.
if (lo <= (ranges[i].end + 1)) {
diff --git a/src/imports/shapes/qquickshape.cpp b/src/imports/shapes/qquickshape.cpp
index da5a525ff0..f0fdebe162 100644
--- a/src/imports/shapes/qquickshape.cpp
+++ b/src/imports/shapes/qquickshape.cpp
@@ -633,6 +633,7 @@ void QQuickShapePath::resetFillGradient()
*/
QQuickShapePrivate::QQuickShapePrivate()
+ : effectRefCount(0)
{
}
@@ -910,10 +911,12 @@ void QQuickShape::updatePolish()
{
Q_D(QQuickShape);
- if (!d->spChanged)
+ const int currentEffectRefCount = d->extra.isAllocated() ? d->extra->recursiveEffectRefCount : 0;
+ if (!d->spChanged && currentEffectRefCount <= d->effectRefCount)
return;
d->spChanged = false;
+ d->effectRefCount = currentEffectRefCount;
if (!d->renderer) {
d->createRenderer();
@@ -925,7 +928,7 @@ void QQuickShape::updatePolish()
// endSync() is where expensive calculations may happen (or get kicked off
// on worker threads), depending on the backend. Therefore do this only
// when the item is visible.
- if (isVisible())
+ if (isVisible() || d->effectRefCount > 0)
d->sync();
update();
diff --git a/src/imports/shapes/qquickshape_p_p.h b/src/imports/shapes/qquickshape_p_p.h
index c3d84b6353..ef2775885e 100644
--- a/src/imports/shapes/qquickshape_p_p.h
+++ b/src/imports/shapes/qquickshape_p_p.h
@@ -170,6 +170,7 @@ public:
static void asyncShapeReady(void *data);
+ int effectRefCount;
QVector<QQuickShapePath *> sp;
QElapsedTimer syncTimer;
QQuickAbstractPathRenderer *renderer = nullptr;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
index 0d3f78d95d..0d501f48c0 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
@@ -145,9 +145,6 @@ void QSGD3D12RenderLoop::windowDestroyed(QQuickWindow *window)
rc->invalidate();
- if (m_windows.isEmpty())
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
-
delete rc;
delete engine;
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp
index d31156f0eb..9493920100 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp
@@ -91,7 +91,6 @@ void QSGOpenVGRenderLoop::windowDestroyed(QQuickWindow *window)
rc->invalidate();
delete vg;
vg = nullptr;
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
} else if (vg && window == vg->window()) {
vg->doneCurrent();
}
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index c95f8ad344..6de0ed6f7d 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1587,6 +1587,9 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, const QV4:
QV4::CompiledData::Unit *qmlUnit = reinterpret_cast<QV4::CompiledData::Unit *>(data);
qmlUnit->unitSize = totalSize;
qmlUnit->flags |= QV4::CompiledData::Unit::IsQml;
+ // This unit's memory was allocated with malloc on the heap, so it's
+ // definitely not suitable for StaticData access.
+ qmlUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
qmlUnit->offsetToImports = unitSize;
qmlUnit->nImports = output.imports.count();
qmlUnit->offsetToObjects = unitSize + importSize;
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 0a525e418c..7a52f3a12c 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -553,11 +553,11 @@ public:
void appendAliasPropertiesToMetaObjects();
- void appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex);
+ QQmlCompileError appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex);
private:
void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex);
- void propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyRawData::Flags *propertyFlags);
+ QQmlCompileError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyRawData::Flags *propertyFlags);
void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const;
@@ -668,7 +668,7 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl
}
template <typename ObjectContainer>
-inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(
+inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(
const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion,
QQmlPropertyData::Flags *propertyFlags)
{
@@ -687,12 +687,16 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias
auto targetAlias = targetObject.aliasesBegin();
for (uint i = 0; i < alias.localAliasIndex; ++i)
++targetAlias;
- propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags);
- return;
+ return propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags);
} else if (alias.encodedMetaPropertyIndex == -1) {
Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
auto *typeRef = objectContainer->resolvedTypes.value(targetObject.inheritedTypeNameIndex);
- Q_ASSERT(typeRef);
+ if (!typeRef) {
+ // Can be caused by the alias target not being a valid id or property. E.g.:
+ // property alias dataValue: dataVal
+ // invalidAliasComponent { id: dataVal }
+ return QQmlCompileError(targetObject.location, QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
+ }
if (typeRef->type.isValid())
*type = typeRef->type.typeId();
@@ -737,15 +741,16 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias
propertyFlags->isWritable = !(alias.flags & QV4::CompiledData::Property::IsReadOnly) && writable;
propertyFlags->isResettable = resettable;
+ return QQmlCompileError();
}
template <typename ObjectContainer>
-inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache(
+inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPropertyCache(
const CompiledObject &component, int objectIndex)
{
const CompiledObject &object = *objectContainer->objectAt(objectIndex);
if (!object.aliasCount())
- return;
+ return QQmlCompileError();
QQmlPropertyCache *propertyCache = propertyCaches->at(objectIndex);
Q_ASSERT(propertyCache);
@@ -762,7 +767,9 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPrope
int type = 0;
int minorVersion = 0;
QQmlPropertyData::Flags propertyFlags;
- propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags);
+ QQmlCompileError error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags);
+ if (error.isSet())
+ return error;
const QString propertyName = objectContainer->stringAt(alias->nameIndex);
@@ -772,6 +779,8 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesToPrope
propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
type, minorVersion, effectiveSignalIndex++);
}
+
+ return QQmlCompileError();
}
template <typename ObjectContainer>
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index df1f00f2f7..ac373aafb4 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1023,7 +1023,11 @@ bool QQmlComponentAndAliasResolver::resolveAliases(int componentIndex)
}
if (result == AllAliasesResolved) {
- aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex);
+ QQmlCompileError error = aliasCacheCreator.appendAliasesToPropertyCache(*qmlObjects->at(componentIndex), objectIndex);
+ if (error.isSet()) {
+ recordError(error);
+ return false;
+ }
atLeastOneAliasResolved = true;
} else if (result == SomeAliasesResolved) {
atLeastOneAliasResolved = true;
diff --git a/src/qml/doc/snippets/code/src_script_qjsengine.cpp b/src/qml/doc/snippets/code/src_script_qjsengine.cpp
index 3799189f83..6c58fd8a18 100644
--- a/src/qml/doc/snippets/code/src_script_qjsengine.cpp
+++ b/src/qml/doc/snippets/code/src_script_qjsengine.cpp
@@ -114,3 +114,23 @@ engine.globalObject().setProperty("myObject", myScriptQObject);
qDebug() << engine.evaluate("myObject.dynamicProperty").toInt();
//! [6]
+
+
+//! [7]
+class MyObject : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE MyObject() {}
+};
+//! [7]
+
+//! [8]
+QJSValue jsMetaObject = engine.newQMetaObject(&MyObject::staticMetaObject);
+engine.globalObject().setProperty("MyObject", jsMetaObject);
+//! [8]
+
+//! [9]
+engine.evaluate("var myObject = new MyObject()");
+//! [9]
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index 8a62a18eec..f939ddbcf3 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -324,6 +324,19 @@
qmlRegisterSingletonType("Qt.example.qjsvalueApi", 1, 0, "MyApi", example_qjsvalue_singletontype_provider);
\endcode
+ Alternatively, you can use a C++11 lambda:
+
+ \code
+ qmlRegisterSingletonType("Qt.example.qjsvalueApi", 1, 0, "MyApi", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QJSValue {
+ Q_UNUSED(engine)
+
+ static int seedValue = 5;
+ QJSValue example = scriptEngine->newObject();
+ example.setProperty("someProperty", seedValue++);
+ return example;
+ });
+ \endcode
+
In order to use the registered singleton type in QML, you must import the singleton type.
\qml
import QtQuick 2.0
@@ -423,6 +436,18 @@
qmlRegisterSingletonType<SingletonTypeExample>("Qt.example.qobjectSingleton", 1, 0, "MyApi", example_qobject_singletontype_provider);
\endcode
+ Alternatively, you can use a C++11 lambda:
+
+ \code
+ qmlRegisterSingletonType<SingletonTypeExample>("Qt.example.qjsvalueApi", 1, 0, "MyApi", [](QQmlEngine *engine, QJSEngine *scriptEngine) -> QObject * {
+ Q_UNUSED(engine)
+ Q_UNUSED(scriptEngine)
+
+ SingletonTypeExample *example = new SingletonTypeExample();
+ return example;
+ });
+ \endcode
+
In order to use the registered singleton type in QML, you must import the singleton type.
\qml
import QtQuick 2.0
diff --git a/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc b/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc
index 1b645a94c0..9eb8f72cf2 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/basics.qdoc
@@ -38,6 +38,8 @@ imperative code, in the case where complex custom application behavior is needed
QML source code is generally loaded by the engine through QML \e documents, which are
standalone documents of QML code. These can be used to define \l {QML Object Types}{QML object types} that can then be reused throughout an application.
+Note that type names must begin with an uppercase letter in order
+to be declared as QML object types in a QML file.
\section1 Import Statements
diff --git a/src/qml/doc/src/qmllanguageref/typesystem/objecttypes.qdoc b/src/qml/doc/src/qmllanguageref/typesystem/objecttypes.qdoc
index b74646b7d0..5f089b5ebc 100644
--- a/src/qml/doc/src/qmllanguageref/typesystem/objecttypes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/typesystem/objecttypes.qdoc
@@ -45,6 +45,8 @@ type, as discussed in \l {qtqml-documents-definetypes.html}
{Documents as QML object type definitions}, or by defining a QML type from C++
and registering the type with the QML engine, as discussed in
\l{qtqml-cppintegration-definetypes.html}{Defining QML Types from C++}.
+Note that in both cases, the type name must begin with an uppercase letter in
+order to be declared as a QML object type in a QML file.
\section1 Defining Object Types from QML
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 048c5856ce..017eabd850 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -166,16 +166,30 @@ Q_DECLARE_METATYPE(QList<int>)
properties of the proxy object. No binding code is needed because it
is done dynamically using the Qt meta object system.
+ \snippet code/src_script_qjsengine.cpp 5
+
Use newQMetaObject() to wrap a QMetaObject; this gives you a
"script representation" of a QObject-based class. newQMetaObject()
returns a proxy script object; enum values of the class are available
as properties of the proxy object.
- Constructors exposed to the meta-object system ( using Q_INVOKABLE ) can be
+ Constructors exposed to the meta-object system (using Q_INVOKABLE) can be
called from the script to create a new QObject instance with
- JavaScriptOwnership.
+ JavaScriptOwnership. For example, given the following class definition:
- \snippet code/src_script_qjsengine.cpp 5
+ \snippet code/src_script_qjsengine.cpp 7
+
+ The \c staticMetaObject for the class can be exposed to JavaScript like so:
+
+ \snippet code/src_script_qjsengine.cpp 8
+
+ Instances of the class can then be created in JavaScript:
+
+ \snippet code/src_script_qjsengine.cpp 9
+
+ \note Currently only classes using the Q_OBJECT macro are supported; it is
+ not possible to expose the \c staticMetaObject of a Q_GADGET class to
+ JavaScript.
\section2 Dynamic QObject Properties
@@ -541,7 +555,7 @@ QJSValue QJSEngine::newQObject(QObject *object)
When called as a constructor, a new instance of the class will be created.
Only constructors exposed by Q_INVOKABLE will be visible from the script engine.
- \sa newQObject()
+ \sa newQObject(), {QObject Integration}
*/
QJSValue QJSEngine::newQMetaObject(const QMetaObject* metaObject) {
@@ -558,7 +572,7 @@ QJSValue QJSEngine::newQMetaObject(const QMetaObject* metaObject) {
Creates a JavaScript object that wraps the static QMetaObject associated
with class \c{T}.
- \sa newQObject()
+ \sa newQObject(), {QObject Integration}
*/
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index f1f866f5a9..45c0b6cfbb 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -175,6 +175,9 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals
int size = o->internalClass->size;
for (int i = idx; i < size; ++i)
o->setProperty(v4, i, *o->propertyData(i + (accessor ? 2 : 1)));
+ o->setProperty(v4, size, Primitive::undefinedValue());
+ if (accessor)
+ o->setProperty(v4, size + 1, Primitive::undefinedValue());
}
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index 0b31c971f9..973541553a 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -68,6 +68,22 @@ Page *getPage(Value *val) {
return reinterpret_cast<Page *>(reinterpret_cast<quintptr>(val) & ~((quintptr)(WTF::pageSize() - 1)));
}
+QML_NEARLY_ALWAYS_INLINE void insertInFront(PersistentValueStorage *storage, Page *p)
+{
+ p->header.next = reinterpret_cast<Page *>(storage->firstPage);
+ p->header.prev = reinterpret_cast<Page **>(&storage->firstPage);
+ if (p->header.next)
+ p->header.next->header.prev = &p->header.next;
+ storage->firstPage = p;
+}
+
+QML_NEARLY_ALWAYS_INLINE void unlink(Page *p)
+{
+ if (p->header.prev)
+ *p->header.prev = p->header.next;
+ if (p->header.next)
+ p->header.next->header.prev = p->header.prev;
+}
Page *allocatePage(PersistentValueStorage *storage)
{
@@ -78,19 +94,14 @@ Page *allocatePage(PersistentValueStorage *storage)
p->header.engine = storage->engine;
p->header.alloc = page;
- p->header.next = reinterpret_cast<Page *>(storage->firstPage);
- p->header.prev = reinterpret_cast<Page **>(&storage->firstPage);
p->header.refCount = 0;
p->header.freeList = 0;
- if (p->header.next)
- p->header.next->header.prev = &p->header.next;
+ insertInFront(storage, p);
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
p->values[i].setEmpty(i + 1);
}
p->values[kEntriesPerPage - 1].setEmpty(-1);
- storage->firstPage = p;
-
return p;
}
@@ -195,6 +206,12 @@ Value *PersistentValueStorage::allocate()
Value *v = p->values + p->header.freeList;
p->header.freeList = v->int_32();
+
+ if (p->header.freeList != -1 && p != firstPage) {
+ unlink(p);
+ insertInFront(this, p);
+ }
+
++p->header.refCount;
v->setRawValue(Encode::undefined());
@@ -237,10 +254,7 @@ ExecutionEngine *PersistentValueStorage::getEngine(Value *v)
void PersistentValueStorage::freePage(void *page)
{
Page *p = static_cast<Page *>(page);
- if (p->header.prev)
- *p->header.prev = p->header.next;
- if (p->header.next)
- p->header.next->header.prev = p->header.prev;
+ unlink(p);
p->header.alloc.deallocate();
}
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 21af4270fd..9c33966cf7 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -108,8 +108,8 @@ ReturnedValue QQmlContextWrapper::get(const Managed *m, String *name, bool *hasP
return result->asReturnedValue();
}
- // Its possible we could delay the calculation of the "actual" context (in the case
- // of sub contexts) until it is definately needed.
+ // It's possible we could delay the calculation of the "actual" context (in the case
+ // of sub contexts) until it is definitely needed.
QQmlContextData *context = resource->getContext();
QQmlContextData *expressionContext = context;
@@ -248,8 +248,8 @@ bool QQmlContextWrapper::put(Managed *m, String *name, const Value &value)
return Object::put(m, name, value);
}
- // Its possible we could delay the calculation of the "actual" context (in the case
- // of sub contexts) until it is definately needed.
+ // It's possible we could delay the calculation of the "actual" context (in the case
+ // of sub contexts) until it is definitely needed.
QQmlContextData *context = wrapper->getContext();
QQmlContextData *expressionContext = context;
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 843fbc1d91..b3f04d69be 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -57,6 +57,8 @@
#include "qv4global_p.h"
#include <private/qv4heap_p.h>
+#include <private/qnumeric_p.h>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -322,6 +324,8 @@ public:
return d;
}
QML_NEARLY_ALWAYS_INLINE void setDouble(double d) {
+ if (qt_is_nan(d))
+ d = qt_qnan();
memcpy(&_val, &d, 8);
_val ^= NaNEncodeMask;
Q_ASSERT(isDouble());
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 4a0c12b9da..9c51013317 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -342,6 +342,9 @@ bool Chunk::sweep(ExecutionEngine *engine)
v->destroy(b);
b->_checkIsDestroyed();
}
+#ifdef V4_USE_HEAPTRACK
+ heaptrack_report_free(itemToFree);
+#endif
}
Q_V4_PROFILE_DEALLOC(engine, qPopulationCount((objectBitmap[i] | extendsBitmap[i])
- (blackBitmap[i] | e)) * Chunk::SlotSize,
@@ -390,6 +393,9 @@ void Chunk::freeAll(ExecutionEngine *engine)
b->vtable()->destroy(b);
b->_checkIsDestroyed();
}
+#ifdef V4_USE_HEAPTRACK
+ heaptrack_report_free(itemToFree);
+#endif
}
Q_V4_PROFILE_DEALLOC(engine, (qPopulationCount(objectBitmap[i]|extendsBitmap[i])
- qPopulationCount(e)) * Chunk::SlotSize, Profiling::SmallItem);
@@ -602,6 +608,9 @@ HeapItem *BlockAllocator::allocate(size_t size, bool forceAllocation) {
done:
m->setAllocatedSlots(slotsRequired);
Q_V4_PROFILE_ALLOC(engine, slotsRequired * Chunk::SlotSize, Profiling::SmallItem);
+#ifdef V4_USE_HEAPTRACK
+ heaptrack_report_alloc(m, slotsRequired * Chunk::SlotSize);
+#endif
// DEBUG << " " << hex << m->chunk() << m->chunk()->objectBitmap[0] << m->chunk()->extendsBitmap[0] << (m - m->chunk()->realBase());
return m;
}
@@ -659,6 +668,9 @@ HeapItem *HugeItemAllocator::allocate(size_t size) {
chunks.push_back(HugeChunk{c, size});
Chunk::setBit(c->objectBitmap, c->first() - c->realBase());
Q_V4_PROFILE_ALLOC(engine, size, Profiling::LargeItem);
+#ifdef V4_USE_HEAPTRACK
+ heaptrack_report_alloc(c, size);
+#endif
return c->first();
}
@@ -675,6 +687,9 @@ static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocato
b->_checkIsDestroyed();
}
chunkAllocator->free(c.chunk, c.size);
+#ifdef V4_USE_HEAPTRACK
+ heaptrack_report_free(c.chunk);
+#endif
}
void HugeItemAllocator::sweep(ClassDestroyStatsCallback classCountPtr)
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 5794e6f0c5..17d145f939 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -56,6 +56,7 @@
#include <private/qqmlpropertyindex_p.h>
#include <private/qv4value_p.h>
#include <private/qv4persistent_p.h>
+#include <private/qqmlrefcount_p.h>
#include <qjsengine.h>
#include <qvector.h>
@@ -116,6 +117,7 @@ class Q_QML_PRIVATE_EXPORT QQmlData : public QAbstractDeclarativeData
{
public:
QQmlData();
+ ~QQmlData();
static inline void init() {
static bool initialized = false;
@@ -219,12 +221,15 @@ public:
quint32 jsEngineId; // id of the engine that created the jsWrapper
struct DeferredData {
+ DeferredData();
+ ~DeferredData();
unsigned int deferredIdx;
QMultiHash<int, const QV4::CompiledData::Binding *> bindings;
- QV4::CompiledData::CompilationUnit *compilationUnit;//Not always the same as the other compilation unit
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;//Not always the same as the other compilation unit
QQmlContextData *context;//Could be either context or outerContext
+ Q_DISABLE_COPY(DeferredData);
};
- QV4::CompiledData::CompilationUnit *compilationUnit;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
QVector<DeferredData *> deferredData;
void deferData(int objectIndex, QV4::CompiledData::CompilationUnit *, QQmlContextData *);
@@ -299,6 +304,7 @@ private:
const BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
return bits[offset] & bitFlagForBit(bit);
}
+ Q_DISABLE_COPY(QQmlData);
};
bool QQmlData::wasDeleted(const QObject *object)
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 99e55a4300..3de2f736cd 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -759,13 +759,17 @@ QQmlData::QQmlData()
hasInterceptorMetaObject(false), hasVMEMetaObject(false), parentFrozen(false),
bindingBitsArraySize(InlineBindingArraySize), notifyList(0),
bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0),
- lineNumber(0), columnNumber(0), jsEngineId(0), compilationUnit(0),
+ lineNumber(0), columnNumber(0), jsEngineId(0),
propertyCache(0), guards(0), extendedData(0)
{
memset(bindingBitsValue, 0, sizeof(bindingBitsValue));
init();
}
+QQmlData::~QQmlData()
+{
+}
+
void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
{
QQmlData *ddata = static_cast<QQmlData *>(d);
@@ -937,6 +941,14 @@ void QQmlData::flushPendingBindingImpl(QQmlPropertyIndex index)
QQmlPropertyData::DontRemoveBinding);
}
+QQmlData::DeferredData::DeferredData()
+{
+}
+
+QQmlData::DeferredData::~DeferredData()
+{
+}
+
bool QQmlEnginePrivate::baseModulesUninitialized = true;
void QQmlEnginePrivate::init()
{
@@ -1693,7 +1705,6 @@ void QQmlData::deferData(int objectIndex, QV4::CompiledData::CompilationUnit *co
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
deferData->deferredIdx = objectIndex;
deferData->compilationUnit = compilationUnit;
- deferData->compilationUnit->addref();
deferData->context = context;
const QV4::CompiledData::Object *compiledObject = compilationUnit->objectAt(objectIndex);
@@ -1715,7 +1726,6 @@ void QQmlData::releaseDeferredData()
while (it != deferredData.end()) {
DeferredData *deferData = *it;
if (deferData->bindings.isEmpty()) {
- deferData->compilationUnit->release();
delete deferData;
it = deferredData.erase(it);
} else {
@@ -1793,12 +1803,10 @@ void QQmlData::destroyed(QObject *object)
if (bindings && !bindings->ref.deref())
delete bindings;
- if (compilationUnit) {
- compilationUnit->release();
- compilationUnit = 0;
- }
+ compilationUnit = nullptr;
- releaseDeferredData();
+ qDeleteAll(deferredData);
+ deferredData.clear();
QQmlBoundSignal *signalHandler = signalHandlers;
while (signalHandler) {
diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp
index 64f008cd32..1b264b025c 100644
--- a/src/qml/qml/qqmlerror.cpp
+++ b/src/qml/qml/qqmlerror.cpp
@@ -268,7 +268,7 @@ QtMsgType QQmlError::messageType() const
\since 5.9
Sets the \a messageType for this message. The message type determines which
- QDebug handlers are responsible for recieving the message.
+ QDebug handlers are responsible for receiving the message.
*/
void QQmlError::setMessageType(QtMsgType messageType)
{
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index f2757c34be..a9113603b8 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -2080,29 +2080,38 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
// Dynamic plugins are differentiated by their filepath. For static plugins we
// don't have that information so we use their address as key instead.
const QString uniquePluginID = QString::asprintf("%p", instance);
- StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
- QMutexLocker lock(&plugins->mutex);
+ {
+ StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
+ QMutexLocker lock(&plugins->mutex);
- // Plugin types are global across all engines and should only be
- // registered once. But each engine still needs to be initialized.
- bool typesRegistered = plugins->contains(uniquePluginID);
- bool engineInitialized = initializedPlugins.contains(uniquePluginID);
+ // Plugin types are global across all engines and should only be
+ // registered once. But each engine still needs to be initialized.
+ bool typesRegistered = plugins->contains(uniquePluginID);
- if (typesRegistered) {
- Q_ASSERT_X(plugins->value(uniquePluginID).uri == uri,
- "QQmlImportDatabase::importStaticPlugin",
- "Internal error: Static plugin imported previously with different uri");
- } else {
- RegisteredPlugin plugin;
- plugin.uri = uri;
- plugin.loader = 0;
- plugins->insert(uniquePluginID, plugin);
+ if (typesRegistered) {
+ Q_ASSERT_X(plugins->value(uniquePluginID).uri == uri,
+ "QQmlImportDatabase::importStaticPlugin",
+ "Internal error: Static plugin imported previously with different uri");
+ } else {
+ RegisteredPlugin plugin;
+ plugin.uri = uri;
+ plugin.loader = 0;
+ plugins->insert(uniquePluginID, plugin);
- if (!registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors))
- return false;
+ if (!registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors))
+ return false;
+ }
+
+ // Release the lock on plugins early as we're done with the global part. Releasing the lock
+ // also allows other QML loader threads to acquire the lock while this thread is blocking
+ // in the initializeEngine call to the gui thread (which in turn may be busy waiting for
+ // other QML loader threads and thus not process the initializeEngine call).
}
- if (!engineInitialized) {
+ // The plugin's per-engine initialization does not need lock protection, as this function is
+ // only called from the engine specific loader thread and importDynamicPlugin as well as
+ // importStaticPlugin are the only places of access.
+ if (!initializedPlugins.contains(uniquePluginID)) {
initializedPlugins.insert(uniquePluginID);
if (QQmlExtensionInterface *eiface = qobject_cast<QQmlExtensionInterface *>(instance)) {
@@ -2124,68 +2133,77 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
QFileInfo fileInfo(filePath);
const QString absoluteFilePath = fileInfo.absoluteFilePath();
+ QObject *instance = nullptr;
bool engineInitialized = initializedPlugins.contains(absoluteFilePath);
- StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
- QMutexLocker lock(&plugins->mutex);
- bool typesRegistered = plugins->contains(absoluteFilePath);
-
- if (typesRegistered) {
- Q_ASSERT_X(plugins->value(absoluteFilePath).uri == uri,
- "QQmlImportDatabase::importDynamicPlugin",
- "Internal error: Plugin imported previously with different uri");
- }
-
- if (!engineInitialized || !typesRegistered) {
- if (!QQml_isFileCaseCorrect(absoluteFilePath)) {
- if (errors) {
- QQmlError error;
- error.setDescription(tr("File name case mismatch for \"%1\"").arg(absoluteFilePath));
- errors->prepend(error);
- }
- return false;
+ {
+ StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
+ QMutexLocker lock(&plugins->mutex);
+ bool typesRegistered = plugins->contains(absoluteFilePath);
+
+ if (typesRegistered) {
+ Q_ASSERT_X(plugins->value(absoluteFilePath).uri == uri,
+ "QQmlImportDatabase::importDynamicPlugin",
+ "Internal error: Plugin imported previously with different uri");
}
- QPluginLoader* loader = 0;
- if (!typesRegistered) {
- loader = new QPluginLoader(absoluteFilePath);
-
- if (!loader->load()) {
+ if (!engineInitialized || !typesRegistered) {
+ if (!QQml_isFileCaseCorrect(absoluteFilePath)) {
if (errors) {
QQmlError error;
- error.setDescription(loader->errorString());
+ error.setDescription(tr("File name case mismatch for \"%1\"").arg(absoluteFilePath));
errors->prepend(error);
}
- delete loader;
return false;
}
- } else {
- loader = plugins->value(absoluteFilePath).loader;
- }
- QObject *instance = loader->instance();
+ QPluginLoader* loader = 0;
+ if (!typesRegistered) {
+ loader = new QPluginLoader(absoluteFilePath);
- if (!typesRegistered) {
- RegisteredPlugin plugin;
- plugin.uri = uri;
- plugin.loader = loader;
- plugins->insert(absoluteFilePath, plugin);
+ if (!loader->load()) {
+ if (errors) {
+ QQmlError error;
+ error.setDescription(loader->errorString());
+ errors->prepend(error);
+ }
+ delete loader;
+ return false;
+ }
+ } else {
+ loader = plugins->value(absoluteFilePath).loader;
+ }
- // Continue with shared code path for dynamic and static plugins:
- if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, vmaj, errors))
- return false;
+ instance = loader->instance();
+
+ if (!typesRegistered) {
+ RegisteredPlugin plugin;
+ plugin.uri = uri;
+ plugin.loader = loader;
+ plugins->insert(absoluteFilePath, plugin);
+
+ // Continue with shared code path for dynamic and static plugins:
+ if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, vmaj, errors))
+ return false;
+ }
}
- if (!engineInitialized) {
- // things on the engine (eg. adding new global objects) have to be done for every
- // engine.
- // XXX protect against double initialization
- initializedPlugins.insert(absoluteFilePath);
-
- if (QQmlExtensionInterface *eiface = qobject_cast<QQmlExtensionInterface *>(instance)) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- ep->typeLoader.initializeEngine(eiface, uri.toUtf8().constData());
- }
- }
+ // Release the lock on plugins early as we're done with the global part. Releasing the lock
+ // also allows other QML loader threads to acquire the lock while this thread is blocking
+ // in the initializeEngine call to the gui thread (which in turn may be busy waiting for
+ // other QML loader threads and thus not process the initializeEngine call).
+ }
+
+
+ if (!engineInitialized) {
+ // The plugin's per-engine initialization does not need lock protection, as this function is
+ // only called from the engine specific loader thread and importDynamicPlugin as well as
+ // importStaticPlugin are the only places of access.
+ initializedPlugins.insert(absoluteFilePath);
+
+ if (QQmlExtensionInterface *eiface = qobject_cast<QQmlExtensionInterface *>(instance)) {
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ ep->typeLoader.initializeEngine(eiface, uri.toUtf8().constData());
+ }
}
return true;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index b324386bf5..76d40bf442 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1566,6 +1566,12 @@ QString registrationTypeString(QQmlType::RegistrationType typeType)
bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data, const char *uri, const QString &typeName, int majorVersion = -1)
{
if (!typeName.isEmpty()) {
+ if (typeName.at(0).isLower()) {
+ QString failure(QCoreApplication::translate("qmlRegisterType", "Invalid QML %1 name \"%2\"; type names must begin with an uppercase letter"));
+ data->typeRegistrationFailures.append(failure.arg(registrationTypeString(typeType)).arg(typeName));
+ return false;
+ }
+
int typeNameLen = typeName.length();
for (int ii = 0; ii < typeNameLen; ++ii) {
if (!(typeName.at(ii).isLetterOrNumber() || typeName.at(ii) == '_')) {
@@ -1803,6 +1809,9 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
else
return -1;
+ if (!dtype.isValid())
+ return -1;
+
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *typeData = metaTypeData();
typeData->undeletableTypes.insert(dtype);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index f9aba69986..caf063c79f 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -203,10 +203,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (instance) {
QQmlData *ddata = QQmlData::get(instance);
Q_ASSERT(ddata);
- if (ddata->compilationUnit)
- ddata->compilationUnit->release();
ddata->compilationUnit = compilationUnit;
- ddata->compilationUnit->addref();
}
if (topLevelCreator)
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index f4c03af5b7..bef58b8c9a 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -137,7 +137,7 @@ private:
QQmlEngine *engine;
QV4::ExecutionEngine *v4;
- QV4::CompiledData::CompilationUnit *compilationUnit;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
QQmlContextData *context;
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 404bc0612e..8e067932bb 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -134,11 +134,11 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o,
}
static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qobjectSingleton,
- const QQmlType &type)
+ const QQmlType &type, bool *ok)
{
- bool ok;
- int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
- if (ok)
+ Q_ASSERT(ok != nullptr);
+ int value = type.enumValue(QQmlEnginePrivate::get(v4->qmlEngine()), name, ok);
+ if (*ok)
return value;
// ### Optimize
@@ -146,10 +146,11 @@ static int enumForSingleton(QV4::ExecutionEngine *v4, String *name, QObject *qob
const QMetaObject *metaObject = qobjectSingleton->metaObject();
for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
QMetaEnum e = metaObject->enumerator(ii);
- value = e.keyToValue(enumName.constData(), &ok);
- if (ok)
+ value = e.keyToValue(enumName.constData(), ok);
+ if (*ok)
return value;
}
+ *ok = false;
return -1;
}
@@ -192,8 +193,9 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
// check for enum value
const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums;
if (includeEnums && name->startsWithUpper()) {
- const int value = enumForSingleton(v4, name, qobjectSingleton, type);
- if (value != -1)
+ bool ok = false;
+ const int value = enumForSingleton(v4, name, qobjectSingleton, type, &ok);
+ if (ok)
return QV4::Primitive::fromInt32(value).asReturnedValue();
}
@@ -205,8 +207,8 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
// Warn when attempting to access a lowercased enum value, singleton case
if (!ok && includeEnums && !name->startsWithUpper()) {
- const int value = enumForSingleton(v4, name, qobjectSingleton, type);
- if (value != -1)
+ enumForSingleton(v4, name, qobjectSingleton, type, &ok);
+ if (ok)
return throwLowercaseEnumError(v4, name, type);
}
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index d37065ce43..c643beeadc 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -98,6 +98,8 @@ void Heap::QQmlValueTypeWrapper::destroy()
valueType->metaType.destruct(gadgetPtr);
::operator delete(gadgetPtr);
}
+ if (_propertyCache)
+ _propertyCache->release();
Object::destroy();
}
diff --git a/src/qmldebug/qqmlprofilereventreceiver_p.h b/src/qmldebug/qqmlprofilereventreceiver_p.h
index ee8e592858..defe64a42e 100644
--- a/src/qmldebug/qqmlprofilereventreceiver_p.h
+++ b/src/qmldebug/qqmlprofilereventreceiver_p.h
@@ -45,6 +45,17 @@
#include <QtCore/qobject.h>
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
QT_BEGIN_NAMESPACE
class QQmlProfilerEventReceiver : public QObject
diff --git a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
index 27c8e51381..2705ca5e34 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/cppmodels.qdoc
@@ -41,6 +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}.
+
\section2 QStringList-based Model
A model may be a simple \l QStringList, which provides the contents of the list
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index 8313b415bf..a1b4f961ed 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -61,14 +61,20 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
TapHandler is a handler for taps on a touchscreen or clicks on a mouse.
- Detection of a valid tap gesture depends on \l gesturePolicy.
+ Detection of a valid tap gesture depends on \l gesturePolicy. The default
+ value is DragThreshold, which requires the press and release to be close
+ together in both space and time. In this case, DragHandler is able to
+ function using only a passive grab, and therefore does not interfere with
+ event delivery to any other Items or Pointer Handlers. So the default
+ gesturePolicy is useful when you want to modify behavior of an existing
+ control or Item by adding a TapHandler with bindings and/or JavaScript
+ callbacks.
+
Note that buttons (such as QPushButton) are often implemented not to care
whether the press and release occur close together: if you press the button
and then change your mind, you need to drag all the way off the edge of the
- button in order to cancel the click. Therefore the default
- \l gesturePolicy is \c TapHandler.ReleaseWithinBounds. If you want to require
- that the press and release are close together in both space and time,
- set it to \c TapHandler.DragThreshold.
+ button in order to cancel the click. For this use case, set the
+ \l gesturePolicy to \c TapHandler.ReleaseWithinBounds.
For multi-tap gestures (double-tap, triple-tap etc.), the distance moved
must not exceed QPlatformTheme::MouseDoubleClickDistance with mouse and
@@ -81,7 +87,7 @@ int QQuickTapHandler::m_touchMultiTapDistanceSquared(-1);
QQuickTapHandler::QQuickTapHandler(QObject *parent)
: QQuickSinglePointHandler(parent)
, m_pressed(false)
- , m_gesturePolicy(ReleaseWithinBounds)
+ , m_gesturePolicy(DragThreshold)
, m_tapCount(0)
, m_longPressThreshold(-1)
, m_lastTapTimestamp(0.0)
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index f615e85e1b..18e0d30ed5 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2809,7 +2809,8 @@ void QQuickItem::stackBefore(const QQuickItem *sibling)
{
Q_D(QQuickItem);
if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
- qWarning("QQuickItem::stackBefore: Cannot stack before %p, which must be a sibling", sibling);
+ qWarning().nospace() << "QQuickItem::stackBefore: Cannot stack "
+ << this << " before " << sibling << ", which must be a sibling";
return;
}
@@ -2853,7 +2854,8 @@ void QQuickItem::stackAfter(const QQuickItem *sibling)
{
Q_D(QQuickItem);
if (!sibling || sibling == this || !d->parentItem || d->parentItem != QQuickItemPrivate::get(sibling)->parentItem) {
- qWarning("QQuickItem::stackAfter: Cannot stack after %p, which must be a sibling", sibling);
+ qWarning().nospace() << "QQuickItem::stackAfter: Cannot stack "
+ << this << " after " << sibling << ", which must be a sibling";
return;
}
@@ -2943,6 +2945,7 @@ void QQuickItemPrivate::addChild(QQuickItem *child)
if (childPrivate->subtreeHoverEnabled && !subtreeHoverEnabled)
setHasHoverInChild(true);
+ childPrivate->recursiveRefFromEffectItem(extra.value().recursiveEffectRefCount);
markSortedChildrenDirty(child);
dirty(QQuickItemPrivate::ChildrenChanged);
@@ -2971,6 +2974,7 @@ void QQuickItemPrivate::removeChild(QQuickItem *child)
if (childPrivate->subtreeHoverEnabled && subtreeHoverEnabled)
setHasHoverInChild(false);
+ childPrivate->recursiveRefFromEffectItem(-extra.value().recursiveEffectRefCount);
markSortedChildrenDirty(child);
dirty(QQuickItemPrivate::ChildrenChanged);
@@ -6071,28 +6075,48 @@ void QQuickItemPrivate::removeFromDirtyList()
void QQuickItemPrivate::refFromEffectItem(bool hide)
{
++extra.value().effectRefCount;
- if (1 == extra->effectRefCount) {
+ if (extra->effectRefCount == 1) {
dirty(EffectReference);
- if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
+ if (parentItem)
+ QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
}
if (hide) {
if (++extra->hideRefCount == 1)
dirty(HideReference);
}
+ recursiveRefFromEffectItem(1);
+}
+
+void QQuickItemPrivate::recursiveRefFromEffectItem(int refs)
+{
+ Q_Q(QQuickItem);
+ if (!refs)
+ return;
+ extra.value().recursiveEffectRefCount += refs;
+ for (int ii = 0; ii < childItems.count(); ++ii) {
+ QQuickItem *child = childItems.at(ii);
+ QQuickItemPrivate::get(child)->recursiveRefFromEffectItem(refs);
+ }
+ // Polish may rely on the effect ref count so trigger one, if item is not visible
+ // (if visible, it will be triggered automatically).
+ if (!effectiveVisible && refs > 0 && extra.value().recursiveEffectRefCount == 1) // it wasn't referenced, now it's referenced
+ q->polish();
}
void QQuickItemPrivate::derefFromEffectItem(bool unhide)
{
Q_ASSERT(extra->effectRefCount);
--extra->effectRefCount;
- if (0 == extra->effectRefCount) {
+ if (extra->effectRefCount == 0) {
dirty(EffectReference);
- if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
+ if (parentItem)
+ QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged);
}
if (unhide) {
if (--extra->hideRefCount == 0)
dirty(HideReference);
}
+ recursiveRefFromEffectItem(-1);
}
void QQuickItemPrivate::setCulled(bool cull)
@@ -8598,6 +8622,7 @@ QQuickItemPrivate::ExtraData::ExtraData()
layer(0),
#endif
effectRefCount(0), hideRefCount(0),
+ recursiveEffectRefCount(0),
opacityNode(0), clipNode(0), rootNode(0),
acceptedMouseButtons(0), origin(QQuickItem::Center),
transparentForPositioner(false)
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 02e7424d1e..ee854bb2ac 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -360,8 +360,11 @@ public:
#endif
QPointF userTransformOriginPoint;
+ // these do not include child items
int effectRefCount;
int hideRefCount;
+ // updated recursively for child items as well
+ int recursiveEffectRefCount;
QSGOpacityNode *opacityNode;
QQuickDefaultClipNode *clipNode;
@@ -614,6 +617,7 @@ public:
// A reference from an effect item means that this item is used by the effect, so
// it should insert a root node.
void refFromEffectItem(bool hide);
+ void recursiveRefFromEffectItem(int refs);
void derefFromEffectItem(bool unhide);
void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &);
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 856070634c..17a1d124ab 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1894,6 +1894,9 @@ void QQuickItemViewPrivate::layout()
inLayout = true;
+ // viewBounds contains bounds before any add/remove/move operation to the view
+ QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
+
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartOffset());
@@ -1960,7 +1963,6 @@ void QQuickItemViewPrivate::layout()
prepareVisibleItemTransitions();
- QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
for (QList<FxViewItem*>::Iterator it = releasePendingTransition.begin();
it != releasePendingTransition.end(); ) {
FxViewItem *item = *it;
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 1f2828585c..33e22c1e95 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -686,6 +686,13 @@ void QQuickLoaderPrivate::incubatorStateChanged(QQmlIncubator::Status status)
if (status == QQmlIncubator::Ready) {
object = incubator->object();
item = qmlobject_cast<QQuickItem*>(object);
+ if (!item) {
+ QQuickWindow *window = qmlobject_cast<QQuickWindow*>(object);
+ if (window) {
+ qCDebug(lcTransient) << window << "is transient for" << q->window();
+ window->setTransientParent(q->window());
+ }
+ }
emit q->itemChanged();
initResize();
incubator->clear();
@@ -830,6 +837,18 @@ void QQuickLoader::componentComplete()
}
}
+void QQuickLoader::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
+{
+ if (change == ItemSceneChange) {
+ QQuickWindow *loadedWindow = qmlobject_cast<QQuickWindow *>(item());
+ if (loadedWindow) {
+ qCDebug(lcTransient) << loadedWindow << "is transient for" << value.window;
+ loadedWindow->setTransientParent(value.window);
+ }
+ }
+ QQuickItem::itemChange(change, value);
+}
+
/*!
\qmlsignal QtQuick::Loader::loaded()
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
index 27e5d1ec8b..b5137c0783 100644
--- a/src/quick/items/qquickloader_p.h
+++ b/src/quick/items/qquickloader_p.h
@@ -107,6 +107,7 @@ Q_SIGNALS:
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
void componentComplete() override;
+ void itemChange(ItemChange change, const ItemChangeData &value) override;
private:
void setSource(const QUrl &sourceUrl, bool needsClear);
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index a09fc35f1c..557ff393b4 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1108,7 +1108,8 @@ void QQuickTextInputPrivate::checkIsValid()
Q_Q(QQuickTextInput);
ValidatorState state = hasAcceptableInput(m_text);
- m_validInput = state != InvalidInput;
+ if (!m_maskData)
+ m_validInput = state != InvalidInput;
if (state != AcceptableInput) {
if (m_acceptableInput) {
m_acceptableInput = false;
@@ -3561,11 +3562,15 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
#if QT_CONFIG(validator)
if (m_validator) {
QString textCopy = m_text;
+ if (m_maskData)
+ textCopy = maskString(0, m_text, true);
int cursorCopy = m_cursor;
QValidator::State state = m_validator->validate(textCopy, cursorCopy);
+ if (m_maskData)
+ textCopy = m_text;
m_validInput = state != QValidator::Invalid;
m_acceptableInput = state == QValidator::Acceptable;
- if (m_validInput) {
+ if (m_validInput && !m_maskData) {
if (m_text != textCopy) {
internalSetText(textCopy, cursorCopy);
return true;
@@ -3574,31 +3579,8 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
}
}
#endif
-
- if (m_maskData) {
- m_validInput = true;
- if (m_text.length() != m_maxLength) {
- m_validInput = false;
- m_acceptableInput = false;
- } else {
- for (int i = 0; i < m_maxLength; ++i) {
- if (m_maskData[i].separator) {
- if (m_text.at(i) != m_maskData[i].maskChar) {
- m_validInput = false;
- m_acceptableInput = false;
- break;
- }
- } else {
- if (!isValidInput(m_text.at(i), m_maskData[i].maskChar)) {
- m_acceptableInput = false;
- if (m_text.at(i) != m_blank)
- m_validInput = false;
- break;
- }
- }
- }
- }
- }
+ if (m_maskData)
+ checkIsValid();
if (validateFromState >= 0 && wasValidInput && !m_validInput) {
if (m_transactions.count())
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 2e36f07fdb..6fda6ab6c6 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -2430,8 +2430,6 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
done = true;
event->localize(receiver);
handler->handlePointerEvent(event);
- if (event->allPointsAccepted())
- done = true;
}
if (done)
break;
@@ -2532,8 +2530,6 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
}
if (handlersOnly)
return;
- if (pointerEvent->allPointsAccepted() && !pointerEvent->isReleaseEvent())
- return;
// If all points are released and the item is not the grabber, it doesn't get the event.
// But if at least one point is still pressed, we might be in a potential gesture-takeover scenario.
@@ -2545,8 +2541,6 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
auto event = pointerEvent->asPointerMouseEvent();
if (event && item->acceptedMouseButtons() & event->button()) {
auto point = event->point(0);
- if (point->isAccepted())
- return;
// The only reason to already have a mouse grabber here is
// synthetic events - flickable sends one when setPressDelay is used.
auto oldMouseGrabber = q->mouseGrabberItem();
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index f048f12bf9..ab3f49d5b6 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -123,7 +123,13 @@ void QQuickWindowQmlImpl::componentComplete()
{
Q_D(QQuickWindowQmlImpl);
d->complete = true;
- if (transientParent() && !transientParent()->isVisible()) {
+ QQuickItem *itemParent = qmlobject_cast<QQuickItem *>(QObject::parent());
+ if (itemParent && !itemParent->window()) {
+ qCDebug(lcTransient) << "window" << title() << "has invisible Item parent" << itemParent << "transientParent"
+ << transientParent() << "declared visibility" << d->visibility << "; delaying show";
+ connect(itemParent, &QQuickItem::windowChanged, this,
+ &QQuickWindowQmlImpl::setWindowVisibility, Qt::QueuedConnection);
+ } else if (transientParent() && !transientParent()->isVisible()) {
connect(transientParent(), &QQuickWindow::visibleChanged, this,
&QQuickWindowQmlImpl::setWindowVisibility, Qt::QueuedConnection);
} else {
@@ -137,9 +143,10 @@ void QQuickWindowQmlImpl::setWindowVisibility()
if (transientParent() && !transientParent()->isVisible())
return;
- if (sender()) {
- disconnect(transientParent(), &QWindow::visibleChanged, this,
- &QQuickWindowQmlImpl::setWindowVisibility);
+ if (QQuickItem *senderItem = qmlobject_cast<QQuickItem *>(sender())) {
+ disconnect(senderItem, &QQuickItem::windowChanged, this, &QQuickWindowQmlImpl::setWindowVisibility);
+ } else if (sender()) {
+ disconnect(transientParent(), &QWindow::visibleChanged, this, &QQuickWindowQmlImpl::setWindowVisibility);
}
// We have deferred window creation until we have the full picture of what
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
index 3f0d1383b9..423f5f7321 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
@@ -97,7 +97,6 @@ void QSGSoftwareRenderLoop::windowDestroyed(QQuickWindow *window)
if (m_windows.size() == 0) {
rc->invalidate();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
}
}
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 87ecf3e5ad..27b374e47f 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -144,7 +144,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphContextFrame);
QSGMaterialShader *s = material->createShader();
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QOpenGLContext *ctx = context->openglContext();
QSurfaceFormat::OpenGLContextProfile profile = ctx->format().profile();
QOpenGLShaderProgram *p = s->program();
@@ -2035,7 +2035,7 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip)
int vboSize = 0;
bool useVBO = false;
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QOpenGLContext *ctx = m_context->openglContext();
QSurfaceFormat::OpenGLContextProfile profile = ctx->format().profile();
if (!ctx->isOpenGLES() && profile == QSurfaceFormat::CoreProfile) {
@@ -2497,18 +2497,21 @@ void Renderer::updateLineWidth(QSGGeometry *g)
if (g->drawingMode() == GL_LINE_STRIP || g->drawingMode() == GL_LINE_LOOP || g->drawingMode() == GL_LINES)
glLineWidth(g->lineWidth());
#if !defined(QT_OPENGL_ES_2)
- else if (!QOpenGLContext::currentContext()->isOpenGLES() && g->drawingMode() == GL_POINTS) {
- QOpenGLFunctions_1_0 *gl1funcs = 0;
- QOpenGLFunctions_3_2_Core *gl3funcs = 0;
- if (QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile)
- gl3funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
- else
- gl1funcs = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_0>();
- Q_ASSERT(gl1funcs || gl3funcs);
- if (gl1funcs)
- gl1funcs->glPointSize(g->lineWidth());
- else
- gl3funcs->glPointSize(g->lineWidth());
+ else {
+ QOpenGLContext *ctx = m_context->openglContext();
+ if (!ctx->isOpenGLES() && g->drawingMode() == GL_POINTS) {
+ QOpenGLFunctions_1_0 *gl1funcs = 0;
+ QOpenGLFunctions_3_2_Core *gl3funcs = 0;
+ if (ctx->format().profile() == QSurfaceFormat::CoreProfile)
+ gl3funcs = ctx->versionFunctions<QOpenGLFunctions_3_2_Core>();
+ else
+ gl1funcs = ctx->versionFunctions<QOpenGLFunctions_1_0>();
+ Q_ASSERT(gl1funcs || gl3funcs);
+ if (gl1funcs)
+ gl1funcs->glPointSize(g->lineWidth());
+ else
+ gl3funcs->glPointSize(g->lineWidth());
+ }
}
#endif
}
@@ -2614,6 +2617,8 @@ void Renderer::deleteRemovedElements()
void Renderer::render()
{
+ Q_ASSERT(m_context->openglContext() == QOpenGLContext::currentContext());
+
if (Q_UNLIKELY(debug_dump())) {
qDebug("\n");
QSGNodeDumper::dump(rootNode());
@@ -3156,7 +3161,7 @@ void Renderer::visualizeOverdraw()
visualizeOverdraw_helper(m_nodes.value(rootNode()));
// Animate the view...
- QSurface *surface = QOpenGLContext::currentContext()->surface();
+ QSurface *surface = m_context->openglContext()->surface();
if (surface->surfaceClass() == QSurface::Window)
if (QQuickWindow *window = qobject_cast<QQuickWindow *>(static_cast<QWindow *>(surface)))
window->update();
diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp
index 69a8c21ed2..52366bfc35 100644
--- a/src/quick/scenegraph/coreapi/qsggeometry.cpp
+++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp
@@ -768,6 +768,19 @@ void QSGGeometry::updateColoredRectGeometry(QSGGeometry *g, const QRectF &rect)
v[3].y = rect.bottom();
}
+/*!
+ \enum QSGGeometry::AttributeType
+
+ This enum identifies several attribute types.
+
+ \value UnknownAttribute Don't care
+ \value PositionAttribute Position
+ \value ColorAttribute Color
+ \value TexCoordAttribute Texture coordinate
+ \value TexCoord1Attribute Texture coordinate 1
+ \value TexCoord2Attribute Texture coordinate 2
+
+ */
/*!
\enum QSGGeometry::DataPattern
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index 07dc87a643..5c28f4c82f 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -443,7 +443,12 @@ void QSGMaterialShader::compile()
otherwise returns \c false.
*/
+/*!
+ \fn bool QSGMaterialShader::RenderState::isCachedMaterialDataDirty() const
+ Returns \c true if the dirtyStates() contains the dirty cached material state,
+ otherwise returns \c false.
+ */
/*!
\fn QSGMaterialShader::RenderState::DirtyStates QSGMaterialShader::RenderState::dirtyStates() const
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
index 22d57001fc..550a2182f8 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -114,6 +114,10 @@ static void qt_print_node_count()
\value DirtyOpacity The opacity of a QSGOpacityNode has changed.
\value DirtySubtreeBlocked The subtree has been blocked.
+ \omitvalue DirtyForceUpdate
+ \omitvalue DirtyUsePreprocess
+ \omitvalue DirtyPropagationMask
+
\sa QSGNode::markDirty()
*/
@@ -135,6 +139,8 @@ static void qt_print_node_count()
ownership over the opaque material and will delete it when the node is
destroyed or a material is assigned.
\value InternalReserved Reserved for internal use.
+
+ \omitvalue IsVisitableNode
*/
/*!
@@ -149,6 +155,8 @@ static void qt_print_node_count()
\value OpacityNodeType The type of QSGOpacityNode
\value RenderNodeType The type of QSGRenderNode
+ \omitvalue RootNodeType
+
\sa type()
*/
diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h
index f2708b2b96..cd9d689dc1 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.h
+++ b/src/quick/scenegraph/coreapi/qsgnode.h
@@ -77,9 +77,7 @@ public:
TransformNodeType,
ClipNodeType,
OpacityNodeType,
-#ifndef qdoc
RootNodeType,
-#endif
RenderNodeType
};
@@ -96,9 +94,8 @@ public:
OwnsOpaqueMaterial = 0x00040000,
// Uppermost 8 bits are reserved for internal use.
-#ifndef qdoc
IsVisitableNode = 0x01000000
-#else
+#ifdef Q_CLANG_QDOC
InternalReserved = 0x01000000
#endif
};
@@ -113,7 +110,6 @@ public:
DirtyMaterial = 0x2000,
DirtyOpacity = 0x4000,
-#ifndef qdoc
DirtyForceUpdate = 0x8000,
DirtyUsePreprocess = UsePreprocess,
@@ -122,7 +118,6 @@ public:
| DirtyNodeAdded
| DirtyOpacity
| DirtyForceUpdate
-#endif
};
Q_DECLARE_FLAGS(DirtyState, DirtyStateBit)
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index a8954848d6..5e259f2083 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -213,6 +213,22 @@ void QSGRenderNode::releaseResources()
}
/*!
+ \enum QSGRenderNode::StateFlag
+
+ This enum is a bit mask identifying several states.
+
+ \value DepthState Depth
+ \value StencilState Stencil
+ \value ScissorState Scissor
+ \value ColorState Color
+ \value BlendState Blend
+ \value CullState Cull
+ \value ViewportState View poirt
+ \value RenderTargetState Render target
+
+ */
+
+/*!
\enum QSGRenderNode::RenderingFlag
Possible values for the bitmask returned from flags().
@@ -354,7 +370,7 @@ QSGRenderNode::RenderState::~RenderState()
*/
/*!
- \fn const QRegion *QSGRenderNode::clipRegion() const
+ \fn const QRegion *QSGRenderNode::RenderState::clipRegion() const
\return the current clip region or null for backends where clipping is
implemented via stencil or scissoring.
diff --git a/src/quick/scenegraph/util/qsgimagenode.cpp b/src/quick/scenegraph/util/qsgimagenode.cpp
index c03c91d1cb..b154023247 100644
--- a/src/quick/scenegraph/util/qsgimagenode.cpp
+++ b/src/quick/scenegraph/util/qsgimagenode.cpp
@@ -168,7 +168,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QSGImageNode::TextureCoordinatesTransformMode textureCoordinatesTransform() const
+ \fn QSGImageNode::TextureCoordinatesTransformMode QSGImageNode::textureCoordinatesTransform() const
Returns the mode used to generate texture coordinates for this node.
*/
@@ -187,6 +187,15 @@ QT_BEGIN_NAMESPACE
\return \c true if the node takes ownership of the texture; otherwise \c false.
*/
+/*!
+ Updates the geometry \a g with the \a texture, the coordinates
+ in \a rect, and the texture coordinates from \a sourceRect.
+
+ \a g is assumed to be a triangle strip of four vertices of type
+ QSGGeometry::TexturedPoint2D.
+
+ \a texCoordMode is used for normalizing the \a sourceRect.
+ */
void QSGImageNode::rebuildGeometry(QSGGeometry *g,
QSGTexture *texture,
const QRectF &rect,
diff --git a/src/quick/scenegraph/util/qsgsimplematerial.h b/src/quick/scenegraph/util/qsgsimplematerial.h
index b5b8815b4a..8a81917bd2 100644
--- a/src/quick/scenegraph/util/qsgsimplematerial.h
+++ b/src/quick/scenegraph/util/qsgsimplematerial.h
@@ -138,7 +138,7 @@ template <typename State>
class QSGSimpleMaterial : public QSGMaterial
{
public:
-#ifndef qdoc
+#ifndef Q_CLANG_QDOC
QSGSimpleMaterial(const State &aState, PtrShaderCreateFunc func)
: m_state(aState)
, m_func(func)
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
index fbc8f27a63..0f9ee9cfde 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial.cpp
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
@@ -304,7 +304,17 @@ void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture)
The default vertical wrap mode is \c QSGTexture::ClampToEdge.
*/
+/*!
+ \fn void QSGOpaqueTextureMaterial::setAnisotropyLevel(QSGTexture::AnisotropyLevel level)
+
+ Sets this material's anistropy level to \a level.
+*/
+
+/*!
+ \fn QSGTexture::AnisotropyLevel QSGOpaqueTextureMaterial::anisotropyLevel() const
+ Returns this material's anistropy level.
+*/
/*!
\internal
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index 6ee5b95dc7..a1513336a5 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -683,13 +683,15 @@ QSize QQuickImageProviderWithOptions::loadSize(const QSize &originalSize, const
return res;
const bool preserveAspectCropOrFit = options.preserveAspectRatioCrop() || options.preserveAspectRatioFit();
- const bool force_scale = (format == "svg" || format == "svgz");
+
+ if (!preserveAspectCropOrFit && (format == "svg" || format == "svgz"))
+ return requestedSize;
qreal ratio = 0.0;
- if (requestedSize.width() && (preserveAspectCropOrFit || force_scale || requestedSize.width() < originalSize.width())) {
+ if (requestedSize.width() && (preserveAspectCropOrFit || requestedSize.width() < originalSize.width())) {
ratio = qreal(requestedSize.width()) / originalSize.width();
}
- if (requestedSize.height() && (preserveAspectCropOrFit || force_scale || requestedSize.height() < originalSize.height())) {
+ if (requestedSize.height() && (preserveAspectCropOrFit || requestedSize.height() < originalSize.height())) {
qreal hr = qreal(requestedSize.height()) / originalSize.height();
if (ratio == 0.0)
ratio = hr;