From 36ca867c4099d6a804374b8f6a2b897d9ea69a09 Mon Sep 17 00:00:00 2001 From: eficas <> Date: Thu, 19 May 2005 12:18:50 +0000 Subject: [PATCH] CCAR: modifications pour : 1- edition de fichier INCLUDE et POURSUITE 2- ajout d'un fichier de definition des preferences utilisateur (~/Eficas_install/prefs.py) 3- ajout d'un fichier de definition utilisateur du style de l'IHM (~/Eficas_install/style.py) --- Aster/Cata/petitcata/cata.py | 13 +- Aster/eficas_aster.py | 12 - Aster/prefs.py | 2 + Aster/style.py | 0 Editeur/Objecttreeitem.py | 72 ++++++ Editeur/appli.py | 16 +- Editeur/basestyle.py | 26 +++ Editeur/bureau.py | 27 +-- Editeur/compocommandecomm.py | 6 +- Editeur/compofact.py | 73 ++++-- Editeur/compojdc.py | 65 ++++-- Editeur/compomacro.py | 111 +++------ Editeur/compomclist.py | 96 +++++--- Editeur/componiveau.py | 7 +- Editeur/componuplet.py | 11 +- Editeur/compooper.py | 120 ++++++++-- Editeur/composimp.py | 37 ++- Editeur/eficas_go.py | 12 +- Editeur/jdcdisplay.py | 41 ++-- Editeur/macrodisplay.py | 43 +--- Editeur/newsimppanel.py | 32 +-- Editeur/panels.py | 24 +- Editeur/styles.py | 18 ++ Editeur/treewidget.py | 402 ++++++++++++++++++++++++++++++--- Editeur/uniqueassdpanel.py | 14 +- Editeur/uniquepanel.py | 16 +- Editeur/uniquesdcopanel.py | 51 +++-- Editeur/widgets.py | 2 +- Extensions/commande_comm.py | 16 +- Extensions/commentaire.py | 4 +- Extensions/jdc_include.py | 121 ++++++++-- Extensions/parametre.py | 4 +- Ihm/CONNECTOR.py | 116 ++++++++++ Ihm/I_ETAPE.py | 41 +++- Ihm/I_JDC.py | 40 +++- Ihm/I_MACRO_ETAPE.py | 240 +++++++++++++++++++- Ihm/I_MCCOMPO.py | 97 ++++++-- Ihm/I_MCFACT.py | 25 ++ Ihm/I_MCLIST.py | 59 ++++- Ihm/I_MCSIMP.py | 96 ++++++-- Ihm/I_OBJECT.py | 5 +- generator/generator_python.py | 3 +- generator/generator_python6.py | 1 - 43 files changed, 1723 insertions(+), 494 deletions(-) create mode 100644 Aster/style.py create mode 100644 Editeur/basestyle.py create mode 100644 Editeur/styles.py create mode 100644 Ihm/CONNECTOR.py diff --git a/Aster/Cata/petitcata/cata.py b/Aster/Cata/petitcata/cata.py index 9d7b3f1d..a46adfed 100755 --- a/Aster/Cata/petitcata/cata.py +++ b/Aster/Cata/petitcata/cata.py @@ -31,7 +31,7 @@ except: # __version__="$Name: $" -__Id__="$Id: cata_reduit.py,v 1.6 2004/09/20 09:24:11 eficas Exp $" +__Id__="$Id: cata.py,v 1.1 2004/11/19 09:06:23 eficas Exp $" # JdC = JDC_CATA(code='ASTER', execmodul=None, @@ -468,6 +468,17 @@ AFFE_MODELE=OPER(nom="AFFE_MODELE",op=18,sd_prod=modele,docu="U4.41.01-g", VERIF=SIMP(statut='f',typ='TXM',max=2,into=("MAILLE","NOEUD")), ) ; +GLOB_OPER=OPER(nom="GLOB_OPER",op=18,sd_prod=modele,docu="U4.41.01-g", + FORMAT =SIMP(statut='f',typ='TXM',position='global', + into=("TABLEAU","AGRAF","XMGRACE",),), + b_unit1 =BLOC(condition = "FORMAT == 'TABLEAU'", + TOTO1 =SIMP(statut='f',typ='TXM',defaut='AAA',into=('AAA','BBB'),), + ), + b_unit2 =BLOC(condition = "FORMAT == None", + TOTO2 =SIMP(statut='f',typ='TXM',defaut='AAA',into=('AAA','BBB'),), + ), + ) + PLS_BASE_SIMPLE=OPER(nom="PLS_BASE_SIMPLE",op=19,sd_prod=cara_elem, fr="Exemple de PLUSIEURS_BASE_Panel sans validator", docu="U4.42.01-g",reentrant='n', diff --git a/Aster/eficas_aster.py b/Aster/eficas_aster.py index f1870683..1d298b58 100755 --- a/Aster/eficas_aster.py +++ b/Aster/eficas_aster.py @@ -24,21 +24,9 @@ Ce module sert à lancer EFICAS configuré pour Code_Aster """ # Modules Python -import sys # Modules Eficas import prefs -if hasattr(prefs,'encoding'): - # Hack pour changer le codage par defaut des strings - import sys - reload(sys) - sys.setdefaultencoding(prefs.encoding) - del sys.setdefaultencoding - # Fin hack - -sys.path[:0]=[prefs.INSTALLDIR] - -import Editeur from Editeur import eficas_go eficas_go.lance_eficas() diff --git a/Aster/prefs.py b/Aster/prefs.py index 5ee30d25..fcd64885 100644 --- a/Aster/prefs.py +++ b/Aster/prefs.py @@ -99,3 +99,5 @@ if os.path.isfile(userprefs): execfile(userprefs) except: pass + +sys.path[:0]=[INSTALLDIR] diff --git a/Aster/style.py b/Aster/style.py new file mode 100644 index 00000000..e69de29b diff --git a/Editeur/Objecttreeitem.py b/Editeur/Objecttreeitem.py index bdf6ea67..3b928c6d 100644 --- a/Editeur/Objecttreeitem.py +++ b/Editeur/Objecttreeitem.py @@ -136,12 +136,19 @@ class ObjectTreeItem(TreeItem,Delegate): def __init__(self, appli, labeltext, object, setfunction=None): self.labeltext = labeltext self.appli = appli + # L'objet délegué est stocké dans l'attribut object + # L'objet associé à l'item est stocké dans l'attribut _object + # Il peut etre obtenu par appel à la méthode getObject + # Attention : le délégué peut etre différent de l'objet associé (MCLIST) + # Dans le cas d'une MCListe de longueur 1, l'objet associé est la MCListe + # et l'objet délégué est le MCFACT (object = _object.data[0]) Delegate.__init__(self,object) # On cache l'objet initial (pour destruction eventuelle # ultérieure) self._object = object self.setfunction = setfunction self.expandable = 1 + self.sublist=[] self.init() def init(self): @@ -167,6 +174,13 @@ class ObjectTreeItem(TreeItem,Delegate): else: return 1 + def update(self,item): + """ + Met a jour l'item courant a partir d'un autre item passe en argument + Ne fait rien par defaut + """ + pass + def GetLabelText(self): """ Retourne 3 valeurs : - le texte à afficher dans le noeud représentant l'item @@ -239,6 +253,41 @@ class ObjectTreeItem(TreeItem,Delegate): # l contient les anciens mots-clés + le nouveau dans l'ordre return l.index(nom_fils) + def append_child(self,name,pos=None): + """ + Permet d'ajouter un item fils à self + """ + if pos == 'first': + index = 0 + elif pos == 'last': + index = len(self.liste_mc_presents()) + elif type(pos) == types.IntType : + # la position est fixée + index = pos + elif type(pos) == types.InstanceType: + # pos est un item. Il faut inserer name apres pos + index = self.get_index(pos) +1 + elif type(name) == types.InstanceType: + index = self.get_index_child(name.nom) + else: + index = self.get_index_child(name) + return self.addobject(name,index) + + def append_brother(self,name,pos='after'): + """ + Permet d'ajouter un frère à self + par défaut on l'ajoute après self + """ + index = self._object.parent.get_index(self.getObject()) + 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.addobject(name,index) + def get_nom_etape(self): """Retourne le nom de self """ return self.object.get_nom_etape() @@ -412,6 +461,29 @@ class SequenceTreeItem(ObjectTreeItem): return 0 def GetSubList(self): + isublist=iter(self.sublist) + liste=self._object.data + iliste=iter(liste) + self.sublist=[] + + 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=value + it = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction) + self.sublist.append(it) + 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): sublist = [] for obj in self._object.data: def setfunction(value, object=obj): diff --git a/Editeur/appli.py b/Editeur/appli.py index e9f105ab..5787d6fb 100644 --- a/Editeur/appli.py +++ b/Editeur/appli.py @@ -35,6 +35,8 @@ from widgets import showerror # Modules Eficas import splash import prefs +import styles +from styles import style import fontes import tooltip import properties @@ -175,13 +177,13 @@ class APPLI: root.option_add('*Listbox*Font',fontes.standard) def initializeTk_colors_common(self, root): - root.option_add('*background', 'grey') - root.option_add('*foreground', 'black') - root.option_add('*EntryField.Entry.background', 'white') - root.option_add('*Entry*background', 'white') - root.option_add('*Listbox*background', 'white') - root.option_add('*Listbox*selectBackground', '#00008b') - root.option_add('*Listbox*selectForeground', 'white') + root.option_add('*background', style.background) + root.option_add('*foreground', style.foreground) + root.option_add('*EntryField.Entry.background', style.entry_background) + root.option_add('*Entry*background', style.entry_background) + root.option_add('*Listbox*background', style.list_background) + root.option_add('*Listbox*selectBackground', style.list_select_background) + root.option_add('*Listbox*selectForeground', style.list_select_foreground) def initializeTk_mac(self, root): self.initializeTk_colors_common(root) diff --git a/Editeur/basestyle.py b/Editeur/basestyle.py new file mode 100644 index 00000000..4330be36 --- /dev/null +++ b/Editeur/basestyle.py @@ -0,0 +1,26 @@ +class STYLE: + background='gray' + foreground='black' + entry_background='white' + list_background='white' + list_select_background='#00008b' + list_select_foreground='white' + tooltip_background="yellow" + + standard = ("Times",10) + standard_italique = ("Times",10,'italic') + standard_gras = ("Times",10,'bold') + standard_gras_souligne = ("Times",10,'bold','underline') + + canvas = ('times',8) + canvas_italique = ('times',8,'italic') + canvas_gras = ("Times",8,'bold') + canvas_gras_italique = ("Times",10,'bold','italic') + + standard12 = ("Times",12) + standard12_gras = ("Times",12,'bold') + standard12_gras_italique = ( "times",12,'bold','italic') + + standardcourier10 = ("Courier",10) + +style=STYLE() diff --git a/Editeur/bureau.py b/Editeur/bureau.py index ea7f987e..c0776c07 100644 --- a/Editeur/bureau.py +++ b/Editeur/bureau.py @@ -218,7 +218,7 @@ class BUREAU: if not hasattr(self,'JDC') : return titre="rapport de validation du jeu de commandes courant" cr = self.JDC.report() - self.update_jdc_courant() + #self.update_jdc_courant() elif mode == 'CATA': from Noyau.N_CR import CR cr = CR() @@ -352,7 +352,6 @@ class BUREAU: if format == 'homard': self.jdc_homard=g.get_homard() if not g.cr.estvide(): - print g.cr self.appli.affiche_infos("Erreur à la generation") showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC") return @@ -506,26 +505,9 @@ class BUREAU: Lance la suppression du noeud courant """ if not self.JDCDisplay_courant : return - try: - if self.JDCDisplay_courant.modified == 'n' : - self.JDCDisplay_courant.init_modif() - pere = self.JDCDisplay_courant.node_selected.parent - # Le noeud n'est pas au 1er niveau - if pere.parent.parent != None: - self.JDCDisplay_courant.node_selected.delete() - pere.select() - else: - noeudselecte = self.JDCDisplay_courant.node_selected - parent = noeudselecte.parent - enfants = parent.children - index = enfants.index(noeudselecte) - self.JDCDisplay_courant.node_selected.delete() - try: - enfants[index].select() - except : - enfants[index-1].select() - except AttributeError: - pass + if self.JDCDisplay_courant.modified == 'n' : + self.JDCDisplay_courant.init_modif() + self.JDCDisplay_courant.node_selected.delete() def visuJDC_py(self,event=None): """ @@ -557,7 +539,6 @@ class BUREAU: g=generator.plugins[format]() jdc_formate=g.gener(self.JDC,format='beautifie') if not g.cr.estvide(): - print g.cr self.appli.affiche_infos("Erreur à la generation") showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC") return diff --git a/Editeur/compocommandecomm.py b/Editeur/compocommandecomm.py index a50b259e..169f0b19 100644 --- a/Editeur/compocommandecomm.py +++ b/Editeur/compocommandecomm.py @@ -18,6 +18,7 @@ # # # ====================================================================== +import traceback from Tkinter import * import Pmw import string @@ -93,11 +94,13 @@ class COMMANDE_COMMPanel(panels.OngletPanel): Réalise la décommentarisation de self """ try: + pos=self.node.parent.children.index(self.node) commande,nom = self.node.item.uncomment() + self.node.parent.children[pos].select() except Exception,e: showerror("Erreur !",str(e)) return - self.parent.appli.bureau.JDCDisplay_courant.ReplaceObjectNode(self.node,commande,nom) + #self.parent.appli.bureau.JDCDisplay_courant.ReplaceObjectNode(self.node,commande,nom) class COMMANDE_COMMTreeItem(Objecttreeitem.ObjectTreeItem): panel = COMMANDE_COMMPanel @@ -159,6 +162,7 @@ class COMMANDE_COMMTreeItem(Objecttreeitem.ObjectTreeItem): try: commande,nom = self.object.uncomment() except Exception,e: + traceback.print_exc() raise e return commande,nom diff --git a/Editeur/compofact.py b/Editeur/compofact.py index 7a036a6a..e58be4cf 100644 --- a/Editeur/compofact.py +++ b/Editeur/compofact.py @@ -93,27 +93,37 @@ class FACTTreeItem(Objecttreeitem.ObjectTreeItem): return keys def GetSubList(self): - 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 + """ + Reactualise la liste des items fils stockes dans self.sublist + """ + liste=self.object.mc_liste + sublist=[None]*len(liste) + # suppression des items lies aux objets disparus + for item in self.sublist: + old_obj=item.getObject() + if old_obj in liste: + pos=liste.index(old_obj) + sublist[pos]=item + else: + pass # objets supprimes ignores + # ajout des items lies aux nouveaux objets + pos=0 + for obj in liste: + if sublist[pos] is None: + # nouvel objet : on cree un nouvel item + def setfunction(value, object=obj): + object.setval(value) + item = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction) + sublist[pos]=item + pos=pos+1 + + self.sublist=sublist + return self.sublist def additem(self,name,pos): - 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 + #print "compofact.additem",name,pos + objet = self.object.addentite(name,pos) + return objet def suppitem(self,item) : """ @@ -135,7 +145,30 @@ class FACTTreeItem(Objecttreeitem.ObjectTreeItem): self.appli.affiche_infos('Pb interne : impossible de supprimer ce mot-clé') return 0 - def verif_condition_bloc(self): + def GetSubList_BAK(self): + 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): + 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): return self.object.verif_condition_bloc() import Accas diff --git a/Editeur/compojdc.py b/Editeur/compojdc.py index 29eccf59..93b2f6c7 100644 --- a/Editeur/compojdc.py +++ b/Editeur/compojdc.py @@ -61,12 +61,14 @@ 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): @@ -74,7 +76,9 @@ class Node(treewidget.Node): Réalise la copie de l'objet passé en argument qui est nécessairement une commande """ + #child = self.item.append_child(objet_a_copier,pos='first') child = self.append_child(objet_a_copier,pos='first',retour='oui') + #if child is None : return 0 return child @@ -107,14 +111,8 @@ class JDCTreeItem(Objecttreeitem.ObjectTreeItem): return range(len(self.object.etapes)) def additem(self,name,pos): - print self.object - if isinstance(name,Objecttreeitem.ObjectTreeItem) : - cmd=self.object.addentite(name.getObject(),pos) - else : - cmd = self.object.addentite(name,pos) - print cmd - item = self.make_objecttreeitem(self.appli,cmd.nom + " : ", cmd) - return item + cmd = self._object.addentite(name,pos) + return cmd def suppitem(self,item) : # item = item de l'ETAPE à supprimer du JDC @@ -133,35 +131,54 @@ class JDCTreeItem(Objecttreeitem.ObjectTreeItem): return 0 def GetSubList(self): - sublist=[] + """ + Retourne la liste des items fils de l'item jdc. + Cette liste est conservee et mise a jour a chaque appel + """ if self.object.etapes_niveaux != []: liste = self.object.etapes_niveaux else: liste = self.object.etapes - key=0 - for value in liste: - def setfunction(value, key=key, object=liste): - object[key] = value - item = self.make_objecttreeitem(self.appli,value.ident() + " : ", value, setfunction) - sublist.append(item) - key=key+1 - return sublist - - def verif_condition_bloc(self): - # retourne la liste des sous-items dont la condition est valide - # sans objet pour le JDC - return [],[] + sublist=[None]*len(liste) + # suppression des items lies aux objets disparus + for item in self.sublist: + old_obj=item.getObject() + if old_obj in liste: + pos=liste.index(old_obj) + sublist[pos]=item + else: + pass # objets supprimes ignores + # ajout des items lies aux nouveaux objets + pos=0 + for obj in liste: + if sublist[pos] is None: + # nouvel objet : on cree un nouvel item + item = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj) + sublist[pos]=item + pos=pos+1 + + self.sublist=sublist + return self.sublist def get_l_noms_etapes(self): """ Retourne la liste des noms des étapes de self.object""" return self.object.get_l_noms_etapes() def get_liste_cmd(self): - print "get_liste_cmd" - print self.object.niveau.definition + #print "get_liste_cmd",self.object.niveau.definition listeCmd = self.object.niveau.definition.get_liste_cmd() return listeCmd + def additem_BAK(self,name,pos): + cmd=self.addentite(name,pos) + item = self.make_objecttreeitem(self.appli,cmd.nom + " : ", cmd) + return item + + def verif_condition_bloc_BAK(self): + # retourne la liste des sous-items dont la condition est valide + # sans objet pour le JDC + return [],[] + import Accas treeitem =JDCTreeItem diff --git a/Editeur/compomacro.py b/Editeur/compomacro.py index 4df206a1..e15f3950 100644 --- a/Editeur/compomacro.py +++ b/Editeur/compomacro.py @@ -37,7 +37,7 @@ from widgets import showinfo,showerror # __version__="$Name: $" -__Id__="$Id: compomacro.py,v 1.17 2005/04/18 10:20:36 eficas Exp $" +__Id__="$Id: compomacro.py,v 1.18 2005/04/18 14:21:08 eficas Exp $" # class MACROPanel(panels.OngletPanel): @@ -116,23 +116,6 @@ class MACROPanel(panels.OngletPanel): """ Effectue le changement de fichier d'initialisation s'il est valide """ - if not hasattr(self.node.item.object,'fichier_ini'): - self.node.item.object.fichier_ini=None - self.node.item.object.fichier_text=None - self.node.item.object.fichier_err="Le fichier n'est pas defini" - self.node.item.object.contexte_fichier_init={} - self.node.item.object.recorded_units={} - self.node.item.object.fichier_unite="PasDefini" - import Extensions.jdc_include - self.node.item.object.JdC_aux=Extensions.jdc_include.JdC_include - - old_fic = self.node.item.object.fichier_ini - old_text = self.node.item.object.fichier_text - old_err = self.node.item.object.fichier_err - old_context=self.node.item.object.contexte_fichier_init - old_units=self.node.item.object.recorded_units - old_etapes=self.node.item.object.etapes - new_fic = self.entry.get() if not os.path.isfile(new_fic) : showinfo("Fichier introuvable","Le fichier que vous avez saisi\n"+ @@ -144,10 +127,10 @@ class MACROPanel(panels.OngletPanel): # Si probleme a la lecture-conversion on arrete le traitement if not text: return - #self.node.item.object.recorded_units={} try: - self.node.item.object.make_contexte_include(new_fic,text) + self.node.item.object.change_fichier_init(new_fic,text) + self.parent.appli.affiche_infos("Fichier %s modifié" %self.node.item.get_nom()) except: # Erreurs lors de l'evaluation de text dans un JDC auxiliaire self.parent.appli.affiche_infos("Fichier invalide") @@ -160,58 +143,14 @@ class MACROPanel(panels.OngletPanel): if reponse: # On retablit l'ancien fichier self.entry.delete(0,Tkinter.END) - self.node.item.object.fichier_ini=old_fic - self.node.item.object.fichier_text=old_text - self.node.item.object.fichier_err=old_err - self.node.item.object.contexte_fichier_init=old_context - self.node.item.object.recorded_units=old_units - self.node.item.object.etapes=old_etapes + self.node.item.object.restore_fichier_init() self.parent.appli.affiche_infos("Fichier invalide ... Ancien fichier restauré") - if old_fic: - self.entry.insert(0,self.node.item.object.fichier_ini) + fic=self.node.item.object.fichier_ini + if fic: + self.entry.insert(0,fic) else: - # On conserve la memoire du nouveau fichier - # mais on n'utilise pas les concepts crees par ce fichier - # on met l'etape en erreur : fichier_err=string.join(l) - self.node.item.object.init_modif() - self.node.item.object.fichier_ini=new_fic - self.node.item.object.fichier_text=text - self.node.item.object.fichier_err=string.join(l) - # On enregistre la modification de fichier - self.node.item.object.record_unite() - #self.node.item.object.etapes=[] - self.node.item.object.g_context={} - # Le contexte du parent doit etre reinitialise car les concepts produits ont changé - self.node.item.object.parent.reset_context() - - self.node.item.object.old_contexte_fichier_init=old_context - self.node.item.object.contexte_fichier_init={} - self.node.item.object.reevalue_sd_jdc() - - self.node.item.object.fin_modif() + self.node.item.object.force_fichier_init() self.parent.appli.affiche_infos("Fichier invalide ... Nouveau fichier mémorisé") - self.node.update() - return - - # L'evaluation de text dans un JDC auxiliaire s'est bien passé - # on peut poursuivre le traitement - self.node.item.object.init_modif() - self.node.item.object.state="undetermined" - self.node.item.object.fichier_ini = new_fic - self.node.item.object.fichier_text=text - self.node.item.object.fichier_err=None - # On enregistre la modification de fichier - self.node.item.object.record_unite() - # Le contexte du parent doit etre reinitialise car les concepts produits ont changé - self.node.item.object.parent.reset_context() - - # Si des concepts ont disparu lors du changement de fichier, on demande leur suppression - self.node.item.object.old_contexte_fichier_init=old_context - self.node.item.object.reevalue_sd_jdc() - - self.node.item.object.fin_modif() - self.parent.appli.affiche_infos("Fichier %s modifié" %self.node.item.get_nom()) - self.node.update() def annule_fichier_init(self,event=None): """ Restaure dans self.entry le nom de fichier_init""" @@ -242,26 +181,24 @@ class INCLUDETreeItem(MACROTreeItem): def __init__(self,appli, labeltext, object, setfunction): MACROTreeItem.__init__(self,appli, labeltext, object, setfunction) - self.views=[] + + def iscopiable(self): + """ + Retourne 1 si l'objet est copiable, 0 sinon + """ + return 0 def makeEdit(self,appli,node): - print "makeEdit",self.object,self.object.nom - print "makeEdit",self.object.jdc_aux,self.object.jdc_aux.nom + #print "makeEdit",self.object,self.object.nom + #print "makeEdit",self.object.jdc_aux,self.object.jdc_aux.nom + #print "makeEdit",self.object.jdc_aux.context_ini 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.object.jdc_aux.subscribe(self) - - def notify(self,obj): - print "notify",self,obj - self.parent_node.update_valid() - # Il faudrait redessiner l'arbre de maniere optimale - # et pas seulement l'updater - for display in self.views: - display.tree.update() + self.myjdc.fichier=self.object.fichier_ini def makeView(self,appli,node): nom=self.object.nom @@ -271,11 +208,19 @@ class INCLUDETreeItem(MACROTreeItem): else: nom=nom+' '+self.object.fichier_ini macdisp=macrodisplay.makeMacroDisplay(appli,self,nom) - self.views.append(macdisp) -class INCLUDE_MATERIAUTreeItem(INCLUDETreeItem): pass class POURSUITETreeItem(INCLUDETreeItem): pass +class INCLUDE_MATERIAUTreeItem(INCLUDETreeItem): + rmenu_specs=[("View","makeView"), + ] + def iscopiable(self): + """ + Retourne 1 si l'objet est copiable, 0 sinon + """ + return 1 + + def treeitem(appli, labeltext, object, setfunction=None): """ Factory qui retourne l'item adapté au type de macro : INCLUDE, POURSUITE, MACRO diff --git a/Editeur/compomclist.py b/Editeur/compomclist.py index 07bc5a43..f6e403e9 100644 --- a/Editeur/compomclist.py +++ b/Editeur/compomclist.py @@ -23,6 +23,7 @@ from Tkinter import * import Pmw import Objecttreeitem import panels +import traceback class MCLISTPanel(panels.Panel): def init(self): @@ -35,26 +36,28 @@ class MCLISTPanel(panels.Panel): self.label = Label(self,text = texte) self.label.place(relx=0.5,rely=0.4,anchor='center') if test_ajout: - Button(self,text="AJOUTER",command=self.ajout_occurrence).place(relx=0.5,rely=0.6,anchor='center') + self.but=Button(self,text="AJOUTER",command=self.ajout_occurrence) + self.but.place(relx=0.5,rely=0.6,anchor='center') #Button(self,text="NON",command=None).place(relx=0.6,rely=0.6,anchor='center') def ajout_occurrence(self,event=None): self.node.parent.append_child(self.node.item.get_nom()) - import compofact import treewidget class Node(treewidget.Node): def doPaste(self,node_selected): objet_a_copier = self.item.get_copie_objet() child=node_selected.doPaste_MCF(objet_a_copier) + #print "doPaste",child return child def doPaste_MCF(self,objet_a_copier): if self.item.isMCList() : # le noeud courant est une MCList - child = self.parent.append_child(objet_a_copier,pos='first',retour='oui') - elif self.item.isMCFact(): + child = self.append_child(objet_a_copier,pos='first',retour='oui') + #child = self.parent.append_child(objet_a_copier,pos='first',retour='oui') + elif self.item.isMCFact() : # le noeud courant est un MCFACT if self.parent.item.isMCList(): # le noeud selectionne est un MCFACT dans une MCList @@ -69,14 +72,17 @@ class Node(treewidget.Node): "Vous ne pouvez coller le mot-clé facteur copié à ce niveau de l'arborescence !") self.appli.affiche_infos("Copie refusée") child=None + #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: @@ -86,6 +92,7 @@ class Node(treewidget.Node): """ 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 @@ -106,6 +113,7 @@ class Node(treewidget.Node): 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) @@ -162,11 +170,39 @@ class MCListTreeItem(Objecttreeitem.SequenceTreeItem,compofact.FACTTreeItem): def GetSubList(self): self.updateDelegate() - if len(self._object) > 1: - return Objecttreeitem.SequenceTreeItem.GetSubList(self) - else: + if len(self._object) <= 1: + self._object.data[0].alt_parent=self._object return compofact.FACTTreeItem.GetSubList(self) + liste=self._object.data + sublist=[None]*len(liste) + # suppression des items lies aux objets disparus + for item in self.sublist: + old_obj=item.getObject() + if old_obj in liste: + pos=liste.index(old_obj) + sublist[pos]=item + else: + pass # objets supprimes ignores + # ajout des items lies aux nouveaux objets + pos=0 + for obj in liste: + if sublist[pos] is None: + # nouvel objet : on cree un nouvel item + def setfunction(value, object=obj): + object=value + item = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction) + sublist[pos]=item + #Attention : on ajoute une information supplementaire pour l'actualisation de + # la validite. L'attribut parent d'un MCFACT pointe sur le parent de la MCLISTE + # et pas sur la MCLISTE elle meme ce qui rompt la chaine de remontee des + # informations de validite. alt_parent permet de remedier a ce defaut. + obj.alt_parent=self._object + pos=pos+1 + + self.sublist=sublist + return self.sublist + def GetIconName(self): if self._object.isvalid(): return "ast-green-los" @@ -197,47 +233,35 @@ class MCListTreeItem(Objecttreeitem.SequenceTreeItem,compofact.FACTTreeItem): """ return len(self._object) > 1 + def get_copie_objet(self): + return self._object.data[0].copy() + def additem(self,obj,pos): - """ - Ajoute un objet MCFACT à la MCList (self.object) à la position pos - """ + #print "compomclist.additem",obj,pos if len(self._object) <= 1: - return compofact.FACTTreeItem.additem(self,obj,pos) - - if type(obj)==types.StringType : - # on est en mode création d'un motcle - raise "traitement non prevu" - - if not self._object.ajout_possible(): - return None - - if self._object.nom != obj.nom: - return None + return compofact.FACTTreeItem.additem(self,obj,pos) - self.object.init_modif() - obj.verif_existence_sd() - obj.reparent(self.object.parent) - self.object.insert(pos,obj) - self.object.fin_modif() - - item = self.make_objecttreeitem(self.appli, obj.nom + ":", obj) - return item + o= self.object.addentite(obj,pos) + return o def suppitem(self,item): """ Retire un objet MCFACT de la MCList (self.object) """ + #print "compomclist.suppitem",item obj=item.getObject() if len(self._object) <= 1: return compofact.FACTTreeItem.suppitem(self,item) - self.object.init_modif() - self.object.remove(obj) - if len(self._object) == 1: - self.updateDelegate() - message = "Mot-clé " + obj.nom + " supprimé" - self.appli.affiche_infos(message) - return 1 + if self.object.suppentite(obj): + if len(self._object) == 1: self.updateDelegate() + message = "Mot-clé " + obj.nom + " supprimé" + self.appli.affiche_infos(message) + return 1 + else: + self.appli.affiche_infos('Impossible de supprimer ce mot-clé') + return 0 + import Accas objet = Accas.MCList diff --git a/Editeur/componiveau.py b/Editeur/componiveau.py index 4c5c2474..e0414dee 100644 --- a/Editeur/componiveau.py +++ b/Editeur/componiveau.py @@ -42,7 +42,7 @@ class NIVEAUPanel(panels.OngletPanel): import treewidget class Node(treewidget.Node): - def verif_condition(self): + 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 @@ -50,7 +50,7 @@ class Node(treewidget.Node): """ return 0 - def replace_enfant(self,item): + def replace_enfant_BAK(self,item): """ Retourne le noeud fils à éventuellement remplacer """ return None @@ -62,9 +62,6 @@ class NIVEAUTreeItem(Objecttreeitem.ObjectTreeItem): def isactif(self): return self.object.isactif() - def IsExpandable_old(self): - return self.object.isactif() - def IsExpandable(self): return 1 diff --git a/Editeur/componuplet.py b/Editeur/componuplet.py index e86b4a65..e3c63dd7 100644 --- a/Editeur/componuplet.py +++ b/Editeur/componuplet.py @@ -31,7 +31,7 @@ import panels # __version__="$Name: $" -__Id__="$Id: componuplet.py,v 1.4 2003/10/16 14:31:22 eficas Exp $" +__Id__="$Id: componuplet.py,v 1.5 2004/09/10 15:51:49 eficas Exp $" # myrepr = Repr() @@ -96,8 +96,8 @@ class NUPLETPanel(panels.OngletPanel): #obj.set_valeur(val,evaluation='non') obj.set_valeur(val) self.parent.appli.affiche_infos(mess) - self.node.parent.verif() - self.node.update() + #self.node.parent.verif() + #self.node.update() def valid_valeur(self,e,obj=None,mess='Valeur du mot-cl\351 enregistr\351e'): """ @@ -125,8 +125,8 @@ class NUPLETPanel(panels.OngletPanel): e.widget.delete(0,Tkinter.END) e.widget.insert(0,anc_val) - self.node.parent.verif() - self.node.update() + #self.node.parent.verif() + #self.node.update() def gen_aide(self,obj): return "" @@ -167,6 +167,7 @@ class NUPLETTreeItem(Objecttreeitem.ObjectTreeItem): raise "NUPLET" def verif_condition_bloc(self): + raise "OBSOLETE" return self.object.verif_condition_bloc() import Accas diff --git a/Editeur/compooper.py b/Editeur/compooper.py index 1bc69cdc..734fa395 100644 --- a/Editeur/compooper.py +++ b/Editeur/compooper.py @@ -109,7 +109,10 @@ class Node(treewidget.Node): Réalise la copie de l'objet passé en argument qui est nécessairement une commande """ + parent=self.parent + #child = parent.item.append_child(objet_a_copier,self.item.getObject()) child = self.append_brother(objet_a_copier,retour='oui') + #if child is None:return 0 return child def doPaste_MCF(self,objet_a_copier): @@ -178,18 +181,9 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): return "" def additem(self,name,pos): - if isinstance(name,Objecttreeitem.ObjectTreeItem) : - mcent = self.object.addentite(name.getObject(),pos) - else : - mcent = self.object.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 + #print "compooper.additem",name,pos + mcent = self._object.addentite(name,pos) + return mcent def suppitem(self,item) : # item : item du MOCLE de l'ETAPE à supprimer @@ -217,13 +211,68 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): return keys def GetSubList(self): + """ + Reactualise la liste des items fils stockes dans self.sublist + """ + if self.isactif(): + liste=self.object.mc_liste + else: + liste=[] + + sublist=[None]*len(liste) + # suppression des items lies aux objets disparus + for item in self.sublist: + old_obj=item.getObject() + if old_obj in liste: + pos=liste.index(old_obj) + sublist[pos]=item + else: + pass # objets supprimes ignores + + # ajout des items lies aux nouveaux objets + pos=0 + for obj in liste: + if sublist[pos] is None: + # nouvel objet : on cree un nouvel item + def setfunction(value, object=obj): + object.setval(value) + item = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction) + sublist[pos]=item + pos=pos+1 + + self.sublist=sublist + return self.sublist + + def GetSubList_BAK(self): + if self.isactif(): + liste=self.object.mc_liste + else: + liste=[] + 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 + 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() @@ -234,8 +283,9 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): """ return 1 - def verif_condition_bloc(self): - return self.object.verif_condition_bloc() + def update(self,item): + if item.sd and item.sd.nom: + self.nomme_sd(item.sd.nom) def nomme_sd(self,nom): """ Lance la méthode de nommage de la SD """ @@ -268,13 +318,43 @@ class EtapeTreeItem(Objecttreeitem.ObjectTreeItem): parent=self.object.parent) commande_comment.niveau = self.object.niveau commande_comment.jdc = commande_comment.parent = self.object.jdc + + pos=self.object.parent.etapes.index(self.object) + self.object.parent.suppentite(self.object) + self.object.parent.addentite(commande_comment,pos) + return commande_comment + def additem_BAK(self,name,pos): + 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): + 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): + return self.object.verif_condition_bloc() + def replace_child(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() diff --git a/Editeur/composimp.py b/Editeur/composimp.py index ee4506d5..04a894c1 100644 --- a/Editeur/composimp.py +++ b/Editeur/composimp.py @@ -329,6 +329,12 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): return valide def valide_liste_partielle(self,item,listecourante): + valeur=listecourante + valeur.append(item) + valeur = tuple(valeur) + return self.object.valid_valeur_partielle(valeur) + + def valide_liste_partielle_BAK(self,item,listecourante): valeuravant=self.object.valeur valeur=listecourante valeur.append(item) @@ -348,6 +354,9 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): return validite def valide_liste_complete (self,valeur): + return self.object.valid_valeur(valeur) + + def valide_liste_complete_BAK (self,valeur): valeuravant=self.object.valeur retour=self.object.set_valeur(valeur) validite=0 @@ -383,7 +392,7 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): def isvalid(self): valide=self.object.isvalid() - return self.object.isvalid() + return valide #-------------------------------------------------- # @@ -430,7 +439,9 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): """ Affecte au MCS pointé par self l'objet de type CO et de nom nom_co """ - return self.object.set_valeur_co(nom_co) + ret = self.object.set_valeur_co(nom_co) + #print "set_valeur_co",ret + return ret def get_sd_avant_du_bon_type(self): """ @@ -438,8 +449,7 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): le MCS pointé par self et du type requis par ce MCS """ a=self.object.etape.parent.get_sd_avant_du_bon_type(self.object.etape,self.object.definition.type) - return self.object.etape.parent.get_sd_avant_du_bon_type(self.object.etape, - self.object.definition.type) + return a #def verif(self): # pass @@ -555,6 +565,7 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): selon le type de l objet attendu - traite les reels et les parametres """ + #print "eval_valeur_item",valeur if valeur==None or valeur == "" : return None,0 validite=1 @@ -565,20 +576,26 @@ class SIMPTreeItem(Objecttreeitem.AtomicObjectTreeItem): valeurretour,validite = valeur,1 else : valeurretour,validite= self.object.eval_valeur(valeur) + #print "eval_valeur_item",valeurretour,validite + if validite == 0: if type(valeur) == types.StringType and self.object.wait_TXM(): essai_valeur="'" + valeur + "'" valeurretour,validite= self.object.eval_valeur(essai_valeur) + if hasattr(valeurretour,'__class__'): #if valeurretour.__class__.__name__ in ('PARAMETRE','PARAMETRE_EVAL'): if valeurretour.__class__.__name__ in ('PARAMETRE',): validite=1 - if self.wait_co(): - try: - valeurretour=Accas.CO(valeur) - except: - valeurretour=None - validite=0 + + #if self.wait_co(): + # CCAR : il ne faut pas essayer de creer un concept + # il faut simplement en chercher un existant ce qui a du etre fait par self.object.eval_valeur(valeur) + #try: + #valeurretour=Accas.CO(valeur) + #except: + #valeurretour=None + #validite=0 # on est dans le cas où on a évalué et où on n'aurait pas du if self.object.wait_TXM() : if type(valeurretour) != types.StringType: diff --git a/Editeur/eficas_go.py b/Editeur/eficas_go.py index 2446c724..84e8e7a2 100644 --- a/Editeur/eficas_go.py +++ b/Editeur/eficas_go.py @@ -20,13 +20,23 @@ # ====================================================================== """ Ce module permet de lancer l'application EFICAS en affichant - un ecran Splash pour faire patentier l'utilisateur + un ecran Splash pour faire patienter l'utilisateur """ # Modules Python import sys import Tkinter # Modules Eficas +import prefs +if hasattr(prefs,'encoding'): + # Hack pour changer le codage par defaut des strings + import sys + reload(sys) + sys.setdefaultencoding(prefs.encoding) + del sys.setdefaultencoding + # Fin hack + +import styles import import_code import splash import session diff --git a/Editeur/jdcdisplay.py b/Editeur/jdcdisplay.py index 51ee9d4c..863c5b61 100644 --- a/Editeur/jdcdisplay.py +++ b/Editeur/jdcdisplay.py @@ -25,6 +25,7 @@ """ # Modules Python import types +import traceback import Tkinter import Pmw @@ -128,12 +129,13 @@ class JDCDISPLAY: """ if node is not self.node_selected : self.create_panel(node) - # on conserve la trace du noeud sélectionné et de celui d'avant - if self.node_selected : - self.ancien_node = self.node_selected - self.node_selected = node - else: - self.ancien_node = self.node_selected = node + self.node_selected = node + ## on conserve la trace du noeud sélectionné et de celui d'avant + #if self.node_selected : + #self.ancien_node = self.node_selected + #self.node_selected = node + #else: + #self.ancien_node = self.node_selected = node def create_panel(self,node): """ @@ -157,12 +159,14 @@ class JDCDISPLAY: z.show_stats() z.show_cycles() + if node is None: + self.panel_courant=None + return self.panel_courant if node.item.isactif(): if hasattr(node.item,"panel"): self.panel_courant=node.item.panel(self,self.pane.pane('selected'),node) else: - print node.item raise Exception("Le noeud sélectionné n'a pas de panel associé") else: self.panel_courant = panels.Panel_Inactif(self,self.pane.pane('selected'),node) @@ -198,9 +202,10 @@ class JDCDISPLAY: else: self.init_modif() node.delete() - if nom_sd: - child.item.nomme_sd(nom_sd) - child.update() + #if nom_sd: + #child.item.nomme_sd(nom_sd) + child.select() + #child.update() def doCut(self): """ @@ -232,6 +237,7 @@ class JDCDISPLAY: try: child=self.appli.noeud_a_editer.doPaste(self.node_selected) except: + traceback.print_exc() showinfo("Action de coller impossible", "L'action de coller apres un tel objet n'est pas permise") return @@ -241,20 +247,19 @@ class JDCDISPLAY: showerror("Copie refusée",self.appli.message) self.appli.message = '' self.appli.affiche_infos("Copie refusée") + return # il faut déclarer le JDCDisplay_courant modifié self.init_modif() # suppression éventuelle du noeud sélectionné # si possible on renomme l objet comme le noeud couper if self.edit == "couper": - try : - nom = self.appli.noeud_a_editer.item.object.sd.nom - self.appli.noeud_a_editer.delete() - test,mess = child.item.nomme_sd(nom) - child.verif() - child.racine.update() - except : - self.appli.noeud_a_editer.delete() + #nom = self.appli.noeud_a_editer.item.object.sd.nom + item=self.appli.noeud_a_editer.item + self.appli.noeud_a_editer.delete() + child.item.update(item) + #test,mess = child.item.nomme_sd(nom) + child.select() # on rend la copie à nouveau possible en libérant le flag edit self.edit="copier" diff --git a/Editeur/macrodisplay.py b/Editeur/macrodisplay.py index f6b35d6f..971dd10c 100644 --- a/Editeur/macrodisplay.py +++ b/Editeur/macrodisplay.py @@ -34,45 +34,8 @@ import compojdc import treewidget from widgets import Fenetre -#class MACRO2TreeItem(Objecttreeitem.ObjectTreeItem): class MACRO2TreeItem(compojdc.JDCTreeItem): - def IsExpandable(self): - return 1 - - def GetText(self): - return " " - - def GetIconName(self): - if self.object.isvalid(): - return "ast-green-square" - else: - return "ast-red-square" - - def keys(self): - return range(len(self.object.etapes)) - - def GetSubList(self): - sublist=[] - for key in self.keys(): - liste = self.object.etapes - try: - value = liste[key] - except KeyError: - continue - def setfunction(value, key=key, object=liste): - object[key] = value - item = self.make_objecttreeitem(self.appli,value.ident() + " : ", value, setfunction) - sublist.append(item) - return sublist - - def verif_condition_bloc(self): - # retourne la liste des sous-items dont la condition est valide - # sans objet pour le JDC - return [],[] - - def get_l_noms_etapes(self): - """ Retourne la liste des noms des étapes de self.object""" - return self.object.get_l_noms_etapes() + pass class MacroDisplay: def __init__(self,appli,macroitem,nom_jdc): @@ -156,7 +119,7 @@ def makeMacroDisplay(appli,macroitem,nom_item): class TREEITEMINCANVAS: def __init__(self,object,nom="",parent=None,appli=None,sel=None,rmenu=None): - print "TREEITEMINCANVAS",object + #print "TREEITEMINCANVAS",object self.object=object self.nom=nom self.appli=appli @@ -182,7 +145,7 @@ import jdcdisplay class MACRODISPLAY(jdcdisplay.JDCDISPLAY): def __init__(self,jdc,nom_jdc,appli=None,parent=None): - print "MACRODISPLAY",jdc + #print "MACRODISPLAY",jdc self.jdc=jdc self.nom_jdc=nom_jdc self.fichier=None diff --git a/Editeur/newsimppanel.py b/Editeur/newsimppanel.py index bc62e5a6..0ac18553 100644 --- a/Editeur/newsimppanel.py +++ b/Editeur/newsimppanel.py @@ -72,13 +72,13 @@ class newSIMPPanel(panels.OngletPanel): if self.parent.modified == 'n' : self.parent.init_modif() self.node.item.set_valeur(name) self.parent.appli.affiche_infos(mess) - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() - self.node.update() + #if self.node.item.get_position()=='global': + #self.node.etape.verif_all() + #elif self.node.item.get_position()=='global_jdc': + #self.node.racine.verif_all() + #else : + #self.node.parent.verif() + #self.node.update() def record_valeur(self,name=None,mess='Valeur du mot-clé enregistrée'): """ @@ -111,15 +111,15 @@ class newSIMPPanel(panels.OngletPanel): if validite : self.node.item.set_valeur(valeur) self.parent.appli.affiche_infos(mess) - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() - self.node.update() - if self.node.item.isvalid(): - self.node.parent.select() + #if self.node.item.get_position()=='global': + #self.node.etape.verif_all() + #elif self.node.item.get_position()=='global_jdc': + #self.node.racine.verif_all() + #else : + #self.node.parent.verif() + #self.node.update() + #if self.node.item.isvalid(): + # self.node.parent.select() else : self.parent.appli.affiche_infos(commentaire) diff --git a/Editeur/panels.py b/Editeur/panels.py index 8626adec..b6a97e9f 100644 --- a/Editeur/panels.py +++ b/Editeur/panels.py @@ -23,6 +23,7 @@ import os from Tkinter import * import Pmw import time +import traceback import widgets from widgets import ListeChoix @@ -50,6 +51,10 @@ class Panel(Frame) : self.creer_boutons() self.init() + def __del__(self): + """ appele a la destruction du panel """ + #print "PANEL DETRUIT" + def destroy(self): Frame.destroy(self) self.panneau=None @@ -238,6 +243,9 @@ class Panel(Frame) : if name == SEPARATEUR:return if self.parent.modified == 'n' : self.parent.init_modif() if name != "COMMENTAIRE": + #parent=self.node.parent + #new_obj = parent.item.append_child(name,self.node.item.getObject()) + #parent.children[parent.children.index(self.node)+1].select() new_node = self.node.append_brother(name,'after') else : new_node = self.ajout_commentaire() @@ -247,6 +255,8 @@ class Panel(Frame) : if name == SEPARATEUR:return if self.parent.modified == 'n' : self.parent.init_modif() if name != "COMMENTAIRE": + #new_obj = self.node.item.append_child(name,'first') + #self.node.children[0].select() new_node = self.node.append_child(name,'first') else : new_node = self.ajout_commentaire_first() @@ -471,7 +481,7 @@ class OngletPanel(Panel) : def deselectMC(self,name): self.parent.appli.affiche_infos('') - def get_liste_cmd_old(self): + def get_liste_cmd_BAK(self): listeCmd = self.cata.listCmd() return listeCmd @@ -480,9 +490,8 @@ class OngletPanel(Panel) : return jdc.get_groups() def get_liste_cmd(self): - print "get_liste_cmd",self.node.item.object + #print "get_liste_cmd",self.node.item.object jdc=self.node.item.object.get_jdc_root() - print jdc listeCmd = jdc.get_liste_cmd() return listeCmd @@ -501,8 +510,8 @@ class OngletPanel(Panel) : if nom == '' : return # si pas de nom, on ressort sans rien faire ... if self.parent.modified == 'n' : self.parent.init_modif() test,mess = self.node.item.nomme_sd(nom) - self.node.verif() - self.node.racine.update() + #self.node.verif() + #self.node.racine.update() self.parent.appli.affiche_infos(mess) def changed(self): @@ -515,9 +524,12 @@ class OngletPanel(Panel) : # On traite par une exception le cas où l'utilisateur final cherche à désactiver # (commentariser) un commentaire. try : + pos=self.node.parent.children.index(self.node) commande_comment = self.node.item.get_objet_commentarise() - self.parent.appli.bureau.JDCDisplay_courant.ReplaceObjectNode(self.node,commande_comment,None) + self.node.parent.children[pos].select() + #self.parent.appli.bureau.JDCDisplay_courant.ReplaceObjectNode(self.node,commande_comment,None) except Exception,e: + traceback.print_exc() widgets.showerror("TOO BAD",str(e)) return diff --git a/Editeur/styles.py b/Editeur/styles.py new file mode 100644 index 00000000..669e6d72 --- /dev/null +++ b/Editeur/styles.py @@ -0,0 +1,18 @@ +import os +import prefs +import basestyle +from basestyle import STYLE,style + +inistylefile=os.path.join(prefs.REPINI,"style.py") +if os.path.isfile(inistylefile): + execfile(inistylefile) + +userstylefile=os.path.expanduser("~/Eficas_install/style.py") +if os.path.isfile(userstylefile): + execfile(userstylefile) + +import fontes +for attr in dir(style): + if attr[0]=='_':continue + if not hasattr(fontes,attr):continue + setattr(fontes,attr,getattr(style,attr)) diff --git a/Editeur/treewidget.py b/Editeur/treewidget.py index 0ae0d955..9a26db03 100644 --- a/Editeur/treewidget.py +++ b/Editeur/treewidget.py @@ -24,10 +24,11 @@ from Tkinter import * import fontes import images +from Ihm import CONNECTOR # __version__="$Name: $" -__Id__="$Id: treewidget.py,v 1.19 2005/02/25 11:38:03 eficas Exp $" +__Id__="$Id: treewidget.py,v 1.20 2005/04/13 14:59:31 eficas Exp $" # Fonte_Standard = fontes.standard @@ -120,10 +121,13 @@ class Tree : 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() @@ -156,6 +160,9 @@ class Node : def __init__(self,parent,item,command=None,rmenu=None): self.parent = parent self.item = item + self.connections=[] + self.connect() + self.command = command self.rmenu=rmenu self.tree = self.parent.tree @@ -171,23 +178,213 @@ class Node : self.lasty = 0 self.children = None self.id = [] + if self.parent is self.tree: + self.racine=self + else: + self.racine = self.parent.racine + # etape = noeud d'étape auquel appartient self # = self si c'est lui-même - if isinstance(self.parent,Tree) : + #if isinstance(self.parent,Tree) : # on est sur un noeud de JDC - self.racine=self - self.etape=None - self.nature='JDC' - elif isinstance(self.parent.parent,Tree) : + #self.etape=None + #elif isinstance(self.parent.parent,Tree) : # on est sur un noeud d'étape - self.racine = self.parent - self.etape=self - self.nature = 'ETAPE' - else : + #self.etape=self + #else : # on est sur un noeud de mot-clé - self.racine = self.parent.racine - self.etape=self.parent.etape - self.nature = 'MOTCLE' + #self.etape=self.parent.etape + + 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] + + def force_select(self): + if self.selected: + # le noeud est selectionné. On force la reconstruction du panel associé + if self.command:apply(self.command,(None,)) + self.select() + + def onValid(self): + #print "onValid : l'item a changé de validité ",self.item,self.item.object,self.item.object.isvalid() + self.update_node_valid() + self.update_label_texte() + self.update_texte() + + def onAdd(self,objet): + #print "onAdd : un objet a été ajouté aux fils de l'item ",self.item.object,objet + self.expand_node() + old_nodes=self.children + self.update_nodes() + #print "onAdd:nodes",self.children + self.redraw_children(old_nodes) + self.force_select() + + def onSupp(self,objet): + #print "onSupp : un objet a été supprimé des fils de l'item ",self.item.object,objet + self.expand_node() + old_nodes=self.children + self.update_nodes() + #print "onSupp:nodes",self.children + self.redraw_children(old_nodes) + self.force_select() + + def update_nodes(self): + #print "update_nodes",self + newnodes=[] + inodes=iter(self.children) + sublist=self.item._GetSubList() + iliste=iter(sublist) + #print "update_nodes",self.children + #print "update_nodes",sublist + + while(1): + old_item=item=None + for node in inodes: + old_item=node.item + if old_item in sublist:break + #print "item supprime",old_item + for item in iliste: + if item is old_item:break + #print "item ajoute",item + child = item.itemNode(self,item,self.command,self.rmenu) + newnodes.append(child) + + if old_item is None and item is None:break + if old_item is item: + #print "item conserve",item + newnodes.append(node) + + self.children=newnodes + self.reconnect() + + def supprime(self): + self.disconnect() + 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 + + if not self.children : return + for child in self.children: + child.supprime() + self.children=None + + def redraw_children(self,old_nodes): + #print "redraw_children",old_nodes + #print self.children + y = self.y + 20 + x = self.x + 15 + supp_nodes=[] + + inodes=iter(old_nodes) + iliste=iter(self.children) + # on parcourt la liste des anciens noeuds (node) + # et la liste des nouveaux noeuds (new_node) en parallele (iterateurs) + + while(1): + new_node=node=None + for node in inodes: + #print "ancien noeud",node + if node in self.children:break # ancien noeud toujours present + #print "noeud supprime",node,node.item.GetLabelText()[0] + dy=node.y-node.lasty -20 + #print "deplacer noeuds",y,dy + node.move_nodes(y,dy) + node.supprime() + #supp_nodes.append(node) + + for new_node in iliste: + #print "nouveau noeud",new_node + if new_node in old_nodes: break # nouveau noeud deja present + #print "noeud ajoute",new_node,new_node.item.GetLabelText()[0] + y=self.draw_node(new_node,x,y) + + if node is None and new_node is None : break + + if node is new_node: # ancien noeud + #print "noeud conserve",node + node.update_label_texte() + y=y+node.lasty-node.y +20 + + self.racine.update_coords() + self.canvas.delete('line') + self.racine.trace_ligne() + self.tree.resizescrollregion() + # Mettre à 1 pour verifier les cycles entre objets node + #withCyclops=0 + #if withCyclops: + #from Misc import Cyclops + #z = Cyclops.CycleFinder() + #print supp_nodes + #for o in supp_nodes: + #z.register(o) + #del supp_nodes + #del o + #z.find_cycles() + #z.show_stats() + #z.show_cycles() + + def tag_move_nodes(self,y): + """ Marque pour deplacement tous les noeuds au dela de l'ordonnée y """ + self.canvas.dtag(ALL,'move') + # on marque tous les ids au dela de y + x0, y0, x1, y1 = self.canvas.bbox(ALL) + self.canvas.addtag_overlapping('move',x0,y,x1,y1) + + def move_nodes(self,y,dy): + """ Déplace de l'incrément dy les noeuds au dela de l'ordonnée y """ + self.tag_move_nodes(y) + # on déplace tous les items de dy + self.canvas.move('move',0,dy) + + def draw_node(self,new_node,x,y): + """ Dessine le noeud new_node en x,y en deplacant les noeuds existants + en y et au dela + Retourne la position du premier des noeuds deplaces + """ + self.tag_move_nodes(y) + #if new_node.item.isactif(): + #new_node.state = 'expanded' + new_node.state = 'expanded' + new_node.draw(x,y) + dy=(new_node.get_nb_children()+1)*20 + #print "deplacer noeuds",y,dy + self.canvas.move('move',0,dy) + return new_node.lasty+20 def build_children(self): """ Construit la liste des enfants de self """ @@ -207,7 +404,10 @@ class Node : Rend le noeud courant (self) sélectionné et déselectionne tous les autres """ + #print "SELECT",self + #traceback.print_stack() if not self.children : self.build_children() + #if self.selected and self.tree.node_selected is self: return self.tree.deselectall() self.selected = 1 self.tree.node_selected = self @@ -311,6 +511,7 @@ class Node : for child in self.children: if child.item.get_nom() == name: return child return None + #----------------------------------------------- # Méthodes d'affichage d'un noeud #----------------------------------------------- @@ -332,7 +533,7 @@ class Node : callback = self.expand image = self.geticonimage(name=iconname) self.icone_id = self.canvas.create_image(self.x, self.y, image=image) - self.canvas.tag_bind(self.icone_id, "<1>", callback) + self.callback_id=self.canvas.tag_bind(self.icone_id, "<1>", callback) self.id.append(self.icone_id) # création de la ligne horizontale self.ligne_id = self.canvas.create_line(self.x,self.y,self.x+10,self.y) @@ -342,8 +543,8 @@ class Node : image = self.geticonimage() if image != None : self.image_id = self.canvas.create_image(self.x+15,self.y,image = image) - self.canvas.tag_bind(self.image_id,"<1>",self.select) - self.canvas.tag_bind(self.image_id,"<3>",self.popup) + self.select_id2=self.canvas.tag_bind(self.image_id,"<1>",self.select) + self.popup_id2=self.canvas.tag_bind(self.image_id,"<3>",self.popup) self.id.append(self.image_id) else: self.image_id = None @@ -386,10 +587,10 @@ class Node : self.label_id = self.canvas.create_window(textx,texty,window=self.label,anchor='w') self.id.append(self.label_id) # bindings sur le widget label - self.label.bind("<1>", self.select) - self.label.bind("<3>", self.popup) - self.label.bind("",self.enter) - self.label.bind("",self.leave) + self.select_id=self.label.bind("<1>", self.select) + self.popup_id=self.label.bind("<3>", self.popup) + self.enter_id=self.label.bind("",self.enter) + self.leave_id=self.label.bind("",self.leave) # valeur de cet objet à afficher x0, y0, x1, y1 = self.canvas.bbox(self.label_id) textx = max(x1, 200) + 10 @@ -431,7 +632,6 @@ class Node : if not self.children : return for child in self.children: child.state='collapsed' - child.displayed = 0 child.collapse_children() def collapse(self,event = None): @@ -442,13 +642,18 @@ class Node : self.redraw(-nb) self.select() - def expand(self,event = None): + def expand_node(self,event = None): """ Expanse self et le retrace """ - if not self.item.isactif() : return + if self.state == 'expanded':return + #if not self.item.isactif() : return if not self.children : self.build_children() self.state = 'expanded' nb = self.get_nb_children() self.redraw(nb) + + def expand(self,event = None): + """ Expanse self et le retrace """ + self.expand_node() self.select() def redraw(self,nb): @@ -476,10 +681,12 @@ class Node : coords = self.canvas.coords(self.label_id) self.x = coords[0]-15 self.y = coords[1] + self.lasty = self.y if self.state == 'expanded' : for child in self.children: if child.displayed != 0: child.update_coords() + self.lasty = child.lasty def update_icone(self): """ Met à jour les icônes de tous les noeuds : teste la validité de l'objet @@ -492,6 +699,17 @@ class Node : if child.displayed != 0: child.update_icone() + def update_label_texte(self): + # nom,fonte et couleur de l'objet du noeud à afficher + labeltext,fonte,couleur = self.item.GetLabelText() + if labeltext == '' : labeltext = ' ' + if fonte == None : fonte = Fonte_Standard + if couleur == None : couleur = 'black' + self.label.configure(text=labeltext,font=fonte) + if self.state == 'expanded' : + for child in self.children: + if child.displayed != 0 : child.update_label_texte() + def update_texte(self): """ Met à jour les noms des SD et valeurs des mots-clés """ text = self.item.GetText() @@ -501,13 +719,19 @@ class Node : for child in self.children: if child.displayed != 0 : child.update_texte() - def update_valid(self) : - """Cette methode a pour but de mettre a jour la validite du noeud - et de propager la demande de mise à jour à son parent + def update_node_valid(self) : + """Cette methode remet a jour la validite du noeud (icone) + Elle appelle isvalid """ if self.image_id != None : image = self.geticonimage() self.canvas.itemconfig(self.image_id,image=image) + + def update_valid(self) : + """Cette methode a pour but de mettre a jour la validite du noeud + et de propager la demande de mise à jour à son parent + """ + self.update_node_valid() self.parent.update_valid() def update(self,event=None) : @@ -522,17 +746,42 @@ class Node : La métode isvalid est en général appelée par l intermédiaire de update_icone -> geticonimage -> GetIconName """ + #print "update",self + #traceback.print_stack() self.racine.update_coords() self.racine.trace_ligne() self.racine.update_icone() self.racine.update_texte() self.tree.resizescrollregion() + def efface_node(self): + if self.displayed != 0: + self.label.unbind("<1>", self.select_id) + self.label.unbind("<3>", self.popup_id) + self.label.unbind("",self.enter_id) + self.label.unbind("",self.leave_id) + self.canvas.tag_unbind(self.image_id,"<1>",self.select_id2) + self.canvas.tag_unbind(self.image_id,"<3>",self.popup_id2) + if self.item.IsExpandable(): + self.canvas.tag_unbind(self.icone_id, "<1>", self.callback_id) + self.label.destroy() + self.text.destroy() + + for id in self.id : + self.canvas.delete(id) + self.id=[] + self.label_id=None + self.text_id=None + self.image_id=None + self.icone_id=None + self.label=None + self.text=None + self.displayed=0 + def efface(self): """ Efface du canvas les id associés à self : cad les siens et ceux de ses enfants """ - for id in self.id : - self.canvas.delete(id) + self.efface_node() if not self.children : return for child in self.children: child.efface() @@ -559,7 +808,6 @@ class Node : def trace_ligne(self): """ Dessine les lignes verticales entre frères et entre père et premier fils""" if self.state=='collapsed' : return - #if self.displayed == 0 : return if len(self.children)==0 : return # on est bien dans le cas d'un noeud expansé avec enfants ... # il faut rechercher l'ordonnée du dernier fils de self @@ -586,12 +834,14 @@ class Node : #------------------------------------------------------------------ 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): @@ -599,7 +849,8 @@ class Node : Interface avec ACCAS : création de l'objet de nom name et du noeud associé. Retourne le noeud fils ainsi créé """ - print "full_creation",name,pos,self.item + 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 @@ -618,12 +869,13 @@ class Node : self.children.insert(pos,child) return child - def append_brother(self,name,pos='after',retour='non'): + 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': @@ -641,6 +893,7 @@ class Node : 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: @@ -661,12 +914,61 @@ class Node : 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 + par défaut on l'ajoute immédiatement après + Méthode externe + """ + # 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 0 + return self.parent.append_child(name,pos=index) + def append_child(self,name,pos=None,verif='oui',retour='non'): + """ + Methode pour ajouter un objet fils à l'objet associé au noeud self. + On peut l'ajouter en début de liste (pos='first'), en fin (pos='last') + ou en position intermédiaire. + Si pos vaut None, on le place à la position du catalogue. + """ + #print "append_child",self,self.children + if pos == 'first': + index = 0 + elif pos == 'last': + index = len(self.children) + elif type(pos) == types.IntType : + # position fixee + index = pos + elif type(pos) == types.InstanceType: + # pos est un item. Il faut inserer name apres pos + index = self.item.get_index(pos) +1 + elif type(name) == types.InstanceType: + index = self.item.get_index_child(name.nom) + else: + index = self.item.get_index_child(name) + obj=self.item.additem(name,index) + #print obj + if obj is None:obj=0 + if obj == 0:return 0 + #print "append_child",index,self.children + child=self.children[index] + 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': @@ -694,14 +996,13 @@ class Node : child.select() if retour == 'oui': return child - def delete_node_child(self,child): + def delete_node_child_BAK(self,child): """ Supprime child des enfants de self et les id associés """ child.efface() - child.displayed = 0 self.children.remove(child) self.canvas.update() - def delete_child(self,child): + def delete_child_BAK(self,child): """ Supprime child des enfants de self, tous les id associés ET l'objet associé @@ -713,8 +1014,28 @@ class Node : return 0 def delete(self): + """ + Méthode externe pour la destruction de l'objet associé au noeud + La mise à jour des noeuds est faite par onSupp sur notification + """ + index = self.parent.children.index(self) - 1 + if index < 0 : index =0 + #print index + + ret=self.parent.item.suppitem(self.item) + if ret == 0:return + + brothers=self.parent.children + if brothers: + toselect=brothers[index] + else: + toselect=self.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() @@ -758,6 +1079,7 @@ class Node : Réalise la copie de l'objet passé en argument qui est nécessairement une commande """ + raise "OBSOLETE" child = self.append_brother(objet_a_copier,retour='oui') return child @@ -765,9 +1087,13 @@ class Node : # 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 : @@ -778,6 +1104,8 @@ class Node : 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() @@ -790,6 +1118,8 @@ class Node : 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: @@ -812,9 +1142,13 @@ class Node : 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/uniqueassdpanel.py b/Editeur/uniqueassdpanel.py index dbf16bef..89cf1341 100644 --- a/Editeur/uniqueassdpanel.py +++ b/Editeur/uniqueassdpanel.py @@ -63,13 +63,13 @@ class UNIQUE_ASSD_Panel(UNIQUE_Panel): self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée :"+mess) elif self.node.item.isvalid() : self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée') - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() - self.node.update() + #if self.node.item.get_position()=='global': + #self.node.etape.verif_all() + #elif self.node.item.get_position()=='global_jdc': + #self.node.racine.verif_all() + #else : + #self.node.parent.verif() + #self.node.update() else : cr = self.node.item.get_cr() mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal() diff --git a/Editeur/uniquepanel.py b/Editeur/uniquepanel.py index 74475aac..bb3f7a66 100644 --- a/Editeur/uniquepanel.py +++ b/Editeur/uniquepanel.py @@ -84,14 +84,14 @@ class UNIQUE_Panel(newSIMPPanel): self.parent.appli.affiche_infos("Valeur du mot-clé non autorisée : "+mess) elif self.node.item.isvalid() : self.parent.appli.affiche_infos('Valeur du mot-clé enregistrée') - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() - self.node.update() - self.node.parent.select() + #if self.node.item.get_position()=='global': + #self.node.etape.verif_all() + #elif self.node.item.get_position()=='global_jdc': + #self.node.racine.verif_all() + #else : + #self.node.parent.verif() + #self.node.update() + #self.node.parent.select() else : cr = self.node.item.get_cr() mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal() diff --git a/Editeur/uniquesdcopanel.py b/Editeur/uniquesdcopanel.py index 56b80cc8..e81d56e9 100644 --- a/Editeur/uniquesdcopanel.py +++ b/Editeur/uniquesdcopanel.py @@ -108,6 +108,7 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): """ if self.parent.modified == 'n' : self.parent.init_modif() valeur = self.get_valeur() + #print "valid_valeur",valeur self.erase_valeur() anc_val = self.node.item.get_valeur() @@ -136,19 +137,20 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal() self.reset_old_valeur(anc_val,mess=mess) return - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() - self.node.update() + #if self.node.item.get_position()=='global': + #self.node.etape.verif_all() + #elif self.node.item.get_position()=='global_jdc': + #self.node.racine.verif_all() + #else : + #self.node.parent.verif() + #self.node.update() def valid_nom_concept_co(self,event=None): """ Lit le nom donné par l'utilisateur au concept de type CO qui doit être la valeur du MCS courant et stocke cette valeur """ + #print "valid_nom_concept_co" if self.parent.modified == 'n' : self.parent.init_modif() anc_val = self.node.item.get_valeur() if anc_val != None: @@ -159,6 +161,7 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): # et le recalcul du contexte self.node.item.object.etape.parent.reset_context() nom_concept = self.entry_co.get() + #print "valid_nom_concept_co",nom_concept test,mess=self.node.item.set_valeur_co(nom_concept) if not test: # On n'a pas pu créer le concept @@ -172,15 +175,15 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): mess = "Valeur du mot-clé non autorisée :"+cr.get_mess_fatal() self.reset_old_valeur(anc_val,mess=mess) return - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() - if self.node.item.isvalid(): - self.node.parent.select() - self.node.update() + #if self.node.item.get_position()=='global': + #self.node.etape.verif_all() + #elif self.node.item.get_position()=='global_jdc': + #self.node.racine.verif_all() + #else : + #self.node.parent.verif() + #if self.node.item.isvalid(): + #self.node.parent.select() + #self.node.update() def ask_new_concept(self): """ @@ -211,12 +214,14 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): Affiche la valeur de l'objet pointé par self """ valeur = self.node.item.get_valeur() + #print "display_valeur",valeur if valeur == None or valeur == '': self.valeur_choisie.set('') return # pas de valeur à afficher ... # il faut configurer le bouton si la valeur est un objet CO # sinon afficher le nom du concept dans self.valeur_choisie if self.node.item.is_CO(): + #print "display_valeur.is_CO" self.b_co.invoke('OUI') self.entry_co.insert(0,valeur.nom) else: @@ -236,14 +241,14 @@ class UNIQUE_SDCO_Panel(UNIQUE_ASSD_Panel): self.parent.appli.affiche_infos(mess) # On met a jour le display dans le panneau self.display_valeur() - if self.node.item.get_position()=='global': - self.node.etape.verif_all() - elif self.node.item.get_position()=='global_jdc': - self.node.racine.verif_all() - else : - self.node.parent.verif() + #if self.node.item.get_position()=='global': + #self.node.etape.verif_all() + #elif self.node.item.get_position()=='global_jdc': + #self.node.racine.verif_all() + #else : + #self.node.parent.verif() if self.node.item.isvalid(): self.node.parent.select() - self.node.update() + #self.node.update() diff --git a/Editeur/widgets.py b/Editeur/widgets.py index 0f47fd2a..43f3dfd6 100644 --- a/Editeur/widgets.py +++ b/Editeur/widgets.py @@ -882,7 +882,7 @@ class ListeChoix : #except : #pass - def get_liste_old(self): + def get_liste_BAK(self): return self.liste # PN attention à la gestion des paramétres diff --git a/Extensions/commande_comm.py b/Extensions/commande_comm.py index 1bfca260..317bb6a3 100644 --- a/Extensions/commande_comm.py +++ b/Extensions/commande_comm.py @@ -22,8 +22,10 @@ import os,traceback,string from Noyau.N_CR import CR from Noyau.N_Exception import AsException +from Noyau import N_OBJECT +from Ihm import I_OBJECT -class COMMANDE_COMM: +class COMMANDE_COMM(N_OBJECT.OBJECT,I_OBJECT.OBJECT) : """ Cette classe sert à définir les objets de type Commande commentarisée """ @@ -191,13 +193,23 @@ class COMMANDE_COMM: #self.jdc.set_context() print 'erreurs fatales !!!' raise AsException("Erreurs fatales",string.join(J.cr.crfatal)) + if not J.etapes : + # des erreurs ont été rencontrées + raise AsException("Impossible reconstruire commande\n",str(J.cr)) #self.jdc.set_context() + new_etape = J.etapes[0] if new_etape.sd : nom_sd = new_etape.sd.nom else: nom_sd = None - return (new_etape.copy(),nom_sd) + #new_etape=new_etape.copy() + #print "uncomment",new_etape.sd + + pos=self.parent.etapes.index(self) + self.parent.addentite(new_etape,pos) + self.parent.suppentite(self) + return new_etape,nom_sd def active(self): """ diff --git a/Extensions/commentaire.py b/Extensions/commentaire.py index ea98bb3e..a504800b 100644 --- a/Extensions/commentaire.py +++ b/Extensions/commentaire.py @@ -24,8 +24,10 @@ """ from Noyau.N_CR import CR +from Noyau import N_OBJECT +from Ihm import I_OBJECT -class COMMENTAIRE : +class COMMENTAIRE(N_OBJECT.OBJECT,I_OBJECT.OBJECT) : """ Cette classe permet de créer des objets de type COMMENTAIRE """ diff --git a/Extensions/jdc_include.py b/Extensions/jdc_include.py index 2e2778d5..07a6c94e 100644 --- a/Extensions/jdc_include.py +++ b/Extensions/jdc_include.py @@ -28,27 +28,15 @@ avec le contexte avant et apres l'insertion """ from Accas import JDC,ASSD,AsException,JDC_CATA +from Ihm import CONNECTOR -class NOTIFIER: - def __init__(self): - self.subscribers=[] - - def subscribe(self,obj): - if not obj in self.subscribers: - self.subscribers.append(obj) - - def notify(self): - for obj in self.subscribers: - obj.notify(self) - -class JDC_POURSUITE(JDC,NOTIFIER): +class JDC_POURSUITE(JDC): def __init__(self,definition=None,procedure=None,cata=None, cata_ord_dico=None,parent=None, nom='SansNom',appli=None,context_ini=None, jdc_pere=None,etape_include=None,prefix_include=None, recorded_units=None,old_recorded_units=None,**args): - NOTIFIER.__init__(self) JDC.__init__(self, definition=definition, procedure=procedure, cata=cata, @@ -73,6 +61,7 @@ class JDC_POURSUITE(JDC,NOTIFIER): Si le nom est deja utilise, leve une exception Met le concept créé dans le contexe global g_context """ + #print "NommerSdprod",sd,sdnom,restrict if self.prefix_include: if sdnom != self.prefix_include:sdnom=self.prefix_include+sdnom o=self.sds_dict.get(sdnom,None) @@ -111,6 +100,7 @@ class JDC_POURSUITE(JDC,NOTIFIER): Si le contexte ne peut pas etre inséré, la méthode leve une exception sinon elle retourne le contexte inchangé """ + #print "verif_contexte" for nom_sd,sd in context.items(): if not isinstance(sd,ASSD):continue if self.jdc_pere.get_sd_apres_etape_avec_detruire(nom_sd,sd, @@ -144,7 +134,7 @@ class JDC_POURSUITE(JDC,NOTIFIER): mais par un appel à fin_modif pour préserver l'état modified de tous les objets entre temps """ - print "init_modif",self,self.etape_include + #print "jdc_include.init_modif",self,self.etape_include self.state = 'modified' self.etape_include.init_modif() @@ -154,9 +144,26 @@ class JDC_POURSUITE(JDC,NOTIFIER): déclencher d'éventuels traitements post-modification ex : INCLUDE et POURSUITE """ - print "fin_modif",self,self.etape_include + #print "jdc_include.fin_modif",self,self.etape_include + + # Mise a jour du contexte en fin d'include + # On suppose que toutes les modifications sont valides + # On recupere le contexte final dans j_context + j_context=self.get_contexte_avant(None) #get_verif_contexte ??? + # On remplit le dictionnaire des concepts produits de l'etape macro INCLUDE + # sans y mettre les concepts présents dans le contexte initial (context_ini) + # On ajoute egalement les concepts produits dans le sds_dict du parent + # sans verification car on est sur (verification integrée) que + # le nommage est possible + self.etape_include.g_context.clear() + for k,v in j_context.items(): + if not self.context_ini.has_key(k) or self.context_ini[k] != v: + self.etape_include.g_context[k]=v + self.etape_include.parent.sds_dict[k]=v + + CONNECTOR.Emit(self,"valid") self.etape_include.fin_modif() - self.notify() + #print "jdc_include.fin_modif.context_ini",self.context_ini def supprime(self): """ @@ -164,6 +171,86 @@ class JDC_POURSUITE(JDC,NOTIFIER): """ pass + def get_contexte_avant(self,etape): + """ + Retourne le dictionnaire des concepts connus avant etape + On tient compte des concepts produits par le jdc pere + en reactualisant le contexte initial context_ini + On tient compte des commandes qui modifient le contexte + comme DETRUIRE ou les macros + Si etape == None, on retourne le contexte en fin de JDC + """ + self.context_ini = self.etape_include.parent.get_contexte_avant(self.etape_include).copy() + return JDC.get_contexte_avant(self,etape) + + #def get_sd_avant_etape(self,nom_sd,etape): + #sd=self.etape_include.parent.get_sd_avant_etape(nom_sd,self.etape_include) + #if sd:return sd + #return JDC.get_sd_avant_etape(self,nom_sd,etape) + + #def get_sd_avant_du_bon_type(self,etape,types_permis): + #""" + # Retourne la liste des concepts avant etape d'un type acceptable + #""" + #l1=self.etape_include.parent.get_sd_avant_du_bon_type(self.etape_include,types_permis) + #l2=JDC.get_sd_avant_du_bon_type(self,etape,types_permis) + #return l1+l2 + + def get_sd_apres_etape(self,nom_sd,etape,avec='non'): + """ + Cette méthode retourne la SD de nom nom_sd qui est éventuellement + définie apres etape + Si avec vaut 'non' exclut etape de la recherche + """ + sd=self.etape_include.parent.get_sd_apres_etape(nom_sd,self.etape_include,'non') + if sd:return sd + return JDC.get_sd_apres_etape(self,nom_sd,etape,avec) + + def get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec='non'): + """ + On veut savoir ce que devient le concept sd de nom nom_sd apres etape. + Il peut etre detruit, remplacé ou conservé + Cette méthode retourne la SD sd de nom nom_sd qui est éventuellement + définie apres etape en tenant compte des concepts detruits + Si avec vaut 'non' exclut etape de la recherche + """ + autre_sd=JDC.get_sd_apres_etape_avec_detruire(self,nom_sd,sd,etape,avec) + if autre_sd is None or autre_sd is not sd :return autre_sd + return self.etape_include.parent.get_sd_apres_etape_avec_detruire(nom_sd,sd,self.etape_include,'non') + + def delete_concept(self,sd): + """ + Fonction : Mettre a jour les etapes du JDC suite à la disparition du + concept sd + Seuls les mots cles simples MCSIMP font un traitement autre + que de transmettre aux fils + """ + # Nettoyage des etapes de l'include + JDC.delete_concept(self,sd) + # Nettoyage des etapes du parent + self.etape_include.parent.delete_concept_after_etape(self.etape_include,sd) + + def delete_concept_after_etape(self,etape,sd): + """ + Fonction : Mettre à jour les étapes du JDC qui sont après etape suite à + la disparition du concept sd + """ + # Nettoyage des etapes de l'include + JDC.delete_concept_after_etape(self,etape,sd) + # Nettoyage des etapes du parent + self.etape_include.parent.delete_concept_after_etape(self.etape_include,sd) + + def replace_concept_after_etape(self,etape,old_sd,sd): + """ + Fonction : Mettre à jour les étapes du JDC qui sont après etape suite au + remplacement du concept old_sd par sd + """ + # Nettoyage des etapes de l'include + JDC.replace_concept_after_etape(self,etape,old_sd,sd) + # Nettoyage des etapes du parent + self.etape_include.parent.replace_concept_after_etape(self.etape_include,old_sd,sd) + + class JDC_INCLUDE(JDC_POURSUITE): def active_etapes(self): diff --git a/Extensions/parametre.py b/Extensions/parametre.py index 399a9063..7ec6ce70 100644 --- a/Extensions/parametre.py +++ b/Extensions/parametre.py @@ -32,8 +32,10 @@ from math import * # import de modules Eficas from Noyau.N_CR import CR +from Noyau import N_OBJECT +from Ihm import I_OBJECT -class PARAMETRE : +class PARAMETRE(N_OBJECT.OBJECT,I_OBJECT.OBJECT) : """ Cette classe permet de créer des objets de type PARAMETRE cad des affectations directes dans le jeu de commandes (ex: a=10.) diff --git a/Ihm/CONNECTOR.py b/Ihm/CONNECTOR.py new file mode 100644 index 00000000..09d1fbc1 --- /dev/null +++ b/Ihm/CONNECTOR.py @@ -0,0 +1,116 @@ +# -*- coding: iso-8859-15 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG +# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY +# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY +# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT +# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF +# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU +# GENERAL PUBLIC LICENSE FOR MORE DETAILS. +# +# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE +# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# +# +# ====================================================================== +""" + La classe CONNECTOR sert à enregistrer les observateurs d'objets et à délivrer + les messages émis à ces objets. + + Le principe général est le suivant : un objet (subscriber) s'enregistre aupres du + connecteur global (theconnector) pour observer un objet emetteur de messages (publisher) + sur un canal donné (channel). Il demande à etre notifie par appel d'une fonction (listener). + La séquence est donc : + + - enregistrement du subscriber pour le publisher : theconnector.Connect(publisher,channel,listener,args) + - émission du message par le publisher : theconnector.Emit(publisher,channel,cargs) + + args et cargs sont des tuples contenant les arguments de la fonction listener qui sera appelée + comme suit:: + + listener(cargs+args) +""" +import traceback +from copy import copy + +class CONNECTOR: + + def __init__(self): + self.connections={} + + def Connect(self, object, channel, function, args): + ###print "Connect",object, channel, function, args + idx = id(object) + if self.connections.has_key(idx): + channels = self.connections[idx] + else: + channels = self.connections[idx] = {} + + if channels.has_key(channel): + receivers = channels[channel] + else: + receivers = channels[channel] = [] + + info = (function, args) + if info in receivers: + receivers.remove(info) + receivers.append(info) + ###print "Connect",receivers + + + def Disconnect(self, object, channel, function, args): + try: + receivers = self.connections[id(object)][channel] + except KeyError: + raise ConnectorError, \ + 'no receivers for channel %s of %s' % (channel, object) + try: + receivers.remove((function, args)) + except ValueError: + 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 + try: + receivers = self.connections[id(object)][channel] + except KeyError: + return + ###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): + try: + apply(func, args + fargs) + except: + traceback.print_exc() + +_the_connector =CONNECTOR() +Connect = _the_connector.Connect +Emit = _the_connector.Emit +Disconnect = _the_connector.Disconnect + +if __name__ == "__main__": + class A:pass + class B: + def add(self,a): + print "add",a + + a=A() + b=B() + Connect(a,"add",b.add,()) + Emit(a,"add",1) diff --git a/Ihm/I_ETAPE.py b/Ihm/I_ETAPE.py index 0a9fe3f8..642964f4 100644 --- a/Ihm/I_ETAPE.py +++ b/Ihm/I_ETAPE.py @@ -37,6 +37,7 @@ from Noyau.N_Exception import AsException # Modules EFICAS import I_MCCOMPO +import CONNECTOR class ETAPE(I_MCCOMPO.MCCOMPO): @@ -70,7 +71,7 @@ class ETAPE(I_MCCOMPO.MCCOMPO): # La validité devra etre recalculée apres cette modification # mais dans l'appel à fin_modif pour préserver l'état modified # de tous les objets entre temps - print "init_modif",self,self.parent + #print "init_modif",self,self.parent self.state = 'modified' if self.parent: self.parent.init_modif() @@ -81,9 +82,14 @@ class ETAPE(I_MCCOMPO.MCCOMPO): déclencher d'éventuels traitements post-modification ex : INCLUDE et POURSUITE """ - print "fin_modif",self,self.parent + #print "fin_modif",self,self.parent + #if hasattr(self,'jdc_aux'):print "fin_modif",self.jdc_aux.context_ini if self.isvalid() : + #if hasattr(self,'jdc_aux'):print "fin_modif",self.jdc_aux.context_ini d=self.parent.get_contexte_apres(self) + #print d + #if hasattr(self,'jdc_aux'):print "fin_modif",self.jdc_aux.context_ini + CONNECTOR.Emit(self,"valid") if self.parent: self.parent.fin_modif() @@ -211,11 +217,13 @@ class ETAPE(I_MCCOMPO.MCCOMPO): """ if self.actif:return self.actif = 1 - if not self.sd : return - try: - self.jdc.append_sdprod(self.sd) - except: - pass + if self.sd : + try: + self.jdc.append_sdprod(self.sd) + except: + pass + CONNECTOR.Emit(self,"add",None) + CONNECTOR.Emit(self,"valid") def inactive(self): """ @@ -224,9 +232,11 @@ class ETAPE(I_MCCOMPO.MCCOMPO): et de la liste des sd """ self.actif = 0 - if not self.sd : return - self.jdc.del_sdprod(self.sd) - self.jdc.delete_concept_after_etape(self,self.sd) + if self.sd : + self.jdc.del_sdprod(self.sd) + self.jdc.delete_concept_after_etape(self,self.sd) + CONNECTOR.Emit(self,"supp",None) + CONNECTOR.Emit(self,"valid") def control_sdprods(self,d): """ @@ -236,7 +246,12 @@ class ETAPE(I_MCCOMPO.MCCOMPO): deja definis dans le contexte """ if type(self.definition.op_init) == types.FunctionType: - apply(self.definition.op_init,(self,d)) + try: + apply(self.definition.op_init,(self,d)) + except: + #traceback.print_exc() + pass + if self.sd: if d.has_key(self.sd.nom): # Le concept est deja defini @@ -261,6 +276,7 @@ class ETAPE(I_MCCOMPO.MCCOMPO): Une procedure n'en a aucun Une macro en a en général plus d'un """ + #print "supprime_sdprods",self if not self.is_reentrant() : # l'étape n'est pas réentrante # le concept retourné par l'étape est à supprimer car il était @@ -334,6 +350,7 @@ class ETAPE(I_MCCOMPO.MCCOMPO): Vérifie que les structures de données utilisées dans self existent bien dans le contexte avant étape, sinon enlève la référence à ces concepts """ + #print "verif_existence_sd",self.sd for motcle in self.mc_liste : motcle.verif_existence_sd() @@ -370,6 +387,7 @@ class ETAPE(I_MCCOMPO.MCCOMPO): if self.parent : self.jdc = self.parent.get_jdc_root() self.id= self.parent.register(self) + self.UserError=self.jdc.UserError if self.definition.niveau : # La définition est dans un niveau. En plus on # l'enregistre dans le niveau @@ -384,4 +402,5 @@ class ETAPE(I_MCCOMPO.MCCOMPO): self.jdc = self.parent =None self.id=None self.niveau=None + self.UserError="UserError" diff --git a/Ihm/I_JDC.py b/Ihm/I_JDC.py index 53e30030..734ffde2 100644 --- a/Ihm/I_JDC.py +++ b/Ihm/I_JDC.py @@ -30,6 +30,7 @@ from Noyau.N_ASSD import ASSD from Noyau.N_ETAPE import ETAPE from Noyau.N_Exception import AsException from Extensions import commentaire,parametre,parametre_eval +import CONNECTOR class JDC(I_OBJECT.OBJECT): """ @@ -44,6 +45,12 @@ class JDC(I_OBJECT.OBJECT): self.recorded_units={} self.old_recorded_units={} + def get_index(self,objet): + """ + Retourne la position d'objet dans la liste self + """ + return self.etapes.index(objet) + def get_sd_avant_du_bon_type(self,etape,types_permis): """ Retourne la liste des concepts avant etape d'un type acceptable @@ -100,6 +107,7 @@ class JDC(I_OBJECT.OBJECT): self.etapes.insert(pos,objet) self.editmode=0 self.active_etapes() + CONNECTOR.Emit(self,"add",objet) self.fin_modif() return objet elif name == "PARAMETRE": @@ -112,6 +120,7 @@ class JDC(I_OBJECT.OBJECT): self.editmode=0 self.reset_context() self.active_etapes() + CONNECTOR.Emit(self,"add",objet) self.fin_modif() return objet elif name == "PARAMETRE_EVAL": @@ -124,6 +133,7 @@ class JDC(I_OBJECT.OBJECT): self.editmode=0 self.reset_context() self.active_etapes() + CONNECTOR.Emit(self,"add",objet) self.fin_modif() return objet elif type(name)==types.InstanceType: @@ -132,7 +142,9 @@ class JDC(I_OBJECT.OBJECT): # on est donc nécessairement en mode editeur ... objet = name # Il ne faut pas oublier de reaffecter le parent d'obj (si copie) + #if hasattr(objet,'sd'):print "addentite",objet.sd objet.reparent(self) + #if hasattr(objet,'sd'):print "addentite",objet.sd self.set_current_step() if isinstance(objet,ETAPE): if objet.nom_niveau_definition == 'JDC': @@ -146,11 +158,13 @@ class JDC(I_OBJECT.OBJECT): self.etapes.insert(pos,objet) # il faut vérifier que les concepts utilisés par objet existent bien # à ce niveau d'arborescence + #if hasattr(objet,'sd'):print "addentite",objet.sd objet.verif_existence_sd() self.active_etapes() self.editmode=0 self.reset_context() - print "addentite",self.etapes + #print "addentite",self.etapes + CONNECTOR.Emit(self,"add",objet) self.fin_modif() return objet else : @@ -168,7 +182,8 @@ class JDC(I_OBJECT.OBJECT): self.editmode=0 self.reset_context() self.active_etapes() - print "addentite",self.etapes + #print "addentite",self.etapes + CONNECTOR.Emit(self,"add",e) self.fin_modif() return e except AsException,e: @@ -296,10 +311,12 @@ class JDC(I_OBJECT.OBJECT): Retourne 1 si la suppression a pu être effectuée, Retourne 0 dans le cas contraire """ + #print "suppentite",self self.init_modif() # On memorise le contexte avant l'etape a supprimer d=self.get_contexte_avant(etape) index_etape=self.etapes.index(etape) + #print "suppentite",index_etape,d self.etapes.remove(etape) if etape.niveau is not self: @@ -315,6 +332,7 @@ class JDC(I_OBJECT.OBJECT): e.control_sdprods(d) self.reset_context() + CONNECTOR.Emit(self,"supp",etape) self.fin_modif() return 1 @@ -396,14 +414,23 @@ class JDC(I_OBJECT.OBJECT): Méthode appelée au moment où une modification va être faite afin de déclencher d'éventuels traitements pré-modification """ - print "init_modif",self + #print "init_modif",self self.state = 'modified' def fin_modif(self): - print "fin_modif",self + #print "fin_modif",self + CONNECTOR.Emit(self,"valid") self.isvalid() pass + def deep_update_condition_bloc(self): + # pour le moment, on ne fait rien + raise "Not implemented" + + def update_condition_bloc(self): + # pour le moment, on ne fait rien + raise "Not implemented" + def get_liste_mc_inconnus(self): """ Retourne une liste contenant les mots-clés inconnus à la relecture du JDC @@ -456,6 +483,10 @@ class JDC(I_OBJECT.OBJECT): """ Supprime la SD sd de la liste des sd et des dictionnaires de contexte """ + #print "del_sdprod",self,sd + #print "del_sdprod",self.sds + #print "del_sdprod",self.g_context + #print "del_sdprod",self.sds_dict if sd in self.sds : self.sds.remove(sd) if self.g_context.has_key(sd.nom) : del self.g_context[sd.nom] if self.sds_dict.has_key(sd.nom) : del self.sds_dict[sd.nom] @@ -518,6 +549,7 @@ class JDC(I_OBJECT.OBJECT): Seuls les mots cles simples MCSIMP font un traitement autre que de transmettre aux fils """ + #print "delete_concept",self,sd for etape in self.etapes : etape.delete_concept(sd) diff --git a/Ihm/I_MACRO_ETAPE.py b/Ihm/I_MACRO_ETAPE.py index a87db51a..c79ae36b 100644 --- a/Ihm/I_MACRO_ETAPE.py +++ b/Ihm/I_MACRO_ETAPE.py @@ -32,6 +32,7 @@ from Noyau.N_ASSD import ASSD import Noyau, Validation.V_MACRO_ETAPE from Noyau import N_Exception from Noyau.N_Exception import AsException +import Accas # attention aux imports circulaires # fin import à résorber class MACRO_ETAPE(I_ETAPE.ETAPE): @@ -63,10 +64,13 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): ou leve une exception --> utilisée par ops.POURSUITE et INCLUDE """ - print "get_contexte_jdc" + #print "get_contexte_jdc" try: # on essaie de créer un objet JDC auxiliaire avec un contexte initial - context_ini = self.parent.get_contexte_avant(self) + # Attention get_contexte_avant retourne un dictionnaire qui contient + # le contexte courant. Ce dictionnaire est reactualise regulierement. + # Si on veut garder l'etat du contexte fige, il faut en faire une copie. + context_ini = self.parent.get_contexte_avant(self).copy() # Indispensable avant de creer un nouveau JDC CONTEXT.unset_current_step() @@ -98,7 +102,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # On récupère les étapes internes (pour validation) self.etapes=j.etapes self.jdc_aux=j - print "get_contexte_jdc",id(self.etapes) + #print "get_contexte_jdc",id(self.etapes) except: traceback.print_exc() # On force le contexte (etape courante) à self @@ -125,6 +129,8 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # Si aucune erreur rencontrée # On recupere le contexte de l'include verifie + #print "context_ini",j.context_ini + #print "g_context",j.g_context try: j_context=j.get_verif_contexte() except: @@ -132,6 +138,8 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): CONTEXT.set_current_step(self) raise + #print "context_ini",j.context_ini + # On remplit le dictionnaire des concepts produits inclus # en retirant les concepts présents dans le contexte initial # On ajoute egalement le concept produit dans le sds_dict du parent @@ -153,6 +161,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # On rétablit le contexte (etape courante) à self CONTEXT.unset_current_step() CONTEXT.set_current_step(self) + #print "context_ini",self.jdc_aux.context_ini return j_context @@ -161,6 +170,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): Avec la liste des SD qui ont été supprimées, propage la disparition de ces SD dans toutes les étapes et descendants """ + #print "reevalue_sd_jdc" l_sd_supp,l_sd_repl = self.diff_contextes() for sd in l_sd_supp: self.parent.delete_concept_after_etape(self,sd) @@ -230,12 +240,12 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): def supprime_sdprods(self): """ - Fonction: - Lors d'une destruction d'etape, detruit tous les concepts produits + Fonction: Lors de la destruction de la macro-etape, detruit tous les concepts produits Un opérateur n a qu un concept produit Une procedure n'en a aucun Une macro en a en général plus d'un """ + #print "supprime_sdprods" if not self.is_reentrant() : # l'étape n'est pas réentrante # le concept retourné par l'étape est à supprimer car il était @@ -254,13 +264,118 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.parent.delete_concept(co) # On met g_context à blanc self.g_context={} + + def delete_concept(self,sd): + """ + Fonction : Mettre a jour les mots cles de l etape et eventuellement + le concept produit si reuse suite à la disparition du concept sd + Seuls les mots cles simples MCSIMP font un traitement autre + que de transmettre aux fils + """ + #print "delete_concept",sd + I_ETAPE.ETAPE.delete_concept(self,sd) + for etape in self.etapes: + etape.delete_concept(sd) + + def replace_concept(self,old_sd,sd): + """ + Fonction : Mettre a jour les mots cles de l etape et le concept produit si reuse + suite au remplacement du concept old_sd par sd + """ + #print "replace_concept",old_sd,sd + I_ETAPE.ETAPE.replace_concept(self,old_sd,sd) + for etape in self.etapes: + etape.replace_concept(sd) + def change_fichier_init(self,new_fic,text): + """ + Tente de changer le fichier include. Le precedent include est conservé + dans old_xxx + """ + if not hasattr(self,'fichier_ini'): + self.fichier_ini=None + self.fichier_text=None + self.fichier_err="Le fichier n'est pas defini" + self.contexte_fichier_init={} + self.recorded_units={} + self.jdc_aux=None + self.fichier_unite="PasDefini" + import Extensions.jdc_include + self.JdC_aux=Extensions.jdc_include.JdC_include + + self.old_fic = self.fichier_ini + self.old_text = self.fichier_text + self.old_err = self.fichier_err + self.old_context=self.contexte_fichier_init + self.old_units=self.recorded_units + self.old_etapes=self.etapes + self.old_jdc_aux=self.jdc_aux + + self.fichier_ini = new_fic + self.fichier_text=text + + try: + self.make_contexte_include(new_fic,text) + except: + l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1]) + self.fichier_err=string.join(l) + raise + + # L'evaluation de text dans un JDC auxiliaire s'est bien passé + # on peut poursuivre le traitement + self.init_modif() + self.state="undetermined" + self.fichier_err=None + # On enregistre la modification de fichier + self.record_unite() + # Le contexte du parent doit etre reinitialise car les concepts produits ont changé + self.parent.reset_context() + + # Si des concepts ont disparu lors du changement de fichier, on demande leur suppression + self.old_contexte_fichier_init=self.old_context + self.reevalue_sd_jdc() + + self.fin_modif() + + def restore_fichier_init(self): + """ + Restaure le fichier init enregistre dans old_xxx + """ + self.fichier_ini=self.old_fic + self.fichier_text=self.old_text + self.fichier_err=self.old_err + self.contexte_fichier_init=self.old_context + self.recorded_units=self.old_units + self.etapes=self.old_etapes + self.jdc_aux=self.old_jdc_aux + + def force_fichier_init(self): + """ + Force le fichier init en erreur + """ + # On conserve la memoire du nouveau fichier + # mais on n'utilise pas les concepts crees par ce fichier + # on met l'etape en erreur : fichier_err=string.join(l) + self.init_modif() + # On enregistre la modification de fichier + self.record_unite() + #self.etapes=[] + self.g_context={} + # Le contexte du parent doit etre reinitialise car les concepts produits ont changé + self.parent.reset_context() + + self.old_contexte_fichier_init=self.old_context + self.contexte_fichier_init={} + self.reevalue_sd_jdc() + + self.fin_modif() + def make_contexte_include(self,fichier,text): """ Cette méthode sert à créer un contexte en interprétant un texte source Python """ - print "make_contexte_include" + #print "make_contexte_include" # on récupère le contexte d'un nouveau jdc dans lequel on interprete text contexte = self.get_contexte_jdc(fichier,text) if contexte == None : @@ -275,8 +390,9 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # contexte_fichier_init est utilisé pour avoir les concepts supprimés par la macro self.contexte_fichier_init = contexte - def reevalue_fichier_init(self): + def reevalue_fichier_init_OBSOLETE(self): """Recalcule les concepts produits par le fichier enregistre""" + #print "reevalue_fichier_init" old_context=self.contexte_fichier_init try: self.make_contexte_include(self.fichier_ini ,self.fichier_text) @@ -295,13 +411,14 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.fichier_err = None self.old_contexte_fichier_init=old_context self.reevalue_sd_jdc() + #print "reevalue_fichier_init",self.jdc_aux.context_ini def update_fichier_init(self,unite): """Reevalue le fichier init sans demander (dans la mesure du possible) a l'utilisateur les noms des fichiers Ceci suppose que les relations entre unites et noms ont été memorisees préalablement """ - print "update_fichier_init",unite + #print "update_fichier_init",unite self.fichier_err=None self.old_contexte_fichier_init=self.contexte_fichier_init old_fichier_ini=self.fichier_ini @@ -339,6 +456,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): if old_fichier_ini == self.fichier_ini: # Le fichier inclus n'a pas changé. On ne recrée pas le contexte + #print "update_fichier_init.fichier inchange",self.jdc_aux.context_ini return try: @@ -363,6 +481,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): # Si des concepts ont disparu lors du changement de fichier, on # demande leur suppression self.reevalue_sd_jdc() + #print "update_fichier_init",self.jdc_aux.context_ini def record_unite(self): if self.nom == "POURSUITE": @@ -421,7 +540,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): Sinon on retourne None. Les concepts produits par l'INCLUDE sont pris en compte par le JDC parent lors du calcul du contexte (appel de ???) """ - print "make_include",unite + #print "make_include",unite # On supprime l'attribut unite qui bloque l'evaluation du source de l'INCLUDE # car on ne s'appuie pas sur lui dans EFICAS mais sur l'attribut fichier_ini del self.unite @@ -452,6 +571,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): try: self.make_contexte_include(self.fichier_ini ,self.fichier_text) self.parent.record_unit(unite,self) + #print "make_include.context_ini",self.jdc_aux.context_ini except: l=traceback.format_exception_only("Fichier invalide",sys.exc_info()[1]) if self.jdc.appli: @@ -544,7 +664,7 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): def make_poursuite(self): """ Cette methode est appelée par la fonction sd_prod de la macro POURSUITE """ - print "make_poursuite" + #print "make_poursuite" if not hasattr(self,'fichier_ini') : # Si le fichier n'est pas defini on le demande f,text=self.get_file_memo(fic_origine=self.parent.nom) @@ -587,3 +707,103 @@ class MACRO_ETAPE(I_ETAPE.ETAPE): self.update_fichier_init(None) if self.fichier_err is not None: raise Exception(self.fichier_err) +#ATTENTION SURCHARGE: cette methode surcharge celle de Noyau a garder en synchro + def type_sdprod(self,co,t): + """ + Cette methode a pour fonction de typer le concept co avec le type t + dans les conditions suivantes + 1- co est un concept produit de self + 2- co est un concept libre : on le type et on l attribue à self + Elle enregistre egalement les concepts produits (on fait l hypothese + que la liste sdprods a été correctement initialisee, vide probablement) + """ + #print "type_sdprod",co,t + if not hasattr(co,'etape'): + # Le concept vaut None probablement. On ignore l'appel + return + # + # On cherche a discriminer les differents cas de typage d'un concept + # produit par une macro qui est specifie dans un mot cle simple. + # On peut passer plusieurs fois par type_sdprod ce qui explique + # le nombre important de cas. + # + # Cas 1 : Le concept est libre. Il vient d'etre cree par CO(nom) + # Cas 2 : Le concept est produit par la macro. On est deja passe par type_sdprod. + # Cas semblable a Cas 1. + # Cas 3 : Le concept est produit par la macro englobante (parent). On transfere + # la propriete du concept de la macro parent a la macro courante (self) + # en verifiant que le type est valide + # Cas 4 : La concept est la propriete d'une etape fille. Ceci veut dire qu'on est + # deja passe par type_sdprod et que la propriete a ete transfere a une + # etape fille. Cas semblable a Cas 3. + # Cas 5 : Le concept est produit par une etape externe a la macro. + # + if co.etape == None: + # Cas 1 : le concept est libre + # On l'attache a la macro et on change son type dans le type demande + # Recherche du mot cle simple associe au concept + mcs=self.get_mcs_with_co(co) + if len(mcs) != 1: + raise AsException("""Erreur interne. +Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co) + mcs=mcs[0] + # + # Attention : la seule modif est ici : Accas.CO au lieu de CO + # + if not Accas.CO in mcs.definition.type: + raise AsException("""Erreur interne. +Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type)) + co.etape=self + co.__class__ = t + self.sdprods.append(co) + + elif co.etape== self: + # Cas 2 : le concept est produit par la macro (self) + # On est deja passe par type_sdprod (Cas 1 ou 3). + # Il suffit de le mettre dans la liste des concepts produits (self.sdprods) + # Le type du concept doit etre coherent avec le type demande (seulement derive) + if not isinstance(co,t): + raise AsException("""Erreur interne. +Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__)) + self.sdprods.append(co) + + elif co.etape== self.parent: + # Cas 3 : le concept est produit par la macro parente (self.parent) + # on transfere la propriete du concept a la macro fille + # et on change le type du concept comme demande + # Au prealable, on verifie que le concept existant (co) est une instance + # possible du type demande (t) + # Cette règle est normalement cohérente avec les règles de vérification des mots-clés + if not isinstance(co,t): + raise AsException(""" +Impossible de changer le type du concept produit (%s) en (%s). +Le type actuel (%s) devrait etre une classe derivee du nouveau type (%s)""" % (co,t,co.__class__,t)) + mcs=self.get_mcs_with_co(co) + if len(mcs) != 1: + raise AsException("""Erreur interne. +Il ne devrait y avoir qu'un seul mot cle porteur du concept CO (%s)""" % co) + mcs=mcs[0] + if not Accas.CO in mcs.definition.type: + raise AsException("""Erreur interne. +Impossible de changer le type du concept (%s). Le mot cle associe ne supporte pas CO mais seulement (%s)""" %(co,mcs.definition.type)) + co.etape=self + # On ne change pas le type car il respecte la condition isinstance(co,t) + #co.__class__ = t + self.sdprods.append(co) + + elif self.issubstep(co.etape): + # Cas 4 : Le concept est propriété d'une sous etape de la macro (self). + # On est deja passe par type_sdprod (Cas 3 ou 1). + # Il suffit de le mettre dans la liste des concepts produits (self.sdprods) + # Le type du concept et t doivent etre derives. + # Il n'y a aucune raison pour que la condition ne soit pas verifiee. + if not isinstance(co,t): + raise AsException("""Erreur interne. +Le type demande (%s) et le type du concept (%s) devraient etre derives""" %(t,co.__class__)) + self.sdprods.append(co) + + else: + # Cas 5 : le concept est produit par une autre étape + # On ne fait rien + return + diff --git a/Ihm/I_MCCOMPO.py b/Ihm/I_MCCOMPO.py index a50345b8..af50e342 100644 --- a/Ihm/I_MCCOMPO.py +++ b/Ihm/I_MCCOMPO.py @@ -22,6 +22,7 @@ """ import string,types from copy import copy +import traceback from Noyau.N_MCLIST import MCList from Noyau.N_MCSIMP import MCSIMP @@ -29,6 +30,8 @@ from Noyau.N_MCFACT import MCFACT from Noyau.N_MCBLOC import MCBLOC import I_OBJECT +import CONNECTOR + class MCCOMPO(I_OBJECT.OBJECT): def getlabeltext(self): """ @@ -134,6 +137,21 @@ class MCCOMPO(I_OBJECT.OBJECT): l.append(k) return l + def get_index_child(self,nom_fils): + """ + Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils + Permet de savoir à quelle position il faut ajouter un nouveau mot-clé + """ + cata_ordonne = self.jdc.cata_ordonne_dico + liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(self.get_genealogie(),cata_ordonne) + liste_noms_mc_presents = self.liste_mc_presents() + index=0 + for nom in liste_noms_mc_ordonnee: + if nom == nom_fils:break + if nom not in liste_noms_mc_presents :continue + index=index+1 + return index + def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee): """ Retourne liste_mc_a_ordonner ordonnée suivant l'ordre @@ -164,12 +182,19 @@ class MCCOMPO(I_OBJECT.OBJECT): return 0 try : + self.mc_liste.remove(objet) + CONNECTOR.Emit(self,"supp",objet) + if hasattr(objet.definition,'position'): - if objet.definition.position == 'global' : + if objet.definition.position == 'global' : self.delete_mc_global(objet) - elif objet.definition.position == 'global_jdc' : + self.etape.deep_update_condition_bloc() + elif objet.definition.position == 'global_jdc' : self.delete_mc_global_jdc(objet) - self.mc_liste.remove(objet) + self.jdc.deep_update_condition_bloc() + else: + self.update_condition_bloc() + self.fin_modif() return 1 except: @@ -184,6 +209,7 @@ 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 @@ -211,15 +237,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 # 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) self.fin_modif() return objet else: @@ -245,21 +276,14 @@ class MCCOMPO(I_OBJECT.OBJECT): # 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à - if not old_obj.ajout_possible(): - self.jdc.send_message("L'objet %s ne peut pas être répété" %objet.nom) - self.fin_modif() - return 0 - if objet.isMCList(): - objet=objet.data[0] - old_obj.append(objet) - # Il ne faut pas oublier de reaffecter le parent d'obj - objet.reparent(self) - self.fin_modif() + old_obj.addentite(objet) return old_obj def ispermis(self,fils): @@ -287,17 +311,6 @@ class MCCOMPO(I_OBJECT.OBJECT): if fils.parent.nom != self.nom : return 0 return 1 - def liste_mc_presents(self): - """ - Retourne la liste des noms des mots-clés fils de self présents - construite à partir de self.mc_liste - """ - l=[] - for v in self.mc_liste: - k=v.nom - l.append(k) - return l - def delete_concept(self,sd): """ Inputs : @@ -356,6 +369,40 @@ class MCCOMPO(I_OBJECT.OBJECT): l_mc.append(l) return l_mc + def deep_update_condition_bloc(self): + """ + 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() + 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 + """ + #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 + globs= self.jdc and self.jdc.condition_context or {} + bloc=self.get_child(k,restreint = 'oui') + presence=v.verif_presence(dict,globs) + if presence and not bloc: + # le bloc doit être présent + # mais le bloc n'est pas présent et il doit être créé + #print "AJOUT BLOC",k + pos=self.get_index_child(k) + self.addentite(k,pos) + if not presence and bloc: + # le bloc devrait être absent + # le bloc est présent : il faut l'enlever + #print "SUPPRESSION BLOC",k,bloc + self.suppentite(bloc) + def verif_condition_bloc(self): """ Evalue les conditions de tous les blocs fils possibles @@ -366,7 +413,7 @@ class MCCOMPO(I_OBJECT.OBJECT): """ liste_ajouts = [] liste_retraits = [] - dict = self.cree_dict_condition(self.mc_liste) + dict = self.cree_dict_condition(self.mc_liste,condition=1) for k,v in self.definition.entites.items(): if v.label=='BLOC' : globs= self.jdc and self.jdc.condition_context or {} diff --git a/Ihm/I_MCFACT.py b/Ihm/I_MCFACT.py index 6acd8c93..49a3b44f 100644 --- a/Ihm/I_MCFACT.py +++ b/Ihm/I_MCFACT.py @@ -18,7 +18,9 @@ # # # ====================================================================== +import CONNECTOR import I_MCCOMPO + class MCFACT(I_MCCOMPO.MCCOMPO): def isrepetable(self): """ @@ -55,3 +57,26 @@ class MCFACT(I_MCCOMPO.MCCOMPO): except: return "Erreur - mot clé facteur de nom: "+self.nom + def init_modif(self): + """ + Met l'état de l'objet à modified et propage au parent + qui vaut None s'il n'existe pas + """ + self.state = 'modified' + parent= hasattr(self,"alt_parent") and self.alt_parent or self.parent + if parent: + parent.init_modif() + + def fin_modif(self): + """ + Méthode appelée après qu'une modification a été faite afin de déclencher + d'éventuels traitements post-modification + """ + #print "fin_modif",self + # pour les objets autres que les commandes, aucun traitement spécifique + # on remonte l'info de fin de modif au parent + CONNECTOR.Emit(self,"valid") + parent= hasattr(self,"alt_parent") and self.alt_parent or self.parent + if parent: + parent.fin_modif() + diff --git a/Ihm/I_MCLIST.py b/Ihm/I_MCLIST.py index c9442374..f15824cb 100644 --- a/Ihm/I_MCLIST.py +++ b/Ihm/I_MCLIST.py @@ -18,7 +18,9 @@ # # # ====================================================================== +import types,traceback from copy import copy +import CONNECTOR class MCList: def isMCList(self): @@ -64,7 +66,48 @@ class MCList: Une MCList n'est jamais obligatoire (même si le MCFACT qu'elle représente l'est """ return self.data[0].definition.statut=='o' - #return 0 + + def suppentite(self,obj): + """ + Supprime le mot cle facteur obj de la MCLIST + """ + self.init_modif() + self.remove(obj) + CONNECTOR.Emit(self,"supp",obj) + self.fin_modif() + return 1 + + def addentite(self,obj,pos=None): + """ + Ajoute le mot cle facteur obj a la MCLIST a la position pos + Retourne None si l'ajout est impossible + """ + if type(obj)==types.StringType : + # on est en mode création d'un motcle + raise "traitement non prevu" + + if not self.ajout_possible(): + self.jdc.send_message("L'objet %s ne peut pas être ajouté" % obj.nom) + return None + + if self.nom != obj.nom: + return None + + if obj.isMCList(): + obj=obj.data[0] + + # Traitement du copier coller seulement + # Les autres cas d'ajout sont traites dans MCFACT + self.init_modif() + obj.verif_existence_sd() + obj.reparent(self.parent) + if pos is None: + self.append(obj) + else: + self.insert(pos,obj) + CONNECTOR.Emit(self,"add",obj) + self.fin_modif() + return obj def liste_mc_presents(self): return [] @@ -117,6 +160,16 @@ class MCList: # Sans objet pour une liste de mots clés facteurs return [] + def deep_update_condition_bloc(self): + """ + 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 verif_condition_bloc(self): """ Evalue les conditions de tous les blocs fils possibles @@ -125,7 +178,7 @@ class MCList: - la première contient les noms des blocs à rajouter - la seconde contient les noms des blocs à supprimer """ - # Sans objet pour une liste de mots clés facteurs + # Sans objet pour une liste de mots clés facteurs (a voir !!!) return [],[] def init_modif(self): @@ -142,6 +195,8 @@ class MCList: Méthode appelée après qu'une modification a été faite afin de déclencher d'éventuels traitements post-modification """ + #print "fin_modif",self + CONNECTOR.Emit(self,"valid") if self.parent: self.parent.fin_modif() diff --git a/Ihm/I_MCSIMP.py b/Ihm/I_MCSIMP.py index 5cb84cbe..83e9bb29 100644 --- a/Ihm/I_MCSIMP.py +++ b/Ihm/I_MCSIMP.py @@ -40,10 +40,12 @@ from Noyau.N_utils import repr_float from Noyau.N_ASSD import ASSD,assd from Noyau.N_GEOM import GEOM,geom from Noyau.N_CO import CO +import Accas # fin attention from Extensions import parametre import I_OBJECT +import CONNECTOR class MCSIMP(I_OBJECT.OBJECT): @@ -215,10 +217,62 @@ class MCSIMP(I_OBJECT.OBJECT): def isoblig(self): return self.definition.statut=='o' + def valid_valeur(self,new_valeur): + """ + Verifie que la valeur passee en argument (new_valeur) est valide + sans modifier la valeur courante (evite d'utiliser set_valeur et est plus performant) + """ + old_valeur=self.valeur + old_val=self.val + self.valeur = new_valeur + self.val = new_valeur + self.state="modified" + validite=self.isvalid() + self.valeur = old_valeur + self.val = old_valeur + self.state="modified" + self.isvalid() + return validite + + def valid_valeur_partielle(self,new_valeur): + """ + Verifie que la valeur passee en argument (new_valeur) est partiellement valide + sans modifier la valeur courante (evite d'utiliser set_valeur et est plus performant) + """ + old_valeur=self.valeur + old_val=self.val + + self.valeur = new_valeur + self.val = new_valeur + self.state="modified" + validite=0 + if self.isvalid(): + validite=1 + elif self.definition.validators : + validite=self.definition.validators.valide_liste_partielle(new_valeur) + + if validite==0: + min,max=self.get_min_max() + if len(new_valeur) < min : + validite=1 + + self.valeur = old_valeur + self.val = old_valeur + self.state="modified" + self.isvalid() + return validite + 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.fin_modif() return 1 @@ -227,14 +281,15 @@ class MCSIMP(I_OBJECT.OBJECT): Essaie d'évaluer new_valeur comme une SD, une déclaration Python ou un EVAL: Retourne la valeur évaluée (ou None) et le test de réussite (1 ou 0) """ - sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None) + #print "eval_valeur",new_valeur + sd = self.jdc.get_sd_avant_etape(new_valeur,self.etape) + #sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None) if sd : return sd,1 else: d={} # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ?? - from Accas import EVAL - d['EVAL']=EVAL + d['EVAL']=Accas.EVAL try : objet = eval(new_valeur,d) return objet,1 @@ -267,20 +322,24 @@ class MCSIMP(I_OBJECT.OBJECT): Met a jour la valeur du mot cle simple suite à la disparition du concept sd """ + #print "delete_concept",sd if type(self.valeur) == types.TupleType : if sd in self.valeur: + self.init_modif() self.valeur=list(self.valeur) self.valeur.remove(sd) - self.init_modif() + self.fin_modif() elif type(self.valeur) == types.ListType: if sd in self.valeur: - self.valeur.remove(sd) self.init_modif() + self.valeur.remove(sd) + self.fin_modif() else: if self.valeur == sd: + self.init_modif() self.valeur=None self.val=None - self.init_modif() + self.fin_modif() def replace_concept(self,old_sd,sd): """ @@ -291,34 +350,36 @@ class MCSIMP(I_OBJECT.OBJECT): Met a jour la valeur du mot cle simple suite au remplacement du concept old_sd """ + #print "replace_concept",old_sd,sd if type(self.valeur) == types.TupleType : if old_sd in self.valeur: + self.init_modif() self.valeur=list(self.valeur) i=self.valeur.index(old_sd) self.valeur[i]=sd - self.init_modif() + self.fin_modif() elif type(self.valeur) == types.ListType: if old_sd in self.valeur: + self.init_modif() i=self.valeur.index(old_sd) self.valeur[i]=sd - self.init_modif() + self.fin_modif() else: if self.valeur == old_sd: + self.init_modif() self.valeur=sd self.val=sd - self.init_modif() + self.fin_modif() def set_valeur_co(self,nom_co): """ Affecte à self l'objet de type CO et de nom nom_co """ + #print "set_valeur_co",nom_co step=self.etape.parent if nom_co == None or nom_co == '': new_objet=None else: - # Pour le moment on importe en local le CO de Accas. - # Si problème de perfs, il faudra faire autrement - from Accas import CO # Avant de créer un concept il faut s'assurer du contexte : step # courant sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui') @@ -335,7 +396,7 @@ class MCSIMP(I_OBJECT.OBJECT): CONTEXT.unset_current_step() CONTEXT.set_current_step(step) step.set_etape_context(self.etape) - new_objet = CO(nom_co) + new_objet = Accas.CO(nom_co) CONTEXT.unset_current_step() CONTEXT.set_current_step(cs) self.init_modif() @@ -346,6 +407,7 @@ class MCSIMP(I_OBJECT.OBJECT): # On force l'enregistrement de new_objet en tant que concept produit # de la macro en appelant get_type_produit avec force=1 self.etape.get_type_produit(force=1) + #print "set_valeur_co",new_objet return 1,"Concept créé" def verif_existence_sd(self): @@ -353,9 +415,12 @@ class MCSIMP(I_OBJECT.OBJECT): Vérifie que les structures de données utilisées dans self existent bien dans le contexte avant étape, sinon enlève la référence à ces concepts """ + #print "verif_existence_sd" + # Attention : possible probleme avec include l_sd_avant_etape = self.jdc.get_contexte_avant(self.etape).values() if type(self.valeur) in (types.TupleType,types.ListType) : l=[] + self.init_modif() for sd in self.valeur: if isinstance(sd,ASSD) : if sd in l_sd_avant_etape : @@ -363,15 +428,12 @@ class MCSIMP(I_OBJECT.OBJECT): else: l.append(sd) self.valeur=tuple(l) - # Est ce init_modif ou init_modif_up - # Normalement init_modif va avec fin_modif - self.init_modif() self.fin_modif() else: if isinstance(self.valeur,ASSD) : if self.valeur not in l_sd_avant_etape : - self.valeur = None self.init_modif() + self.valeur = None self.fin_modif() def get_min_max(self): diff --git a/Ihm/I_OBJECT.py b/Ihm/I_OBJECT.py index eb00f2a9..0f4d28ea 100644 --- a/Ihm/I_OBJECT.py +++ b/Ihm/I_OBJECT.py @@ -29,7 +29,8 @@ try: lang=prefs.lang except: lang='fr' - + +import CONNECTOR class OBJECT: from Noyau.N_CO import CO @@ -66,8 +67,10 @@ class OBJECT: Méthode appelée après qu'une modification a été faite afin de déclencher d'éventuels traitements post-modification """ + #print "fin_modif",self # pour les objets autres que les commandes, aucun traitement spécifique # on remonte l'info de fin de modif au parent + CONNECTOR.Emit(self,"valid") if self.parent: self.parent.fin_modif() diff --git a/generator/generator_python.py b/generator/generator_python.py index d24071ac..0fbf2c71 100644 --- a/generator/generator_python.py +++ b/generator/generator_python.py @@ -89,7 +89,8 @@ class PythonGenerator: Si format vaut 'standard', retourne un texte obtenu par concaténation de la liste Si format vaut 'beautifie', retourne le meme texte beautifié """ - self.appli=obj.appli + self.appli=obj.get_jdc_root().appli + #self.appli=obj.appli liste= self.generator(obj) if format == 'brut': self.text=liste diff --git a/generator/generator_python6.py b/generator/generator_python6.py index 49c6aba4..f9e01c8b 100644 --- a/generator/generator_python6.py +++ b/generator/generator_python6.py @@ -73,7 +73,6 @@ class PythonGenerator(generator_python.PythonGenerator): """ Méthode particulière pour les objets de type FORMULE """ - print "coucou" l=[] nom = obj.get_nom() if nom == '' : nom = 'sansnom' -- 2.30.2