From 5082b84b386a94cbbe6814c383bb6bac795ed648 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Mon, 30 Nov 2020 14:53:38 +0100 Subject: [PATCH] QMetaObjectPrivate: Add firstMethod QMetaObject::indexfOfMethod returns the method corresponding to a specific signature. In QML, we however only want any of the methods with a given name (and do overload resolution at a later point). For this usecase this patch introduces the internal QMetaObject::firstMethod function. Change-Id: Ie3820354edffb273c4cbe1399201a955ebe79344 Reviewed-by: Lars Knoll --- src/corelib/kernel/qmetaobject.cpp | 18 +++++++++ src/corelib/kernel/qmetaobject_p.h | 1 + .../kernel/qmetaobject/tst_qmetaobject.cpp | 39 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index fe6b4075ef..bdd2af1a2e 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -590,6 +590,24 @@ bool QMetaObjectPrivate::methodMatch(const QMetaObject *m, const QMetaMethod &me return true; } +/*! + \internal + Returns the first method with name \a name found in \a baseObject + */ +QMetaMethod QMetaObjectPrivate::firstMethod(const QMetaObject *baseObject, QByteArrayView name) +{ + for (const QMetaObject *currentObject = baseObject; currentObject; currentObject = currentObject->superClass()) { + const int start = priv(currentObject->d.data)->methodCount - 1; + const int end = 0; + for (int i = start; i >= end; --i) { + auto candidate = QMetaMethod::fromRelativeMethodIndex(currentObject, i); + if (name == candidate.name()) + return candidate; + } + } + return QMetaMethod{}; +} + /** * \internal * helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index efc1eafc8f..dbd82ba27b 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -253,6 +253,7 @@ struct QMetaObjectPrivate static bool methodMatch(const QMetaObject *m, const QMetaMethod &method, const QByteArray &name, int argc, const QArgumentType *types); + Q_CORE_EXPORT static QMetaMethod firstMethod(const QMetaObject *baseObject, QByteArrayView name); }; diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index dca4f0fea5..82d39cbbb3 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -321,6 +321,9 @@ private slots: void indexOfMethod_data(); void indexOfMethod(); + void firstMethod_data(); + void firstMethod(); + void indexOfMethodPMF(); void signalOffset_data(); @@ -1700,6 +1703,42 @@ void tst_QMetaObject::indexOfMethod() QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx); } +class Base : public QObject { + Q_OBJECT +public slots: + int test() {return 0;} + int baseOnly() {return 0;} +}; + +class Derived : public Base { + Q_OBJECT + +public slots: + int test() {return 1;} +}; + +void tst_QMetaObject::firstMethod_data() +{ + QTest::addColumn("name"); + QTest::addColumn("method"); + + const QMetaObject &derived = Derived::staticMetaObject; + const QMetaObject &base = Base::staticMetaObject; + + QTest::newRow("own method") << QByteArray("test") << derived.method(derived.indexOfMethod("test()")); + QTest::newRow("parent method") << QByteArray("baseOnly") << derived.method(base.indexOfMethod("baseOnly()")); + QTest::newRow("invalid") << QByteArray("invalid") << QMetaMethod(); +} + +void tst_QMetaObject::firstMethod() +{ + QFETCH(QByteArray, name); + QFETCH(QMetaMethod, method); + + QMetaMethod firstMethod = QMetaObjectPrivate::firstMethod(&Derived::staticMetaObject, name); + QCOMPARE(firstMethod, method); +} + void tst_QMetaObject::indexOfMethodPMF() { #define INDEXOFMETHODPMF_HELPER(ObjectType, Name, Arguments) { \