1
votes

I'm about to adapt my sources to the new signals and slots syntax in Qt. While the below stated code functioned well with a deprecated const char* signal parameter, it doesn't work with the new QMetaMethod &signal syntax.

class SignalWaiter : public QObject {
    Q_OBJECT
public:
    SignalWaiter(const QObject* sender, const QMetaMethod &signal);

private slots:
    void signalCaught();
};

SignalWaiter::SignalWaiter(const QObject* sender, const QMetaMethod &signal) {
    QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);
}

void SignalWaiter::signalCaught() {
}

The compiler stops at the connect() command with the message:

error: C2664: 'QMetaObject::Connection QObject::connect(const QObject *,const char *,const char *,Qt::ConnectionType) const': cannot convert argument 2 from 'const QMetaMethod' to 'const char *'

and

No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

So obviously the compiler tries to call the overloaded connect method with the old syntax. What am I doing wrong?

3
Compiler is right - const QMetaMethod &signal is not a pointer to function (signal), as you assume. - vahancho
@vahancho hm? compiler error says that it expects a const char* (which is also not a pointer to function) - 463035818_is_not_a_number
Historically, Qt used SIGNAL macro's which evaluated to const char* - MSalters

3 Answers

5
votes

The connect() you're trying to use has the signature:

QMetaObject::Connection QObject::connect(
    const QObject *sender, 
    const QMetaMethod &signal,
    const QObject *receiver,
    const QMetaMethod &method,
    Qt::ConnectionType type = Qt::AutoConnection)

note the 4th parameter const QMetaMethod &method which is not a pointer to member, which is why you get an error.

To do the appropriate convertion, you can use:

auto metaSlot = metaObject()->method(metaObject()->indexOfSlot("signalCaught()"));
QObject::connect(sender, signal, this, metaSlot);

Though, as pointed out by @p-a-o-l-o, new signal/slot syntax uses pointers to member functions, not QMetaMethod. His solution might be what you're really looking for.

3
votes

I think O'Neil answer solves the compilation issue, but if the OP really wants to

adapt my sources to the new signals and slots syntax

maybe they want to give the SignalWaiter class another constructor, like this:

template<typename T>
SignalWaiter(const T* sender, void (T::* signal)())
{
    QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);
}

Having a class MyClass with a void mysignal() signal:

MyClass * myclass = new MyClass();
SignalWaiter * waiter = new SignalWaiter(myclass, &MyClass::mysignal);
0
votes

Changing

QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);

to

QObject::connect(sender, signal, this, QMetaMethod::fromSignal(&SignalWaiter::signalCaught));

worked for me, which is similar to O'Neil's answer, but a little shorter syntax-wise. Note that you need to wrap the signal parameter in every constructor call in a QMetaMethod::fromSignal() command as well.

The solution proposed by p-a-o-l-o didn't work for me, because my SignalWaiter class actually inherits from QObject, which forbids the use of templates.