QObject::connect(): fail to connect to a functor if UniqueConnection is passed
The connect() documentation makes it clear that UniqueConnection does not work with free functions / function objects and the like; only with actual PMFs. Rather than silently *ignoring* the flag, be vocal about its presence by warning, and make the connection fail (as the user has passed an illegal argument). [ChangeLog][QtCore][QObject] QObject::connect() now will refuse to connect a signal to a free function / function object if UniqueConnection is passed. Note that UniqueConnection has never worked for such connections -- the flag was simply ignored, and they were established multiple times. Now, the flag is not ignored and results in a connection failure (as well as a runtime warning by Qt). Change-Id: I6509667018c74f9bd24910cde0a1b16c5f84f064 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
c9830c2fb9
commit
7d4d47de70
@ -4974,6 +4974,19 @@ QMetaObject::Connection QObject::connectImpl(const QObject *sender, void **signa
|
|||||||
return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
|
return QObjectPrivate::connectImpl(sender, signal_index, receiver, slot, slotObj, type, types, senderMetaObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void connectWarning(const QObject *sender,
|
||||||
|
const QMetaObject *senderMetaObject,
|
||||||
|
const QObject *receiver,
|
||||||
|
const char *message)
|
||||||
|
{
|
||||||
|
const char *senderString = sender ? sender->metaObject()->className()
|
||||||
|
: senderMetaObject ? senderMetaObject->className()
|
||||||
|
: "Unknown";
|
||||||
|
const char *receiverString = receiver ? receiver->metaObject()->className()
|
||||||
|
: "Unknown";
|
||||||
|
qCWarning(lcConnect, "QObject::connect(%s, %s): %s", senderString, receiverString, message);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
|
|
||||||
@ -4986,18 +4999,24 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
|
|||||||
QtPrivate::QSlotObjectBase *slotObj, int type,
|
QtPrivate::QSlotObjectBase *slotObj, int type,
|
||||||
const int *types, const QMetaObject *senderMetaObject)
|
const int *types, const QMetaObject *senderMetaObject)
|
||||||
{
|
{
|
||||||
if (!sender || !receiver || !slotObj || !senderMetaObject) {
|
auto connectFailureGuard = qScopeGuard([&]()
|
||||||
const char *senderString = sender ? sender->metaObject()->className()
|
{
|
||||||
: senderMetaObject ? senderMetaObject->className()
|
|
||||||
: "Unknown";
|
|
||||||
const char *receiverString = receiver ? receiver->metaObject()->className()
|
|
||||||
: "Unknown";
|
|
||||||
qCWarning(lcConnect, "QObject::connect(%s, %s): invalid nullptr parameter", senderString, receiverString);
|
|
||||||
if (slotObj)
|
if (slotObj)
|
||||||
slotObj->destroyIfLastRef();
|
slotObj->destroyIfLastRef();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!sender || !receiver || !slotObj || !senderMetaObject) {
|
||||||
|
connectWarning(sender, senderMetaObject, receiver, "invalid nullptr parameter");
|
||||||
return QMetaObject::Connection();
|
return QMetaObject::Connection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type & Qt::UniqueConnection && !slot) {
|
||||||
|
connectWarning(sender, senderMetaObject, receiver, "unique connections require a pointer to member function of a QObject subclass");
|
||||||
|
return QMetaObject::Connection();
|
||||||
|
}
|
||||||
|
|
||||||
|
connectFailureGuard.dismiss();
|
||||||
|
|
||||||
QObject *s = const_cast<QObject *>(sender);
|
QObject *s = const_cast<QObject *>(sender);
|
||||||
QObject *r = const_cast<QObject *>(receiver);
|
QObject *r = const_cast<QObject *>(receiver);
|
||||||
|
|
||||||
|
@ -6241,10 +6241,11 @@ void tst_QObject::connectFunctorWithContextUnique()
|
|||||||
|
|
||||||
SenderObject sender;
|
SenderObject sender;
|
||||||
ReceiverObject receiver;
|
ReceiverObject receiver;
|
||||||
QObject::connect(&sender, &SenderObject::signal1, &receiver, &ReceiverObject::slot1);
|
QVERIFY(QObject::connect(&sender, &SenderObject::signal1, &receiver, &ReceiverObject::slot1));
|
||||||
receiver.count_slot1 = 0;
|
receiver.count_slot1 = 0;
|
||||||
|
|
||||||
QObject::connect(&sender, &SenderObject::signal1, &receiver, SlotFunctor(), Qt::UniqueConnection);
|
QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): unique connections require a pointer to member function of a QObject subclass");
|
||||||
|
QVERIFY(!QObject::connect(&sender, &SenderObject::signal1, &receiver, [&](){ receiver.slot1(); }, Qt::UniqueConnection));
|
||||||
|
|
||||||
sender.emitSignal1();
|
sender.emitSignal1();
|
||||||
QCOMPARE(receiver.count_slot1, 1);
|
QCOMPARE(receiver.count_slot1, 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user