OP-based event/callback System

I, and from what I gather many others, switched to a kind of Event-Driven system in development. Esp of larger systems. I use a custom-made Callback-Manager in combination with Extensions to move arround events in the project. But this approach is still somewhat limited as you cannot fetch events from children and so on.
What I would like to see is an event-system compareable to that of JavaScript where every Dom-Element is able to emit events and I can subscribe to them from anywhere. It is possible to build a system like this using extensions and subscribe/unsubscribe methods. The problem here in lais with the order of initiialisation of extensions and the just in time nature of them. This would also not enable bubbling of events to parent-components.

What I see is a general EmitEvent("Event name", *args, bubble = False, **kwargs) method implemented into the core OP-Class.
Secondary to that it would need a EventDAT, which either has a onEvent-callback, or makes it possible to compose callbacks out of the methodname (basicly taking the Event Name as the method name).

Another approach (semantics) would be to pass a dictionary as data alá JS and have a general onEvent-Callback in the eventDAT and be able to filter for events like in the errorDAT or chopExecuteDAT.


same here :slight_smile:

Yeah this would be awesome for building complex systems.

1 Like

@greg as we talked about this during the meetup.
So, I went to the drawing board and implemented a Emitter/Listener-system and might have gotten a little overboard with it. But it shows nicely in which direction this could go.
eventEmitter.tox (2.2 KB)
eventListener.tox (12.6 KB)

First we have the emitter. The Emitter has a definition. This definition is, in this case, used for two things:

  1. Creating the module-definition for the eventListener, so we do not have to guess the events
  2. Implementing a strict mode where events get checked (name, arguments( existense, type)) even before execution. If this is something useable at all is to discuss, but it should make debugging easier.

Then we have the listener. The listener will simply subscribe to the emitter. When doing that, it is using the definition provided by the emitter to create boilderplate callbacks. Now, when we emit an event in our emitter, the callback in the listener will be executed. The good thing is that we are not even limited to 1 listener, but can have any ammount of them.

What could this be used for? A little usecase:
I have a repeatingTime component, that will emit an event on a given ammount of time. For example to check for an external source, fetch some data, or switch a visual.

So, this secondTimer triggers every second and will force the mediaPlayer to play the next one. This is pretty elegant. Both components are seperated, live on their own, topLevel takes control. This is also the way I work most of the times.
Now, lets imagine I would like to have a second videoPlayer. Simple enough, copy it, and add a line to the callback. But this starts to get extremly tricky when I start dynamicly create mediaPlayers, and I might want them to have several timings, that are changeable but still in synch.
This is where the Emitter/Listener might come in handy:

I create a triggeredVideoPlayer which can listen to a timer-component. Inside is an eventListener that is listening for the Trigger event to play the next file.

The listener created the callback from the definition.of the emitter, so no guessing.
The good thing now is that we can easily create several timerTriggers and several players and switch the refferenced arround.

exampleEventSystem.tox (45.0 KB)

I am use to keep things really simple: i have an extension that change parameter of a comp. And i use it for everything. I m used to make a huge component full of pages and parameter. Than from there i control everything. For repetitive events or on demand events i use chop that give me the right trigger. Than i call the extension to change the parameter.

Check out this small lib, it does exactly this and we’re succesfully using it in touch for a while now. GitHub - dgovil/PySignal: A purely Python implementation of the Qt signal system with no QObject dependencies

Also Tdu.dependency is a way to go. The only thing it can’t do at the moment is to trigger some callbacks in the extension of another component, but I saw somewhere that it’s already implemented in experimantal build

Here’s the details from the Release Notes

  • Dependency Class callbacks method
    • A modifiable list of functions. When the Dependency object is modified, it calls each function on the list.
    • The function is called with a single argument which is a dictionary containing the following:
      • ‘dependency’- The Dependency that was modified.
      • ‘prevVal’ - The previous value if available.
      • ‘callback’ - This callback function, which can be removed the the Dependency callbacks if needed.

Would love to see a simple Event/PubSub system available.

I have to versions you could try (check the releaseFolder for now.)

  1. Operator Based. You have one operator as Emitter and one es Listener, being 1 Emitter to N Listeners.
  2. A name and namespace based with the EventManager. Subscribe by creating callbacks and emit using the emit method. No OP-Refferences.
    GitHub - AlphaMoonbaseBerlin/TD_Event_Listener_System: a event emitter/listener syste, for TD
1 Like

@alphamoonbase thanks I’ll have a look :+1: