From 9540e2b5d67af9a26f431c3e8636bff9946e88c4 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 24 Mar 2010 14:05:38 +0100 Subject: QtScript: Add QObjectWrapOption for not exposing slots This makes it possible to have a prototype object in place that handles all slot calls, rather than having the slots be recreated in each wrapper object. Task-number: QTBUG-3637 Reviewed-by: Simon Hausmann --- src/script/api/qscriptengine.cpp | 1 + src/script/api/qscriptengine.h | 1 + src/script/bridge/qscriptqobject.cpp | 3 +- .../qscriptextqobject/tst_qscriptextqobject.cpp | 87 ++++++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 356b4d0..2650d7f 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -292,6 +292,7 @@ QT_BEGIN_NAMESPACE \value ExcludeSuperClassProperties The script object will not expose properties inherited from the superclass. \value ExcludeSuperClassContents Shorthand form for ExcludeSuperClassMethods | ExcludeSuperClassProperties \value ExcludeDeleteLater The script object will not expose the QObject::deleteLater() slot. + \value ExcludeSlots The script object will not expose the QObject's slots. \value AutoCreateDynamicProperties Properties that don't already exist in the QObject will be created as dynamic properties of that object, rather than as properties of the script object. \value PreferExistingWrapperObject If a wrapper object with the requested configuration already exists, return that object. \value SkipMethodsInEnumeration Don't include methods (signals and slots) when enumerating the object's properties. diff --git a/src/script/api/qscriptengine.h b/src/script/api/qscriptengine.h index 2ce3183..76461bc 100644 --- a/src/script/api/qscriptengine.h +++ b/src/script/api/qscriptengine.h @@ -125,6 +125,7 @@ public: ExcludeSuperClassContents = 0x0006, SkipMethodsInEnumeration = 0x0008, ExcludeDeleteLater = 0x0010, + ExcludeSlots = 0x0020, AutoCreateDynamicProperties = 0x0100, PreferExistingWrapperObject = 0x0200 diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index 765e074..83a811b 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -151,7 +151,8 @@ private: static bool hasMethodAccess(const QMetaMethod &method, int index, const QScriptEngine::QObjectWrapOptions &opt) { return (method.access() != QMetaMethod::Private) - && ((index != 2) || !(opt & QScriptEngine::ExcludeDeleteLater)); + && ((index != 2) || !(opt & QScriptEngine::ExcludeDeleteLater)) + && (!(opt & QScriptEngine::ExcludeSlots) || (method.methodType() != QMetaMethod::Slot)); } static bool isEnumerableMetaProperty(const QMetaProperty &prop, diff --git a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp index b4ce561..c1496f7 100644 --- a/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp +++ b/tests/auto/qscriptextqobject/tst_qscriptextqobject.cpp @@ -533,6 +533,7 @@ private slots: void objectDeleted(); void connectToDestroyedSignal(); void emitAfterReceiverDeleted(); + void inheritedSlots(); private: QScriptEngine *m_engine; @@ -2658,6 +2659,21 @@ void tst_QScriptExtQObject::enumerate_data() << "mySignal()" // slots << "mySlot()" << "myOtherSlot()"); + + QTest::newRow( "don't enumerate slots" ) + << int(QScriptEngine::ExcludeSlots) + << (QStringList() + // meta-object-defined properties: + // inherited + << "objectName" + // non-inherited + << "p1" << "p2" << "p4" << "p6" + // dynamic properties + << "dp1" << "dp2" << "dp3" + // inherited signals + << "destroyed(QObject*)" << "destroyed()" + // signals + << "mySignal()"); } void tst_QScriptExtQObject::enumerate() @@ -2850,6 +2866,28 @@ void tst_QScriptExtQObject::wrapOptions() QVERIFY(obj.property("intProperty").isValid()); QVERIFY(obj.propertyFlags("intProperty") & QScriptValue::QObjectMember); } + // exclude slots + { + QScriptValue obj = m_engine->newQObject(m_myObject, QScriptEngine::QtOwnership, + QScriptEngine::ExcludeSlots); + QVERIFY(!obj.property("deleteLater").isValid()); + QVERIFY(!(obj.propertyFlags("deleteLater") & QScriptValue::QObjectMember)); + QVERIFY(!obj.property("mySlot").isValid()); + QVERIFY(!(obj.propertyFlags("mySlot") & QScriptValue::QObjectMember)); + + QVERIFY(obj.property("myInvokable").isFunction()); + QVERIFY(obj.propertyFlags("myInvokable") & QScriptValue::QObjectMember); + + QVERIFY(obj.property("mySignal").isFunction()); + QVERIFY(obj.propertyFlags("mySignal") & QScriptValue::QObjectMember); + QVERIFY(obj.property("destroyed").isFunction()); + QVERIFY(obj.propertyFlags("destroyed") & QScriptValue::QObjectMember); + + QVERIFY(obj.property("objectName").isValid()); + QVERIFY(obj.propertyFlags("objectName") & QScriptValue::QObjectMember); + QVERIFY(obj.property("intProperty").isValid()); + QVERIFY(obj.propertyFlags("intProperty") & QScriptValue::QObjectMember); + } // exclude all that we can { QScriptValue obj = m_engine->newQObject(m_myObject, QScriptEngine::QtOwnership, @@ -2871,6 +2909,33 @@ void tst_QScriptExtQObject::wrapOptions() QCOMPARE(obj.property("child") .strictlyEquals(QScriptValue(m_engine, 123)), true); } + // exclude absolutely all that we can + { + QScriptValue obj = m_engine->newQObject(m_myObject, QScriptEngine::QtOwnership, + QScriptEngine::ExcludeSuperClassMethods + | QScriptEngine::ExcludeSuperClassProperties + | QScriptEngine::ExcludeChildObjects + | QScriptEngine::ExcludeSlots); + QVERIFY(!obj.property("deleteLater").isValid()); + QVERIFY(!(obj.propertyFlags("deleteLater") & QScriptValue::QObjectMember)); + + QVERIFY(!obj.property("mySlot").isValid()); + QVERIFY(!(obj.propertyFlags("mySlot") & QScriptValue::QObjectMember)); + + QVERIFY(obj.property("mySignal").isFunction()); + QVERIFY(obj.propertyFlags("mySignal") & QScriptValue::QObjectMember); + + QVERIFY(obj.property("myInvokable").isFunction()); + QVERIFY(obj.propertyFlags("myInvokable") & QScriptValue::QObjectMember); + + QVERIFY(!obj.property("objectName").isValid()); + QVERIFY(!(obj.propertyFlags("objectName") & QScriptValue::QObjectMember)); + + QVERIFY(obj.property("intProperty").isValid()); + QVERIFY(obj.propertyFlags("intProperty") & QScriptValue::QObjectMember); + + QVERIFY(!obj.property("child").isValid()); + } delete child; } @@ -3043,5 +3108,27 @@ void tst_QScriptExtQObject::emitAfterReceiverDeleted() } } +void tst_QScriptExtQObject::inheritedSlots() +{ + QScriptEngine eng; + + QPushButton prototypeButton; + QScriptValue scriptPrototypeButton = eng.newQObject(&prototypeButton); + + QPushButton button; + QScriptValue scriptButton = eng.newQObject(&button, QScriptEngine::QtOwnership, + QScriptEngine::ExcludeSlots); + scriptButton.setPrototype(scriptPrototypeButton); + + QVERIFY(scriptButton.property("click").isFunction()); + QVERIFY(scriptButton.property("click").strictlyEquals(scriptPrototypeButton.property("click"))); + + QSignalSpy prototypeButtonClickedSpy(&prototypeButton, SIGNAL(clicked())); + QSignalSpy buttonClickedSpy(&button, SIGNAL(clicked())); + scriptButton.property("click").call(scriptButton); + QCOMPARE(buttonClickedSpy.count(), 1); + QCOMPARE(prototypeButtonClickedSpy.count(), 0); +} + QTEST_MAIN(tst_QScriptExtQObject) #include "tst_qscriptextqobject.moc" -- cgit v0.12