aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp29
-rw-r--r--src/qml/qml/qqmlopenmetaobject_p.h1
-rw-r--r--src/qml/util/qqmlpropertymap.cpp39
-rw-r--r--src/qml/util/qqmlpropertymap.h3
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp44
5 files changed, 103 insertions, 13 deletions
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 221cb3a314..4774f7e126 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -145,10 +145,14 @@ public:
QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q)
: q(_q), parent(0), type(0), cacheProperties(false) {}
- inline QVariant &getData(int idx) {
+ inline QPair<QVariant, bool> &getDataRef(int idx) {
while (data.count() <= idx)
data << QPair<QVariant, bool>(QVariant(), false);
- QPair<QVariant, bool> &prop = data[idx];
+ return data[idx];
+ }
+
+ inline QVariant &getData(int idx) {
+ QPair<QVariant, bool> &prop = getDataRef(idx);
if (!prop.second) {
prop.first = q->initialValue(idx);
prop.second = true;
@@ -156,14 +160,6 @@ public:
return prop.first;
}
- inline void writeData(int idx, const QVariant &value) {
- while (data.count() <= idx)
- data << QPair<QVariant, bool>(QVariant(), false);
- QPair<QVariant, bool> &prop = data[idx];
- prop.first = value;
- prop.second = true;
- }
-
inline bool hasData(int idx) const {
if (idx >= data.count())
return false;
@@ -235,7 +231,9 @@ int QQmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
} else if (c == QMetaObject::WriteProperty) {
if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
propertyWrite(propId);
- d->writeData(propId, *reinterpret_cast<QVariant *>(a[0]));
+ QPair<QVariant, bool> &prop = d->getDataRef(propId);
+ prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
+ prop.second = true;
propertyWritten(propId);
activate(d->object, d->type->d->signalOffset + propId, 0);
}
@@ -261,7 +259,9 @@ QVariant QQmlOpenMetaObject::value(int id) const
void QQmlOpenMetaObject::setValue(int id, const QVariant &value)
{
- d->writeData(id, value);
+ QPair<QVariant, bool> &prop = d->getDataRef(id);
+ prop.first = propertyWriteValue(id, value);
+ prop.second = true;
activate(d->object, id + d->type->d->signalOffset, 0);
}
@@ -354,6 +354,11 @@ void QQmlOpenMetaObject::propertyWrite(int)
{
}
+QVariant QQmlOpenMetaObject::propertyWriteValue(int, const QVariant &value)
+{
+ return value;
+}
+
void QQmlOpenMetaObject::propertyWritten(int)
{
}
diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h
index 188192edc1..a45d7d8259 100644
--- a/src/qml/qml/qqmlopenmetaobject_p.h
+++ b/src/qml/qml/qqmlopenmetaobject_p.h
@@ -113,6 +113,7 @@ protected:
virtual void propertyRead(int);
virtual void propertyWrite(int);
+ virtual QVariant propertyWriteValue(int, const QVariant &);
virtual void propertyWritten(int);
virtual void propertyCreated(int, QMetaPropertyBuilder &);
diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp
index 1571d2dfc9..cdc82fe86e 100644
--- a/src/qml/util/qqmlpropertymap.cpp
+++ b/src/qml/util/qqmlpropertymap.cpp
@@ -56,9 +56,13 @@ public:
QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv);
protected:
+ virtual QVariant propertyWriteValue(int, const QVariant &);
virtual void propertyWritten(int index);
virtual void propertyCreated(int, QMetaPropertyBuilder &);
virtual int createProperty(const char *, const char *);
+
+ const QString &propertyName(int index);
+
private:
QQmlPropertyMap *map;
QQmlPropertyMapPrivate *priv;
@@ -70,8 +74,12 @@ class QQmlPropertyMapPrivate : public QObjectPrivate
public:
QQmlPropertyMapMetaObject *mo;
QStringList keys;
+
+ QVariant updateValue(const QString &key, const QVariant &input);
void emitChanged(const QString &key, const QVariant &value);
bool validKeyName(const QString& name);
+
+ const QString &propertyName(int index) const;
};
bool QQmlPropertyMapPrivate::validKeyName(const QString& name)
@@ -84,21 +92,38 @@ bool QQmlPropertyMapPrivate::validKeyName(const QString& name)
&& name != QLatin1String("deleteLater");
}
+QVariant QQmlPropertyMapPrivate::updateValue(const QString &key, const QVariant &input)
+{
+ Q_Q(QQmlPropertyMap);
+ return q->updateValue(key, input);
+}
+
void QQmlPropertyMapPrivate::emitChanged(const QString &key, const QVariant &value)
{
Q_Q(QQmlPropertyMap);
emit q->valueChanged(key, value);
}
+const QString &QQmlPropertyMapPrivate::propertyName(int index) const
+{
+ Q_ASSERT(index < keys.size());
+ return keys[index];
+}
+
QQmlPropertyMapMetaObject::QQmlPropertyMapMetaObject(QQmlPropertyMap *obj, QQmlPropertyMapPrivate *objPriv) : QQmlOpenMetaObject(obj)
{
map = obj;
priv = objPriv;
}
+QVariant QQmlPropertyMapMetaObject::propertyWriteValue(int index, const QVariant &input)
+{
+ return priv->updateValue(priv->propertyName(index), input);
+}
+
void QQmlPropertyMapMetaObject::propertyWritten(int index)
{
- priv->emitChanged(QString::fromUtf8(name(index)), operator[](index));
+ priv->emitChanged(priv->propertyName(index), operator[](index));
}
void QQmlPropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilder &b)
@@ -298,6 +323,18 @@ QVariant QQmlPropertyMap::operator[](const QString &key) const
}
/*!
+ Returns the new value to be stored for the key \a key. This function is provided
+ to intercept updates to a property from QML, where the value provided from QML is \a input.
+
+ Override this function to manipulate the property value as it is updated. Note that
+ this function is only invoked when the value is updated from QML.
+*/
+QVariant QQmlPropertyMap::updateValue(const QString &key, const QVariant &input)
+{
+ return input;
+}
+
+/*!
\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
is the key corresponding to the \a value that was changed.
diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h
index 53254ab672..bfd11e5c80 100644
--- a/src/qml/util/qqmlpropertymap.h
+++ b/src/qml/util/qqmlpropertymap.h
@@ -79,6 +79,9 @@ public:
Q_SIGNALS:
void valueChanged(const QString &key, const QVariant &value);
+protected:
+ virtual QVariant updateValue(const QString &key, const QVariant &input);
+
private:
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 0ae05ce138..4e39ad3a41 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -45,6 +45,7 @@
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QSignalSpy>
+#include <QDebug>
class tst_QQmlPropertyMap : public QObject
{
@@ -59,6 +60,7 @@ private slots:
void clear();
void changed();
void count();
+ void controlledWrite();
void crashBug();
void QTBUG_17868();
@@ -205,6 +207,48 @@ void tst_QQmlPropertyMap::count()
QCOMPARE(map.size(), map.count());
}
+class MyPropertyMap : public QQmlPropertyMap
+{
+ Q_OBJECT
+protected:
+ virtual QVariant updateValue(const QString &key, const QVariant &src)
+ {
+ if (key == QLatin1String("key1")) {
+ // 'key1' must be all uppercase
+ const QString original(src.toString());
+ return QVariant(original.toUpper());
+ }
+
+ return src;
+ }
+};
+
+void tst_QQmlPropertyMap::controlledWrite()
+{
+ MyPropertyMap map;
+ QCOMPARE(map.isEmpty(), true);
+
+ //make changes in QML
+ QQmlEngine engine;
+ QQmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty(QLatin1String("testdata"), &map);
+
+ const char *qmlSource =
+ "import QtQuick 2.0\n"
+ "Item { Component.onCompleted: { testdata.key1 = 'Hello World'; testdata.key2 = 'Goodbye' } }";
+
+ QQmlComponent component(&engine);
+ component.setData(qmlSource, QUrl::fromLocalFile(""));
+ QVERIFY(component.isReady());
+
+ QObject *obj = component.create();
+ QVERIFY(obj);
+ delete obj;
+
+ QCOMPARE(map.value(QLatin1String("key1")), QVariant("HELLO WORLD"));
+ QCOMPARE(map.value(QLatin1String("key2")), QVariant("Goodbye"));
+}
+
void tst_QQmlPropertyMap::crashBug()
{
QQmlPropertyMap map;