It seems like you need an event bus (where the sender matter or not, could simply be the event sender id). You then could register to listen to even from a particular source only or any source depending on your requirement. The any sender is not really possible with the Signal Slot unless you have a Signal forwarder central unit that would do just like the event bus. But there is many event bus implementation that doesn’t require Qt that could suit your need, you could translate your signal to event with a simple lambda on the event bus.
You should have a bus provider that get or create (goc) the bus with specific identifier (enum, name, etc). So you could have multiple BUS inside your application and different privilege bus (like DBUS user and system for example). You could have an action bus where action could be requested to perform actions (could have a flag into the actions to tell if it was handled or not when completed) and an event bus that reflect the actual events of what did happened into the system. All your conditions then become event listener that trigger actions. For example: system needs to do X when Y happens and if conditions A B and C are met You make an event listener that wait until A, B and C event happen on the BUS (can also request the initial state to begin with) and trigger action X and action Y directly or can even simply request and event/action DoX or DoY which could be process by something else. Decoupling your application by a lot that way. From: Interest <interest-boun...@qt-project.org> on behalf of Tarre Tarkas via Interest <interest@qt-project.org> Date: Wednesday, June 9, 2021 at 3:12 PM To: interest@qt-project.org <interest@qt-project.org> Subject: [Interest] Using a single shared Object as a message bus throughout the application? I'm working on a daemon that needs to stay flexible/tweakable. I get lots of random requirements in the form of "system needs to do X when Y happens and if conditions A B and C are met". Qt's doc and examples seems to exclusively encourage putting signals in each component's class definitions. So that's what I did previously. However I recently found out that you can actually emit a signal in a different QObject. I always thought the "emit MySignal()" to be like a private call, but no, signals are public functions, you can do "someobj->MySignal()", or better yet "Q_EMIT someobj->MySignal()" to make it stand out more. I'd like to hear your thoughts on an application architecture style where you use a single shared object as a public message bus throughout the entire app. So all the components of the app have a reference to this QObject, all the "public" signals used by the application are defined in this QObject instead of being defined in the object that emits them. I've written a very simple example app to showcase this: https://gitlab.com/tarre/message-bus-test Notice how the features in the 2nd and 3rd commits were bolted on to the existing architecture in a very straight-forward way, without having to modify unrelated source files. Pros: 1) Simpler application architecture. Since there's just a single source of major events, a new developer doesn't need to understand (as much) where their code fits with all the rest. They can add certain features by just writing signal handlers for signals coming from that single event bus. Also, they can discover how components interact with each other by searching for the usage of each signal from that single file. When writing new components, they don't need to think as much where to place it, since there's already this structure in place. 2) Signals emitted by objects created at a low "depth" (for example Hardware -> SensorManager -> TemperatureSensor) can be used by components anywhere in the app in a simple clean way, without writing repetitive boilerplate code just to be able to connect a signal to a slot 3) If there's a refactoring somewhere, if a different component is now responsible for emitting SignalX, consumers don't have to change anything. Previously the only way to do this would be to use interfaces, which is boilerplatey. Cons: 1) Not Qt-ic (whatever the Qt equivalent of "pythonic" is) 2) You lose the ability to use sender() to get a reference to the QObject* that did the real emit. With this, the sender is always the message bus object. (Correct me if I'm wrong. If there's a way to get the sender without adding it as an argument in every signal, that would be wonderful.) What do you think? Tarre _______________________________________________ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest
_______________________________________________ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest