Obsah

# Naslouchání událostem v dokumentu

Naslouchání událostem v dokumentu může pomoci v následujících situacích:

- Rozpoznání, že se otevírá nový dokument, nikoli již existující, a provedení určitého nastavení.

- Řízení při zpracování požadavků na ukládání dokumentu, jeho kopírování, tisk a hromadnou korespondenci.

- Přepočítání obsahů, rejstříků či tabulek v dokumentu Writeru ve chvíli, kdy se má dokument zavřít

- Importování matematických balíčků Pythonu před otevřením dokumentu Calcu a jejich uvolnění při zavírání dokumentu.

Kromě přiřazování maker k událostem je možné události vyvolané dokumenty LibreOffice sledovat. Za volání skriptů pro události jsou zodpovědné broadcastery z rozhraní pro programování aplikací (API). Na rozdíl od posluchačů, u nichž je nutné definovat všechny podporované metody (i nepoužité), funkce pro sledování dokumentu vyžadují kromě skriptů pro událost, ke které se vztahují, pouze dvě metody.

## Sledování událostí v dokumentu

Sledování je níže znázorněno pro jazyky Basic a Python a objektově orientované programování. Přiřadíte-li události Otevřít dokument skript OnLoad, můžete sledovat události inicializace a zavření dokumentu. K přiřazení skriptů slouží karta Události z nabídky Nástroje – Přizpůsobit.

Zastavování událostí napomáhá tomu, abyste nastavili prostředí pro skripty, například můžete načíst nebo uvolnit knihovny nebo nastavit na pozadí sledování skriptů. Příkladem posledně jmenované činnosti je použití modulu Access2Base.Trace.

### Pomocí Pythonu

Sledování událostí začíná při vytvoření instance objektu a končí, když je objekt v Pythonu uvolněn. Vyvolané události jsou zaznamenávány pomocí konzole Access2Base.

Události OnLoad a OnUnload můžete využít k tomu, abyste nastavili, případně zrušili nastavení cesty k programům Pythonu. Tyto události jsou uváděny pod názvy Otevřít dokument a Dokument zavřen.

             # -*- coding: utf-8 -*-
             from __future__ import unicode_literals

             import os.path, uno, unohelper
             from com.sun.star.document import DocumentEvent, \
                 XDocumentEventListener as AdapterPattern
             from com.sun.star.lang import EventObject

             class UiDocument(unohelper.Base, AdapterPattern):
                 """ Sledování události v dokumentu """
                 '''
                 upraveno ze stránky 'Python script to monitor OnSave event' na
                 https://forum.openoffice.org/en/forum/viewtopic.php?t=68887
                 '''
                 def __init__(self):
                     """ Sledování událostí v dokumentu """
                     ''' záznam pomocí konzole Access2Base.Trace nebo
                     do prvního sloupce na prvním listu v dokumentu Calcu '''
                     ctx = uno.getComponentContext()
                     smgr = ctx.getServiceManager()
                     desktop = smgr.createInstanceWithContext(
                     'com.sun.star.frame.Desktop' , ctx)
                     self.doc = desktop.CurrentComponent
                     #self.row = 0  # odkomentovat pouze pro dokumenty Calcu
                     Console.setLevel("DEBUG")
                     self.listen()  # Začne sledovat události v dokumentu

                 @property
                 def Filename(self) -> str:
                     sys_filename = uno.fileUrlToSystemPath(self.doc.URL)
                     return os.path.basename(sys_filename)

                 def setCell(self, calcDoc, txt: str):
                     """ Vypíše události v dokumentu do prvního sloupce sešitu Calcu """
                     sheet = calcDoc.getSheets().getByIndex(0)
                     sheet.getCellByPosition(0,self.row).setString(txt)
                     self.row = self.row + 1

                 def listen(self, *args):  # nejprve OnLoad/OnNew
                     """ Začne sledovat události v dokumentu """
                     self.doc.addDocumentEventListener(self)
                     Console.log("INFO", "Události v dokumentu se zaznamenávají", True)

                 def sleep(self, *args):  # nakonec OnUnload (nepovinné)
                     """ Zastaví sledování událostí v dokumentu """
                     self.doc.removeDocumentEventListener(self)
                     Console.log("INFO", "Události v dokumentu byly zaznamenány", True)

                 def documentEventOccured(self, event: DocumentEvent):
                     """ Přeruší každou událost v dokumentu """
                     #self.setCell(event.Source, event.EventName) # pouze pro dokumenty Calcu
                     Console.log("DEBUG",
                         event.EventName+" in "+self.Filename,
                         False)

                 def disposing(self, event: EventObject):
                     """ Uvolní všechny činnosti """
                     self.sleep()
                     Console.show()

             def OnLoad(*args):  # Událost 'Otevřít dokument'
                 listener = UiDocument()  # Inicializuje naslouchání

             def OnUnload(*args):  # Událost 'Dokument zavřen'
                 pass  # (nepovinné) provedeno při uvolňování

             g_exportedScripts = (OnLoad,)

             from com.sun.star.script.provider import XScript
             class Console():
                 """
                 Konzole na pozadí nebo v popředí pro záznam vykonávání programu.
                 """
                 @staticmethod
                 def trace(*args,**kwargs):
                     """ Vypíše do konzole libovolně dlouhý seznam položek """
                     scr = Console._a2bScript(script='DebugPrint', module='Compatible')
                     scr.invoke((args),(),())
                 @staticmethod
                 def log(level: str, text: str, msgBox=False):
                     """ Přidá do konzole zprávu protokolu, volitelně s uživatelským vstupem """
                     scr = Console._a2bScript(script='TraceLog')
                     scr.invoke((level,text,msgBox),(),())
                 @staticmethod
                 def setLevel(logLevel: str):
                     """ Nastaví dolní mez pro úroveň zpráv protokolu """
                     scr = Console._a2bScript(script='TraceLevel')
                     scr.invoke((logLevel,),(),())
                 @staticmethod
                 def show():
                     """ Zobrazí obsah konzole """
                     scr = Console._a2bScript(script='TraceConsole')
                     scr.invoke((),(),())
                 @staticmethod
                 def _a2bScript(script: str, library='Access2Base',
                     module='Trace') -> XScript:
                     ''' Použije skript Basicu pro aplikaci '''
                     sm = uno.getComponentContext().ServiceManager
                     mspf = sm.createInstanceWithContext(
                         "com.sun.star.script.provider.MasterScriptProviderFactory",
                         uno.getComponentContext())
                     scriptPro = mspf.createScriptProvider("")
                     scriptName = "vnd.sun.star.script:"+library+"."+module+"."+script+"?language=Basic&location=application"
                     xScript = scriptPro.getScript(scriptName)
                     return xScript

Název metody documentEventOccured obsahuje pravopisnou chybu, protože stejná chyba se nachází v rozhraní pro programování aplikací (API) pro LibreOffice.

Události Spustit aplikaci a Ukončit aplikaci je možné použít k tomu, abyste nastavili či zrušili nastavení cesty k Pythonu pro uživatelské skripty nebo skripty LibreOffice. Podobným způsobem, pomocí událostí Otevřít dokument a Dokument zavřen, lze načítat a uvolňovat knihovny nebo moduly Pythonu vložené v dokumentu. Další informace naleznete v části Import modulů Pythonu.

### Pomocí jazyka LibreOffice Basic

Po nastavení na kartě Události z nabídky Nástroje - Přizpůsobit spouští událost Otevřít dokument inicializaci instance pro ConsoleLogger. Podprogram _documentEventOccured - který nastavuje ConsoleLogger - slouží jako jediný vstupní bod zachycující všechny události v dokumentu.

#### Modul controller.Events

            Option Explicit

            Global _obj As Object ' instance controller.ConsoleLogger

            Sub OnLoad(evt As com.sun.star.document.DocumentEvent) ' "Otevřít dokument"
                _obj = New ConsoleLogger : _obj.StartAdapter(evt)
            End Sub ' controller.OnLoad
            Sub _documentEventOccured(evt As com.sun.star.document.DocumentEvent)
                ''' jediný vstupní bod pro ConsoleLogger '''
                 _obj.DocumentEventOccurs(evt)
            End Sub ' controller._documentEventOccured

#### Modul třídy controller.ConsoleLogger

Sledování události začíná ve chvíli, kdy je inicializován objekt ConsoleLogger a končí při uzavření dokumentu. Podprogram StartAdapter načte nezbytné knihovny Basicu, zachycené události jsou hlášeny modulem Access2Base.Trace.

              Option Explicit
              Option Compatible
              Option ClassModule

              ' objekt návrhového vzoru adaptér, který se inicializuje v události "Otevřít dokument"
              Private Const UI_PROMPT = True
              Private Const UI_NOPROMPT = False ' Nastavením na True události v dokumentu zobrazíte

              ' členové
              Private _evtAdapter As Object ' com.sun.star.document.XDocumentEventBroadcaster
              Private _txtMsg As String ' textová zpráva zaznamenávaná do konzole

              ' VLASTNOSTI
              Private Property Get FileName As String
                  ''' Název souboru závislý na operačním systému '''
                  Const _LIBRARY = "Tools" : With GlobalScope.BasicLibraries
                      If Not .IsLibraryLoaded(_LIBRARY) Then .LoadLibrary(_LIBRARY)
                  End With
                  Filename = Tools.Strings.FilenameOutofPath(ThisComponent.URL)
              End Property ' controller.ConsoleLogger.Filename

              ' metody
              Public Sub DocumentEventOccurs(evt As com.sun.star.document.DocumentEvent)
                  ''' Sleduje události v dokumentu '''
                  Access2Base.Trace.TraceLog("DEBUG", _
                      evt.EventName &" in "& Filename(evt.Source.URL), _
                      UI_NOPROMPT)
                  Select Case evt.EventName
                      Case "OnUnload" : _StopAdapter(evt)
                  End Select
              End Sub ' controller.ConsoleLogger.DocumentEventOccurs

              Public Sub StartAdapter(Optional evt As com.sun.star.document.DocumentEvent)
                  ''' Inicializuje zápis událostí v dokumentu do protokolu '''
                  Const _LIBRARY = "Access2Base" : With GlobalScope.BasicLibraries
                      If Not .IsLibraryLoaded(_LIBRARY) Then .LoadLibrary(_LIBRARY)
                  End With : Access2Base.Trace.TraceLevel("DEBUG")
                  If IsMissing(evt) Then _txtMsg = "" Else _txtMsg = evt.EventName & "-"
                  Access2Base.Trace.TraceLog("INFO", _txtMsg & "Zaznamenávají se události v dokumentu", UI_PROMPT)
                  _evtAdapter = CreateUnoListener( "_", "com.sun.star.document.XDocumentEventListener" )
                  ThisComponent.addDocumentEventListener( _evtAdapter )
              End Sub ' controller.ConsoleLogger.StartAdapter

              Private Sub _StopAdapter(Optional evt As com.sun.star.document.DocumentEvent)
                  ''' Ukončí zápis událostí v dokumentu do protokolu '''
                  ThisComponent.removeDocumentEventListener( _evtAdapter )
                  If IsMissing(evt) Then _txtMsg = "" Else _txtMsg = evt.EventName & "-"
                  Access2Base.Trace.TraceLog("INFO", _txtMsg & "Události v dokumentu byly zaznamenány", UI_PROMPT)
                  Access2Base.Trace.TraceConsole() ' Dialogové okno se zachycenými událostmi
              End Sub ' controller.ConsoleLogger._StopAdapter

              ' UDÁLOSTI
              ' Místo pro kód pro zpracovávané události

Název metody documentEventOccured obsahuje pravopisnou chybu, protože stejná chyba se nachází v rozhraní pro programování aplikací (API) pro LibreOffice.

## Seznam událostí v dokumentu

Broadcaster, objekt API, umožňuje získat seznam událostí, za něž je zodpovědný:

### Pomocí Pythonu

             # -*- coding: utf-8 -*-
             from __future__ import unicode_literals

             import uno, apso_utils as ui

             def displayAvailableEvents():
                 """ Zobrazí události v dokumentu """
                 '''
                 upraveno z funkce DisplayAvailableEvents() od A. Pitonyaka
                 https://forum.openoffice.org/en/forum/viewtopic.php?&t=43689
                 '''
                 ctx = XSCRIPTCONTEXT.getComponentContext()
                 smgr = ctx.ServiceManager
                 geb = smgr.createInstanceWithContext(
                     "com.sun.star.frame.GlobalEventBroadcaster", ctx)
                 events = geb.Events.getElementNames()
                 ui.msgbox('; '.join(events))

             g_exportedScripts = (displayAvailableEvents,)

Pro výpis informací o událostech na obrazovku se používá rozšíření Alternative Python Script Organizer (APSO).

### Pomocí jazyka LibreOffice Basic

             Sub DisplayAvailableEvents
                 ''' Zobrazí události v dokumentu '''
                 Dim geb As Object ' com.sun.star.frame.GlobalEventBroadcaster
                 Dim events() As String
                 geb = CreateUnoService("com.sun.star.frame.GlobalEventBroadcaster")
                 events = geb.Events.ElementNames()
                 MsgBox Join(events, "; ")
             End Sub

Související témata

Vytváření posluchačů událostí

Import modulů Pythonu

Vytvoření dialogového okna s handlerem

Příklady programování v Pythonu

Programování pomocí skriptů Pythonu

Volání maker Basicu z Pythonu