Emitting signal based on index
-
Supposed I have a number of signals defined in my class' header file:
void signal1(QVariant); void signal2(QVariant); void signal3(QVariant); void signal4(QVariant);
I also have a function which receives two pieces of data:
void myClass::receiveFunction(uint8_t data1, uint8_t data2) { //Do something }
The signal which is to be emitted is determined by the received data1 value in the receiveFunction(). For example:
void myClass::receiveFunction(uint8_t data1, uint8_t data2) { if (data1 == 1) { emit signal1(data2); } else if (data1 == 2) { emit signal2(data2); } //etc. }
What's the best way to emit a specific signal without having to cycle through all the input parameters like above? Can I use the signal index via QMetaObject? Could I use a QHash with 'data1' as the key and a pointer to the signal/method as the value?
Is there a better way to define the signals in the header file (e.g. an array or vector of signals)?
Any input would be greatly appreciated!
-
a single signal that has an index param is probably the easiest paradigm. use a switch() or lookup map in the slot to determine behaviour. if/else is a very naive implementation.
-
@Kent-Dorfman said in Emitting signal based on index:
a single signal that has an index param is probably the easiest paradigm. use a switch() or lookup map in the slot to determine behaviour. if/else is a very naive implementation.
Fair enough, thanks for your input.
My actual use case isn't quite as simple as the example I gave above; which 'data1' value fires which signal is variable and loaded into the application from an external configuration file. I think I'll load the configuration into a QHash, and then perform a switch as you've suggested. I can't imagine I'll face any performance bottlenecks with this approach.
-
I don't want to get into designing your program for you, but my spidey sense tells me that somethingl like a signal broadcast and publish/subscribe model is most beneficial. signals/slots are not expensive, so attach the signal to multiple receivers, broadcast-emit the signal, and let the receivers do as they wish wish in the reveicer slot base on passed param data.
-
Upon further reflection I think you're absolutely right.
At some point there needs to be a switch() to route the signal to the correct action, but I think it does make more sense to incorporate the switch after the signal/slot, rather than before, so I don't have 10+ signals and 10+ slots to manage.
Thanks again!
-
@jars121 just in case you're still looking for a solution to your original question, and/or someone else finds his/her way over google to here:
#include <array> class SomeClass : public QObject { Q_OBJECT typedef void (SomeClass::*SomeClassFunction)(); std::array<SomeClassFunction,3> arrayOfSignalsPointers{&SomeClass::signal1,&SomeClass::signal2, &SomeClass::signal3}; std::array<SomeClassFunction, 3> arrayOfSlotsPointers{&SomeClass::slot1, &SomeClass::slot2, &SomeClass::slot3}; public: explicit SomeClass(QObject *parent = nullptr) : QObject(parent) { QObject::connect(this, &SomeClass::signal1, this, &SomeClass::slot1); QObject::connect(this, &SomeClass::signal2, this, &SomeClass::slot2); QObject::connect(this, &SomeClass::signal3, this, &SomeClass::slot3); qDebug() << "Emit all signals"; for(auto entry : arrayOfSignalsPointers){ (this->*entry)(); } qDebug() << "Call all slots directly"; for(auto entry : arrayOfSlotsPointers){ (this->*entry)(); } } signals: void signal1(); void signal2(); void signal3(); public slots: void slot1(){qDebug() << Q_FUNC_INFO;} void slot2(){qDebug() << Q_FUNC_INFO;} void slot3(){qDebug() << Q_FUNC_INFO;} };