From 4c47079d367d44cf18b91965c351a5e9d834b343 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 29 Apr 2010 18:53:38 +1000 Subject: Simplify QDeclarativeGuard logic --- src/declarative/qml/qdeclarativedata_p.h | 10 ++++++---- src/declarative/qml/qdeclarativeengine.cpp | 12 ++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h index 4a56536..e916273 100644 --- a/src/declarative/qml/qdeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedata_p.h @@ -152,11 +152,11 @@ public: template void QDeclarativeGuard::addGuard() { - if (QObjectPrivate::get(o)->wasDeleted) { - if (prev) remGuard(); + Q_ASSERT(!prev); + + if (QObjectPrivate::get(o)->wasDeleted) return; - } - + QDeclarativeData *data = QDeclarativeData::get(o, true); next = data->guards; if (next) reinterpret_cast *>(next)->prev = &next; @@ -167,6 +167,8 @@ void QDeclarativeGuard::addGuard() template void QDeclarativeGuard::remGuard() { + Q_ASSERT(prev); + if (next) reinterpret_cast *>(next)->prev = prev; *prev = next; next = 0; diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 19d4b57..8992d50 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -870,14 +870,10 @@ void QDeclarativeData::destroyed(QObject *object) if (ownContext && context) context->destroy(); - QDeclarativeGuard *guard = guards; - while (guard) { - QDeclarativeGuard *g = guard; - guard = guard->next; - g->o = 0; - g->prev = 0; - g->next = 0; - g->objectDestroyed(object); + while (guards) { + QDeclarativeGuard *guard = guards; + *guard = (QObject *)0; + guard->objectDestroyed(object); } if (scriptValue) -- cgit v0.12 From e1a60c82d39af5bda99ebea12f6877d6cd9642ac Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 29 Apr 2010 19:04:09 +1000 Subject: Cleanup guards used in synthesized QML meta objects QTCREATORBUG-1289 --- src/declarative/qml/qdeclarativevmemetaobject.cpp | 3 +-- .../data/qtcreatorbug_1289.qml | 13 +++++++++++++ .../tst_qdeclarativeecmascript.cpp | 22 ++++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index 45f04a0..13e9c26 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -106,8 +106,7 @@ QDeclarativeVMEVariant::~QDeclarativeVMEVariant() void QDeclarativeVMEVariant::cleanup() { if (type == QVariant::Invalid) { - } else if (type == QMetaType::QObjectStar || - type == QMetaType::Int || + } else if (type == QMetaType::Int || type == QMetaType::Bool || type == QMetaType::Double) { type = QVariant::Invalid; diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml b/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml new file mode 100644 index 0000000..b6d31d5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/qtcreatorbug_1289.qml @@ -0,0 +1,13 @@ +import Qt 4.7 + +QtObject { + id: root + property QtObject object: QtObject { + id: nested + property QtObject nestedObject + } + + Component.onCompleted: { + nested.nestedObject = root; + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 6cde46b..54c14c2 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -142,6 +142,7 @@ private slots: void libraryScriptAssert(); void variantsAssignedUndefined(); void qtbug_9792(); + void qtcreatorbug_1289(); void noSpuriousWarningsAtShutdown(); void canAssignNullToQObject(); @@ -2205,6 +2206,27 @@ void tst_qdeclarativeecmascript::qtbug_9792() delete object; } +// Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly +void tst_qdeclarativeecmascript::qtcreatorbug_1289() +{ + QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml")); + + QObject *o = component.create(); + QVERIFY(o != 0); + + QObject *nested = qvariant_cast(o->property("object")); + QVERIFY(nested != 0); + + QVERIFY(qvariant_cast(nested->property("nestedObject")) == o); + + delete nested; + nested = qvariant_cast(o->property("object")); + QVERIFY(nested == 0); + + // If the bug is present, the next line will crash + delete o; +} + // Test that we shut down without stupid warnings void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown() { -- cgit v0.12 From e1c3dc3dad4604c8b0d2f70ef4602c5bead71ade Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 29 Apr 2010 15:01:58 +0200 Subject: Don't show warnings log window by default Disable it for the time being. The default annoyed more people then it helped. Reviewed-by: mae --- tools/qml/main.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 9ccc3d2..f2c0530 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -125,7 +125,7 @@ void usage() qWarning(" -sizeviewtorootobject .................... the view resizes to the changes in the content"); qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view"); qWarning(" -qmlbrowser .............................. use a QML-based file browser"); - qWarning(" -nolog ................................... do not show log window"); + qWarning(" -warnings ................................ show warnings in a separate log window"); qWarning(" -recordfile ..................... set video recording file"); qWarning(" - ImageMagick 'convert' for GIF)"); qWarning(" - png file for raw frames"); @@ -229,7 +229,8 @@ int main(int argc, char ** argv) bool stayOnTop = false; bool maximized = false; bool useNativeFileBrowser = true; - bool showLogWidget = true; + + bool showLogWidget = false; bool sizeToView = true; #if defined(Q_OS_SYMBIAN) @@ -290,8 +291,8 @@ int main(int argc, char ** argv) useGL = true; } else if (arg == "-qmlbrowser") { useNativeFileBrowser = false; - } else if (arg == "-nolog") { - showLogWidget = false; + } else if (arg == "-warnings") { + showLogWidget = true; } else if (arg == "-I" || arg == "-L") { if (arg == "-L") qWarning("-L option provided for compatibility only, use -I instead"); -- cgit v0.12 From 204cf6be3d63b16981843b0ae6a544e30da35134 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 30 Apr 2010 08:19:00 +1000 Subject: Warn on assigning a function to a QML property. This is not supported, and should not silently be converting the function to a string. See QTBUG-10302 for why we check !isRegExp as well as isFunction. Task-number: QTBUG-10237 Reviewed-by: Aaron Kennedy --- src/declarative/qml/qdeclarativebinding.cpp | 13 +++++++- .../qml/qdeclarativeobjectscriptclass.cpp | 3 ++ .../data/functionAssignment.1.qml | 5 +++ .../data/functionAssignment.2.qml | 13 ++++++++ .../tst_qdeclarativeecmascript.cpp | 39 ++++++++++++++++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index d44e7fb..8043ea9 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -193,7 +193,18 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) data->error.setColumn(-1); data->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(data->property.propertyType()))); - } else if (data->property.object() && + } else if (!scriptValue.isRegExp() && scriptValue.isFunction()) { + + QUrl url = QUrl(data->url); + int line = data->line; + if (url.isEmpty()) url = QUrl(QLatin1String("")); + + data->error.setUrl(url); + data->error.setLine(line); + data->error.setColumn(-1); + data->error.setDescription(QLatin1String("Unable to assign a function to a property.")); + + } else if (data->property.object() && !QDeclarativePropertyPrivate::write(data->property, value, flags)) { QUrl url = QUrl(data->url); diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 671a262..33e47fb 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -368,6 +368,9 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, QString error = QLatin1String("Cannot assign [undefined] to ") + QLatin1String(QMetaType::typeName(lastData->propType)); context->throwError(error); + } else if (!value.isRegExp() && value.isFunction()) { + QString error = QLatin1String("Cannot assign a function to a property."); + context->throwError(error); } else { QVariant v; if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml new file mode 100644 index 0000000..09540f1 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.1.qml @@ -0,0 +1,5 @@ +import Qt.test 1.0 + +MyQmlObject { + property variant a: function myFunction() { return 2; } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml new file mode 100644 index 0000000..948b39c --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/functionAssignment.2.qml @@ -0,0 +1,13 @@ +import Qt.test 1.0 + +MyQmlObject { + property variant a + property bool runTest: false + onRunTestChanged: { + function myFunction() { + console.log("hello world"); + } + a = myFunction; + } + +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 54c14c2..49ee335 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -145,6 +145,7 @@ private slots: void qtcreatorbug_1289(); void noSpuriousWarningsAtShutdown(); void canAssignNullToQObject(); + void functionAssignment(); void callQtInvokables(); private: @@ -2291,6 +2292,44 @@ void tst_qdeclarativeecmascript::canAssignNullToQObject() } } +void tst_qdeclarativeecmascript::functionAssignment() +{ + { + QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml")); + + QString url = component.url().toString(); + QString warning = url + ":4: Unable to assign a function to a property."; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + + MyQmlObject *o = qobject_cast(component.create()); + QVERIFY(o != 0); + + QVERIFY(!o->property("a").isValid()); + + delete o; + } + + { + QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml")); + + MyQmlObject *o = qobject_cast(component.create()); + QVERIFY(o != 0); + + QVERIFY(!o->property("a").isValid()); + + QString url = component.url().toString(); + QString warning = url + ":10: Error: Cannot assign a function to a property."; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + + o->setProperty("runTest", true); + + QVERIFY(!o->property("a").isValid()); + + delete o; + } +} + + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" -- cgit v0.12 From ce20af2d343e2d707f93ac4cb724feb2562680c6 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Fri, 30 Apr 2010 09:38:43 +1000 Subject: missed files --- .../data/connection-unknownsignals-ignored.qml | 8 ++++++++ .../data/connection-unknownsignals-notarget.qml | 7 +++++++ .../data/connection-unknownsignals-parent.qml | 7 +++++++ .../qdeclarativeconnection/data/connection-unknownsignals.qml | 7 +++++++ 4 files changed, 29 insertions(+) create mode 100644 tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml create mode 100644 tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml create mode 100644 tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml create mode 100644 tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml new file mode 100644 index 0000000..764d5ab --- /dev/null +++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-ignored.qml @@ -0,0 +1,8 @@ +import Qt 4.7 + +Item { + id: screen + + Connections { target: screen; onNotFooBar1: {} ignoreUnknownSignals: true } + Connections { objectName: "connections"; onNotFooBar2: {} ignoreUnknownSignals: true } +} diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml new file mode 100644 index 0000000..09e7812 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-notarget.qml @@ -0,0 +1,7 @@ +import Qt 4.7 + +Item { + id: screen + + Connections { objectName: "connections"; target: null; onNotFooBar: {} } +} diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml new file mode 100644 index 0000000..478503d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals-parent.qml @@ -0,0 +1,7 @@ +import Qt 4.7 + +Item { + id: screen + + Connections { objectName: "connections"; onFooBar: {} } +} diff --git a/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml new file mode 100644 index 0000000..d4e8d7e --- /dev/null +++ b/tests/auto/declarative/qdeclarativeconnection/data/connection-unknownsignals.qml @@ -0,0 +1,7 @@ +import Qt 4.7 + +Item { + id: screen + + Connections { objectName: "connections"; target: screen; onFooBar: {} } +} -- cgit v0.12 From 5fc59b64642b8af7b449770bae471a2a72bfa490 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 30 Apr 2010 09:13:10 +1000 Subject: Fix translation context when qsTr is used in PropertyChanges. This should also lead to better error meesages coming from PropertyChanges. Task-number: QTBUG-10300 --- src/declarative/util/qdeclarativepropertychanges.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 4b2d5a0..c7e3bc5 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include @@ -302,12 +303,18 @@ void QDeclarativePropertyChangesPrivate::decode() QDeclarativeProperty prop = property(name); //### better way to check for signal property? if (prop.type() & QDeclarativeProperty::SignalProperty) { QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), data.toString(), object); + QDeclarativeData *ddata = QDeclarativeData::get(q); + if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) + expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); QDeclarativeReplaceSignalHandler *handler = new QDeclarativeReplaceSignalHandler; handler->property = prop; handler->expression = expression; signalReplacements << handler; } else if (isScript) { QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(q), data.toString(), object); + QDeclarativeData *ddata = QDeclarativeData::get(q); + if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) + expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); expressions << qMakePair(name, expression); } else { properties << qMakePair(name, data); @@ -437,9 +444,11 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() if (d->isExplicit) { a.toValue = d->expressions.at(ii).second->evaluate(); } else { + QDeclarativeExpression *e = d->expressions.at(ii).second; QDeclarativeBinding *newBinding = - new QDeclarativeBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); + new QDeclarativeBinding(e->expression(), object(), qmlContext(this)); newBinding->setTarget(prop); + newBinding->setSourceLocation(e->sourceFile(), e->lineNumber()); a.toBinding = newBinding; a.deletableToBinding = true; } -- cgit v0.12 From 3ff9ff75f1caf9514dd43fb84826d57f2df91088 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Fri, 30 Apr 2010 10:58:58 +1000 Subject: Compile with QT_NO_GRAPHICSEFFECT. --- src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 2945b6c..7c55009 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -143,7 +143,9 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType(); qmlRegisterType(); qmlRegisterType(); +#ifndef QT_NO_GRAPHICSEFFECT qmlRegisterType(); +#endif qmlRegisterUncreatableType("Qt",4,7,"KeyNavigation",QDeclarativeKeyNavigationAttached::tr("KeyNavigation is only available via attached properties")); qmlRegisterUncreatableType("Qt",4,7,"Keys",QDeclarativeKeysAttached::tr("Keys is only available via attached properties")); -- cgit v0.12