QSignalSpy: share more code

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 <marten.nordheim@qt.io>
This commit is contained in:
Marc Mutz 2024-03-20 14:14:23 +01:00
parent 12a432c80f
commit e68edd6a07

View File

@ -19,20 +19,29 @@ class QVariant;
class QSignalSpy: public QObject, public QList<QList<QVariant> >
{
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 <typename PointerToMemberFunction>
QSignalSpy(const QObject *object, PointerToMemberFunction signal);
#else
template <typename Func>
QSignalSpy(const typename QtPrivate::FunctionPointer<Func>::Object *obj, Func signal0)
: QSignalSpy(verify(obj, signal0)) {}
private:
template <typename Func>
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))