aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqml.h9
-rw-r--r--src/qml/qml/qqmldata_p.h3
-rw-r--r--src/qml/qml/qqmlengine.cpp60
-rw-r--r--src/qml/qml/qqmlmetatype.cpp35
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp4
-rw-r--r--src/qml/qml/qqmlprivate.h5
-rw-r--r--src/qml/qml/qqmlproperty.cpp4
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp7
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp8
10 files changed, 87 insertions, 50 deletions
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 05a9f70247..9eacc5bc22 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -582,6 +582,10 @@ namespace QtQml {
Q_QML_EXPORT QObject *qmlAttachedPropertiesObjectById(int, const QObject *, bool create = true);
Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(int *, const QObject *,
const QMetaObject *, bool create);
+ Q_QML_EXPORT QQmlAttachedPropertiesFunc qmlAttachedPropertiesFunction(QObject *,
+ const QMetaObject *);
+ Q_QML_EXPORT QObject *qmlAttachedPropertiesObject(QObject *, QQmlAttachedPropertiesFunc func,
+ bool create = true);
#ifndef Q_QDOC
}
#endif
@@ -601,8 +605,9 @@ Q_QML_EXPORT void qmlRegisterModule(const char *uri, int versionMajor, int versi
template<typename T>
QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
{
- static int idx = -1;
- return qmlAttachedPropertiesObject(&idx, obj, &T::staticMetaObject, create);
+ QObject *mutableObj = const_cast<QObject *>(obj);
+ return qmlAttachedPropertiesObject(
+ mutableObj, qmlAttachedPropertiesFunction(mutableObj, &T::staticMetaObject), create);
}
Q_QML_EXPORT void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor);
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 2468de6857..f4c03fc17c 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -57,6 +57,7 @@
#include <private/qv4value_p.h>
#include <private/qv4persistent_p.h>
#include <private/qqmlrefcount_p.h>
+#include <qqmlprivate.h>
#include <qjsengine.h>
#include <qvector.h>
@@ -265,7 +266,7 @@ public:
}
bool hasExtendedData() const { return extendedData != nullptr; }
- QHash<int, QObject *> *attachedProperties() const;
+ QHash<QQmlAttachedPropertiesFunc, QObject *> *attachedProperties() const;
static inline bool wasDeleted(const QObject *);
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 5841a480fc..7cd4bf8579 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -1647,29 +1647,38 @@ QQmlEngine *qmlEngine(const QObject *obj)
return data->context->engine;
}
-QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
+static QObject *resolveAttachedProperties(QQmlAttachedPropertiesFunc pf, QQmlData *data,
+ QObject *object, bool create)
{
- QQmlData *data = QQmlData::get(object, create);
- if (!data)
- return nullptr; // Attached properties are only on objects created by QML, unless explicitly requested (create==true)
+ if (!pf)
+ return nullptr;
- QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0;
+ QObject *rv = data->hasExtendedData() ? data->attachedProperties()->value(pf) : 0;
if (rv || !create)
return rv;
- QQmlEnginePrivate *engine = QQmlEnginePrivate::get(data->context);
- QQmlAttachedPropertiesFunc pf = QQmlMetaType::attachedPropertiesFuncById(engine, id);
- if (!pf)
- return nullptr;
-
- rv = pf(const_cast<QObject *>(object));
+ rv = pf(object);
if (rv)
- data->attachedProperties()->insert(id, rv);
+ data->attachedProperties()->insert(pf, rv);
return rv;
}
+QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create)
+{
+ QQmlData *data = QQmlData::get(object, create);
+
+ // Attached properties are only on objects created by QML,
+ // unless explicitly requested (create==true)
+ if (!data)
+ return nullptr;
+
+ QQmlEnginePrivate *engine = QQmlEnginePrivate::get(data->context);
+ return resolveAttachedProperties(QQmlMetaType::attachedPropertiesFuncById(engine, id), data,
+ const_cast<QObject *>(object), create);
+}
+
QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
const QMetaObject *attachedMetaObject, bool create)
{
@@ -1684,6 +1693,29 @@ QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object,
return qmlAttachedPropertiesObjectById(*idCache, object, create);
}
+QQmlAttachedPropertiesFunc qmlAttachedPropertiesFunction(QObject *object,
+ const QMetaObject *attachedMetaObject)
+{
+ QQmlEngine *engine = object ? qmlEngine(object) : nullptr;
+ return QQmlMetaType::attachedPropertiesFunc(engine ? QQmlEnginePrivate::get(engine) : nullptr,
+ attachedMetaObject);
+}
+
+QObject *qmlAttachedPropertiesObject(QObject *object, QQmlAttachedPropertiesFunc func, bool create)
+{
+ if (!object)
+ return nullptr;
+
+ QQmlData *data = QQmlData::get(object, create);
+
+ // Attached properties are only on objects created by QML,
+ // unless explicitly requested (create==true)
+ if (!data)
+ return nullptr;
+
+ return resolveAttachedProperties(func, data, object, create);
+}
+
} // namespace QtQml
#if QT_DEPRECATED_SINCE(5, 1)
@@ -1724,7 +1756,7 @@ public:
QQmlDataExtended();
~QQmlDataExtended();
- QHash<int, QObject *> attachedProperties;
+ QHash<QQmlAttachedPropertiesFunc, QObject *> attachedProperties;
};
QQmlDataExtended::QQmlDataExtended()
@@ -1870,7 +1902,7 @@ void QQmlData::disconnectNotifiers()
}
}
-QHash<int, QObject *> *QQmlData::attachedProperties() const
+QHash<QQmlAttachedPropertiesFunc, QObject *> *QQmlData::attachedProperties() const
{
if (!extendedData) extendedData = new QQmlDataExtended;
return &extendedData->attachedProperties;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index f801e9aeba..1873a99a71 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -224,7 +224,6 @@ public:
QQmlCustomParser *customParser;
QQmlAttachedPropertiesFunc attachedPropertiesFunc;
const QMetaObject *attachedPropertiesType;
- int attachedPropertiesId;
int propertyValueSourceCast;
int propertyValueInterceptorCast;
bool registerEnumClassesUnscoped;
@@ -269,8 +268,6 @@ public:
mutable QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums
mutable QList<QStringHash<int>*> scopedEnums;
- static QHash<const QMetaObject *, int> attachedPropertyIds;
-
struct PropertyCacheByMinorVersion
{
PropertyCacheByMinorVersion() : cache(nullptr), minorVersion(-1) {}
@@ -363,8 +360,6 @@ QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const
return scriptApis.value(e);
}
-QHash<const QMetaObject *, int> QQmlTypePrivate::attachedPropertyIds;
-
QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
: refCount(1), regType(type), iid(nullptr), typeId(0), listId(0), revision(0),
containsRevisionedAttributes(false), baseMetaObject(nullptr),
@@ -498,14 +493,6 @@ QQmlType::QQmlType(QQmlMetaTypeData *data, const QString &elementName, const QQm
d->baseMetaObject = type.metaObject;
d->extraData.cd->attachedPropertiesFunc = type.attachedPropertiesFunction;
d->extraData.cd->attachedPropertiesType = type.attachedPropertiesMetaObject;
- if (d->extraData.cd->attachedPropertiesType) {
- auto iter = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject);
- if (iter == QQmlTypePrivate::attachedPropertyIds.end())
- iter = QQmlTypePrivate::attachedPropertyIds.insert(d->baseMetaObject, d->index);
- d->extraData.cd->attachedPropertiesId = *iter;
- } else {
- d->extraData.cd->attachedPropertiesId = -1;
- }
d->extraData.cd->parserStatusCast = type.parserStatusCast;
d->extraData.cd->propertyValueSourceCast = type.valueSourceCast;
d->extraData.cd->propertyValueInterceptorCast = type.valueInterceptorCast;
@@ -571,16 +558,8 @@ QQmlType::QQmlType(QQmlTypePrivate *priv)
QQmlType::~QQmlType()
{
- if (d && !d->refCount.deref()) {
- // If attached properties were successfully registered, deregister them.
- // (They may not have been registered if some other type used the same baseMetaObject)
- if (d->regType == CppType && d->extraData.cd->attachedPropertiesType) {
- auto it = QQmlTypePrivate::attachedPropertyIds.find(d->baseMetaObject);
- if (it != QQmlTypePrivate::attachedPropertyIds.end() && *it == d->index)
- QQmlTypePrivate::attachedPropertyIds.erase(it);
- }
+ if (d && !d->refCount.deref())
delete d;
- }
}
QHashedString QQmlType::module() const
@@ -1228,7 +1207,7 @@ int QQmlType::attachedPropertiesId(QQmlEnginePrivate *engine) const
if (!d)
return -1;
if (d->regType == CppType)
- return d->extraData.cd->attachedPropertiesId;
+ return d->extraData.cd->attachedPropertiesType ? d->index : -1;
QQmlType base;
if (d->regType == CompositeType)
@@ -2188,6 +2167,16 @@ QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(QQmlEnginePr
return data->types.at(id).attachedPropertiesFunction(engine);
}
+QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFunc(QQmlEnginePrivate *engine,
+ const QMetaObject *mo)
+{
+ QMutexLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+
+ QQmlType type(data->metaObjectToType.value(mo));
+ return type.attachedPropertiesFunction(engine);
+}
+
QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject)
{
int idx = metaObject->indexOfClassInfo("DefaultProperty");
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 8256212207..3c1589d19b 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -119,6 +119,8 @@ public:
static int listType(int);
static int attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMetaObject *);
static QQmlAttachedPropertiesFunc attachedPropertiesFuncById(QQmlEnginePrivate *, int);
+ static QQmlAttachedPropertiesFunc attachedPropertiesFunc(QQmlEnginePrivate *,
+ const QMetaObject *);
enum TypeCategory { Unknown, Object, List };
static TypeCategory typeCategory(int);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 5af658194f..b62b07e39c 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -793,8 +793,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
else
return false;
}
- const int id = attachedType.attachedPropertiesId(QQmlEnginePrivate::get(engine));
- QObject *qmlObject = qmlAttachedPropertiesObjectById(id, _qobject);
+ QObject *qmlObject = qmlAttachedPropertiesObject(
+ _qobject, attachedType.attachedPropertiesFunction(QQmlEnginePrivate::get(engine)));
if (!populateInstance(binding->value.objectIndex, qmlObject, qmlObject, /*value type property*/nullptr))
return false;
return true;
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index c0232a7691..fa05b3fe19 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -77,6 +77,11 @@ typedef void (*IRLoaderFunction)(Document *, const QQmlPrivate::CachedQmlUnit *)
typedef QObject *(*QQmlAttachedPropertiesFunc)(QObject *);
+inline uint qHash(QQmlAttachedPropertiesFunc func, uint seed = 0)
+{
+ return qHash(quintptr(func), seed);
+}
+
template <typename TYPE>
class QQmlTypeInfo
{
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 000b88ebaa..c8166695ba 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -277,7 +277,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
if (!func) return; // Not an attachable type
- currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
+ currentObject = qmlAttachedPropertiesObject(currentObject, func);
if (!currentObject) return; // Something is broken with the attachable type
} else if (r.importNamespace) {
if ((ii + 1) == path.count()) return; // No type following the namespace
@@ -289,7 +289,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate);
if (!func) return; // Not an attachable type
- currentObject = qmlAttachedPropertiesObjectById(r.type.attachedPropertiesId(enginePrivate), currentObject);
+ currentObject = qmlAttachedPropertiesObject(currentObject, func);
if (!currentObject) return; // Something is broken with the attachable type
} else if (r.scriptIndex != -1) {
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index d30c225741..246de04316 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -263,7 +263,9 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons
// Fall through to base implementation
} else if (w->d()->object) {
- QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(v4->qmlEngine())), object);
+ QObject *ao = qmlAttachedPropertiesObject(
+ object,
+ type.attachedPropertiesFunction(QQmlEnginePrivate::get(v4->qmlEngine())));
if (ao)
return QV4::QObjectWrapper::getQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
@@ -335,7 +337,8 @@ bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value,
if (type.isValid() && !type.isSingleton() && w->d()->object) {
QObject *object = w->d()->object;
QQmlEngine *e = scope.engine->qmlEngine();
- QObject *ao = qmlAttachedPropertiesObjectById(type.attachedPropertiesId(QQmlEnginePrivate::get(e)), object);
+ QObject *ao = qmlAttachedPropertiesObject(
+ object, type.attachedPropertiesFunction(QQmlEnginePrivate::get(e)));
if (ao)
return QV4::QObjectWrapper::setQmlProperty(scope.engine, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
return false;
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index 7f103dc5ed..a7805922a5 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -550,8 +550,8 @@ void tst_qqmlmetatype::unregisterAttachedProperties()
c.setData("import QtQuick 2.2\n Item { }", dummy);
const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2);
- QCOMPARE(attachedType.attachedPropertiesId(QQmlEnginePrivate::get(&e)),
- attachedType.index());
+ QCOMPARE(attachedType.attachedPropertiesType(QQmlEnginePrivate::get(&e)),
+ attachedType.metaObject());
QVERIFY(c.create());
}
@@ -569,8 +569,8 @@ void tst_qqmlmetatype::unregisterAttachedProperties()
"Item { KeyNavigation.up: null }", dummy);
const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", 2, 2);
- QCOMPARE(attachedType.attachedPropertiesId(QQmlEnginePrivate::get(&e)),
- attachedType.index());
+ QCOMPARE(attachedType.attachedPropertiesType(QQmlEnginePrivate::get(&e)),
+ attachedType.metaObject());
QVERIFY(c.create());
}