Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using lambda syntax in Qt signal and slot and accessing passed arguments

I have a class that has a signal with this signature:

// CLASS A
signals:
    void requestToChangeRange(voltage_range_e vr, current_range_e cr, uint16_t bits);

There is another class which has a slot like this (notice the extra parameter)

// CLASS C
public slots:
    void handleRequestRangeChange(voltage_range_e vr, current_range_e cr, uint16_t bits, uint16_t limiter);

Then I have a class "B" which acts as a meeting point of all other classes. When the class "A" emits the signal, class "C" should redirect it into class "B". But that extra argument on the slot of class "B" is the problem, because that extra argument comes from another class "X".

So if the signal and slots of classes "A" and "C" were matching I would do the following in class "B":

// somewhere in CLASS B (the manager of all other classes)
connect(pClassA, &ClassA::requestToChangeRange,
    pClassC, &ClassC::handleRequestRangeChange);

But obviously this does not work because of function signatures. What I want to do is something like:

// somewhere in CLASS B (the manager of all other classes)
connect(pClassA, &ClassA::requestToChangeRange,
this /* class B */, []() {
    // Get that last required parameter from class X
    uint16_t limiter = pClassX->getValue();
    // Call slot of class C
    pClassC->handleRequestRangeChange(vr, cr, bits, limiter);
});

So how can I access those passed parameters inside the lambda? Is this even possible?

like image 873
DEKKER Avatar asked Jan 27 '23 10:01

DEKKER


1 Answers

Your lambda should know both objects: [pClassX, pClassC] and accept the original parameters of the signal: (voltage_range_e vr, current_range_e cr, uint16_t bits).

So your connect should start like this:

connect(pClassA, &ClassA::requestToChangeRange, this,
    [pClassX, pClassC](voltage_range_e vr, current_range_e cr, uint16_t bits) {
    //...
});

About the 'receiver' in the connect() statement:

This pointer to QObject is actually not needed when connecting to a lambda, but it serves the purpose that the signal-slot-connection will be removed if either sender or receiver gets destroyed.

Using this means you have to make sure that after deleting either one of pClassX, pClassC you don't emit the signal anymore. Alternatively you could use pClassC as receiver, then you have to be sure that pClassX stays valid as long as pClassC and pClassA are alive... Ideally you'd specify pClassX AND pClassC as receivers, but that's not possible. You could utilize the guarding functionality of a QPointer for that.

like image 72
Martin Hennings Avatar answered Jan 30 '23 05:01

Martin Hennings