Change the return value of QObject::connect
From a bool to a handle to to connection. Also added a new overload of disconnect that disconnect a handle This is required because with the new syntax taking lambda or functors, it is the only way to disconnect a connection (as it is impossible to compare functors) The new return value is QMetaObject::Connection, it is a wrapper around the internal QObjectPrivate::Connection. QObjectPrivate::Connection is now reference counted. tst_qglobal.cpp: This test set up an internal callback, and the callback do not set any proper connection handle (and tbh, it would be hard for it to do so). So the returned QMetaObject::Connection is invalid, and ok is false (Internal callbacks are only used for jambi and should probably be removed) Change-Id: I111626fb4f47efc4db5e2ea5bff9da15f08fea7b Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
e759f9580e
commit
79f675a1e0
@ -137,7 +137,7 @@ struct QMetaObjectPrivate
|
||||
enum DisconnectType { DisconnectAll, DisconnectOne };
|
||||
static void memberIndexes(const QObject *obj, const QMetaMethod &member,
|
||||
int *signalIndex, int *methodIndex);
|
||||
static bool connect(const QObject *sender, int signal_index,
|
||||
static QObjectPrivate::Connection *connect(const QObject *sender, int signal_index,
|
||||
const QObject *receiver, int method_index_relative,
|
||||
const QMetaObject *rmeta = 0,
|
||||
int type = 0, int *types = 0);
|
||||
|
@ -373,7 +373,7 @@ void QObjectPrivate::cleanConnectionLists()
|
||||
} else {
|
||||
QObjectPrivate::Connection *next = c->nextConnectionList;
|
||||
*prev = next;
|
||||
delete c;
|
||||
c->deref();
|
||||
c = next;
|
||||
}
|
||||
}
|
||||
@ -854,7 +854,7 @@ QObject::~QObject()
|
||||
while (QObjectPrivate::Connection *c = connectionList.first) {
|
||||
if (!c->receiver) {
|
||||
connectionList.first = c->nextConnectionList;
|
||||
delete c;
|
||||
c->deref();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -865,11 +865,12 @@ QObject::~QObject()
|
||||
*c->prev = c->next;
|
||||
if (c->next) c->next->prev = c->prev;
|
||||
}
|
||||
c->receiver = 0;
|
||||
if (needToUnlock)
|
||||
m->unlock();
|
||||
|
||||
connectionList.first = c->nextConnectionList;
|
||||
delete c;
|
||||
c->deref();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2280,7 +2281,8 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
|
||||
|
||||
Creates a connection of the given \a type from the \a signal in
|
||||
the \a sender object to the \a method in the \a receiver object.
|
||||
Returns true if the connection succeeds; otherwise returns false.
|
||||
Returns a handle to the connection that can be used to disconnect
|
||||
it later.
|
||||
|
||||
You must use the \c SIGNAL() and \c SLOT() macros when specifying
|
||||
the \a signal and the \a method, for example:
|
||||
@ -2309,11 +2311,12 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
|
||||
in the same order as the order the connection was made, when the
|
||||
signal is emitted.
|
||||
|
||||
The function returns true if it successfully connects the signal
|
||||
to the slot. It will return false if it cannot create the
|
||||
connection, for example, if QObject is unable to verify the
|
||||
existence of either \a signal or \a method, or if their signatures
|
||||
aren't compatible.
|
||||
The function returns a handle to a connection if it successfully
|
||||
connects the signal to the slot. The Connection handle will be invalid
|
||||
if it cannot create the connection, for example, if QObject is unable
|
||||
to verify the existence of either \a signal or \a method, or if their
|
||||
signatures aren't compatible.
|
||||
You can check if the QMetaObject::Connection is valid by casting it to a bool.
|
||||
|
||||
By default, a signal is emitted for every connection you make;
|
||||
two signals are emitted for duplicate connections. You can break
|
||||
@ -2339,15 +2342,15 @@ static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaM
|
||||
|
||||
\sa disconnect(), sender(), qRegisterMetaType()
|
||||
*/
|
||||
|
||||
bool QObject::connect(const QObject *sender, const char *signal,
|
||||
QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal,
|
||||
const QObject *receiver, const char *method,
|
||||
Qt::ConnectionType type)
|
||||
{
|
||||
{
|
||||
const void *cbdata[] = { sender, signal, receiver, method, &type };
|
||||
void *result = 0;
|
||||
const void *cbdata[] = { sender, signal, receiver, method, &type , &result};
|
||||
if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
|
||||
return true;
|
||||
return QMetaObject::Connection(result);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
@ -2366,12 +2369,12 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
(signal && *signal) ? signal+1 : "(null)",
|
||||
receiver ? receiver->metaObject()->className() : "(null)",
|
||||
(method && *method) ? method+1 : "(null)");
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
QByteArray tmp_signal_name;
|
||||
|
||||
if (!check_signal_macro(sender, signal, "connect", "bind"))
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
const QMetaObject *smeta = sender->metaObject();
|
||||
const char *signal_arg = signal;
|
||||
++signal; //skip code
|
||||
@ -2393,7 +2396,7 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
if (signal_index < 0) {
|
||||
err_method_notfound(sender, signal_arg, "connect");
|
||||
err_info_about_objects("connect", sender, receiver);
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
|
||||
int signalOffset, methodOffset;
|
||||
@ -2405,7 +2408,7 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
int membcode = extract_code(method);
|
||||
|
||||
if (!check_method_code(membcode, receiver, method, "connect"))
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
const char *method_arg = method;
|
||||
++method; // skip code
|
||||
|
||||
@ -2444,7 +2447,7 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
if (method_index_relative < 0) {
|
||||
err_method_notfound(receiver, method_arg, "connect");
|
||||
err_info_about_objects("connect", sender, receiver);
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
if (!QMetaObject::checkConnectArgs(signal, method)) {
|
||||
@ -2452,13 +2455,13 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
"\n %s::%s --> %s::%s",
|
||||
sender->metaObject()->className(), signal,
|
||||
receiver->metaObject()->className(), method);
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
int *types = 0;
|
||||
if ((type == Qt::QueuedConnection)
|
||||
&& !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
if (warnCompat) {
|
||||
@ -2467,10 +2470,11 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
check_and_warn_compat(smeta, smethod, rmeta, rmethod);
|
||||
}
|
||||
#endif
|
||||
if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index_relative, rmeta ,type, types))
|
||||
return false;
|
||||
QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
|
||||
sender, signal_index, receiver, method_index_relative, rmeta ,type, types));
|
||||
if (handle)
|
||||
const_cast<QObject*>(sender)->connectNotify(signal - 1);
|
||||
return true;
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2478,7 +2482,12 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
|
||||
Creates a connection of the given \a type from the \a signal in
|
||||
the \a sender object to the \a method in the \a receiver object.
|
||||
Returns true if the connection succeeds; otherwise returns false.
|
||||
Returns a handle to the connection that can be used to disconnect
|
||||
it later.
|
||||
|
||||
The Connection handle will be invalid if it cannot create the
|
||||
connection, for example, the parameters were invalid.
|
||||
You can check if the QMetaObject::Connection is valid by casting it to a bool.
|
||||
|
||||
This function works in the same way as
|
||||
connect(const QObject *sender, const char *signal,
|
||||
@ -2490,7 +2499,7 @@ bool QObject::connect(const QObject *sender, const char *signal,
|
||||
const QObject *receiver, const char *method,
|
||||
Qt::ConnectionType type)
|
||||
*/
|
||||
bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
|
||||
QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal,
|
||||
const QObject *receiver, const QMetaMethod &method,
|
||||
Qt::ConnectionType type)
|
||||
{
|
||||
@ -2513,7 +2522,7 @@ bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
|
||||
signal.signature(),
|
||||
receiver ? receiver->metaObject()->className() : "(null)",
|
||||
method.signature() );
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
// Reconstructing SIGNAL() macro result for signal.signature() string
|
||||
@ -2528,12 +2537,12 @@ bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
|
||||
methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
|
||||
: method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
|
||||
methodSignature.append(method.signature());
|
||||
const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type };
|
||||
void *result = 0;
|
||||
const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type, &result };
|
||||
if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
|
||||
return true;
|
||||
return QMetaObject::Connection(result);
|
||||
}
|
||||
|
||||
|
||||
int signal_index;
|
||||
int method_index;
|
||||
{
|
||||
@ -2547,12 +2556,12 @@ bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
|
||||
if (signal_index == -1) {
|
||||
qWarning("QObject::connect: Can't find signal %s on instance of class %s",
|
||||
signal.signature(), smeta->className());
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
if (method_index == -1) {
|
||||
qWarning("QObject::connect: Can't find method %s on instance of class %s",
|
||||
method.signature(), rmeta->className());
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) {
|
||||
@ -2560,23 +2569,23 @@ bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
|
||||
"\n %s::%s --> %s::%s",
|
||||
smeta->className(), signal.signature(),
|
||||
rmeta->className(), method.signature());
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
}
|
||||
|
||||
int *types = 0;
|
||||
if ((type == Qt::QueuedConnection)
|
||||
&& !(types = queuedConnectionTypes(signal.parameterTypes())))
|
||||
return false;
|
||||
return QMetaObject::Connection(0);
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
if (warnCompat)
|
||||
check_and_warn_compat(smeta, signal, rmeta, method);
|
||||
#endif
|
||||
if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, 0, type, types))
|
||||
return false;
|
||||
|
||||
QMetaObject::Connection handle = QMetaObject::Connection(QMetaObjectPrivate::connect(
|
||||
sender, signal_index, receiver, method_index, 0, type, types));
|
||||
if (handle)
|
||||
const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
|
||||
return true;
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2958,22 +2967,24 @@ static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_in
|
||||
if \a signal_index is -1, then we effectively connect *all* signals
|
||||
from the sender to the receiver's slot
|
||||
*/
|
||||
bool QMetaObject::connect(const QObject *sender, int signal_index,
|
||||
QMetaObject::Connection QMetaObject::connect(const QObject *sender, int signal_index,
|
||||
const QObject *receiver, int method_index, int type, int *types)
|
||||
{
|
||||
signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
|
||||
return QMetaObjectPrivate::connect(sender, signal_index,
|
||||
return Connection(QMetaObjectPrivate::connect(sender, signal_index,
|
||||
receiver, method_index,
|
||||
0, //FIXME, we could speed this connection up by computing the relative index
|
||||
type, types);
|
||||
type, types));
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
|
||||
|
||||
method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
|
||||
|
||||
the QObjectPrivate::Connection* has a refcount of 2, so it must be passed to a QMetaObject::Connection
|
||||
*/
|
||||
bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
|
||||
QObjectPrivate::Connection *QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
|
||||
const QObject *receiver, int method_index,
|
||||
const QMetaObject *rmeta, int type, int *types)
|
||||
{
|
||||
@ -2998,7 +3009,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
|
||||
|
||||
while (c2) {
|
||||
if (c2->receiver == receiver && c2->method() == method_index_absolute)
|
||||
return false;
|
||||
return 0;
|
||||
c2 = c2->nextConnectionList;
|
||||
}
|
||||
}
|
||||
@ -3030,8 +3041,7 @@ bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
|
||||
sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
|
||||
}
|
||||
|
||||
c.take(); // stop tracking
|
||||
return true;
|
||||
return c.take();
|
||||
}
|
||||
|
||||
/*!\internal
|
||||
@ -4032,6 +4042,82 @@ void qDeleteInEventHandler(QObject *o)
|
||||
delete o;
|
||||
}
|
||||
|
||||
/*!
|
||||
Disconnect a connection.
|
||||
|
||||
If the \a connection is invalid or has already been disconnected, do nothing
|
||||
and return false.
|
||||
|
||||
\sa connect()
|
||||
*/
|
||||
bool QObject::disconnect(const QMetaObject::Connection &connection)
|
||||
{
|
||||
QObjectPrivate::Connection *c = static_cast<QObjectPrivate::Connection *>(connection.d_ptr);
|
||||
|
||||
if (!c || !c->receiver)
|
||||
return false;
|
||||
|
||||
QMutex *senderMutex = signalSlotLock(c->sender);
|
||||
QMutex *receiverMutex = signalSlotLock(c->receiver);
|
||||
QOrderedMutexLocker locker(senderMutex, receiverMutex);
|
||||
|
||||
QObjectConnectionListVector *connectionLists = QObjectPrivate::get(c->sender)->connectionLists;
|
||||
Q_ASSERT(connectionLists);
|
||||
connectionLists->dirty = true;
|
||||
|
||||
*c->prev = c->next;
|
||||
if (c->next)
|
||||
c->next->prev = c->prev;
|
||||
c->receiver = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \class QMetaObject::Connection
|
||||
Represents a handle to a signal-slot connection.
|
||||
It can be used to disconnect that connection, or check if
|
||||
the connection was successful
|
||||
|
||||
\sa QObject::disconnect
|
||||
*/
|
||||
|
||||
/*!
|
||||
Create a copy of the handle to the connection
|
||||
*/
|
||||
QMetaObject::Connection::Connection(const QMetaObject::Connection &other) : d_ptr(other.d_ptr)
|
||||
{
|
||||
if (d_ptr)
|
||||
static_cast<QObjectPrivate::Connection *>(d_ptr)->ref();
|
||||
}
|
||||
|
||||
QMetaObject::Connection& QMetaObject::Connection::operator=(const QMetaObject::Connection& other)
|
||||
{
|
||||
if (other.d_ptr != d_ptr) {
|
||||
if (d_ptr)
|
||||
static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
|
||||
d_ptr = other.d_ptr;
|
||||
if (other.d_ptr)
|
||||
static_cast<QObjectPrivate::Connection *>(other.d_ptr)->ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
QMetaObject::Connection::Connection() : d_ptr(0) {}
|
||||
|
||||
QMetaObject::Connection::~Connection()
|
||||
{
|
||||
if (d_ptr)
|
||||
static_cast<QObjectPrivate::Connection *>(d_ptr)->deref();
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn bool QMetaObject::Connection::operator bool()
|
||||
|
||||
Returns true if the connection is valid.
|
||||
|
||||
The connection is valid if the call to QObject::connect succeeded.
|
||||
The connection is invalid if QObject::connect was not able to find
|
||||
the signal or the slot, or if the arguments do not match.
|
||||
*/
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -194,15 +194,14 @@ public:
|
||||
void installEventFilter(QObject *);
|
||||
void removeEventFilter(QObject *);
|
||||
|
||||
|
||||
static bool connect(const QObject *sender, const char *signal,
|
||||
static QMetaObject::Connection connect(const QObject *sender, const char *signal,
|
||||
const QObject *receiver, const char *member, Qt::ConnectionType = Qt::AutoConnection);
|
||||
|
||||
static bool connect(const QObject *sender, const QMetaMethod &signal,
|
||||
static QMetaObject::Connection connect(const QObject *sender, const QMetaMethod &signal,
|
||||
const QObject *receiver, const QMetaMethod &method,
|
||||
Qt::ConnectionType type = Qt::AutoConnection);
|
||||
|
||||
inline bool connect(const QObject *sender, const char *signal,
|
||||
inline QMetaObject::Connection connect(const QObject *sender, const char *signal,
|
||||
const char *member, Qt::ConnectionType type = Qt::AutoConnection) const;
|
||||
|
||||
static bool disconnect(const QObject *sender, const char *signal,
|
||||
@ -214,6 +213,7 @@ public:
|
||||
{ return disconnect(this, signal, receiver, member); }
|
||||
inline bool disconnect(const QObject *receiver, const char *member = 0)
|
||||
{ return disconnect(this, 0, receiver, member); }
|
||||
static bool disconnect(const QMetaObject::Connection &);
|
||||
|
||||
void dumpObjectTree();
|
||||
void dumpObjectInfo();
|
||||
@ -275,7 +275,7 @@ private:
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
|
||||
};
|
||||
|
||||
inline bool QObject::connect(const QObject *asender, const char *asignal,
|
||||
inline QMetaObject::Connection QObject::connect(const QObject *asender, const char *asignal,
|
||||
const char *amember, Qt::ConnectionType atype) const
|
||||
{ return connect(asender, asignal, this, amember, atype); }
|
||||
|
||||
|
@ -121,11 +121,22 @@ public:
|
||||
Connection *next;
|
||||
Connection **prev;
|
||||
QAtomicPointer<int> argumentTypes;
|
||||
QAtomicInt ref_;
|
||||
ushort method_offset;
|
||||
ushort method_relative;
|
||||
ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
|
||||
Connection() : nextConnectionList(0), ref_(2) {
|
||||
//ref_ is 2 for the use in the internal lists, and for the use in QMetaObject::Connection
|
||||
}
|
||||
~Connection();
|
||||
int method() const { return method_offset + method_relative; }
|
||||
void ref() { ref_.ref(); }
|
||||
void deref() {
|
||||
if (!ref_.deref()) {
|
||||
Q_ASSERT(!receiver);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
};
|
||||
// ConnectionList is a singly-linked list
|
||||
struct ConnectionList {
|
||||
|
@ -291,6 +291,7 @@ public:
|
||||
|
||||
struct Q_CORE_EXPORT QMetaObject
|
||||
{
|
||||
class Connection;
|
||||
const char *className() const;
|
||||
const QMetaObject *superClass() const;
|
||||
|
||||
@ -336,7 +337,7 @@ struct Q_CORE_EXPORT QMetaObject
|
||||
static QByteArray normalizedType(const char *type);
|
||||
|
||||
// internal index-based connect
|
||||
static bool connect(const QObject *sender, int signal_index,
|
||||
static Connection connect(const QObject *sender, int signal_index,
|
||||
const QObject *receiver, int method_index,
|
||||
int type = 0, int *types = 0);
|
||||
// internal index-based disconnect
|
||||
@ -458,6 +459,30 @@ struct Q_CORE_EXPORT QMetaObject
|
||||
} d;
|
||||
};
|
||||
|
||||
class Q_CORE_EXPORT QMetaObject::Connection {
|
||||
void *d_ptr; //QObjectPrivate::Connection*
|
||||
explicit Connection(void *data) : d_ptr(data) { }
|
||||
friend class QObject;
|
||||
friend struct QMetaObject;
|
||||
public:
|
||||
~Connection();
|
||||
Connection();
|
||||
Connection(const Connection &other);
|
||||
Connection &operator=(const Connection &other);
|
||||
#ifdef qdoc
|
||||
operator bool() const;
|
||||
#else
|
||||
typedef void *Connection::*RestrictedBool;
|
||||
operator RestrictedBool() const { return d_ptr ? &Connection::d_ptr : 0; }
|
||||
#endif
|
||||
|
||||
#ifdef Q_COMPILER_RVALUE_REFS
|
||||
inline Connection(Connection &&o) : d_ptr(o.d_ptr) { o.d_ptr = 0; }
|
||||
inline Connection &operator=(Connection &&other)
|
||||
{ qSwap(d_ptr, other.d_ptr); return *this; }
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef const QMetaObject& (*QMetaObjectAccessor)();
|
||||
|
||||
struct QMetaObjectExtraData
|
||||
|
@ -110,7 +110,7 @@ void tst_QGlobal::qInternalCallbacks()
|
||||
// Test that connect works as expected...
|
||||
connect_info.reset();
|
||||
bool ok = QObject::connect(&a, signal.toLatin1(), &b, slot.toLatin1(), Qt::AutoConnection);
|
||||
QVERIFY(ok);
|
||||
QVERIFY(!ok); // our dummy callback do not return a valid QMetaObject::Connection
|
||||
QCOMPARE(&a, connect_info.sender);
|
||||
QCOMPARE(&b, connect_info.receiver);
|
||||
QCOMPARE(signal, connect_info.signal);
|
||||
|
Loading…
Reference in New Issue
Block a user