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;
}
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,
#include <qobject.h>
#include <qmetaobject.h>
#include <qlabel.h>
+#include <private/qmetaobject_p.h>
+
+Q_DECLARE_METATYPE(const QMetaObject *)
struct MyStruct
{
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 &);
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"