diff options
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 83 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_p.h | 5 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro | 2 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 137 |
5 files changed, 210 insertions, 18 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 2dbabc77c6..417c49bc42 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -798,31 +798,82 @@ int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArra return -1; } +/*! + \internal + \since 5.0 + + Returns the signal offset for the class \a m; i.e., the index position + of the class's first signal. + + Similar to QMetaObject::methodOffset(), but non-signal methods are + excluded. +*/ +int QMetaObjectPrivate::signalOffset(const QMetaObject *m) +{ + Q_ASSERT(m != 0); + int offset = 0; + for (m = m->d.superdata; m; m = m->d.superdata) + offset += priv(m->d.data)->signalCount; + return offset; +} + +/*! + \internal + \since 5.0 + + Returns the number of signals for the class \a m, including the signals + for the base class. + + Similar to QMetaObject::methodCount(), but non-signal methods are + excluded. +*/ +int QMetaObjectPrivate::absoluteSignalCount(const QMetaObject *m) +{ + Q_ASSERT(m != 0); + int n = priv(m->d.data)->signalCount; + for (m = m->d.superdata; m; m = m->d.superdata) + n += priv(m->d.data)->signalCount; + return n; +} + +/*! + \internal + \since 5.0 + + Returns the index of the signal method \a m. + + Similar to QMetaMethod::methodIndex(), but non-signal methods are + excluded. +*/ +int QMetaObjectPrivate::signalIndex(const QMetaMethod &m) +{ + if (!m.mobj) + return -1; + return ((m.handle - priv(m.mobj->d.data)->methodData) / 5) + signalOffset(m.mobj); +} + /*! \internal - Returns the signal for the given \a metaObject at \a signal_index. + \since 5.0 + + Returns the signal for the given meta-object \a m at \a signal_index. It it different from QMetaObject::method(); the index should not include non-signal methods. - - The index must correspond to a signal defined in \ a metaObject itself; - it should not be an inherited signal. */ -QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *metaObject, int signal_index) +QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *m, int signal_index) { QMetaMethod result; if (signal_index < 0) return result; - Q_ASSERT(metaObject != 0); - - int signalOffset = 0; - for (const QMetaObject *m = metaObject->d.superdata; m; m = m->d.superdata) - signalOffset += priv(m->d.data)->signalCount; - - Q_ASSERT(signal_index >= signalOffset); - int signal_index_relative = signal_index - signalOffset; - if (signal_index_relative < priv(metaObject->d.data)->signalCount) { - result.mobj = metaObject; - result.handle = priv(metaObject->d.data)->methodData + 5*signal_index_relative; + Q_ASSERT(m != 0); + int i = signal_index; + i -= signalOffset(m); + if (i < 0 && m->d.superdata) + return signal(m->d.superdata, signal_index); + + if (i >= 0 && i < priv(m->d.data)->signalCount) { + result.mobj = m; + result.handle = priv(m->d.data)->methodData + 5*i; } return result; } diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 1c49506926..353b99f3a2 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -255,6 +255,7 @@ private: int idx; QMetaEnum menum; friend struct QMetaObject; + friend struct QMetaObjectPrivate; }; class Q_CORE_EXPORT QMetaClassInfo diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 320b8dd9d7..855a0e04e7 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -203,7 +203,10 @@ struct QMetaObjectPrivate int argc, const QArgumentType *types); static int indexOfConstructor(const QMetaObject *m, const QByteArray &name, int argc, const QArgumentType *types); - static QMetaMethod signal(const QMetaObject *m, int signal_index); + Q_CORE_EXPORT static QMetaMethod signal(const QMetaObject *m, int signal_index); + Q_CORE_EXPORT static int signalOffset(const QMetaObject *m); + Q_CORE_EXPORT static int absoluteSignalCount(const QMetaObject *m); + Q_CORE_EXPORT static int signalIndex(const QMetaMethod &m); static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes, int methodArgc, const QArgumentType *methodTypes); static bool checkConnectArgs(const QMetaMethodPrivate *signal, diff --git a/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro b/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro index b92c8036b5..a28b8a8d38 100644 --- a/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro +++ b/tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro @@ -1,5 +1,5 @@ CONFIG += testcase CONFIG += parallel_test TARGET = tst_qmetaobject -QT = core gui widgets testlib +QT = core-private gui widgets testlib SOURCES = tst_qmetaobject.cpp diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 5cf28b5141..78ca386822 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -44,6 +44,9 @@ #include <qobject.h> #include <qmetaobject.h> #include <qlabel.h> +#include <private/qmetaobject_p.h> + +Q_DECLARE_METATYPE(const QMetaObject *) struct MyStruct { @@ -173,6 +176,15 @@ private slots: void indexOfMethodPMF(); + void signalOffset_data(); + void signalOffset(); + void signalCount_data(); + void signalCount(); + void signal_data(); + void signal(); + void signalIndex_data(); + void signalIndex(); + signals: void value6Changed(); void value7Changed(const QString &); @@ -1151,5 +1163,130 @@ void tst_QMetaObject::indexOfMethodPMF() INDEXOFMETHODPMF_HELPER(QtTestCustomObject, sig_custom, (const CustomString &)) } +namespace SignalTestHelper +{ +// These functions use the public QMetaObject/QMetaMethod API to implement +// the functionality of the internal API, and are used to check the results. + +static int signalCount(const QMetaObject *mo) +{ + int n = 0; + for (int i = 0; i < mo->methodCount(); ++i) { + QMetaMethod mm = mo->method(i); + if (mm.methodType() == QMetaMethod::Signal) + ++n; + } + return n; +} + +static int signalOffset(const QMetaObject *mo) +{ + return mo->superClass() ? signalCount(mo->superClass()) : 0; +} + +static QMetaMethod signal(const QMetaObject *mo, int index) +{ + int k = 0; + for (int i = 0; i < mo->methodCount(); ++i) { + QMetaMethod mm = mo->method(i); + if (mm.methodType() != QMetaMethod::Signal) + continue; + if (k == index) + return mm; + ++k; + } + return QMetaMethod(); +} + +static int signalIndex(const QMetaMethod &mm) +{ + int k = mm.methodIndex(); + const QMetaObject *mo = mm.enclosingMetaObject(); + for (int i = 0; i < mm.methodIndex(); ++i) { + if (mo->method(i).methodType() != QMetaMethod::Signal) + --k; + } + return k; +} + +} // namespace SignalTestHelper + +void tst_QMetaObject::signalOffset_data() +{ + QTest::addColumn<const QMetaObject *>("metaObject"); + + QTest::newRow("QObject") << &QObject::staticMetaObject; + QTest::newRow("tst_QMetaObject") << &tst_QMetaObject::staticMetaObject; + QTest::newRow("QtTestObject") << &QtTestObject::staticMetaObject; +} + +void tst_QMetaObject::signalOffset() +{ + QFETCH(const QMetaObject *, metaObject); + QCOMPARE(QMetaObjectPrivate::signalOffset(metaObject), + SignalTestHelper::signalOffset(metaObject)); +} + +void tst_QMetaObject::signalCount_data() +{ + signalOffset_data(); +} + +void tst_QMetaObject::signalCount() +{ + QFETCH(const QMetaObject *, metaObject); + QCOMPARE(QMetaObjectPrivate::absoluteSignalCount(metaObject), + SignalTestHelper::signalCount(metaObject)); +} + +void tst_QMetaObject::signal_data() +{ + QTest::addColumn<const QMetaObject *>("metaObject"); + QTest::addColumn<int>("index"); + + struct SignalTestDataHelper + { + static void addSignals(const QMetaObject *mo) + { + int count = SignalTestHelper::signalCount(mo); + for (int i = 0; i < count; ++i) { + QMetaMethod mm = SignalTestHelper::signal(mo, i); + QByteArray tag(mo->className()); + tag.append("::"); + tag.append(mm.methodSignature()); + QTest::newRow(tag.constData()) << mo << i; + } + } + }; + + SignalTestDataHelper::addSignals(&QObject::staticMetaObject); + SignalTestDataHelper::addSignals(&tst_QMetaObject::staticMetaObject); + SignalTestDataHelper::addSignals(&QtTestObject::staticMetaObject); +} + +void tst_QMetaObject::signal() +{ + QFETCH(const QMetaObject *, metaObject); + QFETCH(int, index); + + QCOMPARE(QMetaObjectPrivate::signal(metaObject, index), + SignalTestHelper::signal(metaObject, index)); +} + +void tst_QMetaObject::signalIndex_data() +{ + signal_data(); +} + +void tst_QMetaObject::signalIndex() +{ + QFETCH(const QMetaObject *, metaObject); + QFETCH(int, index); + + QMetaMethod mm = SignalTestHelper::signal(metaObject, index); + QCOMPARE(QMetaObjectPrivate::signalIndex(mm), + SignalTestHelper::signalIndex(mm)); +} + QTEST_MAIN(tst_QMetaObject) #include "tst_qmetaobject.moc" |