Python: Monitorar eventos de documentos

Conteúdo
Índice 🔎︎

# Monitorar eventos de documentos

Além de atribuir macros a eventos, você pode monitorar eventos ativados por documentos do LibreOffice. Os broadcasters da Application Programming Interface (API) são responsáveis pelas chamadas a macros de eventos. Diferente dos listeners que requerem a definição de todos os métodos suportados, mesmo que não utilizados, a monitoração de documentos requer somente dois métodos além dos scripts de eventos conectados.

## Ouvir eventos de documentos

A monitoração é ilustrada abaixo para as linguagens Basic e Python utilizando a programação orientada a objetos. Atribuir o script OnLoad ao evento Abrir documento, é o bastante para iniciar e terminar a monitoração de eventos do documento. A aba Eventos do menu Ferramentas - Personalizar é utilizada para especificar ambos os scripts.

Interceptar eventos ajuda a definir pré e pós-condições tais como carregar e descarregar bibliotecas ou rastrear processamento de scripts que rodam em modo silencioso. O módulo Access2Base.Trace ilustra o segundo contexto.

### Com Python

A monitoração de eventos começa da instanciação do objeto e termina quando o Python libera o objeto. Eventos levantados são reportados utilizando a console do Access2Base.

Os eventos OnLoad e OnUnload podem ser utilizados, respectivamente, para configurar e desconfigurar caminhos de programas python. Eles são descritos como Abrir documento e Documento fechado.

             # -*- 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):
                 """ Monitorar eventos de documento """
                 '''
                 adaptado de 'Python script to monitor OnSave event' de
                 https://forum.openoffice.org/en/forum/viewtopic.php?t=68887
                 '''
                 def __init__(self):
                     """ Monitorar eventos de documento """
                     ''' reportar utilizando a console Access2Base.Trace OU
                     reportar na 1ª planilha, 1ª coluna para documentos do Calc '''
                     ctx = uno.getComponentContext()
                     smgr = ctx.getServiceManager()
                     desktop = smgr.createInstanceWithContext(
                     'com.sun.star.frame.Desktop' , ctx)
                     self.doc = desktop.CurrentComponent
                     #self.row = 0  # descomente somente para documentos do Calc
                     Console.setLevel("DEBUG")
                     self.listen()  # Comece a monitorar eventos de documento

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

                 def setCell(self, calcDoc, txt: str):
                     """ Saída dos eventos de doc na 1ª coluna de uma planilha Calc """
                     sheet = calcDoc.getSheets().getByIndex(0)
                     sheet.getCellByPosition(0,self.row).setString(txt)
                     self.row = self.row + 1

                 def listen(self, *args):  # OnLoad/OnNew o mais cedo
                     """ Começar monitoração de eventos de documento """
                     self.doc.addDocumentEventListener(self)
                     Console.log("INFO", "Os eventos de documento estão sendo registrados", True)

                 def sleep(self, *args):  # OnUnload por último (opcional)
                     """ Encerrar monitoração de eventos de documento """
                     self.doc.removeDocumentEventListener(self)
                     Console.log("INFO", "Os eventos de documento foram registrados", True)

                 def documentEventOccured(self, event: DocumentEvent):
                     """ Interceptar todos os eventos de documento """
                     #self.setCell(event.Source, event.EventName) # somente para documentos do Calc
                     Console.log("DEBUG",
                         event.EventName+" in "+self.Filename,
                         False)

                 def disposing(self, event: EventObject):
                     """ Liberar todas as atividades """
                     self.sleep()
                     Console.show()

             def OnLoad(*args):  # evento 'Abrir documento'
                 listener = UiDocument()  # Initiates listening

             def OnUnload(*args):  # evento 'Documento foi fechado'
                 pass  # (opcional) executado quando dispensado

             g_exportedScripts = (OnLoad,)

             from com.sun.star.script.provider import XScript
             class Console():
                 """
                 Console de foreground ou background para reportar ou registrar execução de programa.
                 """
                 @staticmethod
                 def trace(*args,**kwargs):
                     """ Console de foreground ou background para reportar ou registrar execução de programa. """
                     scr = Console._a2bScript(script='DebugPrint', module='Compatible')
                     scr.invoke((args),(),())
                 @staticmethod
                 def log(level: str, text: str, msgBox=False):
                     """ Anexa a mensagem de registro na console, prompt de usuário opcional """
                     scr = Console._a2bScript(script='TraceLog')
                     scr.invoke((level,text,msgBox),(),())
                 @staticmethod
                 def setLevel(logLevel: str):
                     """ Define limite inferior para mensagens de registro """
                     scr = Console._a2bScript(script='TraceLevel')
                     scr.invoke((logLevel,),(),())
                 @staticmethod
                 def show():
                     """ Exibe o conteúdo ou diálogo da console """
                     scr = Console._a2bScript(script='TraceConsole')
                     scr.invoke((),(),())
                 @staticmethod
                 def _a2bScript(script: str, library='Access2Base',
                     module='Trace') -> XScript:
                     ''' Grab application-based Basic script '''
                     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

Note o erro no nome do método documentEventOccured que herda um erro da LibreOffice Application Programming Interface (API).

Os eventos Inciar aplicação e Fechar aplicação podem ser respectivamente utilizados para configurar e desconfigurar caminhos Python para scripts de usuários ou scripts de LibreOffice. De forma similar, bibliotecas ou módulos Python baseados em documentos podem ser carregados e descarregados utilizando os eventos Abrir documento e Documento fechado. Consulte Importar módulos Python para mais informações.

### Com LibreOffice Basic

O script Onload é atribuído ao evento Abrir documento utilizando a aba Eventos do menu Ferramentas - Personalizar. A monitoração de eventos inicia no momento em que um objeto ConsoleLogger é instanciado e encerra apenas quando o motor do Basic o libera. O evento OnLoad carrega as bibliotecas do Basic necessárias, enquanto eventos capturados são reportados utilizando o módulo Access2Base.Trace.

              REM Módulo controller.Events
              Option Explicit
              Private _obj As Object ' instância do controller.ConsoleLogger

              Sub OnLoad(evt As com.sun.star.document.DocumentEvent) ' >> Abrir documento <<
                  _obj = New ConsoleLogger : _obj.Start(evt)
              End Sub ' controller.OnLoad
              ' ----
              REM Módulo de classe controller.ConsoleLogger
              Option Explicit
              Option Compatible
              Option ClassModule

              ' objeto de padrão de design ADAPTER a ser instanciado no evento "Abrir documento"
              Private Const UI_PROMPT = True
              Private Const UI_NOPROMPT = False ' Set it to True to visualise documents events

              ' CONSTRUTOR/DESTRUTOR
              Private Sub Class_Initialize()
              End Sub ' controller.ConsoleLogger.Initialize
              Private Sub Class_Terminate()
              End Sub ' controller.ConsoleLogger.Terminate

              ' MEMBROS
              Private _evtAdapter As Object ' com.sun.star.document.XDocumentEventBroadcaster

              ' PROPERTIES
              Private Property Get FileName As String
                  ''' nome de arquivo dependente do Sistema '''
                  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

              ' MÉTODOS
              Private Sub _documentEventOccured(evt As com.sun.star.document.DocumentEvent)
                  ''' Monitorar eventos de documento '''
                  Access2Base.Trace.TraceLog("DEBUG", _
                      evt.EventName &" in "& Filename(evt.Source.URL), _
                      UI_NOPROMPT)
                  Select Case evt.EventName
                      Case "OnUnload" : _Stop(evt)
                  End Select
              End Sub ' controller.ConsoleLogger._documentEventOccured

              Private Sub _disposing(evt As com.sun.star.lang.EventObject)
              End Sub ' controller.ConsoleLogger.disposing

              Public Sub Start(Optional evt As com.sun.star.document.DocumentEvent)
                  ''' Inicializar registros de eventos de documento '''
                  Const _LIBRARY = "Access2Base" : With GlobalScope.BasicLibraries
                      If Not .IsLibraryLoaded(_LIBRARY) Then .LoadLibrary(_LIBRARY)
                  End With : Access2Base.Trace.TraceLevel("DEBUG")
                  Access2Base.Trace.TraceLog("INFO", _
                      IIf(IsMissing(evt),"",evt.EventName & "-") & "Eventos de documento estão sendo registrados", _
                      UI_PROMPT)

                  _evtAdapter = CreateUnoListener( "_", "com.sun.star.document.XDocumentEventListener" )
                  ThisComponent.addDocumentEventListener( _evtAdapter )
              End Sub ' controller.ConsoleLogger.Start

              Private Sub _Stop(Optional evt As com.sun.star.document.DocumentEvent)
                  ''' Encerrar registro de eventos de documento '''
                  ThisComponent.removeDocumentEventListener( _evtAdapter )
                  Access2Base.Trace.TraceLog("INFO", _
                      IIf(IsMissing(evt),"",evt.EventName & "-") & "Eventos de documento foram registrados", _
                      UI_PROMPT)
                  Access2Base.Trace.TraceConsole() ' Captured events dialog
              End Sub ' controller.ConsoleLogger._Stop

              ' EVENTS
              ' Seu código para tratar eventos segue aqui

Note o erro no nome do método documentEventOccured que herda um erro da LibreOffice Application Programming Interface (API).

## Descobrir eventos de documento

O objeto API broadcaster fornece a lista de eventos dos quais é responsável:

### Com Python

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

             import uno, apso_utils as ui

             def displayAvailableEvents():
                 """ Exibe eventos de documento """
                 '''
                 adaptado de DisplayAvailableEvents() por A. Pitonyak
                 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,)

A extensão Alternative Python Script Organizer (APSO) é utilizada para mostrar informações de eventos na tela.

### Com LibreOffice Basic

             Sub DisplayAvailableEvents
                 ''' Exibe eventos de documento '''
                 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

Tópicos relacionados

Criar listeners de evento

Importar módulos Python

Criar um manipulador de caixa de diálogo

Exemplos de programação em Python

Programando com scripts Python

Chamar macros Basic pelo Python