summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2010-10-14 08:22:57 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2010-10-14 08:23:52 (GMT)
commitc407d79f79c67f2f2bb84efc93061fd57fe4cf54 (patch)
treed56dcae60c345acaf5d4e3a0251dde99785b3ec6
parent1048ac9f491bf2e79c469d0451e437a1a485bef5 (diff)
downloadQt-c407d79f79c67f2f2bb84efc93061fd57fe4cf54.zip
Qt-c407d79f79c67f2f2bb84efc93061fd57fe4cf54.tar.gz
Qt-c407d79f79c67f2f2bb84efc93061fd57fe4cf54.tar.bz2
Correctly splice properties from derived metaobjects together
Task-number: QTBUG-14449
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp77
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h9
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml10
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp1
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/testtypes.h9
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp13
6 files changed, 61 insertions, 58 deletions
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 9e1ceb8..82fa98f 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -252,7 +252,8 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
}
int methodCount = metaObject->methodCount();
- int methodOffset = qMax(2, metaObject->methodOffset()); // 2 to block the destroyed signal
+ // 3 to block the destroyed signal and the deleteLater() slot
+ int methodOffset = qMax(3, metaObject->methodOffset());
methodIndexCache.resize(methodCount);
for (int ii = methodOffset; ii < methodCount; ++ii) {
@@ -268,17 +269,17 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
RData *data = new RData;
data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
- if (stringCache.contains(methodName)) {
- stringCache[methodName]->release();
- identifierCache[data->identifier.identifier]->release();
- }
-
data->load(m);
if (m.methodType() == QMetaMethod::Slot || m.methodType() == QMetaMethod::Method)
data->flags |= methodFlags;
else if (m.methodType() == QMetaMethod::Signal)
data->flags |= signalFlags;
+ if (stringCache.contains(methodName)) {
+ stringCache[methodName]->release();
+ identifierCache[data->identifier.identifier]->release();
+ }
+
methodIndexCache[ii] = data;
stringCache.insert(methodName, data);
@@ -287,6 +288,16 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
}
}
+void QDeclarativePropertyCache::updateRecur(QDeclarativeEngine *engine, const QMetaObject *metaObject)
+{
+ if (!metaObject)
+ return;
+
+ updateRecur(engine, metaObject->superClass());
+
+ append(engine, metaObject);
+}
+
void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaObject *metaObject)
{
Q_ASSERT(engine);
@@ -295,57 +306,11 @@ void QDeclarativePropertyCache::update(QDeclarativeEngine *engine, const QMetaOb
clear();
- // ### The properties/methods should probably be spliced on a per-metaobject basis
- int propCount = metaObject->propertyCount();
-
- indexCache.resize(propCount);
- for (int ii = propCount - 1; ii >= 0; --ii) {
- QMetaProperty p = metaObject->property(ii);
- if (!p.isScriptable()) {
- indexCache[ii] = 0;
- continue;
- }
- QString propName = QString::fromUtf8(p.name());
+ // Optimization to prevent unnecessary reallocation of lists
+ indexCache.reserve(metaObject->propertyCount());
+ methodIndexCache.reserve(metaObject->methodCount());
- RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
-
- data->load(p, engine);
-
- indexCache[ii] = data;
-
- if (stringCache.contains(propName))
- continue;
-
- stringCache.insert(propName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
- data->addref();
- }
-
- int methodCount = metaObject->methodCount();
- for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot
- QMetaMethod m = metaObject->method(ii);
- if (m.access() == QMetaMethod::Private)
- continue;
- QString methodName = QString::fromUtf8(m.signature());
-
- int parenIdx = methodName.indexOf(QLatin1Char('('));
- Q_ASSERT(parenIdx != -1);
- methodName = methodName.left(parenIdx);
-
- if (stringCache.contains(methodName))
- continue;
-
- RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
-
- data->load(m);
-
- stringCache.insert(methodName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
- }
+ updateRecur(engine,metaObject);
}
QDeclarativePropertyCache::Data *
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 79b126d..922010d 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -96,7 +96,7 @@ public:
IsVMEFunction = 0x00000400,
HasArguments = 0x00000800,
IsSignal = 0x00001000,
- IsVMESignal = 0x00002000,
+ IsVMESignal = 0x00002000
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -105,7 +105,10 @@ public:
Flags flags;
int propType;
int coreIndex;
- int notifyIndex;
+ union {
+ int notifyIndex; // When !IsFunction
+ int relatedIndex; // When IsFunction
+ };
static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0);
void load(const QMetaProperty &, QDeclarativeEngine *engine = 0);
@@ -152,6 +155,8 @@ private:
typedef QHash<QString, RData *> StringCache;
typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+ void updateRecur(QDeclarativeEngine *, const QMetaObject *);
+
QDeclarativeEngine *engine;
IndexCache indexCache;
IndexCache methodIndexCache;
diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml b/tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml
new file mode 100644
index 0000000..7deb84a
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeecmascript/data/propertySplicing.qml
@@ -0,0 +1,10 @@
+import Qt.test 1.0
+import QtQuick 1.0
+
+MyDerivedObject {
+ property bool test: false
+
+ Component.onCompleted: {
+ test = intProperty()
+ }
+}
diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
index 810a0f7..94135f9 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp
@@ -109,6 +109,7 @@ void registerTypes()
qmlRegisterExtendedType<MyBaseExtendedObject, BaseExtensionObject>("Qt.test", 1,0, "MyBaseExtendedObject");
qmlRegisterExtendedType<MyExtendedObject, ExtensionObject>("Qt.test", 1,0, "MyExtendedObject");
qmlRegisterType<MyTypeObject>("Qt.test", 1,0, "MyTypeObject");
+ qmlRegisterType<MyDerivedObject>("Qt.test", 1,0, "MyDerivedObject");
qmlRegisterType<NumberAssignment>("Qt.test", 1,0, "NumberAssignment");
qmlRegisterExtendedType<DefaultPropertyExtendedObject, DefaultPropertyExtensionObject>("Qt.test", 1,0, "DefaultPropertyExtendedObject");
qmlRegisterType<OverrideDefaultPropertyObject>("Qt.test", 1,0, "OverrideDefaultPropertyObject");
diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
index 220318d..182c4fa 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
+++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h
@@ -562,6 +562,15 @@ signals:
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MyTypeObject::MyFlags)
+class MyDerivedObject : public MyTypeObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE bool intProperty() const {
+ return true;
+ }
+};
+
Q_DECLARE_METATYPE(QScriptValue);
class MyInvokableObject : public QObject
{
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 02832f3..66dc160 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -139,6 +139,7 @@ private slots:
void strictlyEquals();
void compiled();
void numberAssignment();
+ void propertySplicing();
void bug1();
void bug2();
@@ -2175,6 +2176,18 @@ void tst_qdeclarativeecmascript::numberAssignment()
delete object;
}
+void tst_qdeclarativeecmascript::propertySplicing()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+}
+
// Test that assigning a null object works
// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
void tst_qdeclarativeecmascript::nullObjectBinding()