[Résolu][Python] Ajout d'entrée au menu contextuel
Publié : 03 août 2010 21:11
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 : Le code
Voici le code épuré de ce qui n’est pas utile :
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.
Avecxray affiche:
Ce qui n’est pas conforme avec ce que dit l’API sur cet objet : ActionTrigger
C’est pourquoi les lignes ici commentéessoulè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 :devient en Python :
En Java :
devient en Python :
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 :Modifiez le chemin d’écriture du log.
Le log renvoie quelque chose comme ceci :
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 : 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",),)
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)
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
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;
Code : Tout sélectionner
xContextMenu = event.ActionTriggerContainer
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" ));
Code : Tout sélectionner
xMenuElementFactory = xContextMenu
xRootMenuEntry = xMenuElementFactory.createInstance("com.sun.star.ui.ActionTrigger")
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()
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