From 48ea5a5c74620f9811debc6bf1e49bf095d30722 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 4 Nov 2009 15:49:26 +1000 Subject: tests --- src/declarative/qml/qmlmetaproperty.cpp | 112 +-- src/declarative/qml/qmlmetaproperty.h | 6 +- src/declarative/qml/qmlmetaproperty_p.h | 5 +- tests/auto/declarative/qmllanguage/qmllanguage.pro | 1 + .../declarative/qmllanguage/tst_qmllanguage.cpp | 5 +- .../qmlmetaproperty/tst_qmlmetaproperty.cpp | 820 ++++++++++++++++++++- 6 files changed, 856 insertions(+), 93 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 8385352..28878b8 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -111,27 +111,12 @@ void QmlMetaPropertyPrivate::initDefault(QObject *obj) if (!obj) return; - object = obj; QMetaProperty p = QmlMetaType::defaultProperty(obj); core.load(p); - if (core.isValid()) + if (core.isValid()) { isDefaultProperty = true; -} - -/*! - \internal - - Creates a QmlMetaProperty for the property at index \a idx of \a obj. - */ -QmlMetaProperty::QmlMetaProperty(QObject *obj, int idx, QmlContext *ctxt) -: d(new QmlMetaPropertyPrivate) -{ - Q_ASSERT(obj); - - d->q = this; - d->context = ctxt; - d->object = obj; - d->core.load(obj->metaObject()->property(idx)); + object = obj; + } } /*! @@ -142,6 +127,7 @@ QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name) { d->q = this; d->initProperty(obj, name); + if (!isValid()) d->object = 0; } /*! @@ -154,6 +140,7 @@ QmlMetaProperty::QmlMetaProperty(QObject *obj, const QString &name, QmlContext * d->q = this; d->context = ctxt; d->initProperty(obj, name); + if (!isValid()) { d->object = 0; d->context = 0; } } void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) @@ -425,12 +412,14 @@ bool QmlMetaProperty::isWritable() const { QmlMetaProperty::PropertyCategory category = propertyCategory(); + if (!d->object) + return false; if (category == List || category == QmlList) return true; else if (type() & SignalProperty) - return true; + return false; else if (d->core.isValid() && d->object) - return d->object->metaObject()->property(d->core.coreIndex).isWritable(); + return d->core.flags & QmlPropertyCache::Data::IsWritable; else return false; } @@ -456,25 +445,6 @@ bool QmlMetaProperty::isValid() const } /*! - Returns all of \a obj's Qt properties. -*/ -QStringList QmlMetaProperty::properties(QObject *obj) -{ - // ### What is this used for? - if (!obj) - return QStringList(); - - QStringList rv; - const QMetaObject *mo = obj->metaObject(); - for (int ii = 0; ii < mo->propertyCount(); ++ii) { - QMetaProperty prop = mo->property(ii); - rv << QString::fromUtf8(prop.name()); - } - - return rv; -} - -/*! Return the name of this QML property. */ QString QmlMetaProperty::name() const @@ -494,7 +464,13 @@ QString QmlMetaProperty::name() const return rv; } else { - return d->core.name; + if (type() & SignalProperty) { + QString name = QLatin1String("on") + d->core.name; + name[2] = name.at(2).toUpper(); + return name; + } else { + return d->core.name; + } } } @@ -562,8 +538,10 @@ QmlAbstractBinding *QmlMetaProperty::binding() const QmlAbstractBinding * QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) const { - if (!isProperty() || (type() & Attached) || !d->object) + if (!isProperty() || (type() & Attached) || !d->object) { + delete newBinding; return 0; + } return d->setBinding(d->object, d->core, newBinding, flags); } @@ -627,8 +605,10 @@ QmlExpression *QmlMetaProperty::signalExpression() const */ QmlExpression *QmlMetaProperty::setSignalExpression(QmlExpression *expr) const { - if (!(type() & SignalProperty)) + if (!(type() & SignalProperty)) { + delete expr; return 0; + } const QObjectList &children = d->object->children(); @@ -683,13 +663,7 @@ QVariant QmlMetaProperty::read() const if (type() & SignalProperty) { - const QObjectList &children = object()->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii)); - if (sig && sig->index() == d->core.coreIndex) - return sig->expression()->expression(); - } + return QVariant(); } else if (type() & Property) { @@ -854,7 +828,7 @@ bool QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data return false; if (context && u.isRelative() && !u.isEmpty()) - u = context->baseUrl().resolved(u); + u = context->resolvedUrl(u); int status = -1; void *argv[] = { &u, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); @@ -987,7 +961,7 @@ bool QmlMetaProperty::write(const QVariant &value) const bool QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const { - if (d->object && type() & Property && d->core.isValid()) + if (d->object && type() & Property && d->core.isValid() && isWritable()) return d->writeValueProperty(value, flags); else return false; @@ -1080,27 +1054,6 @@ Q_GLOBAL_STATIC(QmlValueTypeFactory, qmlValueTypes); Returns the property information serialized into a single integer. QmlMetaProperty uses the bottom 24 bits only. */ -quint32 QmlMetaProperty::save() const -{ - quint32 rv = 0; - if (type() & Attached) { - rv = d->attachedFunc; - } else if (type() != Invalid) { - rv = d->core.coreIndex; - } - - Q_ASSERT(rv <= 0x7FF); - Q_ASSERT(type() <= 0x3F); - Q_ASSERT(d->valueTypeCoreIdx <= 0x7F); - - rv |= (type() << 18); - - if (type() & ValueTypeProperty) - rv |= (d->valueTypeCoreIdx << 11); - - return rv; -} - quint32 QmlMetaPropertyPrivate::saveValueType(int core, int valueType) { Q_ASSERT(core <= 0x7FF); @@ -1127,8 +1080,11 @@ quint32 QmlMetaPropertyPrivate::saveProperty(int core) to QmlMetaProperty::save(). Only the bottom 24-bits are used, the high bits can be set to any value. */ -void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) +void QmlMetaPropertyPrivate::restore(QmlMetaProperty &prop, quint32 id, + QObject *obj, QmlContext *ctxt) { + QmlMetaPropertyPrivate *d = prop.d; + QmlEnginePrivate *enginePrivate = 0; if (ctxt && ctxt->engine()) enginePrivate = QmlEnginePrivate::get(ctxt->engine()); @@ -1140,9 +1096,9 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) uint type = id >> 18; id &= 0xFFFF; - if (type & Attached) { + if (type & QmlMetaProperty::Attached) { d->attachedFunc = id; - } else if (type & ValueTypeProperty) { + } else if (type & QmlMetaProperty::ValueTypeProperty) { int coreIdx = id & 0x7FF; int valueTypeIdx = id >> 11; @@ -1156,7 +1112,7 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) d->core.load(p); d->valueTypeCoreIdx = valueTypeIdx; d->valueTypePropType = p2.userType(); - } else if (type & Property) { + } else if (type & QmlMetaProperty::Property) { QmlPropertyCache *cache = enginePrivate?enginePrivate->cache(obj):0; @@ -1168,12 +1124,12 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) d->core.load(p); } - } else if (type & SignalProperty) { + } else if (type & QmlMetaProperty::SignalProperty) { QMetaMethod method = obj->metaObject()->method(id); d->core.load(method); } else { - *this = QmlMetaProperty(); + prop = QmlMetaProperty(); } } diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index ce4ac1e..6db99c6 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -79,10 +79,8 @@ public: QmlMetaProperty(QObject *, const QString &, QmlContext *); QmlMetaProperty(const QmlMetaProperty &); QmlMetaProperty &operator=(const QmlMetaProperty &); - QmlMetaProperty(QObject *, int, QmlContext * = 0); ~QmlMetaProperty(); - static QStringList properties(QObject *); QString name() const; QVariant read() const; @@ -96,9 +94,6 @@ public: bool connectNotifier(QObject *dest, const char *slot) const; bool connectNotifier(QObject *dest, int method) const; - quint32 save() const; - void restore(quint32, QObject *, QmlContext * = 0); - QMetaMethod method() const; enum Type { Invalid = 0x00, @@ -138,6 +133,7 @@ public: int valueTypeCoreIndex() const; private: friend class QmlEnginePrivate; + friend class QmlMetaPropertyPrivate;; QmlMetaPropertyPrivate *d; }; typedef QList QmlMetaProperties; diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 925f1ea..d225afa 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -104,8 +104,9 @@ public: static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *, QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding); - static quint32 saveValueType(int, int); - static quint32 saveProperty(int); + static void Q_AUTOTEST_EXPORT restore(QmlMetaProperty &prop, quint32, QObject *, QmlContext * = 0); + static quint32 Q_AUTOTEST_EXPORT saveValueType(int, int); + static quint32 Q_AUTOTEST_EXPORT saveProperty(int); static bool equal(const QMetaObject *, const QMetaObject *); static bool canConvert(const QMetaObject *from, const QMetaObject *to); diff --git a/tests/auto/declarative/qmllanguage/qmllanguage.pro b/tests/auto/declarative/qmllanguage/qmllanguage.pro index 80228a9..e45d73a 100644 --- a/tests/auto/declarative/qmllanguage/qmllanguage.pro +++ b/tests/auto/declarative/qmllanguage/qmllanguage.pro @@ -1,5 +1,6 @@ load(qttest_p4) contains(QT_CONFIG,declarative): QT += declarative +QT += script macx:CONFIG -= app_bundle SOURCES += tst_qmllanguage.cpp \ diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 8e0dd3e..c82aa4d 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "testtypes.h" #include "../../../shared/util.h" @@ -638,9 +639,9 @@ void tst_qmllanguage::valueTypes() p.write(13); QCOMPARE(p.read(), QVariant(13)); - quint32 r = p.save(); + quint32 r = QmlMetaPropertyPrivate::saveValueType(p.coreIndex(), p.valueTypeCoreIndex()); QmlMetaProperty p2; - p2.restore(r, object); + QmlMetaPropertyPrivate::restore(p2, r, object); QCOMPARE(p2.read(), QVariant(13)); } diff --git a/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp index 52c673f..7fbffdb 100644 --- a/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp +++ b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include class MyQmlObject : public QObject @@ -73,13 +75,27 @@ private: QML_DECLARE_TYPE(MyContainer); QML_DEFINE_TYPE(Test,1,0,0,MyContainer,MyContainer); -class tst_QmlMetaProperty : public QObject +class tst_qmlmetaproperty : public QObject { Q_OBJECT public: - tst_QmlMetaProperty() {} + tst_qmlmetaproperty() {} private slots: + + // Constructors + void qmlmetaproperty(); + void qmlmetaproperty_object(); + void qmlmetaproperty_object_string(); + void qmlmetaproperty_object_context(); + void qmlmetaproperty_object_string_context(); + + // Methods + void name(); + void read(); + void write(); + + // Functionality void writeObjectToList(); void writeListToList(); void writeObjectToQmlList(); @@ -90,7 +106,799 @@ private: QmlEngine engine; }; -void tst_QmlMetaProperty::writeObjectToList() +void tst_qmlmetaproperty::qmlmetaproperty() +{ + QmlMetaProperty prop; + + QGuard binding(new QmlBinding(QString(), 0, 0)); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString()); + QCOMPARE(prop.read(), QVariant()); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), false); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), QmlMetaProperty::Invalid); + QCOMPARE(prop.isProperty(), false); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), false); + QCOMPARE(prop.isValid(), false); + QCOMPARE(prop.object(), (QObject *)0); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty); + QCOMPARE(prop.propertyType(), 0); + QCOMPARE(prop.propertyTypeName(), (const char *)0); + QVERIFY(prop.property().name() == 0); + QVERIFY(prop.binding() == 0); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding == 0); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), -1); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; +} + +class PropertyObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int defaultProperty READ defaultProperty); + Q_PROPERTY(QRect rectProperty READ rectProperty); + Q_PROPERTY(QRect wrectProperty READ wrectProperty WRITE setWRectProperty); + Q_PROPERTY(QUrl url READ url WRITE setUrl); + + Q_CLASSINFO("DefaultProperty", "defaultProperty"); +public: + int defaultProperty() { return 10; } + QRect rectProperty() { return QRect(10, 10, 1, 209); } + + QRect wrectProperty() { return m_rect; } + void setWRectProperty(const QRect &r) { m_rect = r; } + + QUrl url() { return m_url; } + void setUrl(const QUrl &u) { m_url = u; } + +signals: + void clicked(); + +private: + QRect m_rect; + QUrl m_url; +}; + +void tst_qmlmetaproperty::qmlmetaproperty_object() +{ + QObject object; // Has no default property + PropertyObject dobject; // Has default property + + { + QmlMetaProperty prop(&object); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString()); + QCOMPARE(prop.read(), QVariant()); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), false); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), QmlMetaProperty::Invalid); + QCOMPARE(prop.isProperty(), false); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), false); + QCOMPARE(prop.isValid(), false); + QCOMPARE(prop.object(), (QObject *)0); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty); + QCOMPARE(prop.propertyType(), 0); + QCOMPARE(prop.propertyTypeName(), (const char *)0); + QVERIFY(prop.property().name() == 0); + QVERIFY(prop.binding() == 0); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding == 0); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), -1); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } + + { + QmlMetaProperty prop(&dobject); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + binding->setTarget(prop); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString("defaultProperty")); + QCOMPARE(prop.read(), QVariant(10)); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), true); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), (QmlMetaProperty::Type)(QmlMetaProperty::Property | QmlMetaProperty::Default)); + QCOMPARE(prop.isProperty(), true); + QCOMPARE(prop.isDefault(), true); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), true); + QCOMPARE(prop.isValid(), true); + QCOMPARE(prop.object(), &dobject); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal); + QCOMPARE(prop.propertyType(), (int)QVariant::Int); + QCOMPARE(prop.propertyTypeName(), "int"); + QCOMPARE(QString(prop.property().name()), QString("defaultProperty")); + QVERIFY(prop.binding() == 0); + QTest::ignoreMessage(QtWarningMsg, ":-1: Unable to assign null to int"); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding != 0); + QVERIFY(prop.binding() == binding); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty")); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } +} + +void tst_qmlmetaproperty::qmlmetaproperty_object_string() +{ + QObject object; + PropertyObject dobject; + + { + QmlMetaProperty prop(&object, QString("defaultProperty")); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString()); + QCOMPARE(prop.read(), QVariant()); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), false); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), QmlMetaProperty::Invalid); + QCOMPARE(prop.isProperty(), false); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), false); + QCOMPARE(prop.isValid(), false); + QCOMPARE(prop.object(), (QObject *)0); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty); + QCOMPARE(prop.propertyType(), 0); + QCOMPARE(prop.propertyTypeName(), (const char *)0); + QVERIFY(prop.property().name() == 0); + QVERIFY(prop.binding() == 0); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding == 0); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), -1); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } + + { + QmlMetaProperty prop(&dobject, QString("defaultProperty")); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + binding->setTarget(prop); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString("defaultProperty")); + QCOMPARE(prop.read(), QVariant(10)); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), true); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), QmlMetaProperty::Property); + QCOMPARE(prop.isProperty(), true); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), true); + QCOMPARE(prop.isValid(), true); + QCOMPARE(prop.object(), &dobject); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal); + QCOMPARE(prop.propertyType(), (int)QVariant::Int); + QCOMPARE(prop.propertyTypeName(), "int"); + QCOMPARE(QString(prop.property().name()), QString("defaultProperty")); + QVERIFY(prop.binding() == 0); + QTest::ignoreMessage(QtWarningMsg, ":-1: Unable to assign null to int"); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding != 0); + QVERIFY(prop.binding() == binding); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty")); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } + + { + QmlMetaProperty prop(&dobject, QString("onClicked")); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + binding->setTarget(prop); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString("onClicked")); + QCOMPARE(prop.read(), QVariant()); + QCOMPARE(prop.write(QVariant("Hello")), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), false); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QCOMPARE(QString(prop.method().signature()), QString("clicked()")); + QCOMPARE(prop.type(), QmlMetaProperty::SignalProperty); + QCOMPARE(prop.isProperty(), false); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), false); + QCOMPARE(prop.isValid(), true); + QCOMPARE(prop.object(), &dobject); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty); + QCOMPARE(prop.propertyType(), 0); + QCOMPARE(prop.propertyTypeName(), (const char *)0); + QCOMPARE(prop.property().name(), (const char *)0); + QVERIFY(prop.binding() == 0); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding == 0); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression != 0); + QVERIFY(prop.signalExpression() == expression); + QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfMethod("clicked()")); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } +} + +void tst_qmlmetaproperty::qmlmetaproperty_object_context() +{ + QObject object; // Has no default property + PropertyObject dobject; // Has default property + + { + QmlMetaProperty prop(&object, engine.rootContext()); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString()); + QCOMPARE(prop.read(), QVariant()); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), false); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), QmlMetaProperty::Invalid); + QCOMPARE(prop.isProperty(), false); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), false); + QCOMPARE(prop.isValid(), false); + QCOMPARE(prop.object(), (QObject *)0); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty); + QCOMPARE(prop.propertyType(), 0); + QCOMPARE(prop.propertyTypeName(), (const char *)0); + QVERIFY(prop.property().name() == 0); + QVERIFY(prop.binding() == 0); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding == 0); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), -1); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } + + { + QmlMetaProperty prop(&dobject, engine.rootContext()); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + binding->setTarget(prop); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString("defaultProperty")); + QCOMPARE(prop.read(), QVariant(10)); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), true); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), (QmlMetaProperty::Type)(QmlMetaProperty::Property | QmlMetaProperty::Default)); + QCOMPARE(prop.isProperty(), true); + QCOMPARE(prop.isDefault(), true); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), true); + QCOMPARE(prop.isValid(), true); + QCOMPARE(prop.object(), &dobject); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal); + QCOMPARE(prop.propertyType(), (int)QVariant::Int); + QCOMPARE(prop.propertyTypeName(), "int"); + QCOMPARE(QString(prop.property().name()), QString("defaultProperty")); + QVERIFY(prop.binding() == 0); + QTest::ignoreMessage(QtWarningMsg, ":-1: Unable to assign null to int"); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding != 0); + QVERIFY(prop.binding() == binding); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty")); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } +} + +void tst_qmlmetaproperty::qmlmetaproperty_object_string_context() +{ + QObject object; + PropertyObject dobject; + + { + QmlMetaProperty prop(&object, QString("defaultProperty"), engine.rootContext()); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString()); + QCOMPARE(prop.read(), QVariant()); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), false); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), QmlMetaProperty::Invalid); + QCOMPARE(prop.isProperty(), false); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), false); + QCOMPARE(prop.isValid(), false); + QCOMPARE(prop.object(), (QObject *)0); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty); + QCOMPARE(prop.propertyType(), 0); + QCOMPARE(prop.propertyTypeName(), (const char *)0); + QVERIFY(prop.property().name() == 0); + QVERIFY(prop.binding() == 0); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding == 0); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), -1); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } + + { + QmlMetaProperty prop(&dobject, QString("defaultProperty"), engine.rootContext()); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + binding->setTarget(prop); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString("defaultProperty")); + QCOMPARE(prop.read(), QVariant(10)); + QCOMPARE(prop.write(QVariant()), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), true); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QVERIFY(prop.method().signature() == 0); + QCOMPARE(prop.type(), QmlMetaProperty::Property); + QCOMPARE(prop.isProperty(), true); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), true); + QCOMPARE(prop.isValid(), true); + QCOMPARE(prop.object(), &dobject); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::Normal); + QCOMPARE(prop.propertyType(), (int)QVariant::Int); + QCOMPARE(prop.propertyTypeName(), "int"); + QCOMPARE(QString(prop.property().name()), QString("defaultProperty")); + QVERIFY(prop.binding() == 0); + QTest::ignoreMessage(QtWarningMsg, ":-1: Unable to assign null to int"); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding != 0); + QVERIFY(prop.binding() == binding); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression == 0); + QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfProperty("defaultProperty")); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } + + { + QmlMetaProperty prop(&dobject, QString("onClicked"), engine.rootContext()); + + QGuard binding(new QmlBinding(QString(), 0, 0)); + binding->setTarget(prop); + QVERIFY(binding != 0); + QGuard expression(new QmlExpression()); + QVERIFY(expression != 0); + + QObject *obj = new QObject; + + QCOMPARE(prop.name(), QString("onClicked")); + QCOMPARE(prop.read(), QVariant()); + QCOMPARE(prop.write(QVariant("Hello")), false); + QCOMPARE(prop.hasChangedNotifier(), false); + QCOMPARE(prop.needsChangedNotifier(), false); + QCOMPARE(prop.connectNotifier(0, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, SLOT(deleteLater())), false); + QCOMPARE(prop.connectNotifier(obj, 0), false); + QCOMPARE(prop.connectNotifier(0, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, obj->metaObject()->indexOfMethod("deleteLater()")), false); + QCOMPARE(prop.connectNotifier(obj, -1), false); + QCOMPARE(QString(prop.method().signature()), QString("clicked()")); + QCOMPARE(prop.type(), QmlMetaProperty::SignalProperty); + QCOMPARE(prop.isProperty(), false); + QCOMPARE(prop.isDefault(), false); + QCOMPARE(prop.isWritable(), false); + QCOMPARE(prop.isDesignable(), false); + QCOMPARE(prop.isValid(), true); + QCOMPARE(prop.object(), &dobject); + QCOMPARE(prop.propertyCategory(), QmlMetaProperty::InvalidProperty); + QCOMPARE(prop.propertyType(), 0); + QCOMPARE(prop.propertyTypeName(), (const char *)0); + QCOMPARE(prop.property().name(), (const char *)0); + QVERIFY(prop.binding() == 0); + QVERIFY(prop.setBinding(binding) == 0); + QVERIFY(binding == 0); + QVERIFY(prop.signalExpression() == 0); + QVERIFY(prop.setSignalExpression(expression) == 0); + QVERIFY(expression != 0); + QVERIFY(prop.signalExpression() == expression); + QCOMPARE(prop.coreIndex(), dobject.metaObject()->indexOfMethod("clicked()")); + QCOMPARE(prop.valueTypeCoreIndex(), -1); + + delete obj; + } +} + +void tst_qmlmetaproperty::name() +{ + { + QmlMetaProperty p; + QCOMPARE(p.name(), QString()); + } + + { + PropertyObject o; + QmlMetaProperty p(&o); + QCOMPARE(p.name(), QString("defaultProperty")); + } + + { + QObject o; + QmlMetaProperty p(&o, QString("objectName")); + QCOMPARE(p.name(), QString("objectName")); + } + + { + PropertyObject o; + QmlMetaProperty p(&o, "onClicked"); + QCOMPARE(p.name(), QString("onClicked")); + } + + { + QObject o; + QmlMetaProperty p(&o, "onClicked"); + QCOMPARE(p.name(), QString()); + } + + { + QObject o; + QmlMetaProperty p(&o, "foo"); + QCOMPARE(p.name(), QString()); + } + + { + QmlMetaProperty p(0, "foo"); + QCOMPARE(p.name(), QString()); + } + + { + PropertyObject o; + QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty"); + QCOMPARE(p.name(), QString("rectProperty")); + } + + { + PropertyObject o; + QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.x"); + QCOMPARE(p.name(), QString("rectProperty.x")); + } + + { + PropertyObject o; + QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.foo"); + QCOMPARE(p.name(), QString()); + } +} + +void tst_qmlmetaproperty::read() +{ + // Invalid + { + QmlMetaProperty p; + QCOMPARE(p.read(), QVariant()); + } + + // Default prop + { + PropertyObject o; + QmlMetaProperty p(&o); + QCOMPARE(p.read(), QVariant(10)); + } + + // Invalid default prop + { + QObject o; + QmlMetaProperty p(&o); + QCOMPARE(p.read(), QVariant()); + } + + // Value prop by name + { + QObject o; + + QmlMetaProperty p(&o, "objectName"); + QCOMPARE(p.read(), QVariant(QString())); + + o.setObjectName("myName"); + + QCOMPARE(p.read(), QVariant("myName")); + } + + // Value-type prop + { + PropertyObject o; + QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.x"); + QCOMPARE(p.read(), QVariant(10)); + } + + // Invalid value-type prop + { + PropertyObject o; + QmlMetaProperty p = QmlMetaProperty::createProperty(&o, "rectProperty.foo"); + QCOMPARE(p.read(), QVariant()); + } + + // Signal property + { + PropertyObject o; + QmlMetaProperty p(&o, "onClicked"); + QCOMPARE(p.read(), QVariant()); + + QVERIFY(0 == p.setSignalExpression(new QmlExpression())); + QVERIFY(0 != p.signalExpression()); + + QCOMPARE(p.read(), QVariant()); + } + + // Deleted object + { + PropertyObject *o = new PropertyObject; + QmlMetaProperty p = QmlMetaProperty::createProperty(o, "rectProperty.x"); + QCOMPARE(p.read(), QVariant(10)); + delete o; + QCOMPARE(p.read(), QVariant()); + } +} + +void tst_qmlmetaproperty::write() +{ + // Invalid + { + QmlMetaProperty p; + QCOMPARE(p.write(QVariant(10)), false); + } + + // Read-only default prop + { + PropertyObject o; + QmlMetaProperty p(&o); + QCOMPARE(p.write(QVariant(10)), false); + } + + // Invalid default prop + { + QObject o; + QmlMetaProperty p(&o); + QCOMPARE(p.write(QVariant(10)), false); + } + + // Read-only prop by name + { + PropertyObject o; + QmlMetaProperty p(&o, QString("defaultProperty")); + QCOMPARE(p.write(QVariant(10)), false); + } + + // Writable prop by name + { + PropertyObject o; + QmlMetaProperty p(&o, QString("objectName")); + QCOMPARE(o.objectName(), QString()); + QCOMPARE(p.write(QVariant(QString("myName"))), true); + QCOMPARE(o.objectName(), QString("myName")); + } + + // Deleted object + { + PropertyObject *o = new PropertyObject; + QmlMetaProperty p(o, QString("objectName")); + QCOMPARE(p.write(QVariant(QString("myName"))), true); + QCOMPARE(o->objectName(), QString("myName")); + + delete o; + + QCOMPARE(p.write(QVariant(QString("myName"))), false); + } + + // Signal property + { + PropertyObject o; + QmlMetaProperty p(&o, "onClicked"); + QCOMPARE(p.write(QVariant("print(1921)")), false); + + QVERIFY(0 == p.setSignalExpression(new QmlExpression())); + QVERIFY(0 != p.signalExpression()); + + QCOMPARE(p.write(QVariant("print(1921)")), false); + + QVERIFY(0 != p.signalExpression()); + } + + // Value-type property + { + PropertyObject o; + QmlMetaProperty p(&o, "wrectProperty"); + + QCOMPARE(o.wrectProperty(), QRect()); + QCOMPARE(p.write(QRect(1, 13, 99, 8)), true); + QCOMPARE(o.wrectProperty(), QRect(1, 13, 99, 8)); + + QmlMetaProperty p2 = QmlMetaProperty::createProperty(&o, "wrectProperty.x"); + QCOMPARE(p2.read(), QVariant(1)); + QCOMPARE(p2.write(QVariant(6)), true); + QCOMPARE(p2.read(), QVariant(6)); + QCOMPARE(o.wrectProperty(), QRect(6, 13, 99, 8)); + } + + // URL-property + { + PropertyObject o; + QmlMetaProperty p(&o, "url"); + + QCOMPARE(p.write(QUrl("main.qml")), true); + QCOMPARE(o.url(), QUrl("main.qml")); + + QmlMetaProperty p2(&o, "url", engine.rootContext()); + + QUrl result = engine.baseUrl().resolved(QUrl("main.qml")); + QVERIFY(result != QUrl("main.qml")); + + QCOMPARE(p2.write(QUrl("main.qml")), true); + QCOMPARE(o.url(), result); + } +} + +void tst_qmlmetaproperty::writeObjectToList() { QmlComponent containerComponent(&engine, "import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl()); MyContainer *container = qobject_cast(containerComponent.create()); @@ -105,7 +913,7 @@ void tst_QmlMetaProperty::writeObjectToList() } Q_DECLARE_METATYPE(QList); -void tst_QmlMetaProperty::writeListToList() +void tst_qmlmetaproperty::writeListToList() { QmlComponent containerComponent(&engine, "import Test 1.0\nMyContainer { children: MyQmlObject {} }", QUrl()); MyContainer *container = qobject_cast(containerComponent.create()); @@ -125,7 +933,7 @@ void tst_QmlMetaProperty::writeListToList() QCOMPARE(container->children()->size(), 1);*/ } -void tst_QmlMetaProperty::writeObjectToQmlList() +void tst_qmlmetaproperty::writeObjectToQmlList() { QmlComponent containerComponent(&engine, "import Test 1.0\nMyContainer { qmlChildren: MyQmlObject {} }", QUrl()); MyContainer *container = qobject_cast(containerComponent.create()); @@ -139,6 +947,6 @@ void tst_QmlMetaProperty::writeObjectToQmlList() QCOMPARE(container->qmlChildren()->at(1), object); } -QTEST_MAIN(tst_QmlMetaProperty) +QTEST_MAIN(tst_qmlmetaproperty) #include "tst_qmlmetaproperty.moc" -- cgit v0.12