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 programação orientada a objetos. Atribuir o script OnLoad ao evento OpenDocument, é o bastante para iniciar e terminar a monitoração de eventos do documento. Utilize a abaEventos do menu Ferramentas - Personalizar, para atribuir ambos os scripts.

Interceptar eventos ajuda a definir pré-condições e pós-condições tais como carregar e descarregar bibliotecas ou rastrear processamento de scripts no plano de fundo. 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 para definir e liberar caminhos dos 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()  # Começe 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çãopodem ser respectivamente utilizados para definir e liberar o caminho Python para scripts de usuários no LibreOffice. De forma similar, bibliotecas e módulos Python em documentos podem ser carregados e liberados utilizando os eventos Abrir documento e Documento fechado. consulte Importar módulos Python para mais informações

### Com LibreOffice Basic

A macro Onload é atribuída ao evento Abrir documento utilizando a aba Eventos do menu Ferramentas - Personalizar. A monitoração de eventos inicia no momento que um objeto ConsoleLogger é instanciado e por último encerra quando o motor do Basic o libera. O evento OnLoad carrega as bibliotecas 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 parão de design ADAPTER a ser instanciada 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

Exemplos de programação em Python

Programando com scripts Python