[Résolu][Python] Ajout d'entrée au menu contextuel

Discussions et questions sur tout ce qui concerne la programmation tous langages et tous modules confondus.

Modérateur : Vilains modOOs

Règles du forum
:alerte: Balisage obligatoire dans cette section !
Aidez-nous à vous aider au mieux en balisant correctement votre question : reportez-vous sur les règles de cette section avant de poster !
OlivierR
SuppOOrter
SuppOOrter
Messages : 1037
Inscription : 24 mai 2006 20:34
Localisation : Lorraine, France

[Résolu][Python] Ajout d'entrée au menu contextuel

Message par OlivierR »

Bonjour à tous,

But
J’essaie d’ajouter des entrées au menu contextuel. Je parviens à ajouter un séparateur et une entrée au menu, mais impossible d’y mettre un texte. Une image s’y trouve par défaut, je ne l’y ai pas ajoutée. Voilà ce que ça donne :
xMenu.png
Le code
Voici le code épuré de ce qui n’est pas utile :

Code : Tout sélectionner

import uno
import unohelper

def writeLog (s):
    log = codecs.open("C:\_log.txt", "a", "utf-8")
    log.write(s+"\n")
    log.close()

from com.sun.star.task import XJob
from com.sun.star.ui import XContextMenuInterceptor
from com.sun.star.lang import XMultiServiceFactory
from com.sun.star.beans import XPropertySet
from com.sun.star.container import XIndexContainer
from com.sun.star.uno import Exception as UnoException
from com.sun.star.beans import UnknownPropertyException
from com.sun.star.lang import IllegalArgumentException

def analyzeWord (word):
    [ écrit l’analyse de word dans le fichier de log et renvoie un tableau de chaînes comme résultat ]

class MyContextMenuInterceptor (XContextMenuInterceptor, unohelper.Base):
    def __init__ (self, ctx):
        self.ctx = ctx
        writeLog('Init menu interceptor!')

    def notifyContextMenuExecute (self, event):
        try:
            writeLog(' >begin menu')
            # Retrieve context menu container and query for service factory to create sub menus, menu entries and separators
            xContextMenu = event.ActionTriggerContainer
            xMenuElementFactory = xContextMenu 
            #xray(xMenuElementFactory)
            if (xMenuElementFactory):
                # create a line separator
                xSeparator = xMenuElementFactory.createInstance("com.sun.star.ui.ActionTriggerSeparator")
                xSeparator.SeparatorType = uno.getConstantByName("com.sun.star.ui.ActionTriggerSeparatorType.LINE")
                writeLog(' >1')
                
                # create root menu entry
                xRootMenuEntry = xMenuElementFactory.createInstance("com.sun.star.ui.ActionTrigger")
                xray(xRootMenuEntry)
                lMorphWord = analyzeWord('m**de')
                writeLog(' >2')
                # query sub menu for index container to get access
                xSubMenuContainer = xMenuElementFactory.createInstance("com.sun.star.ui.ActionTriggerContainer")
                writeLog(' >3')
                # intialize root menu entry "Help"
                #xRootMenuEntry.setPropertyValue('Text', 'Grammalecte')
                #xRootMenuEntry.Text = "Grammalecte"
                xRootMenuEntry.CommandURL = "slot:5410"
                xRootMenuEntry.HelpURL = "5410"
                #xRootMenuEntry.SubContainer = xSubMenuContainer
                #xray(xSubMenuContainer)
                writeLog(' >4')
                # create menu entries for the new sub menu

                [ création des éléments du sous-menu ]
                
                # add separator into the given context menu
                xContextMenu.insertByIndex(0, xSeparator)
                # add new sub menu into the given context menu
                xContextMenu.insertByIndex(0, xRootMenuEntry)
                writeLog(' >end menu')
                
                # The controller should execute the modified context menu and stop notifying other interceptors.
                return uno.getConstantByName("com.sun.star.ui.ContextMenuInterceptorAction.EXECUTE_MODIFIED")
        except:
            writeLog('ERREUR!')

        return uno.getConstantByName("com.sun.star.ui.ContextMenuInterceptorAction.IGNORED")

class JobExecutor (XJob, unohelper.Base):
    def __init__ (self, ctx):
        self.ctx = ctx
        [ initialisation du correcteur orthographique ]
        
    def execute (self, args):
        [ initialisation du MyContextMenuInterceptor ]

g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(JobExecutor, "grammalecte.by.OlivierR.ContextMenuHandler", ("grammalecte.by.OlivierR.ContextMenuHandler",),)
Ceci est une transcription du code en Java.


Focus sur le problème
En regardant l’objet avec xray, je constate que deux propriétés de cet élément de menu ne sont pas conformes à l’API et que l’objet est d’un type inconnu de xray. Apparemment donc, si je comprends bien, c’est la commande createInstance n’est pas faite correctement.

Avec

Code : Tout sélectionner

                xRootMenuEntry = xMenuElementFactory.createInstance("com.sun.star.ui.ActionTrigger")
                xray(xRootMenuEntry)
xray affiche:
xRootMenuEntry.png
Ce qui n’est pas conforme avec ce que dit l’API sur cet objet : ActionTrigger

C’est pourquoi les lignes ici commentées

Code : Tout sélectionner

                #xRootMenuEntry.setPropertyValue('Text', 'Grammalecte')
                #xRootMenuEntry.Text = "Grammalecte"
                xRootMenuEntry.CommandURL = "slot:5410"
                xRootMenuEntry.HelpURL = "5410"
                #xRootMenuEntry.SubContainer = xSubMenuContainer
soulèvent immanquablement une erreur (si elles sont décommentées bien sûr). Le type des propriétés n’est pas conforme à ce que je suis censé y écrire! Du reste, sur SubContainer et Text, xray déclare lui-même que le type des données n’est pas cohérent.


Analyse
Le souci vient certainement de ma compréhension du sac de nœuds services/interfaces/structures qui est assez embrouillée. J’ai probablement mal traduit de Java à Python. Alors je reprends ligne par ligne sur le passage délicat :

En Java :

Code : Tout sélectionner

com.sun.star.container.XIndexContainer xContextMenu = aEvent.ActionTriggerContainer;
devient en Python :

Code : Tout sélectionner

xContextMenu = event.ActionTriggerContainer
En Java :

Code : Tout sélectionner

com.sun.star.lang.XMultiServiceFactory xMenuElementFactory = (com.sun.star.lang.XMultiServiceFactory) UnoRuntime.queryInterface ( com.sun.star.lang.XMultiServiceFactory.class, xContextMenu );
com.sun.star.beans.XPropertySet xRootMenuEntry = (XPropertySet)UnoRuntime.queryInterface ( com.sun.star.beans.XPropertySet.class, xMenuElementFactory.createInstance ( "com.sun.star.ui.ActionTrigger" ));
devient en Python :

Code : Tout sélectionner

xMenuElementFactory = xContextMenu
xRootMenuEntry = xMenuElementFactory.createInstance("com.sun.star.ui.ActionTrigger")
La ligne [xMenuElementFactory = xContextMenu] ne sert évidemment à rien, hormis me rappeler qu’en Java, il faut explicitement appeler une interface dont les méthodes sont directement disponibles par l’objet en Python (si je ne m’abuse, mais mon erreur est peut-être là?).


Extension fournie
Je vous joins l’extension qui fait tout ça. Il suffit d’installer.
[[ lien supprimé ]]
:!: Si vous êtes sous Linux, avant de relancer OOo, éditez le fichier grammalecte.py et modifiez la méthode writeLog :

Code : Tout sélectionner

def writeLog (s):
    log = codecs.open("C:\_log.txt", "a", "utf-8")
    log.write(s+"\n")
    log.close()
Modifiez le chemin d’écriture du log.

Le log renvoie quelque chose comme ceci :

Code : Tout sélectionner

====== Init job! ======
Hunspell & Locale FR!
execute job
Init menu interceptor!
job done
 >begin menu
 >1
 st:m**de po:interj
 st:m**de po:nom is:fem
 st:merder po:verb is:spré is:3sg
 st:merder po:verb is:spré is:1sg
 st:merder po:verb is:ipré is:3sg
 st:merder po:verb is:ipré is:1sg
 >2
 >3
 >4
 >5
 >6
 >7
 >end menu
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
Dernière modification par OlivierR le 05 juin 2013 23:29, modifié 3 fois.
LibreOffice 7.1Windows 10Grammalecte, correcteur grammatical et orthotypographique
bm92
ManitOOu
ManitOOu
Messages : 2562
Inscription : 26 nov. 2005 13:42

Re: [Python] un service renvoie un objet inconnu de xray

Message par bm92 »

Bonjour,
Je n'ai pas vu d'erreur dans le (trans)codage, je penche plutôt pour une erreur de l'API, qui renvoie un objet incorrect.

Xray retransmet le message d'erreur de Basic quand il essaie de lire la propriété Text avec .getPropertyValue()
Or cette propriété existe, car elle est listée grâce à l'introspection. Ton erreur signifie que .setPropertyValue() ne marche pas non plus.

Plus bizarre : les propriétés CommandURL et HelpURL fonctionnent pour toi (car non commentées) alors que Xray voit la même erreur. Cela semble dire que .getPropertyValue() ne marche pas, mais .setPropertyValue() marche pour ces deux propriétés. Tu pourrais le vérifier en essayant de lire les propriétés, avant de les modifier.

Si tu fais un rapport d'anomalie, ou si tu poses la question dans la liste de diffusion dev@api (s'incrire avec un message à dev_subscribe@api.openoffice.org ), il faudrait réduire le codage à une tentative d'écriture sur cette propriété Text de xRootMenuEntry, qui déclenche une erreur.
Inutile de parler de Xray, les développeurs Sun ne connaissent pas :mrgreen:
Bernard

OpenOffice.org 1.1.5 fr / Apache OpenOffice 4.1.1 / LibreOffice 5.0.5.2 (X64)
MS-Windows 7 SP1 64bits Familial
jjk
HédOOniste
HédOOniste
Messages : 1696
Inscription : 27 oct. 2008 14:30

Re: [Python] un service renvoie un objet inconnu de xray

Message par jjk »

Bonjour à tous
bm92 a écrit :Inutile de parler de Xray, les développeurs Sun ne connaissent pas
Non ? j'y crois pas :fou:
Et ceux d'Oracle alors ?
OpenOffice 3.1.1 sous XP-SP2 et LibreOffice 3.5.0 sous Win 7
adibe
Fraîchement OOthentifié
Messages : 1
Inscription : 27 juil. 2011 14:22

Re: [Python] un service renvoie un objet inconnu de Xray

Message par adibe »

Bonjour!

Avez-vous résoudre le problème d'affichage de texte? Je rencontre le même problème.

Merci,
Adrian.
OpenOffice 3.3 on Windows 7
Avatar de l’utilisateur
Don Corleone
MOOdérateur
MOOdérateur
Messages : 629
Inscription : 20 avr. 2010 14:48

Re: [Python] un service renvoie un objet inconnu de Xray

Message par Don Corleone »

Bonjour,

Nous vous rappelons les règles de ce forum et notamment la n° 7
Un sujet = le problème d'une seule personne
Vous ne devez pas poser une question dans le fil d'un autre. Celle-ci ne fait qu'interférer et les réponses éventuellement postées ne feront qu'embrouiller la lecture du problème initial. Vous ne pourrez pas ajouter [Résolu] car vous n'êtes pas l'auteur de la première question.
Donc dans tous les cas, vous devez ouvrir un nouveau sujet pour votre question en rappelant que vous avez le même problème que dans ce fil.

Merci de votre collaboration.
Votre question a trouvé sa solution ?
Balisez votre fil [Résolu] ou [Issue] dans le titre de votre 1er message.

Tout sur le fonctionnement du forum
OlivierR
SuppOOrter
SuppOOrter
Messages : 1037
Inscription : 24 mai 2006 20:34
Localisation : Lorraine, France

Re: [Python] un service renvoie un objet inconnu de Xray

Message par OlivierR »

Bonjour,

(J’avais oublié que j’avais posté ce sujet.)

Le bogue reste d’actualité. Il faudrait que je pense à faire un rapport digne de ce nom. Les dévs de LibO connaissent-ils XRay ? :mrgreen:

J’ai résolu l’affaire en contournant le problème il y a assez longtemps. J’ai repris la méthode d’une extension écrite en Basic, mais j’ai oublié laquelle.
ctxmenu.png
Je vous livre l’extension telle quelle, avec plein de lignes de code inutiles. Je vous laisse faire le nettoyage. Je n’ai pas le temps de m’en occuper pour l’instant. Je m’en sers surtout pour déboguer le correcteur grammatical, pour vérifier l’étiquetage des mots. Ça fonctionne.
ContextualMenu.oxt
Je ne sais pas trop s’il faut que je tague [issue] ou [résolu]. :wink:
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.
LibreOffice 7.1Windows 10Grammalecte, correcteur grammatical et orthotypographique