2017-06-22 10 views
1

LibreOffice writer permet à l'utilisateur d'insérer des annotations (notes/commentaires) dans le texte.Comment lire le contenu d'une annotation d'auteur LibreOffice à partir d'une macro python

Mon problème est que je suis incapable de trouver une méthode pour accéder au contenu d'une annotation spécifique à la ligne.
Le code python suivant recherche le texte sélectionné/surligné, puis supprime tout sauf un code temporel formaté (par exemple 01:10:23 ou 11:10) qu'il convertit en secondes.
Si aucun texte n'a été sélectionné, il sélectionne toute la ligne actuelle et tente de trouver le code temporel. Cependant, le code temporel pourrait être dans une annotation.

J'ai réussi à obtenir une liste de toutes les annotations dans le document, commentées au début du code mais cela ne me sert à rien.

Je suis incapable de découvrir une méthode de divinatoire

a) si la ligne actuelle a une annotation ou
b) comment accéder à son contenu.

Si quelqu'un a réussi à atteindre cet objectif, j'apprécierais n'importe quel pointeur.

def fs2_GoToTimestamp(*args): 
#get the doc from the scripting context which is made available to all scripts 
    desktop = XSCRIPTCONTEXT.getDesktop() 
    model = desktop.getCurrentComponent() 
    oSelected = model.getCurrentSelection() 
#access annotations for the whole document 
# oEnum = model.getTextFields().createEnumeration() 
# cursor = desktop.getCurrentComponent().getCurrentController().getViewCursor() 
# while oEnum.hasMoreElements(): 
#  oField = oEnum.nextElement() 
#  cursor.gotoRange(oField,False) 
#  print (cursor.getPosition()) 
#  if oField.supportsService('com.sun.star.text.TextField.Annotation'): 
#   print (oField.Content) 
#   x = oField.getAnchor() 
#   print (dir(x)) 
    oText = "" 
    try: #Grab the text selected/highlighted 
     oSel = oSelected.getByIndex(0) 
     oText= oSel.getString() 
    except:pass 
    try: 
     if oText == "": # Nothing selected grab the whole line 
      cursor = desktop.getCurrentComponent().getCurrentController().getViewCursor() 
      cursor.gotoStartOfLine(False) #move cursor to start without selecting (False) 
      cursor.gotoEndOfLine(True) #now move cursor to end of line selecting all (True) 
      oSelected = model.getCurrentSelection() 
      oSel = oSelected.getByIndex(0) 
      oText= oSel.getString() 
      # Deselect line to avoid inadvertently deleting it on next keystroke 
      cursor.gotoStartOfLine(False) 
    except:pass 
    time = str(oText) 
    valid_chars=(':') 
    time = ''.join(char for char in time if char in valid_chars) 
    if time.count(":") == 1: 
     oM, oS = time.split(":") 
     oH = "00" 
    elif time.count(":") == 2: 
     oH,oM,oS = time.split(":") 
    else: 
     return None 
    if len(oS) != 2: 
     oS=oS[:2] 
    try: 
     secs = int(oS) 
     secs = secs + int(oM) * 60 
     secs = secs + int(oH) *3600 
    except: 
     return None 
    seek_instruction = 'seek'+str(secs)+'\n' 
    #Now do something with the seek instruction 
+0

Énumérer les annotations et utilisez [getAnchor()] (https://www.openoffice.org/api/docs/common/ref/com/sun/star/text/XTextContent.html#getAnchor) à savoir où chacun est situé. Voir https://wiki.openoffice.org/wiki/Documentation/DevGuide/Text/Editing_Text#Text_Contents_Other_Than_Strings. –

+0

Merci pour la réponse. Peut-être que c'est moi mais je ne peux trouver aucune méthode retournée par oField ou oField.getAnchor() quand j'énumère oEnum qui fournit une position pour l'annotation dans le document. Si je crée un curseur et que j'essaie de 'gotoRange (oField, False)', il prétend qu'il n'y a pas d'interface de ce type. J'ai ajouté mes tentatives mal conçues à la question, dans l'espoir que vous puissiez repérer l'erreur flagrante. Je vais admettre avoir du mal avec la documentation de l'API, c'est comme nager dans la mélasse –

Répondre

1

énumèrent les annotations et utiliser getAnchor() pour savoir où chacun se trouve. Cette réponse est basée sur https://wiki.openoffice.org/wiki/Documentation/DevGuide/Text/Editing_Text#Text_Contents_Other_Than_Strings.

Votre code est sur le point de fonctionner.

while oEnum.hasMoreElements(): 
    oField = oEnum.nextElement() 
    if oField.supportsService('com.sun.star.text.TextField.Annotation'): 
     xTextRange = oField.getAnchor() 
     cursor.gotoRange(xTextRange, False) 

Au lieu de print (dir(x)), un outil d'introspection, comme XrayTool ou IRM donnera une meilleure information. Cela rend les documents API plus faciles à comprendre.

+0

Être à quelques millimètres seulement est finalement le même que miles. Merci pour le coup de pouce dans la bonne direction. J'ai posté la version (finale) dans une auto-réponse pour quelqu'un d'autre patauger dans ce genre de chose. - –

0

Avec beaucoup d'aide nécessaire de Jim K une réponse est affichée ci-dessous. J'ai commenté où je crois que cela aidera le plus.

#!/usr/bin/python 
from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK 
from com.sun.star.awt.MessageBoxType import INFOBOX 
def fs2_GoToTimestamp(*args): 
    desktop = XSCRIPTCONTEXT.getDesktop() 
    model = desktop.getCurrentComponent() 
    oSelected = model.getCurrentSelection() 
    doc = XSCRIPTCONTEXT.getDocument() 
    parentwindow = doc.CurrentController.Frame.ContainerWindow 
    cursor = desktop.getCurrentComponent().getCurrentController().getViewCursor() 
    try: 
     CursorPos = cursor.getText().createTextCursorByRange(cursor)#Store original cursor position 
    except:# The cursor has been placed in the annotation not the text 
     mess = "Position cursor in the text\nNot the comment box" 
     heading = "Positioning Error" 
     MessageBox(parentwindow, mess, heading, INFOBOX, BUTTONS_OK) 
     return None 
    oText = "" 
    try: #Grab the text selected/highlighted 
     oSel = oSelected.getByIndex(0) 
     oText= oSel.getString() 
    except:pass 
    try: 
     if oText == "": # Nothing selected grab the whole line 
      store_position = 0 
      cursor.gotoStartOfLine(False) #move cursor to start without selecting (False) 
      cursor.gotoEndOfLine(True) #now move cursor to end of line selecting all (True) 
      oSelected = model.getCurrentSelection() 
      oSel = oSelected.getByIndex(0) 
      oText= oSel.getString() 
      y = cursor.getPosition() 
      store_position = y.value.Y 
      # Deselect line to avoid inadvertently deleting it on next user keystroke 
      cursor.gotoStartOfLine(False) 

      if oText.count(":") == 0: 
      # Still nothing found check for an annotation at this location 
      #enumerate through annotations for the whole document 
       oEnum = model.getTextFields().createEnumeration() 
       while oEnum.hasMoreElements(): 
        oField = oEnum.nextElement() 
        if oField.supportsService('com.sun.star.text.TextField.Annotation'): 
         anno_at = oField.getAnchor() 
         cursor.gotoRange(anno_at,False) 
         pos = cursor.getPosition() 
         if pos.value.Y == store_position: # Found an annotation at this location 
          oText = oField.Content 
          break 
       # Re-set cursor to original position after enumeration & deselect 
       cursor.gotoRange(CursorPos,False) 
    except:pass 

    time = str(oText) 
    valid_chars=(':') 
    time = ''.join(char for char in time if char in valid_chars) #Strip out all invalid characters 
    if time.count(":") == 1: # time 00:00 
     oM, oS = time.split(":") 
     oH = "00" 
    elif time.count(":") == 2: # time 00:00:00 
     oH,oM,oS = time.split(":") 
    else: 
     return None 
    if len(oS) != 2: # in case time includes tenths 00:00.0 reduce to whole seconds 
     oS=oS[:2] 
    try: 
     secs = int(oS) 
     secs = secs + int(oM) * 60 
     secs = secs + int(oH) *3600 
    except: 
     return None 
    seek_instruction = 'seek'+str(secs)+'\n' 
    print("Seconds",str(secs)) 
    # Do something with seek_instruction 

def MessageBox(ParentWindow, MsgText, MsgTitle, MsgType, MsgButtons): 
    ctx = XSCRIPTCONTEXT.getComponentContext() 
    sm = ctx.ServiceManager 
    si = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx) 
    mBox = si.createMessageBox(ParentWindow, MsgType, MsgButtons, MsgTitle, MsgText) 
    mBox.execute()