diff options
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject_p.h | 2 | ||||
-rw-r--r-- | src/qml/util/qqmlpropertymap.cpp | 40 | ||||
-rw-r--r-- | src/qml/util/qqmlpropertymap.h | 11 | ||||
-rw-r--r-- | tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp | 43 |
5 files changed, 92 insertions, 8 deletions
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index 4774f7e126..bd40cc3993 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -175,13 +175,13 @@ public: bool cacheProperties; }; -QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, bool automatic) +QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base, bool automatic) : d(new QQmlOpenMetaObjectPrivate(this)) { d->autoCreate = automatic; d->object = obj; - d->type = new QQmlOpenMetaObjectType(obj->metaObject(), 0); + d->type = new QQmlOpenMetaObjectType(base ? base : obj->metaObject(), 0); d->type->d->referers.insert(this); QObjectPrivate *op = QObjectPrivate::get(obj); diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h index a45d7d8259..bfd96f7cd7 100644 --- a/src/qml/qml/qqmlopenmetaobject_p.h +++ b/src/qml/qml/qqmlopenmetaobject_p.h @@ -83,7 +83,7 @@ class QQmlOpenMetaObjectPrivate; class Q_QML_PRIVATE_EXPORT QQmlOpenMetaObject : public QAbstractDynamicMetaObject { public: - QQmlOpenMetaObject(QObject *, bool = true); + QQmlOpenMetaObject(QObject *, const QMetaObject * = 0, bool = true); QQmlOpenMetaObject(QObject *, QQmlOpenMetaObjectType *, bool = true); ~QQmlOpenMetaObject(); diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp index cdc82fe86e..37f9e3118a 100644 --- a/src/qml/util/qqmlpropertymap.cpp +++ b/src/qml/util/qqmlpropertymap.cpp @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE class QQmlPropertyMapMetaObject : public QQmlOpenMetaObject { public: - QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv); + QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv, const QMetaObject *staticMetaObject); protected: virtual QVariant propertyWriteValue(int, const QVariant &); @@ -110,7 +110,8 @@ const QString &QQmlPropertyMapPrivate::propertyName(int index) const return keys[index]; } -QQmlPropertyMapMetaObject::QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv) : QQmlOpenMetaObject(obj) +QQmlPropertyMapMetaObject::QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv, const QMetaObject *staticMetaObject) + : QQmlOpenMetaObject(obj, staticMetaObject) { map = obj; priv = objPriv; @@ -176,16 +177,20 @@ int QQmlPropertyMapMetaObject::createProperty(const char *name, const char *valu \note It is not possible to remove keys from the map; once a key has been added, you can only modify or clear its associated value. + + \note When deriving a class from QQmlPropertyMap, use the + \l {QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent)} + {protected two-argument constructor} + which ensures that the class is correctly registered with the Qt \l {Meta-Object System}. */ /*! Constructs a bindable map with parent object \a parent. */ QQmlPropertyMap::QQmlPropertyMap(QObject *parent) -: QObject(*(new QQmlPropertyMapPrivate), parent) +: QObject(*allocatePrivate(), parent) { - Q_D(QQmlPropertyMap); - d->mo = new QQmlPropertyMapMetaObject(this, d); + init(metaObject()); } /*! @@ -331,9 +336,23 @@ QVariant QQmlPropertyMap::operator[](const QString &key) const */ QVariant QQmlPropertyMap::updateValue(const QString &key, const QVariant &input) { + Q_UNUSED(key) return input; } +/*! \internal */ +void QQmlPropertyMap::init(const QMetaObject *staticMetaObject) +{ + Q_D(QQmlPropertyMap); + d->mo = new QQmlPropertyMapMetaObject(this, d, staticMetaObject); +} + +/*! \internal */ +QObjectPrivate *QQmlPropertyMap::allocatePrivate() +{ + return new QQmlPropertyMapPrivate; +} + /*! \fn void QQmlPropertyMap::valueChanged(const QString &key, const QVariant &value) This signal is emitted whenever one of the values in the map is changed. \a key @@ -343,4 +362,15 @@ QVariant QQmlPropertyMap::updateValue(const QString &key, const QVariant &input) or clear() - it is only emitted when a value is updated from QML. */ +/*! + \fn QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent) + + Constructs a bindable map with parent object \a parent. Use this constructor + in classes derived from QQmlPropertyMap. + + The type of \a derived is used to register the property map with the \l {Meta-Object System}, + which is necessary to ensure that properties of the derived class are accessible. + This type must be derived from QQmlPropertyMap. +*/ + QT_END_NAMESPACE diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h index bfd11e5c80..f7d69be7fb 100644 --- a/src/qml/util/qqmlpropertymap.h +++ b/src/qml/util/qqmlpropertymap.h @@ -82,7 +82,18 @@ Q_SIGNALS: protected: virtual QVariant updateValue(const QString &key, const QVariant &input); + template<class DerivedType> + QQmlPropertyMap(DerivedType *derived, QObject *parent = 0) + : QObject(*allocatePrivate(), parent) + { + Q_UNUSED(derived) + init(&DerivedType::staticMetaObject); + } + private: + void init(const QMetaObject *staticMetaObject); + static QObjectPrivate *allocatePrivate(); + Q_DECLARE_PRIVATE(QQmlPropertyMap) Q_DISABLE_COPY(QQmlPropertyMap) }; diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp index 4e39ad3a41..3fd9dbec8f 100644 --- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp +++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp @@ -64,6 +64,7 @@ private slots: void crashBug(); void QTBUG_17868(); + void metaObjectAccessibility(); }; void tst_QQmlPropertyMap::insert() @@ -280,6 +281,48 @@ void tst_QQmlPropertyMap::QTBUG_17868() } +class MyEnhancedPropertyMap : public QQmlPropertyMap +{ + Q_OBJECT +public: + MyEnhancedPropertyMap() : QQmlPropertyMap(this) {} + +signals: + void testSignal(); + +public slots: + void testSlot() {} +}; + +namespace +{ + QStringList messages; + void msgHandler(QtMsgType, const char *msg) + { + messages << QLatin1String(msg); + } +} + +void tst_QQmlPropertyMap::metaObjectAccessibility() +{ + messages.clear(); + QtMsgHandler old = qInstallMsgHandler(msgHandler); + + QQmlEngine engine; + + MyEnhancedPropertyMap map; + + // Verify that signals and slots of QQmlPropertyMap-derived classes are accessible + QObject::connect(&map, SIGNAL(testSignal()), &engine, SIGNAL(quit())); + QObject::connect(&engine, SIGNAL(quit()), &map, SLOT(testSlot())); + + QCOMPARE(map.metaObject()->className(), "MyEnhancedPropertyMap"); + + qInstallMsgHandler(old); + + QCOMPARE(messages.count(), 0); +} + QTEST_MAIN(tst_QQmlPropertyMap) #include "tst_qqmlpropertymap.moc" |