Test template-based connect() with qmetaobjectbuilder

For template-based connect(), the meta-object is resolved at
compile-time (the virtual metaObject() function isn't called).
But we can make it work by copying the members of the dynamically
constructed meta-object to the statically defined one.

Change-Id: Ia4d3263a89008e36e187c584db6d25d9042f32b3
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
Kent Hansen 2012-02-04 22:51:41 +01:00 committed by Qt by Nokia
parent 58d6c856ec
commit e121d6d7e8

View File

@ -1341,11 +1341,11 @@ class TestObject : public QObject
// Manually expanded from Q_OBJECT macro // Manually expanded from Q_OBJECT macro
public: public:
Q_OBJECT_CHECK Q_OBJECT_CHECK
static QMetaObject staticMetaObject;
virtual const QMetaObject *metaObject() const; virtual const QMetaObject *metaObject() const;
virtual void *qt_metacast(const char *); virtual void *qt_metacast(const char *);
virtual int qt_metacall(QMetaObject::Call, int, void **); virtual int qt_metacall(QMetaObject::Call, int, void **);
private: private:
Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData;
Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
//Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged) //Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged)
@ -1378,14 +1378,15 @@ private:
int m_voidSlotIntArg; int m_voidSlotIntArg;
}; };
const QMetaObjectExtraData TestObject::staticMetaObjectExtraData = { QMetaObject TestObject::staticMetaObject = {
0, qt_static_metacall { 0, 0, 0, 0 }
}; };
TestObject::TestObject(QObject *parent) TestObject::TestObject(QObject *parent)
: QObject(parent), m_metaObject(buildMetaObject()), : QObject(parent), m_metaObject(buildMetaObject()),
m_intProp(-1), m_voidSlotIntArg(-1) m_intProp(-1), m_voidSlotIntArg(-1)
{ {
staticMetaObject = *m_metaObject;
} }
TestObject::~TestObject() TestObject::~TestObject()
@ -1481,9 +1482,6 @@ void TestObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
} }
} }
} else if (_c == QMetaObject::IndexOfMethod) { } else if (_c == QMetaObject::IndexOfMethod) {
// This code is currently unreachable because it's only used by the
// template-based versions of connect() and disconnect(), which don't
// work with dynamically generated meta-objects (see test).
int *result = reinterpret_cast<int *>(_a[0]); int *result = reinterpret_cast<int *>(_a[0]);
void **func = reinterpret_cast<void **>(_a[1]); void **func = reinterpret_cast<void **>(_a[1]);
{ {
@ -1504,7 +1502,6 @@ void TestObject::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
*result = 2; *result = 2;
} }
} }
qFatal("You forgot to add one or more IndexOfMethod cases");
} }
} }
@ -1668,11 +1665,22 @@ void tst_QMetaObjectBuilder::usage_templateConnect()
{ {
QScopedPointer<TestObject> testObject(new TestObject); QScopedPointer<TestObject> testObject(new TestObject);
QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in QObject");
QMetaObject::Connection con = QObject::connect(testObject.data(), &TestObject::intPropChanged, QMetaObject::Connection con = QObject::connect(testObject.data(), &TestObject::intPropChanged,
testObject.data(), &TestObject::voidSlotInt); testObject.data(), &TestObject::voidSlotInt);
QEXPECT_FAIL("", "template-based connect() fails because meta-object is deduced at compile-time", Abort);
QVERIFY(con); QVERIFY(con);
QVERIFY(testObject->voidSlotIntArgument() == -1);
testObject->setProperty("intProp", 123);
QCOMPARE(testObject->voidSlotIntArgument(), 123);
QVERIFY(QObject::disconnect(testObject.data(), &TestObject::intPropChanged,
testObject.data(), &TestObject::voidSlotInt));
// Something that isn't a signal
QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in TestObject");
con = QObject::connect(testObject.data(), &TestObject::setIntProp,
testObject.data(), &TestObject::intPropChanged);
QVERIFY(!con);
} }
QTEST_MAIN(tst_QMetaObjectBuilder) QTEST_MAIN(tst_QMetaObjectBuilder)