Class Events
Events class is a locally scoped class.
Once an instance of Events is created it can be used to subscribe to any internal event of OooDev.
Example
In the following example local_events is created in the open_remove_save() method.
While open_remove_save() is running any row index listed in protected_rows will not
be deleted even if they are passed into open_remove_save()
As soon as the open_remove_save() method is executed local_events goes out of scope.
When local_events is out of scope the events it was subscribe to get released.
Also setting local_events = None would release any events it was subscribed to.
from typing import Any
from ooodev.loader.lo import Lo
from ooodev.office.calc import Calc
from ooodev.events.lo_events import Events
from ooodev.events.args.calc.sheet_cancel_args import SheetCancelArgs
from ooodev.events.calc_named_event import CalcNamedEvent
protected_rows = (1, 3, 10, 15, 18)
def protect_row(source:Any, args:SheetCancelArgs) -> None:
nonlocal protected_rows
if args.index in protected_rows:
args.cancel = True
def open_remove_save(fnm:str, *indexes:int) -> None:
if len(indexes) == 0:
return
local_events = Events()
events.on(CalcNamedEvent.SHEET_ROW_DELETING, protect_row)
idxs = list(indexes)
idxs.sort()
idxs.reverse() # must remove from hightest to lowest.
with Lo.Loader(Lo.ConnectSocket()) as loader:
doc = Calc.open_doc(fnm=fnm, loader=loader)
sheet = Calc.get_sheet(doc=doc, index=0)
for idx in idxs:
Calc.delete_row(sheet=sheet, idx=idx)
Lo.save(doc)
Events uses weak reference internally.
For this reason assigning events in a class instance may not work as expected.
For instance assigning a class method as an event handler will not work unless the class method is a static method.
Sometimes it may be useful to pass a class instance to the event so a class property can be set.
The way Events enables class instance to be sent to a method is by way of EventArgs.event_source property.
Example
In the following example class constructor creates Events instance and assigns to class instance.
It is important that the Events instance be assigned to class or it will go out of scope when constructor is done
and that will result in no events being triggered for class.
Events is constructed it passes in the current class instanceself.events = Events(source=self)Note that on_disposed() is a static method. Events is not able to attach to instance methods.
The object passed into Events constructor (class instance in this case) are assigned to the EventArg.event_source property.
Now class instance properties can be set when the event is triggered event.event_source.bridge_disposed = True.
For a complete example see Office Window Monitor
#!/usr/bin/env python
from __future__ import annotations
import time
import sys
from typing import Any
from ooodev.adapter.lang.event_events import EventEvents
from ooodev.events.args.event_args import EventArgs
from ooodev.events.lo_events import Events
from ooodev.events.lo_named_event import LoNamedEvent
from ooodev.office.calc import Calc
from ooodev.gui import GUI
from ooodev.loader.lo import Lo
class DocMonitor:
def __init__(self) -> None:
self.closed = False
self.bridge_disposed = False
loader = Lo.load_office(Lo.ConnectPipe(), opt=Lo.Options(verbose=True))
self.doc = Calc.create_doc(loader=loader)
self._fn_on_disposed = self.on_disposed
self.events = Events(source=self)
self.events.on(LoNamedEvent.BRIDGE_DISPOSED, self._fn_on_disposed)
self._bridge_events = EventEvents()
self._bridge_events.add_event_disposing(self._fn_on_disposing)
Lo.bridge.addEventListener(self._bridge_events.events_listener_event)
GUI.set_visible(True, self.doc)
def on_disposed(self, source: Any, event_args: EventArgs) -> None:
# just another way of knowing when bridge is gone.
print("LO: Office bridge has gone!!")
self.bridge_disposed = True
def main_loop() -> None:
dw = DocMonitor()
# check an see if user passed in a auto terminate option
if len(sys.argv) > 1:
if str(sys.argv[1]).casefold() in ("t", "true", "y", "yes"):
Lo.delay(5000)
Lo.close_office()
# while Writer is open, keep running the script unless specifically ended by user
while 1:
if dw.bridge_disposed is True:
print("\nExiting due to office bridge is gone\n")
raise SystemExit(1)
time.sleep(0.1)
if __name__ == "__main__":
print("Press 'ctl+c' to exit script early.")
try:
main_loop()
except SystemExit as e:
SystemExit(e.code)
except KeyboardInterrupt:
# ctrl+c exist the script early
print("\nExiting by user request.\n", file=sys.stderr)
SystemExit(0)
Note
Events are limited to OooDev.
For instance OooDev can capture when are row is being removed from a spreadsheet internally; However, OooDev is not aware when other methods are used such as user input.
For more indepth Events look into LibreOffice Listeners and Chapter 4. Listening, and Other Techniques.
See also
- class ooodev.events.lo_events.Events(source=None, trigger_args=None)[source]
Class for sharing events among classes and functions.
Note
If an events source is
Nonethen it is set tosourceorEventsinstance ifsourceis None.- Parameters:
source (Any | None) –
trigger_args (GenericArgs | None) –
- __init__(source=None, trigger_args=None)[source]
Construct for Events
- Parameters:
source (Any | None, optional) – Source can be class or any object. The value of
sourceis the value assigned to theEventArgs.event_sourceproperty. Defaults to current instance of this class.trigger_args (GenericArgs, optional) – Args that are passed to events when they are triggered.
- Return type:
None
- add_observer(*args)
Adds observers that gets their
triggermethod called when this classtriggermethod is called.- Parameters:
args (EventObserver) – One or more observers to add.
- Return type:
None
Note
Observers are removed automatically when they are out of scope.
- has_event(event_name, callback)
Gets if event exists.
- Parameters:
event_name (str) – Event name
callback (EventCallback) – Callback function
- Returns:
True if event exists; Otherwise, False
- Return type:
bool
- has_event_name(event_name)
Gets if event exists.
- Parameters:
event_name (str) – Event name
- Returns:
True if event exists; Otherwise, False
- Return type:
bool
- on(event_name, callback)
Registers an event
- Parameters:
event_name (str) – Unique event name
callback (Callable[[object, EventArgs], None]) – Callback function
- remove(event_name, callback)
Removes an event callback
- Parameters:
event_name (str) – Unique event name
callback (Callable[[object, EventArgs], None]) – Callback function
- Returns:
Trueif callback has been removed; Otherwise,False.False means the callback was not found.
- Return type:
bool
- remove_observer(observer)
Removes an observer.
- Parameters:
observer (EventObserver) – Observers to remove.
- Returns:
Trueif observer has been removed; Otherwise,False.- Return type:
bool
- trigger(event_name, event_args)[source]
Trigger event(s) for a given name.
- Parameters:
event_name (str) – Name of event to trigger
event_args (EventArgsT) – Event args passed to the callback for trigger.
args (Any, optional) – Optional positional args to pass to callback
kwargs (Any, optional) – Optional keyword args to pass to callback
Note
Events are removed automatically when they are out of scope.