aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2025-08-22 09:33:17 +0300
committerTarja Sundqvist <tarja.sundqvist@qt.io>2025-08-22 09:33:17 +0300
commitc6fdadd916a7568c1d71b750e054ca9aa2fd5dfc (patch)
treebbd5690b38a5e0df66dd070a9e9f42b0d1b2b673 /src
parenta7c766a9863605eb81e8f0cdb4d2b93e087b5bde (diff)
parente436dad999060b92965291b45c0e95a3b93f5866 (diff)
Merge tag 'v6.2.13-lts' into tqtc/lts-6.2-opensourcev6.2.13-lts-lgpl6.2
Qt 6.2.13-lts release Conflicts solved: dependencies.yaml Change-Id: I3cbe1ce4293179888e236dd1a3a299cd2c66c950
Diffstat (limited to 'src')
-rw-r--r--src/imports/tooling/Enum.qml1
-rw-r--r--src/particles/qquickparticlesystem.cpp5
-rw-r--r--src/particles/qquickparticlesystem_p.h2
-rw-r--r--src/qml/common/qv4compileddata_p.h4
-rw-r--r--src/qml/jsruntime/qv4engine.cpp11
-rw-r--r--src/qml/jsruntime/qv4estable.cpp23
-rw-r--r--src/qml/jsruntime/qv4estable_p.h11
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h44
-rw-r--r--src/qml/memory/qv4heap_p.h2
-rw-r--r--src/qml/qml/qqml.cpp52
-rw-r--r--src/qml/qml/qqmlproperty.cpp16
-rw-r--r--src/qml/qml/qqmltypedata.cpp15
-rw-r--r--src/qml/qml/qqmltypedata_p.h10
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp1
-rw-r--r--src/qmlcompiler/qqmljsmetatypes_p.h14
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader.cpp4
-rw-r--r--src/qmlmodels/qqmllistmodel.cpp26
-rw-r--r--src/qmlmodels/qqmllistmodel_p.h2
-rw-r--r--src/qmlmodels/qqmllistmodel_p_p.h24
-rw-r--r--src/qmltest/doc/src/qtquicktest-index.qdoc70
-rw-r--r--src/qmltyperegistrar/qmltypesclassdescription.cpp24
-rw-r--r--src/qmltyperegistrar/qmltypesclassdescription.h1
-rw-r--r--src/qmltyperegistrar/qmltypescreator.cpp22
-rw-r--r--src/qmltyperegistrar/qmltypescreator.h5
-rw-r--r--src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml74
-rw-r--r--src/quick/doc/snippets/pointerHandlers/draggableGridView.qml168
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp92
-rw-r--r--src/quick/items/qquickgridview.cpp46
-rw-r--r--src/quick/items/qquicklistview.cpp17
-rw-r--r--src/quick/items/qquicktableview.cpp34
-rw-r--r--src/quick/items/qquicktext.cpp4
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp7
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode.cpp7
-rw-r--r--src/quick/util/qquickanimation.cpp5
-rw-r--r--src/quicklayouts/qquicklinearlayout.cpp2
-rw-r--r--src/quicktemplates2/qquickcontrol.cpp14
-rw-r--r--src/quicktemplates2/qquickoverlay.cpp7
-rw-r--r--src/quickwidgets/qquickwidget.cpp17
38 files changed, 732 insertions, 151 deletions
diff --git a/src/imports/tooling/Enum.qml b/src/imports/tooling/Enum.qml
index cd5904b6b6..0d0e90d621 100644
--- a/src/imports/tooling/Enum.qml
+++ b/src/imports/tooling/Enum.qml
@@ -42,5 +42,6 @@ import QML
Member {
property string alias
property bool isFlag: false
+ property bool isScoped: false
property var values: []
}
diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp
index 5744c61849..0bb71d1d70 100644
--- a/src/particles/qquickparticlesystem.cpp
+++ b/src/particles/qquickparticlesystem.cpp
@@ -240,8 +240,7 @@ void QQuickParticleDataHeap::insertTimed(QQuickParticleData* data, int time)
int QQuickParticleDataHeap::top()
{
- if (m_end == 0)
- return 1 << 30;
+ Q_ASSERT(!isEmpty());
return m_data[0].time;
}
@@ -391,7 +390,7 @@ bool QQuickParticleGroupData::recycle()
{
m_latestAliveParticles.clear();
- while (dataHeap.top() <= m_system->timeInt) {
+ while (!dataHeap.isEmpty() && dataHeap.top() <= m_system->timeInt) {
for (QQuickParticleData *datum : dataHeap.pop()) {
if (!datum->stillAlive(m_system)) {
freeList.free(datum->index);
diff --git a/src/particles/qquickparticlesystem_p.h b/src/particles/qquickparticlesystem_p.h
index 0ae2a5f345..ab5cc9cd7f 100644
--- a/src/particles/qquickparticlesystem_p.h
+++ b/src/particles/qquickparticlesystem_p.h
@@ -117,6 +117,8 @@ public:
int top();
+ bool isEmpty() const { return m_end == 0; }
+
QSet<QQuickParticleData*> pop();
void clear();
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index 1452027dcb..3d7fc92a30 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -1334,14 +1334,14 @@ struct TypeReferenceMap : QHash<int, TypeReference>
if (!formal->type.indexIsBuiltinType()) {
TypeReference &r
= this->add(formal->type.typeNameIndexOrBuiltinType(), it->location);
- r.errorWhenNotFound = true;
+ r.errorWhenNotFound = false;
}
}
if (!it->returnType.indexIsBuiltinType()) {
TypeReference &r
= this->add(it->returnType.typeNameIndexOrBuiltinType(), it->location);
- r.errorWhenNotFound = true;
+ r.errorWhenNotFound = false;
}
}
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index b303dd497a..964bb78d3a 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -2497,16 +2497,15 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, QMetaType metaType, voi
return true;
}
- if (metaType == QMetaType::fromType<QQmlListReference>()) {
- if (const QV4::QmlListWrapper *wrapper = value.as<QV4::QmlListWrapper>()) {
+ if (const QV4::QmlListWrapper *wrapper = value.as<QV4::QmlListWrapper>()) {
+ if (metaType == QMetaType::fromType<QQmlListReference>()) {
*reinterpret_cast<QQmlListReference *>(data) = wrapper->toListReference();
return true;
}
- }
- if (metaType == QMetaType::fromType<QQmlListProperty<QObject>>()) {
- if (const QV4::QmlListWrapper *wrapper = value.as<QV4::QmlListWrapper>()) {
- *reinterpret_cast<QQmlListProperty<QObject> *>(data) = wrapper->d()->property();
+ const auto wrapperPrivate = wrapper->d();
+ if (QMetaType(wrapperPrivate->propertyType) == metaType) {
+ *reinterpret_cast<QQmlListProperty<QObject> *>(data) = wrapperPrivate->property();
return true;
}
}
diff --git a/src/qml/jsruntime/qv4estable.cpp b/src/qml/jsruntime/qv4estable.cpp
index 99f6bf6aa0..2e504a70cb 100644
--- a/src/qml/jsruntime/qv4estable.cpp
+++ b/src/qml/jsruntime/qv4estable.cpp
@@ -147,21 +147,18 @@ ReturnedValue ESTable::get(const Value &key, bool *hasValue) const
// Removes the given \a key from the table
bool ESTable::remove(const Value &key)
{
- bool found = false;
- uint idx = 0;
- for (; idx < m_size; ++idx) {
- if (m_keys[idx].sameValueZero(key)) {
- found = true;
- break;
+ for (uint index = 0; index < m_size; ++index) {
+ if (m_keys[index].sameValueZero(key)) {
+ // Remove the element at |index| by moving all elements to the right
+ // of |index| one place to the left.
+ size_t count = (m_size - (index + 1)) * sizeof(Value);
+ memmove(m_keys + index, m_keys + index + 1, count);
+ memmove(m_values + index, m_values + index + 1, count);
+ m_size--;
+ return true;
}
}
-
- if (found == true) {
- memmove(m_keys + idx, m_keys + idx + 1, (m_size - idx)*sizeof(Value));
- memmove(m_values + idx, m_values + idx + 1, (m_size - idx)*sizeof(Value));
- m_size--;
- }
- return found;
+ return false;
}
// Returns the size of the table. Note that the size may not match the underlying allocation.
diff --git a/src/qml/jsruntime/qv4estable_p.h b/src/qml/jsruntime/qv4estable_p.h
index f54fc37a7b..e63dda7a4d 100644
--- a/src/qml/jsruntime/qv4estable_p.h
+++ b/src/qml/jsruntime/qv4estable_p.h
@@ -53,12 +53,13 @@
#include "qv4value_p.h"
+class tst_qv4estable;
+
QT_BEGIN_NAMESPACE
-namespace QV4
-{
+namespace QV4 {
-class ESTable
+class Q_AUTOTEST_EXPORT ESTable
{
public:
ESTable();
@@ -76,13 +77,15 @@ public:
void removeUnmarkedKeys();
private:
+ friend class ::tst_qv4estable;
+
Value *m_keys = nullptr;
Value *m_values = nullptr;
uint m_size = 0;
uint m_capacity = 0;
};
-}
+} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index 248fcdb02f..daa21baf06 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -146,8 +146,8 @@ struct Q_QML_EXPORT SparseArray
{
SparseArray();
~SparseArray() {
- if (root())
- freeTree(header.left, alignof(SparseArrayNode));
+ if (SparseArrayNode *n = root())
+ freeTree(n, alignof(SparseArrayNode));
}
SparseArray(const SparseArray &other);
@@ -323,37 +323,45 @@ inline QList<int> SparseArray::keys() const
inline const SparseArrayNode *SparseArray::lowerBound(uint akey) const
{
- const SparseArrayNode *lb = root()->lowerBound(akey);
- if (!lb)
- lb = end();
- return lb;
+ if (SparseArrayNode *n = root()) {
+ if (const SparseArrayNode *lb = n->lowerBound(akey))
+ return lb;
+ }
+
+ return end();
}
inline SparseArrayNode *SparseArray::lowerBound(uint akey)
{
- SparseArrayNode *lb = root()->lowerBound(akey);
- if (!lb)
- lb = end();
- return lb;
+ if (SparseArrayNode *n = root()) {
+ if (SparseArrayNode *lb = n->lowerBound(akey))
+ return lb;
+ }
+
+ return end();
}
inline const SparseArrayNode *SparseArray::upperBound(uint akey) const
{
- const SparseArrayNode *ub = root()->upperBound(akey);
- if (!ub)
- ub = end();
- return ub;
+ if (SparseArrayNode *n = root()) {
+ if (const SparseArrayNode *ub = n->upperBound(akey))
+ return ub;
+ }
+
+ return end();
}
inline SparseArrayNode *SparseArray::upperBound(uint akey)
{
- SparseArrayNode *ub = root()->upperBound(akey);
- if (!ub)
- ub = end();
- return ub;
+ if (SparseArrayNode *n = root()) {
+ if (SparseArrayNode *ub = n->upperBound(akey))
+ return ub;
+ }
+
+ return end();
}
}
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index 5fb14332ab..8989efe701 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -251,7 +251,7 @@ struct QV4QPointer {
private:
QtSharedPointer::ExternalRefCountData *d;
- QObject *qObject;
+ T *qObject;
};
Q_STATIC_ASSERT(std::is_trivial< QV4QPointer<QObject> >::value);
#endif
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 127fdf7ebb..ec596c0506 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -697,7 +697,13 @@ void qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>(
QQmlEngine *AOTCompiledContext::qmlEngine() const
{
- return qmlContext ? qmlContext->engine() : nullptr;
+ return engine->handle()->qmlEngine();
+}
+
+static QQmlPropertyCapture *propertyCapture(const AOTCompiledContext *aotContext)
+{
+ QQmlEngine *engine = aotContext->qmlEngine();
+ return engine ? QQmlEnginePrivate::get(aotContext->qmlEngine())->propertyCapture : nullptr;
}
QJSValue AOTCompiledContext::jsMetaType(int index) const
@@ -722,31 +728,23 @@ void AOTCompiledContext::setReturnValueUndefined() const
static void captureFallbackProperty(
QObject *object, int coreIndex, int notifyIndex, bool isConstant,
- QQmlContextData *qmlContext)
+ const AOTCompiledContext *aotContext)
{
- if (!qmlContext || isConstant)
+ if (isConstant)
return;
- QQmlEngine *engine = qmlContext->engine();
- Q_ASSERT(engine);
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- Q_ASSERT(ep);
- if (QQmlPropertyCapture *capture = ep->propertyCapture)
+ if (QQmlPropertyCapture *capture = propertyCapture(aotContext))
capture->captureProperty(object, coreIndex, notifyIndex);
}
static void captureObjectProperty(
QObject *object, const QQmlPropertyCache *propertyCache,
- const QQmlPropertyData *property, QQmlContextData *qmlContext)
+ const QQmlPropertyData *property, const AOTCompiledContext *aotContext)
{
- if (!qmlContext || property->isConstant())
+ if (property->isConstant())
return;
- QQmlEngine *engine = qmlContext->engine();
- Q_ASSERT(engine);
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- Q_ASSERT(ep);
- if (QQmlPropertyCapture *capture = ep->propertyCapture)
+ if (QQmlPropertyCapture *capture = propertyCapture(aotContext))
capture->captureProperty(object, propertyCache, property);
}
@@ -762,7 +760,7 @@ static bool inherits(const QQmlPropertyCache *descendent, const QQmlPropertyCach
enum class ObjectPropertyResult { OK, NeedsInit, Deleted };
static ObjectPropertyResult loadObjectProperty(
- QV4::Lookup *l, QObject *object, void *target, QQmlContextData *qmlContext)
+ QV4::Lookup *l, QObject *object, void *target, const AOTCompiledContext *aotContext)
{
QQmlData *qmlData = QQmlData::get(object);
if (!qmlData)
@@ -779,13 +777,13 @@ static ObjectPropertyResult loadObjectProperty(
if (qmlData->hasPendingBindingBit(coreIndex))
qmlData->flushPendingBinding(coreIndex);
- captureObjectProperty(object, propertyCache, property, qmlContext);
+ captureObjectProperty(object, propertyCache, property, aotContext);
property->readProperty(object, target);
return ObjectPropertyResult::OK;
}
static ObjectPropertyResult loadFallbackProperty(
- QV4::Lookup *l, QObject *object, void *target, QQmlContextData *qmlContext)
+ QV4::Lookup *l, QObject *object, void *target, const AOTCompiledContext *aotContext)
{
QQmlData *qmlData = QQmlData::get(object);
if (qmlData && qmlData->isQueuedForDeletion)
@@ -803,7 +801,7 @@ static ObjectPropertyResult loadFallbackProperty(
qmlData->flushPendingBinding(coreIndex);
captureFallbackProperty(object, coreIndex, l->qobjectFallbackLookup.notifyIndex,
- l->qobjectFallbackLookup.isConstant, qmlContext);
+ l->qobjectFallbackLookup.isConstant, aotContext);
void *a[] = { target, nullptr };
metaObject->metacall(object, QMetaObject::ReadProperty, coreIndex, a);
@@ -984,7 +982,7 @@ bool AOTCompiledContext::captureLookup(uint index, QObject *object) const
|| l->getter == QV4::Lookup::getterQObject) {
const QQmlPropertyData *property = l->qobjectLookup.propertyData;
QQmlData::flushPendingBinding(object, property->coreIndex());
- captureObjectProperty(object, l->qobjectLookup.propertyCache, property, qmlContext);
+ captureObjectProperty(object, l->qobjectLookup.propertyCache, property, this);
return true;
}
@@ -993,7 +991,7 @@ bool AOTCompiledContext::captureLookup(uint index, QObject *object) const
QQmlData::flushPendingBinding(object, coreIndex);
captureFallbackProperty(
object, coreIndex, l->qobjectFallbackLookup.notifyIndex,
- l->qobjectFallbackLookup.isConstant, qmlContext);
+ l->qobjectFallbackLookup.isConstant, this);
return true;
}
@@ -1007,7 +1005,7 @@ bool AOTCompiledContext::captureQmlContextPropertyLookup(uint index) const
&& l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupContextObjectProperty) {
const QQmlPropertyData *property = l->qobjectLookup.propertyData;
QQmlData::flushPendingBinding(qmlScopeObject, property->coreIndex());
- captureObjectProperty(qmlScopeObject, l->qobjectLookup.propertyCache, property, qmlContext);
+ captureObjectProperty(qmlScopeObject, l->qobjectLookup.propertyCache, property, this);
return true;
}
@@ -1015,7 +1013,7 @@ bool AOTCompiledContext::captureQmlContextPropertyLookup(uint index) const
const int coreIndex = l->qobjectFallbackLookup.coreIndex;
QQmlData::flushPendingBinding(qmlScopeObject, coreIndex);
captureFallbackProperty(qmlScopeObject, coreIndex, l->qobjectFallbackLookup.notifyIndex,
- l->qobjectFallbackLookup.isConstant, qmlContext);
+ l->qobjectFallbackLookup.isConstant, this);
return true;
}
@@ -1267,9 +1265,9 @@ bool AOTCompiledContext::loadScopeObjectPropertyLookup(uint index, void *target)
ObjectPropertyResult result = ObjectPropertyResult::NeedsInit;
if (l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupScopeObjectProperty)
- result = loadObjectProperty(l, qmlScopeObject, target, qmlContext);
+ result = loadObjectProperty(l, qmlScopeObject, target, this);
else if (l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupScopeFallbackProperty)
- result = loadFallbackProperty(l, qmlScopeObject, target, qmlContext);
+ result = loadFallbackProperty(l, qmlScopeObject, target, this);
else
return false;
@@ -1405,9 +1403,9 @@ bool AOTCompiledContext::getObjectLookup(uint index, QObject *object, void *targ
ObjectPropertyResult result = ObjectPropertyResult::NeedsInit;
if (l->getter == QV4::Lookup::getterQObject)
- result = loadObjectProperty(l, object, target, qmlContext);
+ result = loadObjectProperty(l, object, target, this);
else if (l->getter == QV4::Lookup::getterFallback)
- result = loadFallbackProperty(l, object, target, qmlContext);
+ result = loadFallbackProperty(l, object, target, this);
else
return false;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 372103b94f..d4a6ba1dd3 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -812,17 +812,21 @@ static void removeOldBinding(QObject *object, QQmlPropertyIndex index, QQmlPrope
oldBinding = data->bindings;
while (oldBinding && (oldBinding->targetPropertyIndex().coreIndex() != coreIndex ||
- oldBinding->targetPropertyIndex().hasValueTypeIndex()))
+ oldBinding->targetPropertyIndex().hasValueTypeIndex())) {
oldBinding = oldBinding->nextBinding();
+ }
- if (!oldBinding)
- return;
-
- if (valueTypeIndex != -1 && oldBinding->isValueTypeProxy())
+ if (valueTypeIndex != -1
+ && oldBinding
+ && oldBinding->isValueTypeProxy()) {
oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
+ }
- if (!oldBinding)
+ if (!oldBinding) {
+ // Clear the binding bit so that the binding doesn't appear later for any reason
+ data->clearBindingBit(coreIndex);
return;
+ }
if (!(flags & QQmlPropertyPrivate::DontEnable))
oldBinding->setEnabled(false, {});
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index a244bdd0ba..2d2f37261c 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -345,7 +345,9 @@ void QQmlTypeData::done()
++it) {
const TypeReference &type = *it;
Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError() || type.type.isInlineComponentType());
- if (type.type.isInlineComponentType() && !type.type.pendingResolutionName().isEmpty()) {
+ if (type.errorWhenNotFound
+ && type.type.isInlineComponentType()
+ && !type.type.pendingResolutionName().isEmpty()) {
auto containingType = type.type.containingType();
auto objectId = containingType.lookupInlineComponentIdByName(type.type.pendingResolutionName());
if (objectId < 0) { // can be any negative number if we tentatively resolved it in QQmlImport but it actually was not an inline component
@@ -365,7 +367,7 @@ void QQmlTypeData::done()
type.type.setInlineComponentObjectId(objectId);
}
}
- if (type.typeData && type.typeData->isError()) {
+ if (type.errorWhenNotFound && type.typeData && type.typeData->isError()) {
const QString typeName = stringAt(it.key());
QList<QQmlError> errors = type.typeData->errors();
@@ -887,6 +889,7 @@ void QQmlTypeData::resolveTypes()
ref.version = version;
ref.location = unresolvedRef->location;
ref.needsCreation = unresolvedRef->needsCreation;
+ ref.errorWhenNotFound = unresolvedRef->errorWhenNotFound;
m_resolvedTypes.insert(unresolvedRef.key(), ref);
}
@@ -930,8 +933,12 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
} else {
objectId = resolvedType->type.inlineComponentId();
}
- Q_ASSERT(objectId != -1);
- ref->setTypePropertyCache(resolvedType->typeData->compilationUnit()->propertyCaches.at(objectId));
+
+ if (objectId >= 0) {
+ ref->setTypePropertyCache(
+ resolvedType->typeData->compilationUnit()->propertyCaches.at(objectId));
+ }
+
ref->setType(qmlType);
Q_ASSERT(ref->type().isInlineComponentType());
}
diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h
index 2c56ede9bd..e55e5ebae6 100644
--- a/src/qml/qml/qqmltypedata_p.h
+++ b/src/qml/qml/qqmltypedata_p.h
@@ -62,16 +62,16 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
public:
struct TypeReference
{
- TypeReference() : version(QTypeRevision::zero()), needsCreation(true) {}
-
QV4::CompiledData::Location location;
QQmlType type;
- QTypeRevision version;
+ QTypeRevision version = QTypeRevision::zero();
QQmlRefPointer<QQmlTypeData> typeData;
- bool selfReference = false;
QString prefix; // used by CompositeSingleton types
+ bool selfReference = false;
+ bool needsCreation = true;
+ bool errorWhenNotFound = true;
+
QString qualifiedName() const;
- bool needsCreation;
};
struct ScriptReference
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index 733cb3b2c0..827d2c2cf5 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -1340,6 +1340,7 @@ void QQmlJSImportVisitor::endVisit(UiArrayBinding *)
bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiEnumDeclaration *uied)
{
QQmlJSMetaEnum qmlEnum(uied->name.toString());
+ qmlEnum.setIsQml(true);
for (const auto *member = uied->members; member; member = member->next) {
qmlEnum.addKey(member->member.toString());
qmlEnum.addValue(int(member->value));
diff --git a/src/qmlcompiler/qqmljsmetatypes_p.h b/src/qmlcompiler/qqmljsmetatypes_p.h
index 513414d87f..c0b3144819 100644
--- a/src/qmlcompiler/qqmljsmetatypes_p.h
+++ b/src/qmlcompiler/qqmljsmetatypes_p.h
@@ -66,6 +66,8 @@ class QQmlJSMetaEnum
QString m_alias;
QSharedPointer<const QQmlJSScope> m_type;
bool m_isFlag = false;
+ bool m_isScoped = false;
+ bool m_isQml = false;
public:
QQmlJSMetaEnum() = default;
@@ -82,6 +84,12 @@ public:
bool isFlag() const { return m_isFlag; }
void setIsFlag(bool isFlag) { m_isFlag = isFlag; }
+ bool isScoped() const { return m_isScoped; }
+ void setIsScoped(bool v) { m_isScoped = v; }
+
+ bool isQml() const { return m_isQml; }
+ void setIsQml(bool v) { m_isQml = v; }
+
void addKey(const QString &key) { m_keys.append(key); }
QStringList keys() const { return m_keys; }
@@ -102,7 +110,8 @@ public:
&& a.m_name == b.m_name
&& a.m_alias == b.m_alias
&& a.m_isFlag == b.m_isFlag
- && a.m_type == b.m_type;
+ && a.m_type == b.m_type
+ && a.m_isScoped == b.m_isScoped;
}
friend bool operator!=(const QQmlJSMetaEnum &a, const QQmlJSMetaEnum &b)
@@ -112,7 +121,8 @@ public:
friend size_t qHash(const QQmlJSMetaEnum &e, size_t seed = 0)
{
- return qHashMulti(seed, e.m_keys, e.m_values, e.m_name, e.m_alias, e.m_isFlag, e.m_type);
+ return qHashMulti(
+ seed, e.m_keys, e.m_values, e.m_name, e.m_alias, e.m_isFlag, e.m_type, e.m_isScoped);
}
};
diff --git a/src/qmlcompiler/qqmljstypedescriptionreader.cpp b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
index 04293fd14c..779e040a2d 100644
--- a/src/qmlcompiler/qqmljstypedescriptionreader.cpp
+++ b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
@@ -418,9 +418,11 @@ void QQmlJSTypeDescriptionReader::readEnum(UiObjectDefinition *ast, const QQmlJS
metaEnum.setIsFlag(readBoolBinding(script));
} else if (name == QLatin1String("values")) {
readEnumValues(script, &metaEnum);
+ } else if (name == QLatin1String("isScoped")) {
+ metaEnum.setIsScoped(readBoolBinding(script));
} else {
addWarning(script->firstSourceLocation(),
- tr("Expected only name and values script bindings."));
+ tr("Expected only name, alias, isFlag, values, or isScoped."));
}
}
diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp
index c060aaec97..1663471ab5 100644
--- a/src/qmlmodels/qqmllistmodel.cpp
+++ b/src/qmlmodels/qqmllistmodel.cpp
@@ -1699,9 +1699,12 @@ bool ModelObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Val
ExecutionEngine *eng = that->engine();
const int elementIndex = that->d()->elementIndex();
- int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName, value, eng);
- if (roleIndex != -1)
- that->d()->m_model->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
+ if (QQmlListModel *model = that->d()->m_model) {
+ const int roleIndex
+ = model->listModel()->setExistingProperty(elementIndex, propName, value, eng);
+ if (roleIndex != -1)
+ model->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
+ }
ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
if (mo->initialized())
@@ -1717,7 +1720,11 @@ ReturnedValue ModelObject::virtualGet(const Managed *m, PropertyKey id, const Va
const ModelObject *that = static_cast<const ModelObject*>(m);
Scope scope(that);
ScopedString name(scope, id.asStringOrSymbol());
- const ListLayout::Role *role = that->d()->m_model->m_listModel->getExistingRole(name);
+ QQmlListModel *model = that->d()->m_model;
+ if (!model)
+ return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
+
+ const ListLayout::Role *role = model->listModel()->getExistingRole(name);
if (!role)
return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
if (hasProperty)
@@ -1730,7 +1737,7 @@ ReturnedValue ModelObject::virtualGet(const Managed *m, PropertyKey id, const Va
}
const int elementIndex = that->d()->elementIndex();
- QVariant value = that->d()->m_model->data(elementIndex, role->index);
+ QVariant value = model->data(elementIndex, role->index);
return that->engine()->fromVariant(value);
}
@@ -1753,16 +1760,19 @@ PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *p
const ModelObject *that = static_cast<const ModelObject *>(o);
ExecutionEngine *v4 = that->engine();
- if (roleNameIndex < that->listModel()->roleCount()) {
+
+ QQmlListModel *model = that->d()->m_model;
+ ListModel *listModel = model ? model->listModel() : nullptr;
+ if (listModel && roleNameIndex < listModel->roleCount()) {
Scope scope(that->engine());
- const ListLayout::Role &role = that->listModel()->getExistingRole(roleNameIndex);
+ const ListLayout::Role &role = listModel->getExistingRole(roleNameIndex);
++roleNameIndex;
ScopedString roleName(scope, v4->newString(role.name));
if (attrs)
*attrs = QV4::Attr_Data;
if (pd) {
- QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index);
+ QVariant value = model->data(that->d()->elementIndex(), role.index);
if (auto recursiveListModel = qvariant_cast<QQmlListModel*>(value)) {
auto size = recursiveListModel->count();
auto array = ScopedArrayObject{scope, v4->newArrayObject(size)};
diff --git a/src/qmlmodels/qqmllistmodel_p.h b/src/qmlmodels/qqmllistmodel_p.h
index 7cd2b4662b..3ebdf209a4 100644
--- a/src/qmlmodels/qqmllistmodel_p.h
+++ b/src/qmlmodels/qqmllistmodel_p.h
@@ -115,6 +115,8 @@ public:
bool dynamicRoles() const { return m_dynamicRoles; }
void setDynamicRoles(bool enableDynamicRoles);
+ ListModel *listModel() const { return m_listModel; }
+
Q_SIGNALS:
void countChanged();
diff --git a/src/qmlmodels/qqmllistmodel_p_p.h b/src/qmlmodels/qqmllistmodel_p_p.h
index 19cba980f4..da04b0a5f5 100644
--- a/src/qmlmodels/qqmllistmodel_p_p.h
+++ b/src/qmlmodels/qqmllistmodel_p_p.h
@@ -161,13 +161,23 @@ struct ModelObject : public QObjectWrapper {
{
QObjectWrapper::init(object);
m_model = model;
- QObjectPrivate *op = QObjectPrivate::get(object);
- m_nodeModelMetaObject = static_cast<ModelNodeMetaObject *>(op->metaObject);
}
- void destroy() { QObjectWrapper::destroy(); }
- int elementIndex() const { return m_nodeModelMetaObject->m_elementIndex; }
- QQmlListModel *m_model;
- ModelNodeMetaObject *m_nodeModelMetaObject;
+
+ void destroy()
+ {
+ m_model.destroy();
+ QObjectWrapper::destroy();
+ }
+
+ int elementIndex() const {
+ if (const QObject *o = object()) {
+ const QObjectPrivate *op = QObjectPrivate::get(o);
+ return static_cast<ModelNodeMetaObject *>(op->metaObject)->m_elementIndex;
+ }
+ return -1;
+ }
+
+ QV4QPointer<QQmlListModel> m_model;
};
}
@@ -177,8 +187,6 @@ struct ModelObject : public QObjectWrapper
V4_OBJECT2(ModelObject, QObjectWrapper)
V4_NEEDS_DESTROY
- ListModel *listModel() const { return d()->m_model->m_listModel; }
-
protected:
static bool virtualPut(Managed *m, PropertyKey id, const Value& value, Value *receiver);
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc
index 5a3fdfeef4..48cfdf205f 100644
--- a/src/qmltest/doc/src/qtquicktest-index.qdoc
+++ b/src/qmltest/doc/src/qtquicktest-index.qdoc
@@ -118,15 +118,67 @@
\snippet src_qmltest_qquicktest_snippet.cpp 1
Where "example" is the identifier to use to uniquely identify
- this set of tests. Finally, add \c{CONFIG += qmltestcase} to the project
- file:
+ this set of tests.
+
+ \if defined(onlinedocs)
+ \tab {run-qtquicktest}{tab-cmake}{CMake}{checked}
+ \tab {run-qtquicktest}{tab-qmake}{qmake}{}
+ \tabcontent {tab-cmake}
+ \else
+ \section1 Using CMake
+ \endif
+ Configure your CMakeLists.txt file and build your project using your
+ favorite generator.
+ \badcode
+ cmake_minimum_required(VERSION 3.2)
+
+ project(tst_example LANGUAGES CXX)
+
+ enable_testing()
+
+ find_package(Qt6 REQUIRED COMPONENTS QuickTest Qml)
+
+ #[[The test harness scans the specified source directory recursively
+ for "tst_*.qml" files. By default, it looks in the current directory,
+ which is usually where the executable is. This command makes it look
+ in the project's source directory instead.]]
+ add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
+
+ qt_standard_project_setup(REQUIRES 6.6)
+
+ add_executable(tst_example tst_example.cpp)
+
+ add_test(NAME tst_example COMMAND tst_example)
+
+ target_link_libraries(tst_example
+ PRIVATE
+ Qt6::QuickTest
+ Qt6::Qml
+ )
+ \endcode
+ \if defined(onlinedocs)
+ \endtabcontent
+ \tabcontent {tab-qmake}
+ \else
+ \section1 Using qmake
+ \endif
+ Add \c{CONFIG += qmltestcase} to your project file:
+ \badcode
+ TEMPLATE = app
+ TARGET = tst_example
+ CONFIG += warn_on qmltestcase
+ SOURCES += tst_example.cpp
+ \endcode
+
+ If \c IMPORTPATH is specified in your .pro file, each import path added to \c IMPORTPATH
+ will be passed as a command-line argument when the test is run using "make check":
\badcode
- TEMPLATE = app
- TARGET = tst_example
- CONFIG += warn_on qmltestcase
- SOURCES += tst_example.cpp
+ IMPORTPATH += $$PWD/../imports/my_module1 $$PWD/../imports/my_module2
\endcode
+ \if defined(onlinedocs)
+ \endtabcontent
+ \endif
The test harness scans the specified source directory recursively
for "tst_*.qml" files. If \c{QUICK_TEST_SOURCE_DIR} is not defined,
@@ -160,12 +212,6 @@
If your test case needs QML imports, then you can add them as
\c{-import} options to the test program command-line.
- If \c IMPORTPATH is specified in your .pro file, each import path added to \c IMPORTPATH
- will be passed as a command-line argument when the test is run using "make check":
-
- \badcode
- IMPORTPATH += $$PWD/../imports/my_module1 $$PWD/../imports/my_module2
- \endcode
The \c{-functions} command-line option will return a list of the current
tests functions. It is possible to run a single test function using the name
diff --git a/src/qmltyperegistrar/qmltypesclassdescription.cpp b/src/qmltyperegistrar/qmltypesclassdescription.cpp
index b58d4ac00a..ec58998ee7 100644
--- a/src/qmltyperegistrar/qmltypesclassdescription.cpp
+++ b/src/qmltyperegistrar/qmltypesclassdescription.cpp
@@ -112,10 +112,16 @@ void QmlTypesClassDescription::collectLocalAnonymous(
const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray();
for (const QJsonValue classInfo : classInfos) {
const QJsonObject obj = classInfo.toObject();
- if (obj[QStringLiteral("name")].toString() == QStringLiteral("DefaultProperty"))
- defaultProp = obj[QStringLiteral("value")].toString();
- if (obj[QStringLiteral("name")].toString() == QStringLiteral("ParentProperty"))
- parentProp = obj[QStringLiteral("value")].toString();
+ const QString name = obj[QStringLiteral("name")].toString();
+ const auto value = [&]() { return obj[QStringLiteral("value")].toString(); };
+ if (name == QStringLiteral("DefaultProperty")) {
+ defaultProp = value();
+ } else if (name == QStringLiteral("ParentProperty")) {
+ parentProp = value();
+ } else if (name == QStringLiteral("RegisterEnumClassesUnscoped")
+ && value() == QStringLiteral("false")) {
+ registerEnumClassesScoped = true;
+ }
}
collectInterfaces(classDef);
@@ -143,6 +149,9 @@ void QmlTypesClassDescription::collect(
} else if (name == QLatin1String("ParentProperty")) {
if (mode != RelatedType && parentProp.isEmpty())
parentProp = value;
+ } else if (name == QLatin1String("RegisterEnumClassesUnscoped")) {
+ if (mode != RelatedType && value == QLatin1String("false"))
+ registerEnumClassesScoped = true;
} else if (name == QLatin1String("QML.AddedInVersion")) {
const QTypeRevision revision = QTypeRevision::fromEncodedVersion(value.toInt());
if (mode == TopLevel) {
@@ -192,10 +201,12 @@ void QmlTypesClassDescription::collect(
if (const QJsonObject *other = findType(foreign, foreignTypeName)) {
classDef = other;
- // Default properties are always local.
+ // Default properties and enum classes are always local.
defaultProp.clear();
+ registerEnumClassesScoped = false;
// Foreign type can have a default property or an attached types
+ // or RegisterEnumClassesUnscoped classinfo.
const auto classInfos = classDef->value(QLatin1String("classInfos")).toArray();
for (const QJsonValue classInfo : classInfos) {
const QJsonObject obj = classInfo.toObject();
@@ -205,6 +216,9 @@ void QmlTypesClassDescription::collect(
defaultProp = foreignValue;
} else if (parentProp.isEmpty() && foreignName == QLatin1String("ParentProperty")) {
parentProp = foreignValue;
+ } else if (foreignName == QLatin1String("RegisterEnumClassesUnscoped")) {
+ if (foreignValue == QLatin1String("false"))
+ registerEnumClassesScoped = true;
} else if (foreignName == QLatin1String("QML.Attached")) {
attachedType = foreignValue;
collectRelated(foreignValue, types, foreign, defaultRevision);
diff --git a/src/qmltyperegistrar/qmltypesclassdescription.h b/src/qmltyperegistrar/qmltypesclassdescription.h
index 1e043fb925..ecc5eb1ebf 100644
--- a/src/qmltyperegistrar/qmltypesclassdescription.h
+++ b/src/qmltyperegistrar/qmltypesclassdescription.h
@@ -55,6 +55,7 @@ struct QmlTypesClassDescription
bool isSingleton = false;
bool isRootClass = false;
bool hasCustomParser = false;
+ bool registerEnumClassesScoped = false;
QStringList implementsInterfaces;
enum CollectMode {
diff --git a/src/qmltyperegistrar/qmltypescreator.cpp b/src/qmltyperegistrar/qmltypescreator.cpp
index 15740579c0..dbc9721a37 100644
--- a/src/qmltyperegistrar/qmltypescreator.cpp
+++ b/src/qmltyperegistrar/qmltypescreator.cpp
@@ -244,7 +244,8 @@ void QmlTypesCreator::writeMethods(const QJsonArray &methods, const QString &typ
}
}
-void QmlTypesCreator::writeEnums(const QJsonArray &enums)
+void QmlTypesCreator::writeEnums(
+ const QJsonArray &enums, QmlTypesCreator::EnumClassesMode enumClassesMode)
{
for (const QJsonValue item : enums) {
const QJsonObject obj = item.toObject();
@@ -263,6 +264,13 @@ void QmlTypesCreator::writeEnums(const QJsonArray &enums)
auto isFlag = obj.find(QLatin1String("isFlag"));
if (isFlag != obj.end() && isFlag->toBool())
m_qml.writeBooleanBinding(isFlag.key(), true);
+
+ if (enumClassesMode == EnumClassesMode::Scoped) {
+ const auto isClass = obj.find(QLatin1String("isClass"));
+ if (isClass != obj.end() && isClass->toBool())
+ m_qml.writeBooleanBinding(QLatin1String("isScoped"), true);
+ }
+
m_qml.writeArrayBinding(QLatin1String("values"), valueList);
m_qml.writeEndObject();
}
@@ -382,7 +390,11 @@ void QmlTypesCreator::writeComponents()
writeClassProperties(collector);
if (const QJsonObject *classDef = collector.resolvedClass) {
- writeEnums(members(classDef, enumsKey, m_version));
+ writeEnums(
+ members(classDef, enumsKey, m_version),
+ collector.registerEnumClassesScoped
+ ? EnumClassesMode::Scoped
+ : EnumClassesMode::Unscoped);
writeProperties(members(classDef, propertiesKey, m_version));
@@ -411,7 +423,11 @@ void QmlTypesCreator::writeComponents()
collector.collectLocalAnonymous(&component, m_ownTypes, m_foreignTypes, m_version);
writeClassProperties(collector);
- writeEnums(members(&component, enumsKey, m_version));
+ writeEnums(
+ members(&component, enumsKey, m_version),
+ collector.registerEnumClassesScoped
+ ? EnumClassesMode::Scoped
+ : EnumClassesMode::Unscoped);
writeProperties(members(&component, propertiesKey, m_version));
diff --git a/src/qmltyperegistrar/qmltypescreator.h b/src/qmltyperegistrar/qmltypescreator.h
index 3e8fa480a2..aff41485cc 100644
--- a/src/qmltyperegistrar/qmltypescreator.h
+++ b/src/qmltyperegistrar/qmltypescreator.h
@@ -53,7 +53,10 @@ private:
void writeType(const QJsonObject &property, const QString &key);
void writeProperties(const QJsonArray &properties);
void writeMethods(const QJsonArray &methods, const QString &type);
- void writeEnums(const QJsonArray &enums);
+
+ enum class EnumClassesMode { Scoped, Unscoped };
+ void writeEnums(const QJsonArray &enums, EnumClassesMode enumClassesMode);
+
void writeComponents();
QByteArray m_output;
diff --git a/src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml b/src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml
new file mode 100644
index 0000000000..20a3a802cf
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/dragHandlerMargin.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick
+
+//! [entire]
+Item {
+ width: 320
+ height: 240
+ //![draggable]
+ Rectangle {
+ width: 24
+ height: 24
+ border.color: "steelblue"
+ Text {
+ text: "it's\ntiny"
+ font.pixelSize: 7
+ rotation: -45
+ anchors.centerIn: parent
+ }
+
+ DragHandler {
+ margin: 12
+ }
+ }
+ //![draggable]
+}
+//! [entire]
diff --git a/src/quick/doc/snippets/pointerHandlers/draggableGridView.qml b/src/quick/doc/snippets/pointerHandlers/draggableGridView.qml
new file mode 100644
index 0000000000..0b19274e0d
--- /dev/null
+++ b/src/quick/doc/snippets/pointerHandlers/draggableGridView.qml
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2024 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+pragma ComponentBehavior: Bound
+import QtQml
+import QtQuick
+import QtQml.Models
+
+//! [entire]
+GridView {
+ id: root
+ width: 320
+ height: 480
+ cellWidth: 80
+ cellHeight: 80
+ interactive: false
+
+ displaced: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ easing.type: Easing.OutQuad
+ }
+ }
+
+ model: DelegateModel {
+ id: visualModel
+ model: 24
+ property var dropTarget: undefined
+ property bool copy: false
+ delegate: DropArea {
+ id: delegateRoot
+
+ width: 80
+ height: 80
+
+ onEntered: drag => {
+ if (visualModel.copy) {
+ if (drag.source !== icon)
+ visualModel.dropTarget = icon
+ } else {
+ visualModel.items.move(drag.source.DelegateModel.itemsIndex, icon.DelegateModel.itemsIndex)
+ }
+ }
+
+ Rectangle {
+ id: icon
+ objectName: DelegateModel.itemsIndex
+
+ property string text
+ Component.onCompleted: {
+ color = Qt.rgba(0.2 + (48 - DelegateModel.itemsIndex) * Math.random() / 48,
+ 0.3 + DelegateModel.itemsIndex * Math.random() / 48,
+ 0.4 * Math.random(),
+ 1.0)
+ text = DelegateModel.itemsIndex
+ }
+ border.color: visualModel.dropTarget === this ? "black" : "transparent"
+ border.width: 2
+ radius: 3
+ width: 72
+ height: 72
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+
+ states: [
+ State {
+ when: dragHandler.active || controlDragHandler.active
+ ParentChange {
+ target: icon
+ parent: root
+ }
+
+ AnchorChanges {
+ target: icon
+ anchors {
+ horizontalCenter: undefined
+ verticalCenter: undefined
+ }
+ }
+ }
+ ]
+
+ Text {
+ anchors.centerIn: parent
+ color: "white"
+ font.pointSize: 14
+ text: controlDragHandler.active ? "+" : icon.text
+ }
+
+ //! [draghandlers]
+ DragHandler {
+ id: dragHandler
+ acceptedModifiers: Qt.NoModifier
+ onActiveChanged: if (!active) visualModel.dropTarget = undefined
+ }
+
+ DragHandler {
+ id: controlDragHandler
+ acceptedModifiers: Qt.ControlModifier
+ onActiveChanged: {
+ visualModel.copy = active
+ if (!active) {
+ visualModel.dropTarget.text = icon.text
+ visualModel.dropTarget.color = icon.color
+ visualModel.dropTarget = undefined
+ }
+ }
+ }
+ //! [draghandlers]
+
+ Drag.active: dragHandler.active || controlDragHandler.active
+ Drag.source: icon
+ Drag.hotSpot.x: 36
+ Drag.hotSpot.y: 36
+ }
+ }
+ }
+}
+//! [entire]
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 8c9464ee55..c3f57f9b02 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -86,7 +86,8 @@ Q_LOGGING_CATEGORY(lcDragHandler, "qt.quick.handler.drag")
\c target is an Item, \c centroid is the point at which the drag begins and
to which the \c target will be moved (subject to constraints).
- At this time, drag-and-drop is not yet supported.
+ DragHandler can be used together with the \l Drag attached property to
+ implement drag-and-drop.
\sa Drag, MouseArea, {Pointer Handlers Example}
*/
@@ -134,7 +135,7 @@ void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDe
The snap mode configures snapping of the \l target item's center to the \l eventPoint.
Possible values:
- \value DragHandler.SnapNever Never snap
+ \value DragHandler.NoSnap Never snap
\value DragHandler.SnapAuto The \l target snaps if the \l eventPoint was pressed outside of the \l target
item \e and the \l target is a descendant of \l {PointerHandler::}{parent} item (default)
\value DragHandler.SnapWhenPressedOutsideTarget The \l target snaps if the \l eventPoint was pressed outside of the \l target
@@ -394,6 +395,93 @@ void QQuickDragHandler::setActiveTranslation(const QVector2D &trans)
\c {0, 0} again.
*/
+/*!
+ \qmlproperty flags QtQuick::DragHandler::acceptedButtons
+
+ The mouse buttons that can activate this DragHandler.
+
+ By default, this property is set to
+ \l {QtQuick::MouseEvent::button} {Qt.LeftButton}.
+ It can be set to an OR combination of mouse buttons, and will ignore events
+ from other buttons.
+
+ For example, if a component (such as TextEdit) already handles
+ left-button drags in its own way, it can be augmented with a
+ DragHandler that does something different when dragged via the
+ right button:
+
+ \snippet pointerHandlers/dragHandlerAcceptedButtons.qml 0
+*/
+
+/*!
+ \qmlproperty flags DragHandler::acceptedDevices
+
+ The types of pointing devices that can activate this DragHandler.
+
+ By default, this property is set to
+ \l{QInputDevice::DeviceType}{PointerDevice.AllDevices}.
+ If you set it to an OR combination of device types, it will ignore events
+ from non-matching devices.
+
+ \note Not all platforms are yet able to distinguish mouse and touchpad; and
+ on those that do, you often want to make mouse and touchpad behavior the same.
+*/
+
+/*!
+ \qmlproperty flags DragHandler::acceptedModifiers
+
+ If this property is set, it will require the given keyboard modifiers to
+ be pressed in order to react to pointer events, and otherwise ignore them.
+
+ For example, two DragHandlers can perform two different drag-and-drop
+ operations, depending on whether the \c Control modifier is pressed:
+
+ \snippet pointerHandlers/draggableGridView.qml entire
+
+ If this property is set to \c Qt.KeyboardModifierMask (the default value),
+ then the DragHandler ignores the modifier keys.
+
+ If you set \c acceptedModifiers to an OR combination of modifier keys,
+ it means \e all of those modifiers must be pressed to activate the handler.
+
+ The available modifiers are as follows:
+
+ \value NoModifier No modifier key is allowed.
+ \value ShiftModifier A Shift key on the keyboard must be pressed.
+ \value ControlModifier A Ctrl key on the keyboard must be pressed.
+ \value AltModifier An Alt key on the keyboard must be pressed.
+ \value MetaModifier A Meta key on the keyboard must be pressed.
+ \value KeypadModifier A keypad button must be pressed.
+ \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument).
+ A Mode_switch key on the keyboard must be pressed.
+ \value KeyboardModifierMask The handler does not care which modifiers are pressed.
+
+ \sa Qt::KeyboardModifier
+*/
+
+/*!
+ \qmlproperty flags DragHandler::acceptedPointerTypes
+
+ The types of pointing instruments (finger, stylus, eraser, etc.)
+ that can activate this DragHandler.
+
+ By default, this property is set to
+ \l {QPointingDevice::PointerType} {PointerDevice.AllPointerTypes}.
+ If you set it to an OR combination of device types, it will ignore events
+ from non-matching \l {PointerDevice}{devices}.
+*/
+
+/*!
+ \qmlproperty real DragHandler::margin
+
+ The margin beyond the bounds of the \l {PointerHandler::parent}{parent}
+ item within which an \l eventPoint can activate this handler. For example,
+ you can make it easier to drag small items by allowing the user to drag
+ from a position nearby:
+
+ \snippet pointerHandlers/dragHandlerMargin.qml draggable
+*/
+
QT_END_NAMESPACE
#include "moc_qquickdraghandler_p.cpp"
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 916ae61cf5..27438bda14 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -1404,9 +1404,53 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
/*!
\qmlproperty int QtQuick::GridView::count
- This property holds the number of items in the view.
+ This property holds the number of items in the model.
*/
+/*!
+ \qmlproperty bool QtQuick::GridView::reuseItems
+
+ This property enables you to reuse items that are instantiated
+ from the \l delegate. If set to \c false, any currently
+ pooled items are destroyed.
+
+ This property is \c false by default.
+
+ \since 5.15
+
+ \sa {Reusing items}, pooled(), reused()
+*/
+
+/*!
+ \qmlattachedsignal QtQuick::GridView::pooled()
+
+ This signal is emitted after an item has been added to the reuse
+ pool. You can use it to pause ongoing timers or animations inside
+ the item, or free up resources that cannot be reused.
+
+ This signal is emitted only if the \l reuseItems property is \c true.
+
+ \sa {Reusing items}, reuseItems, reused()
+*/
+
+/*!
+ \qmlattachedsignal QtQuick::GridView::reused()
+
+ This signal is emitted after an item has been reused. At this point, the
+ item has been taken out of the pool and placed inside the content view,
+ and the model properties such as \c index and \c row have been updated.
+
+ Other properties that are not provided by the model does not change when an
+ item is reused. You should avoid storing any state inside a delegate, but if
+ you do, manually reset that state on receiving this signal.
+
+ This signal is emitted when the item is reused, and not the first time the
+ item is created.
+
+ This signal is emitted only if the \l reuseItems property is \c true.
+
+ \sa {Reusing items}, reuseItems, pooled()
+*/
/*!
\qmlproperty Component QtQuick::GridView::highlight
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 9e7a8f4803..6c822e62c1 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1721,7 +1721,7 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
updateHighlight();
bottomItem = currentItem;
}
- qreal pos;
+ qreal pos = 0;
bool isInBounds = -position() > maxExtent && -position() <= minExtent;
if (header && !topItem && isInBounds) {
@@ -1802,6 +1802,19 @@ void QQuickListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExte
QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
return;
}
+ // If we have the CurrentLabelAtStart flag set, then we need to consider
+ // the section size while calculating the position
+ if (sectionCriteria
+ && (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart)
+ && currentSectionItem) {
+ auto sectionSize = (orient == QQuickListView::Vertical) ? currentSectionItem->height()
+ : currentSectionItem->width();
+ if (isContentFlowReversed())
+ pos += sectionSize;
+ else
+ pos -= sectionSize;
+ }
+
pos = qBound(-minExtent, pos, -maxExtent);
qreal dist = qAbs(data.move + pos);
@@ -2380,7 +2393,7 @@ QQuickListView::~QQuickListView()
/*!
\qmlproperty int QtQuick::ListView::count
- This property holds the number of items in the view.
+ This property holds the number of items in the model.
*/
/*!
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 9b0334b851..490e89acad 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -3297,11 +3297,18 @@ void QQuickTableViewPrivate::syncSyncView()
q->setColumnSpacing(syncView->columnSpacing());
updateContentWidth();
- if (syncView->leftColumn() != q->leftColumn()) {
- // The left column is no longer the same as the left
- // column in syncView. This requires a rebuild.
- scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn;
- scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ if (scheduledRebuildOptions & RebuildOption::LayoutOnly) {
+ if (syncView->leftColumn() != q->leftColumn()
+ || syncView->d_func()->loadedTableOuterRect.left() != loadedTableOuterRect.left()) {
+ // The left column is no longer the same, or at the same pos, as the left column in
+ // syncView. This can happen if syncView did a relayout that caused its left column
+ // to be resized so small that it ended up outside the viewport. It can also happen
+ // if the syncView loaded and unloaded columns after the relayout. We therefore need
+ // to sync our own left column and pos to be the same, which we do by rebuilding the
+ // whole viewport instead of just doing a plain LayoutOnly.
+ scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftColumn;
+ scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ }
}
}
@@ -3309,11 +3316,18 @@ void QQuickTableViewPrivate::syncSyncView()
q->setRowSpacing(syncView->rowSpacing());
updateContentHeight();
- if (syncView->topRow() != q->topRow()) {
- // The top row is no longer the same as the top
- // row in syncView. This requires a rebuild.
- scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow;
- scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ if (scheduledRebuildOptions & RebuildOption::LayoutOnly) {
+ if (syncView->topRow() != q->topRow()
+ || syncView->d_func()->loadedTableOuterRect.top() != loadedTableOuterRect.top()) {
+ // The top row is no longer the same, or at the same pos, as the top row in
+ // syncView. This can happen if syncView did a relayout that caused its top row
+ // to be resized so small that it ended up outside the viewport. It can also happen
+ // if the syncView loaded and unloaded rows after the relayout. We therefore need
+ // to sync our own top row and pos to be the same, which we do by rebuilding the
+ // whole viewport instead of just doing a plain LayoutOnly.
+ scheduledRebuildOptions |= QQuickTableViewPrivate::RebuildOption::CalculateNewTopLeftRow;
+ scheduledRebuildOptions.setFlag(RebuildOption::ViewportOnly);
+ }
}
}
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index cef0dd2900..cdbcf46380 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -2462,8 +2462,10 @@ void QQuickText::geometryChange(const QRectF &newGeometry, const QRectF &oldGeom
}
}
} else if (!heightChanged && widthMaximum) {
- if (!qFuzzyIsNull(oldGeometry.width())) {
+ if (oldGeometry.width() > 0) {
// no change to height, width is adequate and wasn't 0 before
+ // (old width could also be negative if it was 0 and the margins
+ // were set)
goto geomChangeDone;
}
}
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 9d18868c58..d3aa5ef7a8 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -190,7 +190,12 @@ void QSGDistanceFieldGlyphCache::update()
distanceFields.reserve(pendingGlyphsSize);
for (int i = 0; i < pendingGlyphsSize; ++i) {
GlyphData &gd = glyphData(m_pendingGlyphs.at(i));
- distanceFields.append(QDistanceField(gd.path,
+
+ QSize size = QSize(qCeil(gd.texCoord.width + gd.texCoord.xMargin * 2),
+ qCeil(gd.texCoord.height + gd.texCoord.yMargin * 2));
+
+ distanceFields.append(QDistanceField(size,
+ gd.path,
m_pendingGlyphs.at(i),
m_doubleGlyphResolution));
gd.path = QPainterPath(); // no longer needed, so release memory used by the painter path
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode.cpp b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
index d3e0d5a7c5..fbc2227bae 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
@@ -83,11 +83,14 @@ void QSGDefaultGlyphNode::update()
QRawFont font = m_glyphs.rawFont();
QMargins margins(0, 0, 0, 0);
- if (m_style == QQuickText::Normal) {
+ const auto *fontEngine = QRawFontPrivate::get(font)->fontEngine;
+ const bool isColorFont = fontEngine->glyphFormat == QFontEngine::Format_ARGB;
+
+ if (m_style == QQuickText::Normal || isColorFont) {
QFontEngine::GlyphFormat glyphFormat;
// Don't try to override glyph format of color fonts
- if (QRawFontPrivate::get(font)->fontEngine->glyphFormat == QFontEngine::Format_ARGB) {
+ if (isColorFont) {
glyphFormat = QFontEngine::Format_None;
} else {
switch (m_preferredAntialiasingMode) {
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index af60f5b02b..a2003fdc37 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -310,6 +310,11 @@ void QQuickAbstractAnimation::setRunning(bool r)
// Therefore, the state of d->running will in that case be different than r if we are back in
// the root stack frame of the recursive calls to setRunning()
emit runningChanged(d->running);
+ } else if (d->animationInstance) {
+ // If there was a recursive call, make sure the d->running is set correctly
+ d->running = d->animationInstance->isRunning();
+ } else {
+ d->running = r;
}
}
diff --git a/src/quicklayouts/qquicklinearlayout.cpp b/src/quicklayouts/qquicklinearlayout.cpp
index dc55196c11..f7f7523c21 100644
--- a/src/quicklayouts/qquicklinearlayout.cpp
+++ b/src/quicklayouts/qquicklinearlayout.cpp
@@ -482,7 +482,7 @@ void QQuickGridLayoutBase::itemVisibilityChanged(QQuickItem *item)
void QQuickGridLayoutBase::rearrange(const QSizeF &size)
{
Q_D(QQuickGridLayoutBase);
- if (!isReady())
+ if (!isReady() || !size.isValid())
return;
qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::rearrange" << d->m_recurRearrangeCounter << this;
diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp
index 8a46d040f2..f999aec9b7 100644
--- a/src/quicktemplates2/qquickcontrol.cpp
+++ b/src/quicktemplates2/qquickcontrol.cpp
@@ -385,12 +385,22 @@ void QQuickControlPrivate::resizeBackground()
bool changeHeight = false;
if (((!p->widthValid() || !extra.isAllocated() || !extra->hasBackgroundWidth) && qFuzzyIsNull(background->x()))
|| (extra.isAllocated() && (extra->hasLeftInset || extra->hasRightInset))) {
- background->setX(getLeftInset());
+ const auto leftInset = getLeftInset();
+ if (!qt_is_nan(leftInset) && p->x.valueBypassingBindings() != leftInset) {
+ // We bypass the binding here to prevent it from being removed
+ p->x.setValueBypassingBindings(leftInset);
+ p->dirty(DirtyType::Position);
+ }
changeWidth = !p->width.hasBinding();
}
if (((!p->heightValid() || !extra.isAllocated() || !extra->hasBackgroundHeight) && qFuzzyIsNull(background->y()))
|| (extra.isAllocated() && (extra->hasTopInset || extra->hasBottomInset))) {
- background->setY(getTopInset());
+ const auto topInset = getTopInset();
+ if (!qt_is_nan(topInset) && p->y.valueBypassingBindings() != topInset) {
+ // We bypass the binding here to prevent it from being removed
+ p->y.setValueBypassingBindings(topInset);
+ p->dirty(DirtyType::Position);
+ }
changeHeight = !p->height.hasBinding();
}
if (changeHeight || changeWidth) {
diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp
index 1829f9a30e..62abaae005 100644
--- a/src/quicktemplates2/qquickoverlay.cpp
+++ b/src/quicktemplates2/qquickoverlay.cpp
@@ -498,6 +498,13 @@ bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
case QEvent::HoverEnter:
case QEvent::HoverMove:
case QEvent::HoverLeave:
+ // If the control item has already been hovered, allow the hover leave event
+ // to be processed by the same item for resetting its internal hovered state
+ // instead of filtering it here.
+ if (auto *control = qobject_cast<QQuickControl *>(item)) {
+ if (control->isHovered() && event->type() == QEvent::HoverLeave)
+ return false;
+ }
handled = d->handleHoverEvent(item, static_cast<QHoverEvent *>(event), popup);
break;
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index c593ca2a81..058b959258 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -664,7 +664,24 @@ QQuickWidget::QQuickWidget(QWidget *parent)
{
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
+#ifndef Q_OS_MACOS
+ /*
+ Usually, a QTouchEvent comes from a touchscreen, and we want those
+ touch events in Qt Quick. But on macOS, there are no touchscreens, and
+ WA_AcceptTouchEvents has a different meaning: QApplication::notify()
+ calls the native-integration function registertouchwindow() to change
+ NSView::allowedTouchTypes to include NSTouchTypeMaskIndirect when the
+ trackpad cursor enters the window, and removes that mask when the
+ cursor exits. In other words, WA_AcceptTouchEvents enables getting
+ discrete touchpoints from the trackpad. We rather prefer to get mouse,
+ wheel and native gesture events from the trackpad (because those
+ provide more of a "native feel"). The only exception is for
+ MultiPointTouchArea, and it takes care of that for itself. So don't
+ automatically set WA_AcceptTouchEvents on macOS. The user can still do
+ it, but we don't recommend it.
+ */
setAttribute(Qt::WA_AcceptTouchEvents);
+#endif
d_func()->init();
}