From e68edd6a07adf33db14c2d2f6e4e3785596fa496 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 20 Mar 2024 14:14:23 +0100 Subject: [PATCH] QSignalSpy: share more code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add per-ctor verify() functions that take care of the warnings for invalid inputs, and return a struct { QObject*; QMetaMethod; } to feed into a delegatee constructor. This solves the problem that the varying parts between the ctors are at the beginning, not the end, using another level of indirection, and will eventually allow to make the `args` and `sig` members const, and therefore remove the need to protect either with the mutex. This patch tries to keep the diff minimal. I'm planning to de-inline most of the class in a future commit, so it doesn't matter that private and public sections are interleaved, that will be cleaned up when the code is moved to a .cpp file later. Task-number: QTBUG-123544 Change-Id: Idc628c927736880a8fd580089ed5177361c94ed9 Reviewed-by: MÃ¥rten Nordheim --- src/testlib/qsignalspy.h | 48 ++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h index 75e2668de22..ffc2129e18c 100644 --- a/src/testlib/qsignalspy.h +++ b/src/testlib/qsignalspy.h @@ -19,20 +19,29 @@ class QVariant; class QSignalSpy: public QObject, public QList > { + struct ObjectSignal { + const QObject *obj; + QMetaMethod sig; + }; + public: explicit QSignalSpy(const QObject *obj, const char *aSignal) + : QSignalSpy(verify(obj, aSignal)) {} + +private: + ObjectSignal verify(const QObject *obj, const char *aSignal) { if (!isObjectValid(obj)) - return; + return {}; if (!aSignal) { qWarning("QSignalSpy: Null signal name is not valid"); - return; + return {}; } if (((aSignal[0] - '0') & 0x03) != QSIGNAL_CODE) { qWarning("QSignalSpy: Not a valid signal, use the SIGNAL macro"); - return; + return {}; } const QByteArray ba = QMetaObject::normalizedSignature(aSignal + 1); @@ -40,38 +49,52 @@ public: const int sigIndex = mo->indexOfMethod(ba.constData()); if (sigIndex < 0) { qWarning("QSignalSpy: No such signal: '%s'", ba.constData()); - return; + return {}; } - init(obj, mo->method(sigIndex)); + return verify(obj, mo->method(sigIndex)); } +public: #ifdef Q_QDOC template QSignalSpy(const QObject *object, PointerToMemberFunction signal); #else template QSignalSpy(const typename QtPrivate::FunctionPointer::Object *obj, Func signal0) + : QSignalSpy(verify(obj, signal0)) {} + +private: + template + ObjectSignal verify(const QObject *obj, Func signal0) { if (!isObjectValid(obj)) - return; + return {}; if (!signal0) { qWarning("QSignalSpy: Null signal pointer is not valid"); - return; + return {}; } const QMetaMethod signalMetaMethod = QMetaMethod::fromSignal(signal0); - init(obj, signalMetaMethod); + return verify(obj, signalMetaMethod); } +public: #endif // Q_QDOC QSignalSpy(const QObject *obj, QMetaMethod signal) + : QSignalSpy(verify(obj, signal)) {} + +private: + ObjectSignal verify(const QObject *obj, QMetaMethod signal) { if (isObjectValid(obj)) - init(obj, signal); + return {obj, signal}; + else + return {}; } +public: inline bool isValid() const { return !sig.isEmpty(); } inline QByteArray signal() const { return sig; } @@ -109,6 +132,13 @@ public: } private: + explicit QSignalSpy(ObjectSignal os) + { + if (!os.obj) + return; + init(os.obj, os.sig); + } + void init(const QObject *obj, QMetaMethod signal) { if (!isSignalMetaMethodValid(signal))