summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qmetaobject.cpp83
-rw-r--r--src/corelib/kernel/qmetaobject.h1
-rw-r--r--src/corelib/kernel/qmetaobject_p.h5
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/qmetaobject.pro2
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp137
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"