Support registered QFlags in QML methods and signal handlers.
authorMichael Brasser <michael.brasser@nokia.com>
Thu, 22 Mar 2012 00:38:00 +0000 (10:38 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 26 Mar 2012 00:55:20 +0000 (02:55 +0200)
Change-Id: I2a71122303dcf7af4f07c3ffb73456bcdce62a74
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/qml/qml/qqmlboundsignal.cpp
src/qml/qml/qqmlpropertycache.cpp
tests/auto/qml/qqmlecmascript/data/registeredFlagMethod.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/testtypes.h
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp

index 5cc6032..543b69a 100644 (file)
@@ -55,6 +55,8 @@
 #include <QtCore/qstringbuilder.h>
 #include <QtCore/qdebug.h>
 
+Q_DECLARE_METATYPE(QJSValue)
+
 QT_BEGIN_NAMESPACE
 
 class QQmlBoundSignalParameters : public QObject
@@ -227,10 +229,14 @@ QQmlBoundSignalParameters::QQmlBoundSignalParameters(const QMetaMethod &method,
             prop.setWritable(false);
         } else {
             QByteArray propType = type;
-            if ((QMetaType::typeFlags(t) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration) {
+            QMetaType::TypeFlags flags = QMetaType::typeFlags(t);
+            if (flags & QMetaType::IsEnumeration) {
                 t = QVariant::Int;
                 propType = "int";
-            } else if (t == QVariant::Invalid) {
+            } else if (t == QVariant::Invalid ||
+                       (t >= QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
+                        t != qMetaTypeId<QJSValue>())) {
+                //the UserType clause is to catch registered QFlags
                 QByteArray scope;
                 QByteArray name;
                 int scopeIdx = propType.lastIndexOf("::");
index 318044a..50fd409 100644 (file)
@@ -688,7 +688,7 @@ struct StaticQtMetaObject : public QObject
         { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
 };
 
-static int EnumType(const QMetaObject *metaobj, const QByteArray &str)
+static int EnumType(const QMetaObject *metaobj, const QByteArray &str, int type)
 {
     QByteArray scope;
     QByteArray name;
@@ -709,7 +709,7 @@ static int EnumType(const QMetaObject *metaobj, const QByteArray &str)
         if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
             return QVariant::Int;
     }
-    return QVariant::Invalid;
+    return type;
 }
 
 // Returns an array of the arguments for method \a index.  The first entry in the array
@@ -745,10 +745,14 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
 
         for (int ii = 0; ii < argTypeNames.count(); ++ii) {
             int type = QMetaType::type(argTypeNames.at(ii));
-            if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration)
+            QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
+            if (flags & QMetaType::IsEnumeration)
                 type = QVariant::Int;
-            else if (type == QVariant::Invalid)
-                type = EnumType(object->metaObject(), argTypeNames.at(ii));
+            else if (type == QVariant::Invalid ||
+                     (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
+                      type != qMetaTypeId<QJSValue>()))
+                //the UserType clause is to catch registered QFlags
+                type = EnumType(object->metaObject(), argTypeNames.at(ii), type);
             if (type == QVariant::Invalid) {
                 if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
                 free(args);
@@ -770,10 +774,14 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
 
         for (int ii = 0; ii < argTypeNames.count(); ++ii) {
             int type = QMetaType::type(argTypeNames.at(ii));
-            if ((QMetaType::typeFlags(type) & QMetaType::IsEnumeration) == QMetaType::IsEnumeration)
+            QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
+            if (flags & QMetaType::IsEnumeration)
                 type = QVariant::Int;
-            else if (type == QVariant::Invalid)
-                type = EnumType(object->metaObject(), argTypeNames.at(ii));
+            else if (type == QVariant::Invalid ||
+                     (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
+                      type != qMetaTypeId<QJSValue>()))
+                //the UserType clause is to catch registered QFlags)
+                type = EnumType(object->metaObject(), argTypeNames.at(ii), type);
             if (type == QVariant::Invalid) {
                 if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
                 return 0;
diff --git a/tests/auto/qml/qqmlecmascript/data/registeredFlagMethod.qml b/tests/auto/qml/qqmlecmascript/data/registeredFlagMethod.qml
new file mode 100644 (file)
index 0000000..b323b49
--- /dev/null
@@ -0,0 +1,5 @@
+import Qt.test 1.0
+
+MyQmlObject {
+    onBasicSignal: registeredFlagMethod(Qt.RightButton)
+}
index 54fab26..519f9e4 100644 (file)
@@ -102,7 +102,7 @@ class MyQmlObject : public QObject
     Q_PROPERTY(int intProperty READ intProperty WRITE setIntProperty NOTIFY intChanged)
 
 public:
-    MyQmlObject(): myinvokableObject(0), m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13), m_intProperty(0) {}
+    MyQmlObject(): myinvokableObject(0), m_methodCalled(false), m_methodIntCalled(false), m_object(0), m_value(0), m_resetProperty(13), m_intProperty(0), m_buttons(0) {}
 
     enum MyEnum { EnumValue1 = 0, EnumValue2 = 1 };
     enum MyEnum2 { EnumValue3 = 2, EnumValue4 = 3 };
@@ -173,6 +173,7 @@ public:
     };
     QVariant variant() const { return m_variant; }
     QJSValue qjsvalue() const { return m_qjsvalue; }
+    Qt::MouseButtons buttons() const { return m_buttons; }
 
     int intProperty() const { return m_intProperty; }
     void setIntProperty(int i) { m_intProperty = i; emit intChanged(); }
@@ -201,6 +202,7 @@ public slots:
     void variantMethod(const QVariant &v) { m_variant = v; }
     void qjsvalueMethod(const QJSValue &v) { m_qjsvalue = v; }
     void v8function(QQmlV8Function*);
+    void registeredFlagMethod(Qt::MouseButtons v) { m_buttons = v; }
 
 private:
     friend class tst_qqmlecmascript;
@@ -217,6 +219,7 @@ private:
     QVariant m_variant;
     QJSValue m_qjsvalue;
     int m_intProperty;
+    Qt::MouseButtons m_buttons;
 };
 
 QML_DECLARE_TYPEINFO(MyQmlObject, QML_HAS_ATTACHED_PROPERTIES)
index 403cc63..fa1a6a5 100644 (file)
@@ -244,6 +244,7 @@ private slots:
     void revision();
     void invokableWithQObjectDerived();
     void realTypePrecision();
+    void registeredFlagMethod();
 
     void automaticSemicolon();
     void unaryExpression();
@@ -6354,6 +6355,20 @@ void tst_qqmlecmascript::realTypePrecision()
     QCOMPARE(object->property("test6").toDouble(), 1234567890.*2);
 }
 
+void tst_qqmlecmascript::registeredFlagMethod()
+{
+    QQmlEngine engine;
+    QQmlComponent component(&engine, testFileUrl("registeredFlagMethod.qml"));
+    MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
+    QVERIFY(object != 0);
+
+    QCOMPARE(object->buttons(), 0);
+    emit object->basicSignal();
+    QCOMPARE(object->buttons(), Qt::RightButton);
+
+    delete object;
+}
+
 QTEST_MAIN(tst_qqmlecmascript)
 
 #include "tst_qqmlecmascript.moc"