From ddcd559fb6c778fa4400f545a896da2dbaa92767 Mon Sep 17 00:00:00 2001 From: eficas <> Date: Thu, 3 Nov 2005 09:03:49 +0000 Subject: [PATCH] CCAR: - correction divers problemes avec les blocs conditionnels et les mots cles simples globaux. - nettoyage des methodes obsoletes - correction dans la selection des commandes avec les touches clavier (widgets.py) - correction pour une destruction des objets inutiles (verification du passage dans la methode __del__ pour les objets Node, Item, OBJECT, jdcdisplay, tree, ...) - correction du copier coller pour les mots cles facteurs - utilisation du module weakref pour l'enregistrement des connexions (CONNECTOR.py). Evite que les objets connectes ne soient pas detruits par le garbage collector lorsqu'ils sont uniquement references par cette mecanique. --- Editeur/Objecttreeitem.py | 21 ++- Editeur/appli.py | 2 +- Editeur/bureau.py | 12 +- Editeur/compofact.py | 29 --- Editeur/compojdc.py | 24 --- Editeur/compomacro.py | 19 +- Editeur/compomclist.py | 54 ------ Editeur/componiveau.py | 15 +- Editeur/componuplet.py | 6 +- Editeur/compooper.py | 72 ------- Editeur/composimp.py | 30 --- Editeur/jdcdisplay.py | 19 +- Editeur/macrodisplay.py | 24 ++- Editeur/panels.py | 10 +- Editeur/session.py | 2 +- Editeur/treeitemincanvas.py | 11 ++ Editeur/treewidget.py | 362 +++++------------------------------- Editeur/widgets.py | 119 +++++------- Extensions/jdc_include.py | 9 +- Ihm/CONNECTOR.py | 94 ++++++++-- Ihm/I_ETAPE.py | 17 ++ Ihm/I_JDC.py | 8 +- Ihm/I_MACRO_ETAPE.py | 31 ++- Ihm/I_MCCOMPO.py | 114 ++++-------- Ihm/I_MCFACT.py | 13 ++ Ihm/I_MCLIST.py | 36 +++- Ihm/I_MCSIMP.py | 43 ++++- Ihm/I_OBJECT.py | 13 ++ 28 files changed, 419 insertions(+), 790 deletions(-) diff --git a/Editeur/Objecttreeitem.py b/Editeur/Objecttreeitem.py index 70b404f8..6e7670f3 100644 --- a/Editeur/Objecttreeitem.py +++ b/Editeur/Objecttreeitem.py @@ -28,6 +28,7 @@ from copy import copy,deepcopy # import du chargeur de composants from comploader import gettreeitem,make_objecttreeitem import treewidget +from Ihm import CONNECTOR myrepr = Repr() myrepr.maxstring = 100 @@ -157,6 +158,13 @@ class ObjectTreeItem(TreeItem,Delegate): def getObject(self): return self._object + def connect(self,channel,callable,args): + """ Connecte la fonction callable (avec arguments args) à l'item self sur le + canal channel + """ + CONNECTOR.Connect(self._object,channel,callable,args) + CONNECTOR.Connect(self.object, channel,callable,args) + def copy(self): """ Crée un item copie de self @@ -413,6 +421,9 @@ class ObjectTreeItem(TreeItem,Delegate): c = gettreeitem(object) return c(appli,labeltext, object, setfunction) + #def __del__(self): + # print "__del__",self + class AtomicObjectTreeItem(ObjectTreeItem): def IsExpandable(self): return 0 @@ -482,13 +493,3 @@ class SequenceTreeItem(ObjectTreeItem): if old_obj is None and obj is None:break if old_obj is obj: self.sublist.append(item) return self.sublist - - def GetSubList_BAK(self): - raise "OBSOLETE" - sublist = [] - for obj in self._object.data: - def setfunction(value, object=obj): - object = value - item = make_objecttreeitem(self.appli, obj.nom + ":", obj, setfunction) - sublist.append(item) - return sublist diff --git a/Editeur/appli.py b/Editeur/appli.py index d6f82366..30d696d9 100644 --- a/Editeur/appli.py +++ b/Editeur/appli.py @@ -44,7 +44,7 @@ from widgets import Fenetre from Misc import MakeNomComplet import session -VERSION="EFICAS v1.8" +VERSION="EFICAS v1.9" class APPLI: def __init__ (self,master,code=prefs.code,fichier=None,test=0) : diff --git a/Editeur/bureau.py b/Editeur/bureau.py index 215157fd..0480fb6f 100644 --- a/Editeur/bureau.py +++ b/Editeur/bureau.py @@ -22,7 +22,7 @@ Ce module contient la classe BUREAU qui gere les JDC ouverts """ # Modules Python -import os,string +import os,string,sys import traceback import Pmw from widgets import askopenfilename,asksaveasfilename @@ -212,7 +212,6 @@ class BUREAU: def onClose(self,jdcdisplay): #print "onClose",jdcdisplay - CONNECTOR.Disconnect(jdcdisplay.jdc,"close",self.onClose,(jdcdisplay,)) self.closeJDCDISPLAY(jdcdisplay) def closeJDCDISPLAY(self,jdc): @@ -258,17 +257,20 @@ class BUREAU: if test == 0 : self.appli.affiche_infos("Sauvegarde impossible") return + + CONNECTOR.Disconnect(self.JDCDisplay_courant.jdc,"close",self.onClose,(self.JDCDisplay_courant,)) + self.JDCDisplay_courant.supprime() self.JDCDisplay_courant.jdc.supprime() self.liste_JDCDisplay.remove(self.JDCDisplay_courant) + # Active le mecanisme de selection du notebook (selectJDC) self.nb.delete(self.nb.getcurselection()) - #XXX CCAR: pour le moment mis en commentaire - #self.JDC.unset_context() - self.JDC = None + try: index = self.nb.index(self.nb.getcurselection()) self.JDCDisplay_courant = self.liste_JDCDisplay[index] self.JDC = self.JDCDisplay_courant.jdc except: + self.JDC = None self.JDCDisplay_courant = None self.appli.toolbar.inactive_boutons() diff --git a/Editeur/compofact.py b/Editeur/compofact.py index d3802f3e..389c85a4 100644 --- a/Editeur/compofact.py +++ b/Editeur/compofact.py @@ -145,35 +145,6 @@ class FACTTreeItem(Objecttreeitem.ObjectTreeItem): self.appli.affiche_infos('Pb interne : impossible de supprimer ce mot-clé') return 0 - def GetSubList_BAK(self): - raise "OBSOLETE" - sublist=[] - for obj in self.object.mc_liste: - def setfunction(value, object=obj): - object.setval(value) - item = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction) - sublist.append(item) - return sublist - - def additem_BAK(self,name,pos): - raise "OBSOLETE" - if isinstance(name,Objecttreeitem.ObjectTreeItem) : - objet = self.object.addentite(name.getObject(),pos) - else : - objet = self.object.addentite(name,pos) - self.expandable = 1 - if objet == 0 : - # on ne peut ajouter l'élément de nom name - return 0 - def setfunction(value, object=objet): - object.setval(value) - item = self.make_objecttreeitem(self.appli,objet.nom + " : ", objet, setfunction) - return item - - def verif_condition_bloc_BAK(self): - raise "OBSOLETE" - return self.object.verif_condition_bloc() - import Accas objet = Accas.MCFACT treeitem = FACTTreeItem diff --git a/Editeur/compojdc.py b/Editeur/compojdc.py index 8eb6be36..3fd8e245 100644 --- a/Editeur/compojdc.py +++ b/Editeur/compojdc.py @@ -60,17 +60,6 @@ class JDCPanel(panels.OngletPanel): import treewidget class Node(treewidget.Node): - def verif_all_children(self): - raise "OBSOLETE" - if not self.children : self.build_children() - for child in self.children : - child.verif_all_children() - - def replace_enfant(self,item): - """ Retourne le noeud fils à éventuellement remplacer """ - raise "OBSOLETE" - return None - def doPaste_Commande(self,objet_a_copier): """ Réalise la copie de l'objet passé en argument qui est nécessairement @@ -173,19 +162,6 @@ class JDCTreeItem(Objecttreeitem.ObjectTreeItem): listeCmd = self.object.niveau.definition.get_liste_cmd() return listeCmd - def additem_BAK(self,name,pos): - raise "OBSOLETE" - cmd=self.addentite(name,pos) - item = self.make_objecttreeitem(self.appli,cmd.nom + " : ", cmd) - return item - - def verif_condition_bloc_BAK(self): - raise "OBSOLETE" - # retourne la liste des sous-items dont la condition est valide - # sans objet pour le JDC - return [],[] - - import Accas treeitem =JDCTreeItem objet = Accas.JDC diff --git a/Editeur/compomacro.py b/Editeur/compomacro.py index bafed554..50778fd0 100644 --- a/Editeur/compomacro.py +++ b/Editeur/compomacro.py @@ -34,11 +34,10 @@ import convert from widgets import askopenfilename from widgets import Fenetre,FenetreYesNo from widgets import showinfo,showerror -from Ihm import CONNECTOR # __version__="$Name: $" -__Id__="$Id: compomacro.py,v 1.22 2005/06/10 13:47:49 eficas Exp $" +__Id__="$Id: compomacro.py,v 1.23 2005/06/16 09:27:25 eficas Exp $" # class MACROPanel(panels.OngletPanel): @@ -208,17 +207,10 @@ class INCLUDETreeItemBase(MACROTreeItem): if not hasattr(self.object,"jdc_aux") or self.object.jdc_aux is None: #L'include n'est pas initialise self.object.build_include(None,"") - self.parent_node=node # On cree un nouvel onglet dans le bureau appli.bureau.ShowJDC(self.object.jdc_aux,self.object.jdc_aux.nom, label_onglet=None, JDCDISPLAY=macrodisplay.MACRODISPLAY) - self.myjdc=appli.bureau.JDCDisplay_courant - self.myjdc.fichier=self.object.fichier_ini - - def onClose(self): - #print "onClose",self - self.appli.bureau.closeJDCDISPLAY(self.myjdc) def makeView(self,appli,node): if not hasattr(self.object,"jdc_aux") or self.object.jdc_aux is None: @@ -231,11 +223,6 @@ class INCLUDETreeItemBase(MACROTreeItem): else: nom=nom+' '+self.object.fichier_ini macdisp=macrodisplay.makeMacroDisplay(appli,self,nom) - CONNECTOR.Connect(self.object.jdc_aux,"close",self.onCloseView,(macdisp,)) - - def onCloseView(self,macdisp): - #print "onCloseView",self,macdisp - macdisp.quit() class INCLUDEPanel(MACROPanel): def makeFichierPage(self,page): @@ -258,13 +245,10 @@ class POURSUITETreeItem(INCLUDETreeItemBase): text="""DEBUT() FIN()""" self.object.build_poursuite(None,text) - self.parent_node=node # On cree un nouvel onglet dans le bureau appli.bureau.ShowJDC(self.object.jdc_aux,self.object.jdc_aux.nom, label_onglet=None, JDCDISPLAY=macrodisplay.MACRODISPLAY) - self.myjdc=appli.bureau.JDCDisplay_courant - self.myjdc.fichier=self.object.fichier_ini def makeView(self,appli,node): if not hasattr(self.object,"jdc_aux") or self.object.jdc_aux is None: @@ -277,7 +261,6 @@ FIN()""" else: nom=nom+' '+self.object.fichier_ini macdisp=macrodisplay.makeMacroDisplay(appli,self,nom) - CONNECTOR.Connect(self.object.jdc_aux,"close",self.onCloseView,(macdisp,)) class INCLUDE_MATERIAUTreeItem(INCLUDETreeItemBase): rmenu_specs=[("View","makeView"), diff --git a/Editeur/compomclist.py b/Editeur/compomclist.py index f6e403e9..b80bd15a 100644 --- a/Editeur/compomclist.py +++ b/Editeur/compomclist.py @@ -75,60 +75,6 @@ class Node(treewidget.Node): #print "doPaste_MCF",child return child - def replace_enfant(self,item): - """ Retourne le noeud fils à éventuellement remplacer """ - raise "OBSOLETE" - if self.item.isMCList():return None - return self.get_node_fils(item.get_nom()) - - def verif_condition(self): - raise "OBSOLETE" - if self.item.isMCList(): - self.children[-1].verif_condition() - else: - treewidget.Node.verif_condition(self) - - def after_delete(self): - """ Dans le cas d'une MCList il faut vérifier qu'elle n'est pas vide - ou réduite à un seul élément suite à une destruction - """ - raise "OBSOLETE" - # self représente une MCList - if len(self.item) == 0 : - # la liste est vide : il faut la supprimer - self.delete() - elif len(self.item) == 1: - # il ne reste plus qu'un élément dans la liste - noeud = self.children[0] - # maintenant l'item mclist gere tout seul ce - # changement - self.delete_node_child(noeud) - self.children=noeud.children or [] - self.state=noeud.state - else : - return - - def delete_child(self,child): - """ - Supprime child des enfants de self, tous les id associés - ET l'objet associé - """ - raise "OBSOLETE" - if self.item.isMCList(): - if self.item.suppitem(child.item): - self.delete_node_child(child) - self.after_delete() - return 1 - else : - return 0 - else: - if self.item.suppitem(child.item): - self.delete_node_child(child) - return 1 - else : - return 0 - - class MCListTreeItem(Objecttreeitem.SequenceTreeItem,compofact.FACTTreeItem): """ La classe MCListTreeItem joue le role d'un adaptateur pour les objets du noyau Accas instances de la classe MCLIST. diff --git a/Editeur/componiveau.py b/Editeur/componiveau.py index 918e0322..fa745de8 100644 --- a/Editeur/componiveau.py +++ b/Editeur/componiveau.py @@ -41,20 +41,7 @@ class NIVEAUPanel(panels.OngletPanel): self.makeJDCPage(panneau.pane('left')) import treewidget -class Node(treewidget.Node): - def verif_condition_BAK(self): - """ - on lance la vérification des conditions de chaque bloc de self - on crée ou supprime les noeuds concernés - (self est d'un niveau inférieur ou égal à l'ETAPE) - """ - raise "OBSOLETE" - return 0 - - def replace_enfant_BAK(self,item): - """ Retourne le noeud fils à éventuellement remplacer """ - raise "OBSOLETE" - return None +class Node(treewidget.Node):pass class NIVEAUTreeItem(Objecttreeitem.ObjectTreeItem): diff --git a/Editeur/componuplet.py b/Editeur/componuplet.py index 07582aa4..d66d529a 100644 --- a/Editeur/componuplet.py +++ b/Editeur/componuplet.py @@ -31,7 +31,7 @@ import panels # __version__="$Name: $" -__Id__="$Id: componuplet.py,v 1.6 2005/05/19 12:18:47 eficas Exp $" +__Id__="$Id: componuplet.py,v 1.7 2005/08/09 09:54:04 eficas Exp $" # myrepr = Repr() @@ -168,10 +168,6 @@ class NUPLETTreeItem(Objecttreeitem.ObjectTreeItem): def suppitem(self,item) : raise "NUPLET" - def verif_condition_bloc(self): - raise "OBSOLETE" - return self.object.verif_condition_bloc() - import Accas treeitem=NUPLETTreeItem objet=Accas.MCNUPLET diff --git a/Editeur/compooper.py b/Editeur/compooper.py index 9799b3a9..db5f18f5 100644 --- a/Editeur/compooper.py +++ b/Editeur/compooper.py @@ -245,38 +245,6 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): self.sublist=sublist return self.sublist - def GetSubList_BAK(self): - raise "OBSOLETE" - if self.isactif(): - liste=self.object.mc_liste - else: - liste=[] - - sublist=[] - isublist=iter(self.sublist) - iliste=iter(liste) - - while(1): - old_obj=obj=None - for item in isublist: - old_obj=item.getObject() - if old_obj in liste:break - - for obj in iliste: - if obj is old_obj:break - # nouvel objet : on cree un nouvel item - def setfunction(value, object=obj): - object.setval(value) - it = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction) - sublist.append(it) - - if old_obj is None and obj is None:break - if old_obj is obj: - sublist.append(item) - - self.sublist=sublist - return self.sublist - def isvalid(self): return self.object.isvalid() @@ -333,46 +301,6 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): return commande_comment - def additem_BAK(self,name,pos): - raise "OBSOLETE" - mcent=self.addentite(name,pos) - - self.expandable=1 - if mcent == 0 : - # on ne peut ajouter l'élément de nom name - return 0 - def setfunction(value, object=mcent): - object.setval(value) - item = self.make_objecttreeitem(self.appli,mcent.nom + " : ", mcent, setfunction) - return item - - def GetSubList_BAK(self): - raise "OBSOLETE" - sublist=[] - for obj in self.object.mc_liste: - def setfunction(value, object=obj): - object.setval(value) - item = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction) - sublist.append(item) - return sublist - - def verif_condition_bloc_BAK(self): - raise "OBSOLETE" - return self.object.verif_condition_bloc() - - def replace_child_BAK(self,old_item,new_item): - """ - Remplace old_item.getObject() par new_item.getObject() dans - les fils de self.object - """ - raise "OBSOLETE" - old_itemobject=old_item.getObject() - index = self.object.mc_liste.index(old_itemobject) - self.object.init_modif() - self.object.mc_liste.remove(old_itemobject) - self.object.mc_liste.insert(index,new_item.getObject()) - self.object.fin_modif() - import Accas treeitem = EtapeTreeItem objet = Accas.ETAPE diff --git a/Editeur/composimp.py b/Editeur/composimp.py index 611f4de6..d5fc8d8a 100644 --- a/Editeur/composimp.py +++ b/Editeur/composimp.py @@ -330,39 +330,9 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): valeur = tuple(valeur) return self.object.valid_valeur_partielle(valeur) - def valide_liste_partielle_BAK(self,item,listecourante): - raise "OBSOLETE" - valeuravant=self.object.valeur - valeur=listecourante - valeur.append(item) - valeur = tuple(valeur) - retour=self.object.set_valeur(valeur) - validite=0 - if self.object.isvalid(): - validite=1 - elif self.definition.validators : - validite=self.definition.validators.valide_liste_partielle(valeur) - - if validite==0: - min,max=self.GetMinMax() - if len(valeur) < min : - validite=1 - retour=self.object.set_valeur(valeuravant) - return validite - def valide_liste_complete (self,valeur): return self.object.valid_valeur(valeur) - def valide_liste_complete_BAK (self,valeur): - raise "OBSOLETE" - valeuravant=self.object.valeur - retour=self.object.set_valeur(valeur) - validite=0 - if self.object.isvalid(): - validite=1 - retour=self.object.set_valeur(valeuravant) - return validite - def info_erreur_item(self) : commentaire="" if self.definition.validators : diff --git a/Editeur/jdcdisplay.py b/Editeur/jdcdisplay.py index 4400de16..9680f0e6 100644 --- a/Editeur/jdcdisplay.py +++ b/Editeur/jdcdisplay.py @@ -24,7 +24,7 @@ les informations attachées au noeud de l'arbre sélectionné """ # Modules Python -import types +import types,sys import traceback import Tkinter import Pmw @@ -220,7 +220,7 @@ class JDCDISPLAY: showinfo("Copie impossible", "Cette version d'EFICAS ne permet que la copie d'objets de type 'Commande' ou mot-clé facteur") return - self.edit="couper" + self.appli.edit="couper" self.appli.noeud_a_editer = self.node_selected def doCopy(self): @@ -231,7 +231,7 @@ class JDCDISPLAY: showinfo("Copie impossible", "La copie d'un tel objet n'est pas permise") return - self.edit="copier" + self.appli.edit="copier" self.appli.noeud_a_editer = self.node_selected def doPaste(self): @@ -258,7 +258,7 @@ class JDCDISPLAY: self.init_modif() # suppression éventuelle du noeud sélectionné # si possible on renomme l objet comme le noeud couper - if self.edit == "couper": + if self.appli.edit == "couper": #nom = self.appli.noeud_a_editer.item.object.sd.nom item=self.appli.noeud_a_editer.item self.appli.noeud_a_editer.delete() @@ -266,7 +266,7 @@ class JDCDISPLAY: #test,mess = child.item.nomme_sd(nom) child.select() # on rend la copie à nouveau possible en libérant le flag edit - self.edit="copier" + self.appli.edit="copier" def update(self): """Cette methode est utilisee par le JDC associe pour @@ -274,3 +274,12 @@ class JDCDISPLAY: """ self.tree.update() + def supprime(self): + #print "supprime",self + self.select_node(None) + self.tree.supprime() + self.tree=None + self.pane.destroy() + + #def __del__(self): + # print "__del__",self diff --git a/Editeur/macrodisplay.py b/Editeur/macrodisplay.py index 1be2e911..7d769e9f 100644 --- a/Editeur/macrodisplay.py +++ b/Editeur/macrodisplay.py @@ -23,7 +23,7 @@ des sous commandes d'une macro sous forme d'arbre """ # Modules Python -import types +import types,sys import Tkinter,Pmw # Modules EFICAS @@ -33,6 +33,7 @@ import Objecttreeitem import compojdc import treewidget from widgets import Fenetre +from Ihm import CONNECTOR class MACRO2TreeItem(compojdc.JDCTreeItem): pass @@ -61,9 +62,12 @@ class MacroDisplay: Pmw.Color.changecolor(self.canvas,background='gray95') self.mainPart.pack(padx=10,pady=10,fill = 'both', expand = 1) self.item=MACRO2TreeItem(self.appli,nom_jdc,self.jdc) - import treewidget self.tree = treewidget.Tree(self.appli,self.item,self.mainPart,command=None,rmenu=self.make_rmenu) self.tree.draw() + CONNECTOR.Connect(self.jdc,"close",self.onCloseView,()) + + def onCloseView(self): + self.quit() def visufile(self): Fenetre(self.appli,titre="Source du fichier inclus",texte=self.macroitem.object.fichier_text) @@ -108,13 +112,20 @@ class MacroDisplay: if radio:menu.invoke(radio) def quit(self): + #print "quit",self self.tree.supprime() + self.tree=None self.fenetre.destroy() + #def __del__(self): + # print "__del__",self + def makeMacroDisplay(appli,macroitem,nom_item): return MacroDisplay(appli,macroitem,nom_item) -class TREEITEMINCANVAS: +import treeitemincanvas + +class TREEITEMINCANVAS(treeitemincanvas.TREEITEMINCANVAS): def __init__(self,object,nom="",parent=None,appli=None,sel=None,rmenu=None): #print "TREEITEMINCANVAS",object self.object=object @@ -131,13 +142,6 @@ class TREEITEMINCANVAS: self.tree=treewidget.Tree(self.appli,self.item,self.canvas,command=sel,rmenu=rmenu) self.tree.draw() - def mainloop(self): - self.parent.mainloop() - - def update(self): - """Cette methode est utilisee pour signaler une mise a jour des objets associes""" - self.tree.update() - import jdcdisplay class MACRODISPLAY(jdcdisplay.JDCDISPLAY): diff --git a/Editeur/panels.py b/Editeur/panels.py index e37e19f3..ba98e8a5 100644 --- a/Editeur/panels.py +++ b/Editeur/panels.py @@ -54,9 +54,8 @@ class Panel(Frame) : global panneauCommande panneauCommande=self - def __del__(self): - """ appele a la destruction du panel """ - #print "PANEL DETRUIT" + #def __del__(self): + # print "__del__",self def update_panel(self): """Methode appele pour demander une mise a jour du panneau""" @@ -490,11 +489,6 @@ class OngletPanel(Panel) : def deselectMC(self,name): self.parent.appli.affiche_infos('') - def get_liste_cmd_BAK(self): - raise "OBSOLETE" - listeCmd = self.cata.listCmd() - return listeCmd - def get_groups(self): jdc=self.node.item.object.get_jdc_root() return jdc.get_groups() diff --git a/Editeur/session.py b/Editeur/session.py index e503352c..b863e884 100644 --- a/Editeur/session.py +++ b/Editeur/session.py @@ -203,7 +203,7 @@ def print_d_env(): def create_parser(): # creation du parser des options de la ligne de commande - parser=optparse.OptionParser(usage="usage: %prog [options]",version="%prog 1.8") + parser=optparse.OptionParser(usage="usage: %prog [options]",version="%prog 1.9") parser.add_option("-j","--jdc",dest="comm",type='string', action="callback",callback=check_comm, diff --git a/Editeur/treeitemincanvas.py b/Editeur/treeitemincanvas.py index f0d45572..f007f450 100644 --- a/Editeur/treeitemincanvas.py +++ b/Editeur/treeitemincanvas.py @@ -59,3 +59,14 @@ class TREEITEMINCANVAS: def update(self): """Cette methode est utilisee pour signaler une mise a jour des objets associes""" self.tree.update() + + def supprime(self): + #print "supprime",self + self.tree.supprime() + self.tree=None + self.canvas.destroy() + self.canvas=None + + #def __del__(self): + # print "__del__",self + diff --git a/Editeur/treewidget.py b/Editeur/treewidget.py index 78b3a16c..3519a5ac 100644 --- a/Editeur/treewidget.py +++ b/Editeur/treewidget.py @@ -28,7 +28,7 @@ from Ihm import CONNECTOR # __version__="$Name: $" -__Id__="$Id: treewidget.py,v 1.24 2005/06/10 14:59:37 eficas Exp $" +__Id__="$Id: treewidget.py,v 1.25 2005/06/16 09:27:25 eficas Exp $" # Fonte_Standard = fontes.standard @@ -38,13 +38,13 @@ class Tree : self.item = jdc_item self.scrolledcanvas = scrolledcanvas self.canvas = self.scrolledcanvas.component('canvas') - self.canvas.bind("", self.page_up) - self.canvas.bind("", self.page_down) - self.canvas.bind("", self.unit_up) - self.canvas.bind("", self.unit_down) - self.canvas.bind("", self.mot_up) - self.canvas.bind("", self.mot_down) - self.canvas.bind("<1>", self.canvas_select) + self.id_up=self.canvas.bind("", self.page_up) + self.id_down=self.canvas.bind("", self.page_down) + self.id_uup=self.canvas.bind("", self.unit_up) + self.id_udown=self.canvas.bind("", self.unit_down) + self.id_um=self.canvas.bind("", self.mot_up) + self.id_dm=self.canvas.bind("", self.mot_down) + self.id_s=self.canvas.bind("<1>", self.canvas_select) self.tree = self self.command = command self.rmenu=rmenu @@ -103,8 +103,25 @@ class Tree : def supprime(self): """ supprime tous les éléments de l'arbre """ + #print "supprime",self + self.canvas.unbind("",self.id_up) + self.canvas.unbind("",self.id_down) + self.canvas.unbind("",self.id_uup) + self.canvas.unbind("",self.id_udown) + self.canvas.unbind("",self.id_um) + self.canvas.unbind("",self.id_dm) + self.canvas.unbind("<1>",self.id_s) + self.tree = None + self.racine = None + self.node_selected = None + self.item = None + self.scrolledcanvas = None + self.canvas = None + self.command = None + self.rmenu=None for child in self.children: child.supprime() + self.children=[] def update_valid(self) : """Cette methode a pour but de mettre a jour la validite du noeud @@ -125,17 +142,6 @@ class Tree : def select_previous(self,event): self.node_selected.select_previous() - def full_creation(self,name,index): - raise "OBSOLETE" - # A changer lorsqu'il y aura plusieurs jdc ouverts en même temps - self.children[0].full_creation(name,index) - - def verif_all(self): - raise "OBSOLETE" - traceback.print_stack() - for child in self.children : - self.verif_all_children() - def see(self,items): x1, y1, x2, y2=apply(self.canvas.bbox, items) while x2 > self.canvas.canvasx(0)+self.canvas.winfo_width(): @@ -160,12 +166,15 @@ class Tree : self.canvas.yview_scroll( -1, 'units') if old == self.canvas.canvasy(0): break + + #def __del__(self): + # print "__del__",self + class Node : def __init__(self,parent,item,command=None,rmenu=None): self.parent = parent self.item = item - self.connections=[] self.connect() self.command = command @@ -188,31 +197,13 @@ class Node : else: self.racine = self.parent.racine - def reconnect(self): - self.disconnect() - self.connect() - def connect(self): - self.connections.append(self.item._object) - CONNECTOR.Connect(self.item._object,"add",self.onAdd,()) - CONNECTOR.Connect(self.item._object,"supp",self.onSupp,()) - CONNECTOR.Connect(self.item._object,"valid",self.onValid,()) - if self.item.object is not self.item._object: - CONNECTOR.Connect(self.item.object,"add",self.onAdd,()) - CONNECTOR.Connect(self.item.object,"supp",self.onSupp,()) - CONNECTOR.Connect(self.item.object,"valid",self.onValid,()) - self.connections.append(self.item.object) - - def disconnect(self): - for c in self.connections: - CONNECTOR.Disconnect(c,"add",self.onAdd,()) - CONNECTOR.Disconnect(c,"supp",self.onSupp,()) - CONNECTOR.Disconnect(c,"valid",self.onValid,()) - self.connections=[] - - def __del__(self): - """ appele a la destruction du noeud """ - #print "NOEUD DETRUIT",self,self.item.GetLabelText()[0] + self.item.connect("add",self.onAdd,()) + self.item.connect("supp",self.onSupp,()) + self.item.connect("valid",self.onValid,()) + + #def __del__(self): + # print "__del__",self def force_select(self): if self.selected: @@ -269,26 +260,14 @@ class Node : newnodes.append(node) self.children=newnodes - self.reconnect() + self.connect() def supprime(self): - self.disconnect() + #print "supprime",self self.efface_node() - - #self.label_id=None - #self.text_id=None - #self.label=None - #self.text=None - #self.image_id=None - #self.icone_id=None - #self.etape=None - ####self.parent=None - #self.command = None - #self.rmenu=None - #self.tree = None - #self.appli=None - #self.canvas = None - + self.racine = None + self.command = None + self.rmenu=None if not self.children : return for child in self.children: child.supprime() @@ -834,88 +813,6 @@ class Node : # Méthodes de création et destruction de noeuds # Certaines de ces méthodes peuvent être appelées depuis l'externe #------------------------------------------------------------------ - def replace_node(self,node1,node2): - """ Remplace le noeud 1 par le noeud 2 dans la liste des enfants de self""" - raise "OBSOLETE" - index= self.children.index(node1) - self.delete_node_child(node1) - self.children.insert(index,node2) - - def replace_enfant(self,item): - """ Retourne le noeud fils à éventuellement remplacer """ - raise "OBSOLETE" - return self.get_node_fils(item.get_nom()) - - def full_creation(self,name,pos=None): - """ - Interface avec ACCAS : création de l'objet de nom name et - du noeud associé. Retourne le noeud fils ainsi créé - """ - raise "OBSOLETE" - #print "full_creation",name,pos,self.item - item = self.item.additem(name,pos) - if item == None or item == 0: - # impossible d'ajouter le noeud de nom : name - return 0 - - enfant = self.replace_enfant(item) - if enfant : - # un fils de même nom existe déjà : on le remplace - child = item.itemNode(self,item,self.command,self.rmenu) - self.replace_node(enfant,child) - else : - child = item.itemNode(self, item,self.command,self.rmenu) - if pos is None: - self.children.append(child) - else : - self.children.insert(pos,child) - return child - - def append_brother_BAK(self,name,pos='after',retour='non'): - """ - Permet d'ajouter un frère à self - par défaut on l'ajoute après self - Méthode externe - """ - raise "OBSOLETE" - # on veut ajouter le frère de nom name directement avant ou après self - index = self.parent.children.index(self) - if pos == 'before': - index = index - elif pos == 'after': - index = index +1 - else: - print str(pos)," n'est pas un index valide pour append_brother" - return - return self.parent.append_child(name,pos=index,retour=retour) - - def append_node_child(self,fils,pos=None,verif='oui'): - """ - Fait appel à la création complète de fils et à la vérification - des conditions en fonction du contexte - Attention : fils peut être un nom ou déjà un object (cas d'une copie) - """ - raise "OBSOLETE" - if not self.children : self.build_children() - if pos == None : - if type(fils) == types.InstanceType: - pos = self.item.get_index_child(fils.nom) - else: - pos = self.item.get_index_child(fils) - child = self.full_creation(fils,pos) - if child == 0 : - # on n'a pas pu créer le noeud fils - return 0 - self.state = 'expanded' - child.displayed = 1 - if child.item.isactif(): - child.state = 'expanded' - if not child.children : child.build_children() - if verif == 'oui': - child.verif_condition() - self.verif_condition() - return child - def append_brother(self,name,pos='after',retour='non'): """ Permet d'ajouter un objet frère à l'objet associé au noeud self @@ -964,59 +861,6 @@ class Node : child.select() return child - def append_child_BAK(self,name,pos=None,verif='oui',retour='non'): - """ - Permet d'ajouter un fils à self - on peut l'ajouter en fin de liste (défaut) ou en début - Méthode externe - """ - raise "OBSOLETE" - if pos == 'first': - index = 0 - elif pos == 'last': - index = len(self.children) - elif pos != None and type(pos) == types.IntType : - # on donne la position depuis l'extérieur - # (appel de append_child par append_brother par exemple) - index = pos - elif type(pos) == types.InstanceType: - # pos est un item. Il faut inserer name apres pos - index = self.item.get_index(pos) +1 - else : - if type(name) == types.InstanceType: - index = self.item.get_index_child(name.nom) - else: - index = self.item.get_index_child(name) - nbold = self.get_nb_children() - self.state='expanded' - child = self.append_node_child(name,pos=index) - if child == 0 : - # on n'a pas pu créer le fils - return 0 - nbnew = self.get_nb_children() - self.redraw(nbnew-nbold) - child.select() - if retour == 'oui': return child - - def delete_node_child_BAK(self,child): - """ Supprime child des enfants de self et les id associés """ - raise "OBSOLETE" - child.efface() - self.children.remove(child) - self.canvas.update() - - def delete_child_BAK(self,child): - """ - Supprime child des enfants de self, tous les id associés - ET l'objet associé - """ - raise "OBSOLETE" - if self.item.suppitem(child.item): - self.delete_node_child(child) - return 1 - else : - return 0 - def delete(self): """ Méthode externe pour la destruction de l'objet associé au noeud @@ -1025,132 +869,14 @@ class Node : index = self.parent.children.index(self) - 1 if index < 0 : index =0 - ret=self.parent.item.suppitem(self.item) + parent=self.parent + ret=parent.item.suppitem(self.item) if ret == 0:return - brothers=self.parent.children + brothers=parent.children if brothers: toselect=brothers[index] else: - toselect=self.parent + toselect=parent toselect.select() - def delete_BAK(self): - """ Méthode externe pour la destruction du noeud ET de l'objet - Gère l'update du canvas""" - raise "OBSOLETE" - pere = self.parent - nbold = pere.get_nb_children() - - if self.parent.children.index(self) > 0 : - index = self.parent.children.index(self) - 1 - else: - index=0 - if self.parent.delete_child(self): - if self.item.get_position() == 'global': - self.etape.verif_all() - elif self.item.get_position() == 'global_jdc': - self.racine.verif_all() - else: - self.parent.verif_condition() - else: - print 'Erreur dans la destruction de ',self.item.get_nom(),' dans delete' - - nbnew = pere.get_nb_children() - pere.redraw(nbnew-nbold) - - # Le noeud n'est pas au 1er niveau - if pere.parent.parent != None: - pere.select() - else: - enfants = self.parent.children - try: - enfants[index].select() - except : - try : - enfants[index+1].select() - except : - # on est avant debut - pass - - def doPaste(self,node_selected): - self.appli.message="Vous ne pouvez copier que des commandes ou des mots-clés facteurs !" - return 0 - - def doPaste_Commande(self,objet_a_copier): - """ - Réalise la copie de l'objet passé en argument qui est nécessairement - une commande - """ - child = self.append_brother(objet_a_copier,retour='oui') - return child - - #-------------------------------------------------------------- - # Méthodes de vérification du contexte et de validité du noeud - #-------------------------------------------------------------- - def verif_all(self): - raise "OBSOLETE" - traceback.print_stack() - self.verif_all_children() - - def verif_all_children(self): - raise "OBSOLETE" - traceback.print_stack() - if not self.children : self.build_children() - self.verif() - for child in self.children : - child.verif_all_children() - - def verif(self) : - """ - Lance la vérification des conditions des blocs de self et le cas - échéant redessine self - """ - raise "OBSOLETE" - traceback.print_stack() - nbold = self.get_nb_children() - test = self.verif_condition() - nbnew = self.get_nb_children() - if test != 0 : - self.redraw(nbnew-nbold) - - def verif_condition(self): - """ - on lance la vérification des conditions de chaque bloc de self - on crée ou supprime les noeuds concernés - (self est d'un niveau inférieur ou égal à l'ETAPE) - """ - raise "OBSOLETE" - traceback.print_stack() - test = 0 - l_bloc_arajouter,l_bloc_aenlever = self.verif_condition_bloc() - if len(l_bloc_arajouter) > 0: - test = 1 - for mc in l_bloc_arajouter: - self.append_node_child(mc,verif='non') - if len(l_bloc_aenlever) > 0: - test = 1 - for mc in l_bloc_aenlever: - mocle = self.get_node_fils(mc) - self.delete_child(mocle) - l_mc_presents = self.item.get_liste_mc_presents() - l_mc_arajouter= self.verif_condition_regles(l_mc_presents) - if len(l_mc_arajouter) > 0: - test = 1 - for mc in l_mc_arajouter: - self.append_node_child(mc,verif='non') - if len(l_mc_arajouter)+len(l_bloc_arajouter)+len(l_bloc_aenlever) != 0 : - self.verif_condition() - return test - - def verif_condition_bloc(self): - raise "OBSOLETE" - traceback.print_stack() - return self.item.verif_condition_bloc() - - def verif_condition_regles(self,l_mc_presents): - raise "OBSOLETE" - traceback.print_stack() - return self.item.verif_condition_regles(l_mc_presents) - - diff --git a/Editeur/widgets.py b/Editeur/widgets.py index 0284b5bd..3568dd4f 100644 --- a/Editeur/widgets.py +++ b/Editeur/widgets.py @@ -28,6 +28,7 @@ from Tkinter import * import Pmw import os,sys,re,string import types,fnmatch +import traceback from tkFileDialog import * from tkMessageBox import showinfo,askyesno,showerror,askretrycancel @@ -670,7 +671,8 @@ class Formulaire: class ListeChoix : """ Cette classe est utilisée pour afficher une liste de choix passée en paramètre en passant les commandes à lancer suivant différents bindings """ - def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='',optionReturn=None, fonte_titre=fontes.standard_gras_souligne): + def __init__(self,parent,page,liste,liste_commandes=[],liste_marques =[],active ='oui',filtre='non',titre='', + optionReturn=None, fonte_titre=fontes.standard_gras_souligne): self.parent = parent self.page = page self.liste = liste @@ -780,6 +782,10 @@ class ListeChoix : self.MCbox.config(state=DISABLED) self.selection = None + for event,callback in self.liste_commandes: + if event == "": + self.selection=None,None,callback + break def clear_marque(self): try: @@ -813,45 +819,24 @@ class ListeChoix : showerror(raison.split('\n')[0],raison) def selectNextItem(self,mot,label): - try : - index=self.liste.index(mot) - indexsuivant=index+1 - if indexsuivant > len(self.liste) -1: - indexsuivant=0 - motsuivant=self.liste[indexsuivant] - labelsuivant=self.dico_labels[motsuivant] - self.clear_marque() - if self.selection != None : - self.deselectitem(self.selection[1],self.selection[0],self.selection[2],) - self.selection = (mot,label,self.selection[2]) - index = self.MCbox.index(labelsuivant) - self.MCbox.see(index) - self.highlightitem(labelsuivant) - self.arg_selected=motsuivant - labelsuivant.focus_set() - # PN il faut faire quelque chose pour être dans la fenetre - except: - pass + index=self.liste.index(mot) + indexsuivant=index+1 + if indexsuivant > len(self.liste) -1: + indexsuivant=0 + motsuivant=self.liste[indexsuivant] + labelsuivant=self.dico_labels[motsuivant] + index = self.MCbox.index(labelsuivant) + self.MCbox.see(index) + self.selectitem(motsuivant,labelsuivant,self.selection[2],) def selectPrevItem(self,mot,label): - try : - index=self.liste.index(mot) - indexprec=index-1 - motprec=self.liste[indexprec] - labelprec=self.dico_labels[motprec] - self.clear_marque() - if self.selection != None : - self.deselectitem(self.selection[1],self.selection[0],self.selection[2],) - self.selection = (mot,label,self.selection[2]) - index = self.MCbox.index(labelprec) - self.MCbox.see(index) - self.highlightitem(labelprec) - self.arg_selected=motprec - labelprec.focus_set() - # PN il faut faire quelque chose pour être dans la fenetre - except: - pass - + index=self.liste.index(mot) + indexprec=index-1 + motprec=self.liste[indexprec] + labelprec=self.dico_labels[motprec] + index = self.MCbox.index(labelprec) + self.MCbox.see(index) + self.selectitem(motprec,labelprec,self.selection[2],) def selectitem(self,mot,label,commande) : """ Met l'item sélectionné (représenté par son label) en surbrillance @@ -862,7 +847,7 @@ class ListeChoix : self.highlightitem(label) self.selection = (mot,label,commande) self.arg_selected = mot - commande(mot) + if commande : commande(mot) def highlightitem(self,label) : """ Met l'item représenté par son label en surbrillance """ @@ -875,9 +860,9 @@ class ListeChoix : def deselectitem(self,label,mot='',commande=None) : """ Remet l'item (représenté par son label) en noir""" - label.configure(bg='gray95',fg='black') + if label:label.configure(bg='gray95',fg='black') self.arg_selected = '' - if commande != None : commande(mot) + if commande and mot : commande(mot) def cherche_selected_item(self): index=self.MCbox.index(self.selection[1]) @@ -898,11 +883,10 @@ class ListeChoix : FILTRE = string.upper(filtre) for arg in self.liste : if fnmatch.fnmatch(arg,filtre) or fnmatch.fnmatch(arg,FILTRE) : - self.highlightitem(self.dico_labels[arg]) - index = self.MCbox.index(self.dico_labels[arg]) + label=self.dico_labels[arg] + index = self.MCbox.index(label) self.MCbox.see(index) - self.arg_selected = arg - self.dico_labels[self.arg_selected].focus_set() + self.selectitem(arg,label,self.selection[2]) break #try : @@ -910,9 +894,6 @@ class ListeChoix : #except : #pass - def get_liste_BAK(self): - raise "OBSOLETE" - return self.liste # PN attention à la gestion des paramétres # cela retourne H = 1 , et ni H, ni 1 @@ -1116,7 +1097,7 @@ class ListeChoixParGroupes(ListeChoix) : """ def __init__(self,parent,page,liste_groupes,dict_groupes,liste_commandes=[],liste_marques =[], - active ='oui',filtre='non',titre='',optionReturn=None): + active ='oui',filtre='non',titre='',optionReturn=None,fonte_titre=fontes.standard_gras_souligne): self.parent = parent self.page = page self.liste_groupes = liste_groupes @@ -1130,6 +1111,7 @@ class ListeChoixParGroupes(ListeChoix) : self.titre = titre self.filtre = filtre self.optionReturn = optionReturn + self.fonte_titre=fonte_titre self.init() def affiche_liste(self): @@ -1209,6 +1191,10 @@ class ListeChoixParGroupes(ListeChoix) : self.MCbox.config(state=DISABLED) self.selection = None + for event,callback in self.liste_commandes: + if event == "": + self.selection=None,None,callback + break def selectPrevItem(self,mot,label,callback,group,cmd): g=self.liste_groupes.index(group) @@ -1224,19 +1210,11 @@ class ListeChoixParGroupes(ListeChoix) : else: # debut des groupes. On ne fait rien return - # On a trouve l'item precedent - self.clear_marque() labelsuivant=self.dico_labels[co] - if self.selection != None : - self.deselectitem(self.selection[1],self.selection[0],self.selection[2],) - self.selection = (co,labelsuivant,self.selection[2]) index = self.MCbox.index(labelsuivant) self.MCbox.see(index) - self.arg_selected=co - self.highlightitem(labelsuivant) - labelsuivant.focus_set() - callback(co) + self.selectitem(co,labelsuivant,self.selection[2],) def selectNextItem(self,mot,label,callback,group,cmd): g=self.liste_groupes.index(group) @@ -1253,17 +1231,10 @@ class ListeChoixParGroupes(ListeChoix) : # fin des groupes. On ne fait rien return # On a trouve l'item suivant - self.clear_marque() labelsuivant=self.dico_labels[co] - if self.selection != None : - self.deselectitem(self.selection[1],self.selection[0],self.selection[2],) - self.selection = (co,labelsuivant,self.selection[2]) index = self.MCbox.index(labelsuivant) self.MCbox.see(index) - self.arg_selected=co - self.highlightitem(labelsuivant) - labelsuivant.focus_set() - callback(co) + self.selectitem(co,labelsuivant,self.selection[2],) def entry_changed(self,event=None): """ @@ -1280,23 +1251,21 @@ class ListeChoixParGroupes(ListeChoix) : # for grp in self.liste_groupes: if fnmatch.fnmatch(grp,filtre) or fnmatch.fnmatch(grp,FILTRE) : - self.highlightitem(self.dico_labels[grp]) - index = self.MCbox.index(self.dico_labels[grp]) + cmd=self.dict_groupes[grp][0] + label=self.dico_labels[cmd] + index = self.MCbox.index(label) self.MCbox.see(index) - # On ne selectionne pas le groupe - #self.arg_selected = grp - self.dico_labels[grp].focus_set() + self.selectitem(cmd,label,self.selection[2]) # On a trouve un groupe on arrete la recherche return for grp in self.liste_groupes: for cmd in self.dict_groupes[grp] : if fnmatch.fnmatch(cmd,filtre) or fnmatch.fnmatch(cmd,FILTRE) : - self.highlightitem(self.dico_labels[cmd]) - index = self.MCbox.index(self.dico_labels[cmd]) + label=self.dico_labels[cmd] + index = self.MCbox.index(label) self.MCbox.see(index) - self.arg_selected = cmd - self.dico_labels[self.arg_selected].focus_set() + self.selectitem(cmd,label,self.selection[2]) # On a trouve une commande on arrete la recherche return diff --git a/Extensions/jdc_include.py b/Extensions/jdc_include.py index 39196a23..deb6c558 100644 --- a/Extensions/jdc_include.py +++ b/Extensions/jdc_include.py @@ -173,10 +173,17 @@ class JDC_POURSUITE(JDC): def supprime(self): """ - On ne supprime rien pour un jdc auxiliaire d'include ou de poursuite + On ne supprime rien directement pour un jdc auxiliaire d'include ou de poursuite + Utiliser supprime_aux """ pass + def supprime_aux(self): + #print "supprime_aux",self + JDC.supprime(self) + self.jdc_pere=None + self.etape_include=None + def get_contexte_avant(self,etape): """ Retourne le dictionnaire des concepts connus avant etape diff --git a/Ihm/CONNECTOR.py b/Ihm/CONNECTOR.py index 09d1fbc1..7ca9ea89 100644 --- a/Ihm/CONNECTOR.py +++ b/Ihm/CONNECTOR.py @@ -37,6 +37,10 @@ """ import traceback from copy import copy +import weakref + +class ConnectorError(Exception): + pass class CONNECTOR: @@ -56,10 +60,13 @@ class CONNECTOR: else: receivers = channels[channel] = [] - info = (function, args) - if info in receivers: - receivers.remove(info) - receivers.append(info) + for funct,fargs in receivers[:]: + if funct() is None: + receivers.remove((funct,fargs)) + elif (function,args) == (funct(),fargs): + receivers.remove((funct,fargs)) + + receivers.append((ref(function),args)) ###print "Connect",receivers @@ -69,20 +76,27 @@ class CONNECTOR: except KeyError: raise ConnectorError, \ 'no receivers for channel %s of %s' % (channel, object) - try: - receivers.remove((function, args)) - except ValueError: - raise ConnectorError,\ + + for funct,fargs in receivers[:]: + if funct() is None: + receivers.remove((funct,fargs)) + + for funct,fargs in receivers: + if (function,args) == (funct(),fargs): + receivers.remove((funct,fargs)) + if not receivers: + # the list of receivers is empty now, remove the channel + channels = self.connections[id(object)] + del channels[channel] + if not channels: + # the object has no more channels + del self.connections[id(object)] + return + + raise ConnectorError,\ 'receiver %s%s is not connected to channel %s of %s' \ % (function, args, channel, object) - if not receivers: - # the list of receivers is empty now, remove the channel - channels = self.connections[id(object)] - del channels[channel] - if not channels: - # the object has no more channels - del self.connections[id(object)] def Emit(self, object, channel, *args): ###print "Emit",object, channel, args @@ -93,12 +107,35 @@ class CONNECTOR: ###print "Emit",object, channel, receivers # Attention : copie pour eviter les pbs lies aux deconnexion reconnexion # pendant l'execution des emit - for func, fargs in copy(receivers): + for rfunc, fargs in copy(receivers): try: - apply(func, args + fargs) + func=rfunc() + if func: + apply(func, args + fargs) + else: + # Le receveur a disparu + if (rfunc,fargs) in receivers:receivers.remove((rfunc,fargs)) except: traceback.print_exc() +def ref(target,callback=None): + if hasattr(target,"im_self"): + return BoundMethodWeakref(target) + else: + return weakref.ref(target,callback) + +class BoundMethodWeakref(object): + def __init__(self,callable): + self.Self=weakref.ref(callable.im_self) + self.Func=weakref.ref(callable.im_func) + + def __call__(self): + target=self.Self() + if not target:return None + func=self.Func() + if func: + return func.__get__(self.Self()) + _the_connector =CONNECTOR() Connect = _the_connector.Connect Emit = _the_connector.Emit @@ -108,9 +145,30 @@ if __name__ == "__main__": class A:pass class B: def add(self,a): - print "add",a + print "add",self,a + def __del__(self): + print "__del__",self + def f(a): + print f,a + print "a=A()" a=A() + print "b=B()" b=B() + print "c=B()" + c=B() + Connect(a,"add",b.add,()) Connect(a,"add",b.add,()) + Connect(a,"add",c.add,()) + Connect(a,"add",f,()) + Emit(a,"add",1) + print "del b" + del b + Emit(a,"add",1) + print "del f" + del f Emit(a,"add",1) + Disconnect(a,"add",c.add,()) + Emit(a,"add",1) + + diff --git a/Ihm/I_ETAPE.py b/Ihm/I_ETAPE.py index f05dd1d3..6ad4ee81 100644 --- a/Ihm/I_ETAPE.py +++ b/Ihm/I_ETAPE.py @@ -378,6 +378,23 @@ class ETAPE(I_MCCOMPO.MCCOMPO): #print "verif_existence_sd",self.sd for motcle in self.mc_liste : motcle.verif_existence_sd() + + def update_mc_global(self): + """ + Met a jour les mots cles globaux enregistrés dans l'étape + et dans le jdc parent. + Une etape ne peut pas etre globale. Elle se contente de passer + la requete a ses fils apres avoir reinitialisé le dictionnaire + des mots cles globaux. + """ + self.mc_globaux={} + I_MCCOMPO.MCCOMPO.update_mc_global(self) + + def update_condition_bloc(self): + """ + Realise l'update des blocs conditionnels fils de self + """ + self._update_condition_bloc() #ATTENTION SURCHARGE: a garder en synchro ou a reintegrer dans le Noyau def Build_sd(self,nom): diff --git a/Ihm/I_JDC.py b/Ihm/I_JDC.py index 6bfa025d..f4ee8bc6 100644 --- a/Ihm/I_JDC.py +++ b/Ihm/I_JDC.py @@ -21,11 +21,12 @@ """ """ # Modules Python -import types,traceback +import types,traceback,sys import string,linecache # Modules Eficas import I_OBJECT +import Noyau from Noyau.N_ASSD import ASSD from Noyau.N_LASSD import LASSD from Noyau.N_ETAPE import ETAPE @@ -187,6 +188,7 @@ class JDC(I_OBJECT.OBJECT): # il faut vérifier que les concepts utilisés par objet existent bien # à ce niveau d'arborescence objet.verif_existence_sd() + objet.update_mc_global() self.active_etapes() self.editmode=0 self.reset_context() @@ -350,10 +352,11 @@ class JDC(I_OBJECT.OBJECT): Retourne 0 dans le cas contraire """ #print "suppentite",self - self.init_modif() #PN correction de bugs if etape not in self.etapes: return 0 + + self.init_modif() index_etape=self.etapes.index(etape) self.etapes.remove(etape) @@ -364,6 +367,7 @@ class JDC(I_OBJECT.OBJECT): etape.supprime_sdprods() etape.close() + etape.supprime() self.active_etapes() # Apres suppression de l'etape il faut controler que les etapes diff --git a/Ihm/I_MACRO_ETAPE.py b/Ihm/I_MACRO_ETAPE.py index 18e7ece7..0ca98ea4 100644 --- a/Ihm/I_MACRO_ETAPE.py +++ b/Ihm/I_MACRO_ETAPE.py @@ -26,6 +26,7 @@ import traceback,types,string # Modules Eficas import I_ETAPE +import Noyau from Noyau.N_ASSD import ASSD # import rajoutés suite à l'ajout de Build_sd --> à résorber @@ -65,6 +66,8 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): --> utilisée par ops.POURSUITE et INCLUDE """ #print "get_contexte_jdc",self,self.nom + # On recupere l'etape courante + step=CONTEXT.get_current_step() try: # on essaie de créer un objet JDC auxiliaire avec un contexte initial # Attention get_contexte_avant retourne un dictionnaire qui contient @@ -103,26 +106,26 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.etapes=j.etapes self.jdc_aux=j except: - # On force le contexte (etape courante) à self + # On retablit l'etape courante step CONTEXT.unset_current_step() - CONTEXT.set_current_step(self) + CONTEXT.set_current_step(step) return None if not j.cr.estvide(): # Erreurs dans l'INCLUDE. On garde la memoire du fichier # mais on n'insere pas les concepts - # On force le contexte (etape courante) à self + # On retablit l'etape courante step CONTEXT.unset_current_step() - CONTEXT.set_current_step(self) + CONTEXT.set_current_step(step) raise Exception("Impossible de relire le fichier\n"+str(j.cr)) if not j.isvalid(): # L'INCLUDE n'est pas valide. # on produit un rapport d'erreurs - # On force le contexte (etape courante) à self cr=j.report() + # On retablit l'etape courante step CONTEXT.unset_current_step() - CONTEXT.set_current_step(self) + CONTEXT.set_current_step(step) raise Exception("Le fichier include contient des erreurs\n"+str(cr)) # Si aucune erreur rencontrée @@ -130,8 +133,9 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): try: j_context=j.get_verif_contexte() except: + # On retablit l'etape courante step CONTEXT.unset_current_step() - CONTEXT.set_current_step(self) + CONTEXT.set_current_step(step) raise # On remplit le dictionnaire des concepts produits inclus @@ -151,9 +155,9 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.index_etape_courante=j.index_etape_courante self.jdc_aux=j - # On rétablit le contexte (etape courante) à self + # On retablit l'etape courante step CONTEXT.unset_current_step() - CONTEXT.set_current_step(self) + CONTEXT.set_current_step(step) return j_context @@ -285,6 +289,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.g_context={} def close(self): + #print "close",self if hasattr(self,"jdc_aux") and self.jdc_aux: # La macro a un jdc auxiliaire inclus. On demande sa fermeture self.jdc_aux.close() @@ -664,6 +669,14 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): d[co.nom]=co #print "update_context.fin",d.keys() +#ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro) + def supprime(self): + #print "supprime",self + if hasattr(self,"jdc_aux") and self.jdc_aux: + self.jdc_aux.supprime_aux() + self.jdc_aux=None + Noyau.N_MACRO_ETAPE.MACRO_ETAPE.supprime(self) + #ATTENTION SURCHARGE : cette methode surcharge celle de Noyau (a garder en synchro) def get_file(self,unite=None,fic_origine=''): """Retourne le nom du fichier et le source correspondant a l'unite unite diff --git a/Ihm/I_MCCOMPO.py b/Ihm/I_MCCOMPO.py index 28bb21f1..e8f665c2 100644 --- a/Ihm/I_MCCOMPO.py +++ b/Ihm/I_MCCOMPO.py @@ -20,7 +20,7 @@ # ====================================================================== """ """ -import string,types +import string,types,sys from copy import copy import traceback @@ -175,31 +175,18 @@ class MCCOMPO(I_OBJECT.OBJECT): Retourne 1 si la suppression a pu être effectuée, Retourne 0 dans le cas contraire """ - self.init_modif() if not objet in self.mc_liste: # Impossible de supprimer objet. Il n'est pas dans mc_liste - self.fin_modif() return 0 - try : - self.mc_liste.remove(objet) - CONNECTOR.Emit(self,"supp",objet) - - if hasattr(objet.definition,'position'): - if objet.definition.position == 'global' : - self.delete_mc_global(objet) - self.etape.deep_update_condition_bloc() - elif objet.definition.position == 'global_jdc' : - self.delete_mc_global_jdc(objet) - self.jdc.deep_update_condition_bloc() - else: - self.update_condition_bloc() - - self.fin_modif() - return 1 - except: - self.fin_modif() - return 0 + self.init_modif() + self.mc_liste.remove(objet) + CONNECTOR.Emit(self,"supp",objet) + objet.delete_mc_global() + objet.update_condition_bloc() + objet.supprime() + self.fin_modif() + return 1 def isoblig(self): return 0 @@ -209,17 +196,11 @@ class MCCOMPO(I_OBJECT.OBJECT): Ajoute le mot-cle name à la liste des mots-cles de l'objet MCCOMPOSE """ - #print "I_MCCOMPO.addentite",name,pos self.init_modif() if type(name)==types.StringType : # on est en mode création d'un motcle if self.ispermis(name) == 0 : return 0 objet=self.definition.entites[name](val=None,nom=name,parent=self) - if hasattr(objet.definition,'position'): - if objet.definition.position == 'global' : - self.append_mc_global(objet) - elif objet.definition.position == 'global_jdc' : - self.append_mc_global_jdc(objet) else : # dans ce cas on est en mode copie d'un motcle objet = name @@ -237,20 +218,20 @@ class MCCOMPO(I_OBJECT.OBJECT): # On cherche s'il existe deja un mot cle de meme nom old_obj = self.get_child(objet.nom,restreint = 'oui') - #print "addentite",old_obj - #if old_obj:print "addentite",old_obj.isrepetable(),old_obj.isMCList(),old_obj.ajout_possible() if not old_obj : - #print self.mc_liste,objet + # on normalize l'objet + objet=objet.normalize() # Le mot cle n'existe pas encore. On l'ajoute a la position # demandee (pos) if pos == None : self.mc_liste.append(objet) else : self.mc_liste.insert(pos,objet) - #print self.mc_liste,objet # Il ne faut pas oublier de reaffecter le parent d'obj (si copie) objet.reparent(self) CONNECTOR.Emit(self,"add",objet) + objet.update_mc_global() + objet.update_condition_bloc() self.fin_modif() return objet else: @@ -262,29 +243,10 @@ class MCCOMPO(I_OBJECT.OBJECT): self.fin_modif() return 0 else: - if not old_obj.isMCList(): - # un objet de même nom existe déjà mais ce n'est pas une MCList - # Il faut en créer une - # L'objet existant (old_obj) est certainement un MCFACT - # qui pointe vers un constructeur - # de MCList : definition.liste_instance - index = self.mc_liste.index(old_obj) - new_obj = old_obj.definition.list_instance() - new_obj.init(objet.nom,self) - new_obj.append(old_obj) - new_obj.append(objet) - # Il ne faut pas oublier de reaffecter le parent d'obj - objet.reparent(self) - self.mc_liste.remove(old_obj) - CONNECTOR.Emit(self,"supp",old_obj) - self.mc_liste.insert(index,new_obj) - CONNECTOR.Emit(self,"add",new_obj) - self.fin_modif() - return new_obj - else : - # une liste d'objets de même type existe déjà - old_obj.addentite(objet) - return old_obj + # une liste d'objets de même type existe déjà + old_obj.addentite(objet) + self.fin_modif() + return old_obj def ispermis(self,fils): """ @@ -340,22 +302,6 @@ class MCCOMPO(I_OBJECT.OBJECT): for child in self.mc_liste : child.replace_concept(old_sd,sd) - def delete_mc_global(self,mc): - """ - Supprime le mot-clé mc de la liste des mots-clés globaux de l'étape - """ - etape = self.get_etape() - if etape : - nom = mc.nom - del etape.mc_globaux[nom] - - def delete_mc_global_jdc(self,mc): - """ - Supprime le mot-clé mc de la liste des mots-clés globaux du jdc - """ - nom = mc.nom - del self.jdc.mc_globaux[nom] - def get_liste_mc_inconnus(self): """ Retourne la liste des mots-clés inconnus dans self @@ -378,17 +324,23 @@ class MCCOMPO(I_OBJECT.OBJECT): Parcourt l'arborescence des mcobject et realise l'update des blocs conditionnels par appel de la methode update_condition_bloc """ - #print "deep_update_condition_bloc",self - self.update_condition_bloc() + self._update_condition_bloc() for mcobj in self.mc_liste: if hasattr(mcobj,"deep_update_condition_bloc"): mcobj.deep_update_condition_bloc() def update_condition_bloc(self): + """ + Realise l'update des blocs conditionnels fils de self + et propage au parent + """ + self._update_condition_bloc() + if self.parent:self.parent.update_condition_bloc() + + def _update_condition_bloc(self): """ Realise l'update des blocs conditionnels fils de self """ - #print "update_condition_bloc",self dict = self.cree_dict_condition(self.mc_liste,condition=1) for k,v in self.definition.entites.items(): if v.label != 'BLOC' :continue @@ -440,3 +392,17 @@ class MCCOMPO(I_OBJECT.OBJECT): """ for motcle in self.mc_liste : motcle.verif_existence_sd() + + def update_mc_global(self): + """ + Met a jour les mots cles globaux enregistrés dans l'étape parente + et dans le jdc parent. + Un mot cle compose ne peut pas etre global. Il se contente de passer + la requete a ses fils. + """ + for motcle in self.mc_liste : + motcle.update_mc_global() + + def delete_mc_global(self): + for motcle in self.mc_liste : + motcle.delete_mc_global() diff --git a/Ihm/I_MCFACT.py b/Ihm/I_MCFACT.py index 49a3b44f..a5b9df3e 100644 --- a/Ihm/I_MCFACT.py +++ b/Ihm/I_MCFACT.py @@ -20,6 +20,7 @@ # ====================================================================== import CONNECTOR import I_MCCOMPO +import Noyau class MCFACT(I_MCCOMPO.MCCOMPO): def isrepetable(self): @@ -80,3 +81,15 @@ class MCFACT(I_MCCOMPO.MCCOMPO): if parent: parent.fin_modif() + def normalize(self): + """ Retourne le MCFACT normalisé. Pour un MCFACT isolé, l'objet normalisé + est une MCLIST de longueur 1 qui contient ce MCFACT + """ + new_obj = self.definition.list_instance() + new_obj.init(nom=self.nom,parent=None) + new_obj.append(self) + return new_obj + + def supprime(self): + self.alt_parent=None + Noyau.N_MCFACT.MCFACT.supprime(self) diff --git a/Ihm/I_MCLIST.py b/Ihm/I_MCLIST.py index 41aa9c05..48345ebc 100644 --- a/Ihm/I_MCLIST.py +++ b/Ihm/I_MCLIST.py @@ -71,9 +71,14 @@ class MCList: """ Supprime le mot cle facteur obj de la MCLIST """ + if obj not in self: + return 0 + self.init_modif() self.remove(obj) CONNECTOR.Emit(self,"supp",obj) + self.update_condition_bloc() + obj.supprime() self.fin_modif() return 1 @@ -107,6 +112,7 @@ class MCList: self.insert(pos,obj) CONNECTOR.Emit(self,"add",obj) self.fin_modif() + self.update_condition_bloc() return obj def liste_mc_presents(self): @@ -169,11 +175,17 @@ class MCList: Parcourt l'arborescence des mcobject et realise l'update des blocs conditionnels par appel de la methode update_condition_bloc """ - #print "deep_update_condition_bloc",self for mcfact in self.data : mcfact.deep_update_condition_bloc() + def update_condition_bloc(self): + """ + Propage la mise a jour des conditions au parent. + Une liste ne fait pas de traitement sur les conditions + """ + if self.parent: self.parent.update_condition_bloc() + def verif_condition_bloc(self): """ Evalue les conditions de tous les blocs fils possibles @@ -244,3 +256,25 @@ class MCList: except: return '' + def normalize(self): + """ + Retourne l'objet normalisé. Une liste est déjà normalisée + """ + return self + + def update_mc_global(self): + """ + Met a jour les mots cles globaux enregistrés dans l'étape parente + et dans le jdc parent. + Une liste ne peut pas etre globale. Elle se contente de passer + la requete a ses fils. + """ + for motcle in self.data : + motcle.update_mc_global() + + def delete_mc_global(self): + for motcle in self.data : + motcle.delete_mc_global() + + #def __del__(self): + # print "__del__",self diff --git a/Ihm/I_MCSIMP.py b/Ihm/I_MCSIMP.py index 0cf75cbf..c3d8f4e0 100644 --- a/Ihm/I_MCSIMP.py +++ b/Ihm/I_MCSIMP.py @@ -262,17 +262,22 @@ class MCSIMP(I_OBJECT.OBJECT): self.isvalid() return validite + def update_condition_bloc(self): + """ Met a jour les blocs conditionnels dependant du mot cle simple self + """ + if self.definition.position == 'global' : + self.etape.deep_update_condition_bloc() + elif self.definition.position == 'global_jdc' : + self.jdc.deep_update_condition_bloc() + else: + self.parent.update_condition_bloc() + def set_valeur(self,new_valeur,evaluation='oui'): #print "set_valeur",new_valeur self.init_modif() self.valeur = new_valeur self.val = new_valeur - if self.definition.position == 'global' : - self.etape.deep_update_condition_bloc() - elif self.definition.position == 'global_jdc' : - self.jdc.deep_update_condition_bloc() - else: - self.parent.update_condition_bloc() + self.update_condition_bloc() self.fin_modif() return 1 @@ -457,6 +462,30 @@ class MCSIMP(I_OBJECT.OBJECT): """ return self.definition.type + def delete_mc_global(self): + """ Retire self des declarations globales + """ + if self.definition.position == 'global' : + etape = self.get_etape() + if etape : + del etape.mc_globaux[self.nom] + elif self.definition.position == 'global_jdc' : + del self.jdc.mc_globaux[self.nom] + + def update_mc_global(self): + """ + Met a jour les mots cles globaux enregistrés dans l'étape parente + et dans le jdc parent. + Un mot cle simple peut etre global. + """ + if self.definition.position == 'global' : + etape = self.get_etape() + if etape : + etape.mc_globaux[self.nom]=self + elif self.definition.position == 'global_jdc' : + if self.jdc: + self.jdc.mc_globaux[self.nom]=self + #-------------------------------------------------------------------------------- # PN : ajout pour Salome des methodes suivantes (jusqu aux méthodes surchargees) #-------------------------------------------------------------------------------- @@ -567,3 +596,5 @@ class MCSIMP(I_OBJECT.OBJECT): self.set_valid(valid) return self.valid + + diff --git a/Ihm/I_OBJECT.py b/Ihm/I_OBJECT.py index d794797b..cb8edb50 100644 --- a/Ihm/I_OBJECT.py +++ b/Ihm/I_OBJECT.py @@ -139,3 +139,16 @@ class OBJECT: def update_concept(self,sd): pass + + def normalize(self): + """ Retourne l'objet normalisé. En général self sauf si + pour etre inséré dans l'objet père il doit etre + wrappé dans un autre objet (voir mot cle facteur). + """ + return self + + def delete_mc_global(self): + return + + #def __del__(self): + # print "__del__",self -- 2.39.2