From 1bd2eb8ecd6b2377132beaa789c8b3b8a6f544d9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 3 Sep 2010 11:34:48 +1000 Subject: Support passing QObject derived types to QML methods QTBUG-13047 --- src/declarative/qml/qdeclarativeengine.cpp | 2 +- .../qml/qdeclarativeobjectscriptclass.cpp | 16 +++++++++++-- .../data/invokableObjectArg.qml | 9 ++++++++ .../data/invokableObjectRet.qml | 11 +++++++++ .../declarative/qdeclarativeecmascript/testtypes.h | 6 ++++- .../tst_qdeclarativeecmascript.cpp | 27 ++++++++++++++++++++++ 6 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectArg.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectRet.qml diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 8461368..e77a53e 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -2113,7 +2113,7 @@ bool QDeclarativeEnginePrivate::isQObject(int t) QObject *QDeclarativeEnginePrivate::toQObject(const QVariant &v, bool *ok) const { int t = v.userType(); - if (m_compositeTypes.contains(t)) { + if (t == QMetaType::QObjectStar || m_compositeTypes.contains(t)) { if (ok) *ok = true; return *(QObject **)(v.constData()); } else { diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index f439151..9d74238 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -625,11 +625,12 @@ private: char data[4 * sizeof(void *)]; int type; + bool isObjectType; }; } MetaCallArgument::MetaCallArgument() -: type(QVariant::Invalid) +: type(QVariant::Invalid), isObjectType(false) { } @@ -744,12 +745,23 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, new (&data) QVariant(); type = -1; - QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value); + QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine); + QVariant v = priv->scriptValueToVariant(value); if (v.userType() == callType) { *((QVariant *)&data) = v; } else if (v.canConvert((QVariant::Type)callType)) { *((QVariant *)&data) = v; ((QVariant *)&data)->convert((QVariant::Type)callType); + } else if (const QMetaObject *mo = priv->rawMetaObjectForType(callType)) { + QObject *obj = priv->toQObject(v); + + if (obj) { + const QMetaObject *objMo = obj->metaObject(); + while (objMo && objMo != mo) objMo = objMo->superClass(); + if (!objMo) obj = 0; + } + + *((QVariant *)&data) = QVariant(callType, &obj); } else { *((QVariant *)&data) = QVariant(callType, (void *)0); } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectArg.qml b/tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectArg.qml new file mode 100644 index 0000000..d5d3329 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectArg.qml @@ -0,0 +1,9 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + id: root + Component.onCompleted: { + root.myinvokable(root); + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectRet.qml b/tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectRet.qml new file mode 100644 index 0000000..29d7d01 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/invokableObjectRet.qml @@ -0,0 +1,11 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + id: root + property bool test: false + Component.onCompleted: { + test = (root.returnme() == root) + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index 7d7e3d9..220318d 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -95,7 +95,7 @@ class MyQmlObject : public QObject Q_PROPERTY(int nonscriptable READ nonscriptable WRITE setNonscriptable SCRIPTABLE false); public: - MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13) {} + MyQmlObject(): myinvokableObject(0), m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13) {} enum MyEnum { EnumValue1 = 0, EnumValue2 = 1 }; enum MyEnum2 { EnumValue3 = 2, EnumValue4 = 3 }; @@ -149,6 +149,9 @@ public: int nonscriptable() const { return 0; } void setNonscriptable(int) {} + MyQmlObject *myinvokableObject; + Q_INVOKABLE MyQmlObject *returnme() { return this; } + signals: void basicSignal(); void argumentSignal(int a, QString b, qreal c); @@ -162,6 +165,7 @@ public slots: void methodNoArgs() { m_methodCalled = true; } void method(int a) { if(a == 163) m_methodIntCalled = true; } void setString(const QString &s) { m_string = s; } + void myinvokable(MyQmlObject *o) { myinvokableObject = o; } private: friend class tst_qdeclarativeecmascript; diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 76ca964..33bf7ea 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -164,6 +164,8 @@ private slots: void include(); void callQtInvokables(); + void invokableObjectArg(); + void invokableObjectRet(); private: QDeclarativeEngine engine; }; @@ -1733,6 +1735,31 @@ void tst_qdeclarativeecmascript::callQtInvokables() QCOMPARE(o.actuals().at(0), QVariant(9)); } +// QTBUG-13047 (check that you can pass registered object types as args) +void tst_qdeclarativeecmascript::invokableObjectArg() +{ + QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml")); + + QObject *o = component.create(); + QVERIFY(o); + MyQmlObject *qmlobject = qobject_cast(o); + QVERIFY(qmlobject); + QCOMPARE(qmlobject->myinvokableObject, qmlobject); + + delete o; +} + +// QTBUG-13047 (check that you can return registered object types from methods) +void tst_qdeclarativeecmascript::invokableObjectRet() +{ + QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml")); + + QObject *o = component.create(); + QVERIFY(o); + QCOMPARE(o->property("test").toBool(), true); + delete o; +} + // QTBUG-5675 void tst_qdeclarativeecmascript::listToVariant() { -- cgit v0.12 From e0d41e566c49532dba6ed7eeb6a826f80e11c119 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 3 Sep 2010 11:41:12 +1000 Subject: Doc QTBUG-12665 --- doc/src/declarative/extending.qdoc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/src/declarative/extending.qdoc b/doc/src/declarative/extending.qdoc index 6388764..0cc989d 100644 --- a/doc/src/declarative/extending.qdoc +++ b/doc/src/declarative/extending.qdoc @@ -674,6 +674,16 @@ declaring a new property, and the corresponding C++ type. \row \o variant \o QVariant \endtable +From QML you can also declare object and list properties using any element name +like this: + +\code + property QtObject objectProperty + property Item itemProperty + property MyCustomType customProperty + property list listOfItemsProperty +\endcode + QML supports two methods for adding a new property to a type: a new property definition, and a property alias. -- cgit v0.12 From d758910f3d8d5eb64f7c7d94e5c9ef9ae259230b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 3 Sep 2010 11:56:42 +1000 Subject: Don't modify the signal order on the second dynamic meta object pass QTBUG-13374 --- src/declarative/qml/qdeclarativecompiler.cpp | 12 ++++++++---- .../qdeclarativelanguage/tst_qdeclarativelanguage.cpp | 12 ++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 7847303..61ea9c8 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -2416,13 +2416,17 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn propBuilder.setWritable(!readonly); } - if (mode == ResolveAliases) { - for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { - const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); + for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { + const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); - if (p.type == Object::DynamicProperty::Alias) { + if (p.type == Object::DynamicProperty::Alias) { + if (mode == ResolveAliases) { ((QDeclarativeVMEMetaData *)dynamicData.data())->aliasCount++; compileAlias(builder, dynamicData, obj, p); + } else { + // Need a fake signal so that the metaobject remains consistent across + // the resolve and non-resolve alias runs + builder.addSignal(p.name + "Changed()"); } } } diff --git a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp index dc00e16..1825991 100644 --- a/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp +++ b/tests/auto/declarative/qdeclarativelanguage/tst_qdeclarativelanguage.cpp @@ -118,6 +118,7 @@ private slots: void valueTypes(); void cppnamespace(); void aliasProperties(); + void aliasPropertiesAndSignals(); void componentCompositeType(); void i18n(); void i18n_data(); @@ -1051,6 +1052,17 @@ void tst_qdeclarativelanguage::aliasProperties() } } +// QTBUG-13374 Test that alias properties and signals can coexist +void tst_qdeclarativelanguage::aliasPropertiesAndSignals() +{ + QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertiesAndSignals.qml")); + VERIFY_ERRORS(0); + QObject *o = component.create(); + QVERIFY(o); + QCOMPARE(o->property("test").toBool(), true); + delete o; +} + // Test that the root element in a composite type can be a Component void tst_qdeclarativelanguage::componentCompositeType() { -- cgit v0.12 From 348e8471b7df101fb71d1c651eb92dcc0f45f6ff Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 3 Sep 2010 16:26:07 +1000 Subject: qreal == float fixes QTBUG-11853 --- src/declarative/qml/qdeclarativevaluetypescriptclass.cpp | 2 +- tests/auto/declarative/qdeclarativedom/tst_qdeclarativedom.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index f06d6ae..60f2cb3 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -168,7 +168,7 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier ref->type->read(ref->object, ref->property); QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); - if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::QReal) + if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); p.write(ref->type, v); ref->type->write(ref->object, ref->property, 0); diff --git a/tests/auto/declarative/qdeclarativedom/tst_qdeclarativedom.cpp b/tests/auto/declarative/qdeclarativedom/tst_qdeclarativedom.cpp index 5028ba1..dca5205 100644 --- a/tests/auto/declarative/qdeclarativedom/tst_qdeclarativedom.cpp +++ b/tests/auto/declarative/qdeclarativedom/tst_qdeclarativedom.cpp @@ -480,7 +480,7 @@ void tst_qdeclarativedom::loadDynamicProperty() DP_TEST(0, a, QVariant::Int, 25, 14, "int"); DP_TEST(1, b, QVariant::Bool, 44, 15, "bool"); - DP_TEST(2, c, QVariant::Double, 64, 17, "double"); + DP_TEST(2, c, QMetaType::QReal, 64, 17, "double"); DP_TEST(3, d, QMetaType::QReal, 86, 15, "real"); DP_TEST(4, e, QVariant::String, 106, 17, "string"); DP_TEST(5, f, QVariant::Url, 128, 14, "url"); -- cgit v0.12 From 9be190b01a0a74d133958b030f52656282f31175 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 3 Sep 2010 17:13:45 +1000 Subject: Fix the same bug that was in the demo samegame, in the tutorial version --- examples/declarative/tutorials/samegame/samegame4/content/samegame.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/declarative/tutorials/samegame/samegame4/content/samegame.js b/examples/declarative/tutorials/samegame/samegame4/content/samegame.js index b1f427c..79ff0c1 100755 --- a/examples/declarative/tutorials/samegame/samegame4/content/samegame.js +++ b/examples/declarative/tutorials/samegame/samegame4/content/samegame.js @@ -127,7 +127,7 @@ function shuffleDown() { } else { if (fallDist > 0) { var obj = board[index(column, row)]; - obj.y += fallDist * gameCanvas.blockSize; + obj.y = (row + fallDist) * gameCanvas.blockSize; board[index(column, row + fallDist)] = obj; board[index(column, row)] = null; } @@ -145,7 +145,7 @@ function shuffleDown() { obj = board[index(column, row)]; if (obj == null) continue; - obj.x -= fallDist * gameCanvas.blockSize; + obj.x = (fallDist - column) * gameCanvas.blockSize; board[index(column - fallDist, row)] = obj; board[index(column, row)] = null; } -- cgit v0.12 From 9311f0554b885f6b3ab1ab77f9c65b9f89865675 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 3 Sep 2010 17:18:46 +1000 Subject: Missing file --- .../data/aliasPropertiesAndSignals.qml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativelanguage/data/aliasPropertiesAndSignals.qml diff --git a/tests/auto/declarative/qdeclarativelanguage/data/aliasPropertiesAndSignals.qml b/tests/auto/declarative/qdeclarativelanguage/data/aliasPropertiesAndSignals.qml new file mode 100644 index 0000000..59afe58 --- /dev/null +++ b/tests/auto/declarative/qdeclarativelanguage/data/aliasPropertiesAndSignals.qml @@ -0,0 +1,14 @@ +import Qt 4.7 + +QtObject { + id: root + + property bool test: false + property alias myalias: root.objectName + signal go + onGo: test = true + + Component.onCompleted: { + root.go(); + } +} -- cgit v0.12 From adcb5f115ff768fe68883f392c00e6d2945a377c Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 3 Sep 2010 18:12:09 +1000 Subject: Cleanup visible item checking in positioners Especially in Grid, where it wasn't being done right. Task-number: QTBUG-12610 Reviewed-by: Martin Jones --- .../graphicsitems/qdeclarativepositioners.cpp | 48 +++++++++++----------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index b776b8e..77b26b9 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -247,13 +247,13 @@ void QDeclarativeBasePositioner::prePositioning() positionedItems.append(posItem); item = &positionedItems[positionedItems.count()-1]; item->isNew = true; - if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden) + if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) item->isVisible = false; } else { item = &oldItems[wIdx]; // Items are only omitted from positioning if they are explicitly hidden // i.e. their positioning is not affected if an ancestor is hidden. - if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden) { + if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) { item->isVisible = false; } else if (!item->isVisible) { item->isVisible = true; @@ -321,12 +321,6 @@ void QDeclarativeBasePositioner::finishApplyTransitions() d->moveActions.clear(); } -static inline bool isInvisible(QGraphicsObject *child) -{ - QGraphicsItemPrivate *childPrivate = static_cast(QGraphicsItemPrivate::get(child)); - return child->opacity() == 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height(); -} - /*! \qmlclass Column QDeclarativeColumn \ingroup qml-positioning-elements @@ -449,7 +443,7 @@ void QDeclarativeColumn::doPositioning(QSizeF *contentSize) for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); - if (!child.item || isInvisible(child.item)) + if (!child.item || !child.isVisible) continue; if(child.item->y() != voffset) @@ -584,7 +578,7 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); - if (!child.item || isInvisible(child.item)) + if (!child.item || !child.isVisible) continue; if(child.item->x() != hoffset) @@ -793,9 +787,17 @@ void QDeclarativeGrid::setFlow(Flow flow) void QDeclarativeGrid::doPositioning(QSizeF *contentSize) { + int c = m_columns; int r = m_rows; - int numVisible = positionedItems.count(); + //Is allocating the extra QPODVector too much overhead? + QPODVector visibleItems;//we aren't concerned with invisible items + visibleItems.reserve(positionedItems.count()); + for(int i=0; iwidth() > maxColWidth[j]) maxColWidth[j] = childPrivate->width(); @@ -837,10 +838,9 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) maxColWidth << 0; if (childIndex == positionedItems.count()) - continue; - const PositionedItem &child = positionedItems.at(childIndex++); - if (!child.item || isInvisible(child.item)) - continue; + break; + + const PositionedItem &child = visibleItems.at(childIndex++); QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); if (childPrivate->width() > maxColWidth[j]) maxColWidth[j] = childPrivate->width(); @@ -854,10 +854,8 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) int yoffset=0; int curRow =0; int curCol =0; - for (int i = 0; i < positionedItems.count(); ++i) { - const PositionedItem &child = positionedItems.at(i); - if (!child.item || isInvisible(child.item)) - continue; + for (int i = 0; i < visibleItems.count(); ++i) { + const PositionedItem &child = visibleItems.at(i); if((child.item->x()!=xoffset)||(child.item->y()!=yoffset)){ positionX(xoffset, child); positionY(yoffset, child); @@ -1033,7 +1031,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); - if (!child.item || isInvisible(child.item)) + if (!child.item || !child.isVisible) continue; QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); -- cgit v0.12