aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-02-22 14:26:13 +0100
committerLiang Qi <liang.qi@qt.io>2019-02-22 14:26:13 +0100
commit3baa2d550512702dfc227aef0af3542ab189824f (patch)
treefe2967757ce6abe70f3f819cd8f5691cc384288d /src
parent16aff415a44f5f10c5ac95da72559839305c8ae5 (diff)
parent3ad752e1c16a3d37a71c5a7527c7e67cc333cdd2 (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: tests/auto/quick/qquicktableview/tst_qquicktableview.cpp Change-Id: If3bf1abc23a59c458be0bb862d92f2edcb16b79f
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator.cpp2
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp8
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/jsapi/qjsengine_p.h12
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp31
-rw-r--r--src/qml/qml/qqmlengine_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp14
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp21
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h6
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp19
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h14
-rw-r--r--src/qml/types/qqmltableinstancemodel.cpp5
-rw-r--r--src/qml/types/qqmltableinstancemodel_p.h2
-rw-r--r--src/qml/util/qqmladaptormodel.cpp83
-rw-r--r--src/qml/util/qqmladaptormodel_p.h7
-rw-r--r--src/quick/items/qquicktableview.cpp12
-rw-r--r--src/quick/items/qquicktableview_p_p.h1
18 files changed, 159 insertions, 84 deletions
diff --git a/src/qml/compiler/qqmlpropertycachecreator.cpp b/src/qml/compiler/qqmlpropertycachecreator.cpp
index fd22cd58f1..fb54da5b73 100644
--- a/src/qml/compiler/qqmlpropertycachecreator.cpp
+++ b/src/qml/compiler/qqmlpropertycachecreator.cpp
@@ -74,7 +74,7 @@ QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiating
if (instantiatingProperty->isQObject()) {
return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(), instantiatingProperty->typeMinorVersion());
} else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType())) {
- return enginePrivate->cache(vtmo);
+ return enginePrivate->cache(vtmo, instantiatingProperty->typeMinorVersion());
}
}
return QQmlRefPointer<QQmlPropertyCache>();
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index 4e8f57c2cf..1beaac8095 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -160,10 +160,12 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
QQmlPropertyData *pd = nullptr;
if (!name.isEmpty()) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
pd = propertyResolver.signal(name, &notInRevision);
- else
- pd = propertyResolver.property(name, &notInRevision, isGroupProperty ? QmlIR::PropertyResolver::IgnoreRevision : QmlIR::PropertyResolver::CheckRevision);
+ } else {
+ pd = propertyResolver.property(name, &notInRevision,
+ QmlIR::PropertyResolver::CheckRevision);
+ }
if (notInRevision) {
QString typeName = stringAt(obj->inheritedTypeNameIndex);
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index c90bbf03e6..cb614f7d40 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -854,7 +854,7 @@ QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQm
if (typePropertyCache) {
return typePropertyCache;
} else if (type.isValid()) {
- typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject());
+ typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
return typePropertyCache;
} else {
return compilationUnit->rootPropertyCache();
diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h
index 360c9df075..a77d710cff 100644
--- a/src/qml/jsapi/qjsengine_p.h
+++ b/src/qml/jsapi/qjsengine_p.h
@@ -109,8 +109,8 @@ public:
// These methods may be called from the QML loader thread
- inline QQmlPropertyCache *cache(QObject *obj);
- inline QQmlPropertyCache *cache(const QMetaObject *);
+ inline QQmlPropertyCache *cache(QObject *obj, int minorVersion = -1);
+ inline QQmlPropertyCache *cache(const QMetaObject *, int minorVersion = -1);
};
QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
@@ -160,14 +160,14 @@ and deleted before the loader thread has a chance to use or reference it. This
can't currently happen as the cache holds a reference to the
QQmlPropertyCache until the QQmlEngine is destroyed.
*/
-QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj)
+QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, int minorVersion)
{
if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
return nullptr;
Locker locker(this);
const QMetaObject *mo = obj->metaObject();
- return QQmlMetaType::propertyCache(mo);
+ return QQmlMetaType::propertyCache(mo, minorVersion);
}
/*!
@@ -179,12 +179,12 @@ exist for the lifetime of the QQmlEngine.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject)
+QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, int minorVersion)
{
Q_ASSERT(metaObject);
Locker locker(this);
- return QQmlMetaType::propertyCache(metaObject);
+ return QQmlMetaType::propertyCache(metaObject, minorVersion);
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 6617dd5e89..40be6f41c8 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1206,8 +1206,20 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index
args[0].initAsType(returnType);
for (int ii = 0; ii < argCount; ++ii) {
if (!args[ii + 1].fromValue(argTypes[ii], engine, callArgs->args[ii])) {
- return engine->throwTypeError(QString::fromLatin1("Could not convert argument %1.")
- .arg(ii));
+ qWarning() << QString::fromLatin1("Could not convert argument %1 at").arg(ii);
+ const StackTrace stack = engine->stackTrace();
+ for (const StackFrame &frame : stack) {
+ qWarning() << "\t" << frame.function + QLatin1Char('@') + frame.source
+ + (frame.line > 0
+ ? (QLatin1Char(':') + QString::number(frame.line))
+ : QString());
+
+ }
+ qWarning() << QLatin1String("Passing incompatible arguments to C++ functions from "
+ "JavaScript is dangerous and deprecated.");
+ qWarning() << QLatin1String("This will throw a JavaScript TypeError in future "
+ "releases of Qt!");
+
}
}
QVarLengthArray<void *, 9> argData(args.count());
@@ -1724,6 +1736,7 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
qlistPtr = new (&allocData) QList<QObject *>();
+ type = callType;
QV4::ScopedArrayObject array(scope, value);
if (array) {
Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
@@ -1737,14 +1750,14 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
qlistPtr->append(o);
}
} else {
- QObject *o = nullptr;
- if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
- o = qobjectWrapper->object();
- else if (!value.isNull() && !value.isUndefined())
- return false;
- qlistPtr->append(o);
+ if (const QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>()) {
+ qlistPtr->append(qobjectWrapper->object());
+ } else {
+ qlistPtr->append(nullptr);
+ if (!value.isNull() && !value.isUndefined())
+ return false;
+ }
}
- type = callType;
} else if (callType == qMetaTypeId<QQmlV4Handle>()) {
handlePtr = new (&allocData) QQmlV4Handle(value.asReturnedValue());
type = callType;
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 70e188dc1c..d05c945ae4 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -377,7 +377,7 @@ QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersi
Q_ASSERT(type.isValid());
if (minorVersion == -1 || !type.containsRevisionedAttributes())
- return cache(type.metaObject());
+ return cache(type.metaObject(), minorVersion);
Locker locker(this);
return QQmlMetaType::propertyCache(type, minorVersion);
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 032ee7d6fc..e4fd42932f 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -118,7 +118,7 @@ struct QQmlMetaTypeData
QHash<int, int> qmlLists;
QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches;
- QQmlPropertyCache *propertyCache(const QMetaObject *metaObject);
+ QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion);
QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
void startRecordingTypeRegFailures(QStringList *storage)
@@ -2432,7 +2432,7 @@ QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileI
return QQmlType();
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject)
+QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion)
{
if (QQmlPropertyCache *rv = propertyCaches.value(metaObject))
return rv;
@@ -2442,17 +2442,17 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject
propertyCaches.insert(metaObject, rv);
return rv;
}
- QQmlPropertyCache *super = propertyCache(metaObject->superClass());
- QQmlPropertyCache *rv = super->copyAndAppend(metaObject);
+ QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion);
+ QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion);
propertyCaches.insert(metaObject, rv);
return rv;
}
-QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject)
+QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, int minorVersion)
{
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- return data->propertyCache(metaObject);
+ return data->propertyCache(metaObject, minorVersion);
}
QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion)
@@ -2485,7 +2485,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
return pc;
}
- QQmlPropertyCache *raw = propertyCache(type.metaObject());
+ QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion);
bool hasCopied = false;
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 2a45ddb4bb..3ad2de7bb3 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -103,7 +103,7 @@ public:
static QQmlType qmlType(int typeId, TypeIdCategory category = TypeIdCategory::MetaType);
static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false);
- static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject);
+ static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion = -1);
static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
static void freeUnusedTypesAndCaches();
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index d619730e28..73bfd7bbaa 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -252,12 +252,22 @@ QQmlPropertyCache::QQmlPropertyCache()
/*!
Creates a new QQmlPropertyCache of \a metaObject.
*/
-QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject)
+QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, int metaObjectRevision)
: QQmlPropertyCache()
{
Q_ASSERT(metaObject);
update(metaObject);
+
+ if (metaObjectRevision > 0) {
+ // Set the revision of the meta object that this cache describes to be
+ // 'metaObjectRevision'. This is useful when constructing a property cache
+ // from a type that was created directly in C++, and not through QML. For such
+ // types, the revision for each recorded QMetaObject would normally be zero, which
+ // would exclude any revisioned properties.
+ for (int metaObjectOffset = 0; metaObjectOffset < allowedRevisionCache.size(); ++metaObjectOffset)
+ allowedRevisionCache[metaObjectOffset] = metaObjectRevision;
+ }
}
QQmlPropertyCache::~QQmlPropertyCache()
@@ -454,7 +464,7 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
QQmlPropertyCache *
QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
- int revision,
+ int typeMinorVersion,
QQmlPropertyData::Flags propertyFlags,
QQmlPropertyData::Flags methodFlags,
QQmlPropertyData::Flags signalFlags)
@@ -468,19 +478,17 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
QMetaObjectPrivate::get(metaObject)->signalCount +
QMetaObjectPrivate::get(metaObject)->propertyCount);
- rv->append(metaObject, revision, propertyFlags, methodFlags, signalFlags);
+ rv->append(metaObject, typeMinorVersion, propertyFlags, methodFlags, signalFlags);
return rv;
}
void QQmlPropertyCache::append(const QMetaObject *metaObject,
- int revision,
+ int typeMinorVersion,
QQmlPropertyData::Flags propertyFlags,
QQmlPropertyData::Flags methodFlags,
QQmlPropertyData::Flags signalFlags)
{
- Q_UNUSED(revision);
-
_metaObject = metaObject;
bool dynamicMetaObject = isDynamicMetaObject(metaObject);
@@ -630,6 +638,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
data->setFlags(propertyFlags);
data->lazyLoad(p);
+ data->setTypeMinorVersion(typeMinorVersion);
data->_flags.isDirect = !dynamicMetaObject;
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 0785910cec..c3c818eb77 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -394,7 +394,7 @@ class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount
{
public:
QQmlPropertyCache();
- QQmlPropertyCache(const QMetaObject *);
+ QQmlPropertyCache(const QMetaObject *, int metaObjectRevision = 0);
~QQmlPropertyCache() override;
void update(const QMetaObject *);
@@ -408,7 +408,7 @@ public:
QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
- QQmlPropertyCache *copyAndAppend(const QMetaObject *, int revision,
+ QQmlPropertyCache *copyAndAppend(const QMetaObject *, int typeMinorVersion,
QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
@@ -499,7 +499,7 @@ private:
inline QQmlPropertyCache *copy(int reserve);
- void append(const QMetaObject *, int revision,
+ void append(const QMetaObject *, int typeMinorVersion,
QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyRawData::Flags(),
QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 48cc77bc3d..53e3f65553 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -2036,7 +2036,9 @@ void QV4::Heap::QQmlDelegateModelItemObject::destroy()
}
-QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, int modelIndex, int row, int column)
+QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
+ QQmlAdaptorModel::Accessors *accessor,
+ int modelIndex, int row, int column)
: v4(metaType->v4Engine)
, metaType(metaType)
, contextData(nullptr)
@@ -2053,6 +2055,21 @@ QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *meta
, column(column)
{
metaType->addref();
+
+ if (accessor->propertyCache) {
+ // The property cache in the accessor is common for all the model
+ // items in the model it wraps. It describes available model roles,
+ // together with revisioned properties like row, column and index, all
+ // which should be available in the delegate. We assign this cache to the
+ // model item so that the QML engine can use the revision information
+ // when resolving the properties (rather than falling back to just
+ // inspecting the QObject in the model item directly).
+ QQmlData *qmldata = QQmlData::get(this, true);
+ if (qmldata->propertyCache)
+ qmldata->propertyCache->release();
+ qmldata->propertyCache = accessor->propertyCache.data();
+ qmldata->propertyCache->addref();
+ }
}
QQmlDelegateModelItem::~QQmlDelegateModelItem()
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index 5e480f4df6..0028849828 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -96,11 +96,13 @@ class QQmlDelegateModelItem : public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged)
- Q_PROPERTY(int row MEMBER row NOTIFY rowChanged)
- Q_PROPERTY(int column MEMBER column NOTIFY columnChanged)
+ Q_PROPERTY(int row READ modelRow NOTIFY rowChanged REVISION 12)
+ Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION 12)
Q_PROPERTY(QObject *model READ modelObject CONSTANT)
public:
- QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType, int modelIndex, int row, int column);
+ QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
+ QQmlAdaptorModel::Accessors *accessor, int modelIndex,
+ int row, int column);
~QQmlDelegateModelItem();
void referenceObject() { ++objectRef; }
@@ -124,6 +126,8 @@ public:
int groupIndex(Compositor::Group group);
+ int modelRow() const { return row; }
+ int modelColumn() const { return column; }
int modelIndex() const { return index; }
virtual void setModelIndex(int idx, int newRow, int newColumn);
@@ -154,8 +158,8 @@ public:
Q_SIGNALS:
void modelIndexChanged();
- void rowChanged();
- void columnChanged();
+ Q_REVISION(12) void rowChanged();
+ Q_REVISION(12) void columnChanged();
protected:
void objectDestroyed(QObject *);
diff --git a/src/qml/types/qqmltableinstancemodel.cpp b/src/qml/types/qqmltableinstancemodel.cpp
index 1054158dc8..2170e2daec 100644
--- a/src/qml/types/qqmltableinstancemodel.cpp
+++ b/src/qml/types/qqmltableinstancemodel.cpp
@@ -82,6 +82,11 @@ QQmlTableInstanceModel::QQmlTableInstanceModel(QQmlContext *qmlContext, QObject
{
}
+void QQmlTableInstanceModel::useImportVersion(int minorVersion)
+{
+ m_adaptorModel.useImportVersion(minorVersion);
+}
+
QQmlTableInstanceModel::~QQmlTableInstanceModel()
{
for (const auto modelItem : m_modelItems) {
diff --git a/src/qml/types/qqmltableinstancemodel_p.h b/src/qml/types/qqmltableinstancemodel_p.h
index 03761af326..3dd5c4e4ce 100644
--- a/src/qml/types/qqmltableinstancemodel_p.h
+++ b/src/qml/types/qqmltableinstancemodel_p.h
@@ -93,6 +93,8 @@ public:
QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent = nullptr);
~QQmlTableInstanceModel() override;
+ void useImportVersion(int minorVersion);
+
int count() const override { return m_adaptorModel.count(); }
int rows() const { return m_adaptorModel.rowCount(); }
int columns() const { return m_adaptorModel.columnCount(); }
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index 831663fb7b..d9cb6506b8 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -121,21 +121,12 @@ class VDMModelDelegateDataType
public:
VDMModelDelegateDataType(QQmlAdaptorModel *model)
: model(model)
- , metaObject(nullptr)
- , propertyCache(nullptr)
, propertyOffset(0)
, signalOffset(0)
, hasModelData(false)
{
}
- ~VDMModelDelegateDataType()
- {
- if (propertyCache)
- propertyCache->release();
- free(metaObject);
- }
-
bool notify(
const QQmlAdaptorModel &,
const QList<QQmlDelegateModelItem *> &items,
@@ -255,15 +246,13 @@ public:
QList<QByteArray> watchedRoles;
QHash<QByteArray, int> roleNames;
QQmlAdaptorModel *model;
- QMetaObject *metaObject;
- QQmlPropertyCache *propertyCache;
int propertyOffset;
int signalOffset;
bool hasModelData;
};
QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *metaType, VDMModelDelegateDataType *dataType, int index, int row, int column)
- : QQmlDelegateModelItem(metaType, index, row, column)
+ : QQmlDelegateModelItem(metaType, dataType, index, row, column)
, type(dataType)
{
if (index == -1)
@@ -272,10 +261,6 @@ QQmlDMCachedModelData::QQmlDMCachedModelData(QQmlDelegateModelItemMetaType *meta
QObjectPrivate::get(this)->metaObject = type;
type->addref();
-
- QQmlData *qmldata = QQmlData::get(this, true);
- qmldata->propertyCache = dataType->propertyCache;
- qmldata->propertyCache->addref();
}
int QQmlDMCachedModelData::metaCall(QMetaObject::Call call, int id, void **arguments)
@@ -538,9 +523,9 @@ public:
addProperty(&builder, 1, propertyName, propertyType);
}
- metaObject = builder.toMetaObject();
+ metaObject.reset(builder.toMetaObject());
*static_cast<QMetaObject *>(this) = *metaObject;
- propertyCache = new QQmlPropertyCache(metaObject);
+ propertyCache = new QQmlPropertyCache(metaObject.data(), model.modelItemRevision);
}
};
@@ -553,8 +538,10 @@ class QQmlDMListAccessorData : public QQmlDelegateModelItem
Q_OBJECT
Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
public:
- QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType, int index, int row, int column, const QVariant &value)
- : QQmlDelegateModelItem(metaType, index, row, column)
+ QQmlDMListAccessorData(QQmlDelegateModelItemMetaType *metaType,
+ QQmlAdaptorModel::Accessors *accessor,
+ int index, int row, int column, const QVariant &value)
+ : QQmlDelegateModelItem(metaType, accessor, index, row, column)
, cachedData(value)
{
}
@@ -635,10 +622,18 @@ private:
};
-class VDMListDelegateDataType : public QQmlAdaptorModel::Accessors
+class VDMListDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
{
public:
- inline VDMListDelegateDataType() {}
+ VDMListDelegateDataType()
+ : QQmlRefCount()
+ , QQmlAdaptorModel::Accessors()
+ {}
+
+ void cleanup(QQmlAdaptorModel &) const override
+ {
+ const_cast<VDMListDelegateDataType *>(this)->release();
+ }
int rowCount(const QQmlAdaptorModel &model) const override
{
@@ -662,8 +657,15 @@ public:
QQmlDelegateModelItemMetaType *metaType,
int index, int row, int column) const override
{
+ VDMListDelegateDataType *dataType = const_cast<VDMListDelegateDataType *>(this);
+ if (!propertyCache) {
+ dataType->propertyCache = new QQmlPropertyCache(
+ &QQmlDMListAccessorData::staticMetaObject, model.modelItemRevision);
+ }
+
return new QQmlDMListAccessorData(
metaType,
+ dataType,
index, row, column,
index >= 0 && index < model.list.count() ? model.list.at(index) : QVariant());
}
@@ -721,15 +723,13 @@ Q_SIGNALS:
class VDMObjectDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
{
public:
- QMetaObject *metaObject;
int propertyOffset;
int signalOffset;
bool shared;
QMetaObjectBuilder builder;
VDMObjectDelegateDataType()
- : metaObject(nullptr)
- , propertyOffset(0)
+ : propertyOffset(0)
, signalOffset(0)
, shared(true)
{
@@ -738,11 +738,10 @@ public:
VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
: QQmlRefCount()
, QQmlAdaptorModel::Accessors()
- , metaObject(nullptr)
, propertyOffset(type.propertyOffset)
, signalOffset(type.signalOffset)
, shared(false)
- , builder(type.metaObject, QMetaObjectBuilder::Properties
+ , builder(type.metaObject.data(), QMetaObjectBuilder::Properties
| QMetaObjectBuilder::Signals
| QMetaObjectBuilder::SuperClass
| QMetaObjectBuilder::ClassName)
@@ -750,11 +749,6 @@ public:
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
}
- ~VDMObjectDelegateDataType()
- {
- free(metaObject);
- }
-
int rowCount(const QQmlAdaptorModel &model) const override
{
return model.list.count();
@@ -785,11 +779,18 @@ public:
: nullptr;
}
- void initializeMetaType(QQmlAdaptorModel &)
+ void initializeMetaType(QQmlAdaptorModel &model)
{
+ Q_UNUSED(model);
setModelDataType<QQmlDMObjectData>(&builder, this);
- metaObject = builder.toMetaObject();
+ metaObject.reset(builder.toMetaObject());
+ // Note: ATM we cannot create a shared property cache for this class, since each model
+ // object can have different properties. And to make those properties available to the
+ // delegate, QQmlDMObjectData makes use of a QAbstractDynamicMetaObject subclass
+ // (QQmlDMObjectDataMetaObject), which we cannot represent in a QQmlPropertyCache.
+ // By not having a shared property cache, revisioned properties in QQmlDelegateModelItem
+ // will always be available to the delegate, regardless of the import version.
}
void cleanup(QQmlAdaptorModel &) const override
@@ -888,9 +889,7 @@ public:
propertyBuilder.setConstant(property.isConstant());
}
- if (m_type->metaObject)
- free(m_type->metaObject);
- m_type->metaObject = m_type->builder.toMetaObject();
+ m_type->metaObject.reset(m_type->builder.toMetaObject());
*static_cast<QMetaObject *>(this) = *m_type->metaObject;
notifierId = previousMethodCount;
@@ -913,7 +912,7 @@ QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType,
VDMObjectDelegateDataType *dataType,
int index, int row, int column,
QObject *object)
- : QQmlDelegateModelItem(metaType, index, row, column)
+ : QQmlDelegateModelItem(metaType, dataType, index, row, column)
, object(object)
{
new QQmlDMObjectDataMetaObject(this, dataType);
@@ -924,7 +923,6 @@ QQmlDMObjectData::QQmlDMObjectData(QQmlDelegateModelItemMetaType *metaType,
//-----------------------------------------------------------------
static const QQmlAdaptorModel::Accessors qt_vdm_null_accessors;
-static const VDMListDelegateDataType qt_vdm_list_accessors;
QQmlAdaptorModel::Accessors::~Accessors()
{
@@ -958,7 +956,7 @@ void QQmlAdaptorModel::setModel(const QVariant &variant, QObject *parent, QQmlEn
} else if (list.type() != QQmlListAccessor::Invalid
&& list.type() != QQmlListAccessor::Instance) { // Null QObject
setObject(nullptr, parent);
- accessors = &qt_vdm_list_accessors;
+ accessors = new VDMListDelegateDataType;
} else {
setObject(nullptr, parent);
accessors = &qt_vdm_null_accessors;
@@ -1010,6 +1008,11 @@ int QQmlAdaptorModel::indexAt(int row, int column) const
return column * rowCount() + row;
}
+void QQmlAdaptorModel::useImportVersion(int minorVersion)
+{
+ modelItemRevision = minorVersion;
+}
+
void QQmlAdaptorModel::objectDestroyed(QObject *)
{
setModel(QVariant(), nullptr, nullptr);
diff --git a/src/qml/util/qqmladaptormodel_p.h b/src/qml/util/qqmladaptormodel_p.h
index b5e0881078..8c18466ab5 100644
--- a/src/qml/util/qqmladaptormodel_p.h
+++ b/src/qml/util/qqmladaptormodel_p.h
@@ -104,12 +104,17 @@ public:
return QVariant(); }
virtual bool canFetchMore(const QQmlAdaptorModel &) const { return false; }
virtual void fetchMore(QQmlAdaptorModel &) const {}
+
+ QScopedPointer<QMetaObject, QScopedPointerPodDeleter> metaObject;
+ QQmlRefPointer<QQmlPropertyCache> propertyCache;
};
const Accessors *accessors;
QPersistentModelIndex rootIndex;
QQmlListAccessor list;
+ int modelItemRevision = 0;
+
QQmlAdaptorModel();
~QQmlAdaptorModel();
@@ -125,6 +130,8 @@ public:
int columnAt(int index) const;
int indexAt(int row, int column) const;
+ void useImportVersion(int minorVersion);
+
inline bool adaptsAim() const { return qobject_cast<QAbstractItemModel *>(object()); }
inline QAbstractItemModel *aim() { return static_cast<QAbstractItemModel *>(object()); }
inline const QAbstractItemModel *aim() const { return static_cast<const QAbstractItemModel *>(object()); }
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 28871e8068..675208d75c 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -1760,6 +1760,17 @@ void QQuickTableViewPrivate::fixup(QQuickFlickablePrivate::AxisData &data, qreal
QQuickFlickablePrivate::fixup(data, minExtent, maxExtent);
}
+int QQuickTableViewPrivate::resolveImportVersion()
+{
+ const auto data = QQmlData::get(q_func());
+ if (!data || !data->propertyCache)
+ return 0;
+
+ const auto cppMetaObject = data->propertyCache->firstCppMetaObject();
+ const auto qmlTypeView = QQmlMetaType::qmlType(cppMetaObject);
+ return qmlTypeView.minorVersion();
+}
+
void QQuickTableViewPrivate::createWrapperModel()
{
Q_Q(QQuickTableView);
@@ -1769,6 +1780,7 @@ void QQuickTableViewPrivate::createWrapperModel()
// common interface to any kind of model (js arrays, QAIM, number etc), and
// help us create delegate instances.
tableModel = new QQmlTableInstanceModel(qmlContext(q));
+ tableModel->useImportVersion(resolveImportVersion());
model = tableModel;
}
diff --git a/src/quick/items/qquicktableview_p_p.h b/src/quick/items/qquicktableview_p_p.h
index 9bea8040dc..f2fef0d774 100644
--- a/src/quick/items/qquicktableview_p_p.h
+++ b/src/quick/items/qquicktableview_p_p.h
@@ -359,6 +359,7 @@ public:
void scheduleRebuildTable(QQuickTableViewPrivate::RebuildOptions options);
void invalidateColumnRowPositions();
+ int resolveImportVersion();
void createWrapperModel();
void initItemCallback(int modelIndex, QObject *item);