Qt signal/slots - consume signal in one of many slots? -
is there way consume future slots (and stop them executing) in 1 of many slots connected same signal?
my goal here emit signal message many qobjects , consume (stopping iteration future slots) when qobject in message belongs finds it.
from understand in qt documentation:
if several slots connected 1 signal, slots executed 1 after other, in order have been connected, when signal emitted.
i want able stop process within slot.
suggestions?
no, there's no way it, , should not think of way. sender should perform same no matter number of slots connected signal. that's basic contract of signal-slot mechanism: sender decoupled from, , unaware of, receiver.
what you're trying qualified dispatch: there multiple receivers, , each receiver can process 1 or more message types. 1 way of implementing follows:
emit (signal)
qevent
. lets maintain signal-slot decoupling between transmitter , receiver(s).the event can consumed custom event dispatcher knows objects process events of given type.
the objects sent event in usual fashion, , receive in
event()
method.
the implementation below allows receiver objects live in other threads. that's why needs able clone events.
class <qcoreapplication> class <qevent> class clonableevent : public qevent { q_disable_copy(clonableevent) public: clonableevent(int type) : qevent(static_cast<qevent::type>(type)) {} virtual clonableevent * clone() const { return new clonableevent(type()); } } q_register_metatype(clonableevent*) class dispatcher : public qobject { q_object qmap<int, qset<qobject*>> m_handlers; public: q_slot void dispatch(clonableevent * ev) { auto = m_handlers.find(ev->type()); if (it == m_handlers.end()) return; (auto object : *it) { if (obj->thread() == qthread::currentthread()) qcoreapplication::sendevent(obj, ev); else qcoreapplication::postevent(obj, ev.clone()); } } void addmapping(qclonableevent * ev, qobject * obj) { addmapping(ev->type(), obj); } void addmapping(int type, qobject * obj) { qset<qobject*> & handlers = m_handlers[type]; auto = handlers.find(obj); if (it != handlers.end()) return; handlers.insert(obj); qobject::connect(obj, &qobject::destroyed, [this, type, obj]{ unregister(type, obj); }); m_handlers[type].insert(obj); } void removemapping(int type, qobject * obj) { auto = m_handlers.find(type); if (it == m_handlers.end()) return; it->remove(obj); } } class eventdisplay : public qobject { bool event(qevent * ev) { qdebug() << objectname() << "got event" << ev.type(); return qobject::event(ev); } public: eventdisplay() {} }; class eventsource : public qobject { q_object public: q_signal void indication(clonableevent *); } #define named(x) x; x.setobjectname(#x) int main(int argc, char ** argv) { qcoreapplication app(argc, argv); clonableevent ev1(qevent::user + 1); clonableevent ev2(qevent::user + 2); eventdisplay named(dp1); eventdisplay named(dp12); eventdisplay named(dp2); dispatcher d; d.addmapping(ev1, dp1); // dp1 handles ev1 d.addmapping(ev1, dp12); // dp12 handles both ev1 , ev2 d.addmapping(ev2, dp12); d.addmapping(ev2, dp2); // dp2 handles ev2 eventsource s; qobject::connect(&s, &eventsource::indication, &d, &dispatcher::dispatch); emit s.indication(&ev1); emit s.indication(&ev2); return 0; } #include "main.moc"
Comments
Post a Comment