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
None
then it is set tosource
orEvents
instance ifsource
is 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
source
is the value assigned to theEventArgs.event_source
property. 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
trigger
method called when this classtrigger
method 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:
True
if 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:
True
if 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.