1 # -*- coding: utf-8 -*-
2 # CONFIGURATION MANAGEMENT OF EDF VERSION
3 # ======================================================================
4 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
5 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
6 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
7 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
8 # (AT YOUR OPTION) ANY LATER VERSION.
10 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
11 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
12 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
13 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
15 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
16 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
17 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
20 # ======================================================================
22 Ce module contient la classe BUREAU qui gere les JDC ouverts
28 from widgets import askopenfilename,asksaveasfilename
29 from widgets import showinfo,askyesno,showerror
37 from jdcdisplay import JDCDISPLAY
38 from utils import extension_fichier,stripPath,save_in_file
39 from widgets import Fenetre,Ask_Format_Fichier
40 from fenetre_mc_inconnus import fenetre_mc_inconnus
45 ('Nouveau','newJDC','<Control-n>'),
46 ('Ouvrir','openJDC','<Control-o>'),
47 ('Enregistrer','saveJDC','<Control-e>'),
48 ('Enregistrer sous','saveasJDC','<Control-s>'),
50 ('Fermer','closeJDC','<Control-f>'),
51 ('Quitter','exitEFICAS','<Control-q>'),
55 ('Copier','copy','<Control-c>'),
56 ('Couper','cut','<Control-x>'),
57 ('Coller','paste','<Control-v>'),
61 ('Rapport de validation','visuCRJDC','<Control-r>'),
62 ('Fichier à plat','visu_a_plat','<Control-p>'),
63 ('Fichier .py','visuJDC_py'),
64 ('Fichier source','visu_txt_brut_JDC','<Control-b>'),
65 ('Paramètres Eficas','affichage_fichier_ini'),
66 ('Mots-clés inconnus','mc_inconnus'),
70 ('Aide EFICAS','aideEFICAS'),
75 button_defs = (('New24',"newJDC","Création d'un nouveau fichier",'always'),
76 ('Open24',"openJDC","Ouverture d'un fichier existant",'always'),
77 ('Save24',"saveJDC","Sauvegarde du fichier courant",'always'),
78 ('Zoom24',"visuJDC","Visualisation du fichier de commandes",'always'),
80 ('Copy24',"copy","Copie l'objet courant",'jdc'),
81 ('Cut24',"cut","Coupe l'objet courant",'jdc'),
82 ('Paste24',"paste","Colle l'objet copié après l'objet courant",'jdc'),
84 ('Delete24',"delete","Supprime l'objet courant",'jdc'),
85 ('Help24',"view_doc","Documentation de l'objet courant",'jdc')
88 menu_defs=prefs.menu_defs['bureau']
92 button_defs=prefs.button_defs['bureau']
96 def __init__(self,appli,parent):
99 splash._splash.configure(text = "Création du bureau")
100 self.nb = Pmw.NoteBook(self.parent,raisecommand=self.selectJDC)
101 self.nb.pack(fill='both',expand=1)
102 self.JDCDisplay_courant=None
104 self.liste_JDCDisplay=[]
107 def cree_cataitem(self):
109 On récupère dans l'appli_composant readercata les variables
110 qui servent par la suite pour la création des JDC
112 self.cataitem=self.appli.readercata.cataitem
113 self.cata=self.appli.readercata.cata
114 self.cata_ordonne_dico=self.appli.readercata.cata_ordonne_dico
115 self.code=self.appli.readercata.code
116 self.version_code=self.appli.readercata.version_code
117 self.fic_cata=self.appli.readercata.fic_cata
119 def selectJDC(self,event=None):
121 Cette méthode est appelée chaque fois que l'on sélectionne
122 l'onglet d'un JDC dans le NoteBook des JDC.
123 Elle permet de stocker dans les variable self.JDC et
124 self.JDCDisplay_courant les valeurs concernant le JDC courant
126 if len(self.liste_JDCDisplay) == 0 : return
127 #if self.JDCDisplay_courant : self.JDCDisplay_courant.jdc.unset_context()
128 numero_jdc = self.nb.index(self.nb.getcurselection())
129 self.JDCDisplay_courant = self.liste_JDCDisplay[numero_jdc]
130 self.JDC = self.JDCDisplay_courant.jdc
131 #self.JDC.set_context()
132 self.JDCName = self.JDC.nom
134 def newJDC(self,event=None):
136 Initialise un nouveau JDC vierge
138 self.appli.statusbar.reset_affichage_infos()
140 CONTEXT.unset_current_step()
141 J=self.cata[0].JdC(cata=self.cata,
142 cata_ord_dico=self.cata_ordonne_dico,
144 rep_mat=self.appli.CONFIGURATION.rep_mat,
148 self.ShowJDC(J,self.JDCName)
149 self.appli.toolbar.active_boutons()
151 def ShowJDC(self,JDC,nom,label_onglet=None):
153 Lance l'affichage du JDC cad création du JDCDisplay
154 Rajoute le JDCDisplay à la liste des JDCDisplay si label_onglet == None cad si on crée
155 bien un nouveau JDCDisplay et non si on remplace (renommage de l'onglet)
158 self.JDCName = self.JDC.nom = nom
159 #XXX CCAR: pour le moment mis en commentaire
160 #self.JDC.set_context()
161 if label_onglet == None :
162 label_onglet = self.GetLabelJDC()
163 self.nb.add(label_onglet,tab_text = nom,tab_width=20)
167 self.JDCDisplay_courant=JDCDISPLAY(self.JDC,nom,appli=self.appli,parent=self.nb.page(label_onglet))
169 self.liste_JDCDisplay.append(self.JDCDisplay_courant)
170 self.JDCDisplay_courant.modified='n'
171 self.JDCDisplay_courant.fichier=self.fileName
172 self.nb.selectpage(label_onglet)
173 self.nb.setnaturalsize()
174 texte = "Jeu de commandes :" + self.JDCName+" ouvert"
175 self.appli.affiche_infos(texte)
177 def closeJDC (self,event=None) :
179 Ferme le JDC courant et détruit l'onglet associé dans le notebook self.nb
181 if self.JDCDisplay_courant.modified == 'o' :
182 message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
183 reponse = askyesno(title="Sauvegarde du jdc courant",
186 test = self.saveJDC()
188 self.appli.affiche_infos("Sauvegarde impossible")
190 self.JDCDisplay_courant.jdc.supprime()
191 self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
192 self.nb.delete(self.nb.getcurselection())
193 #XXX CCAR: pour le moment mis en commentaire
194 #self.JDC.unset_context()
197 index = self.nb.index(self.nb.getcurselection())
198 self.JDCDisplay_courant = self.liste_JDCDisplay[index]
199 self.JDC = self.JDCDisplay_courant.jdc
201 self.JDCDisplay_courant = None
202 self.appli.toolbar.inactive_boutons()
204 def visuCRJDC(self,event=None):
205 return self.visuCR(mode='JDC')
207 def visuCR(self,mode):
209 Méthode permettant l'affichage du rapport de validation
212 if not hasattr(self,'JDC') : return
213 titre="rapport de validation du jeu de commandes courant"
214 cr = self.JDC.report()
215 self.update_jdc_courant()
217 from Noyau.N_CR import CR
219 cr.debut = "Début rapport de validation du catalogue"
220 cr.fin = "Fin rapport de validation du catalogue"
221 titre="rapport de validation du catalogue"
222 if hasattr(self,'cata_ordonne_cr') :
223 cr.add(self.cata_ordonne_cr)
224 if hasattr(self,'cata_dev_ordonne_cr') :
225 cr.add(self.cata_dev_ordonne_cr)
226 for cata in self.cata:
227 if hasattr(cata,'JdC'):
228 cr.add(cata.JdC.report())
230 self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
232 def openJDC(self,file=None):
234 Demande à l'utilisateur quel JDC existant il veut ouvrir
236 if self.code == 'ASTER':
237 filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
238 elif self.code == 'HOMARD' :
239 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),("Tous",'*'))
241 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
242 if not hasattr(self,'initialdir'):
243 #self.initialdir = self.appli.CONFIGURATION.rep_user
244 self.initialdir = self.appli.CONFIGURATION.initialdir
245 if file.__class__.__name__ in ('Event',):
248 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
249 defaultextension=".comm",
250 filetypes = filetypes,
251 initialdir = self.initialdir)
254 e=extension_fichier(file)
255 self.JDCName=stripPath(file)
256 self.initialdir = os.path.dirname(file)
259 #XXX CCAR: pour le moment mis en commentaire
260 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
262 format=self.appli.format_fichier.get()
263 # Il faut convertir le contenu du fichier en fonction du format
264 if convert.plugins.has_key(format):
265 # Le convertisseur existe on l'utilise
266 p=convert.plugins[format]()
268 text=p.convert('exec')
269 if not p.cr.estvide():
270 self.appli.affiche_infos("Erreur à la conversion")
272 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
273 texte = str(p.cr)).wait()
276 # Il n'existe pas c'est une erreur
277 self.appli.affiche_infos("Type de fichier non reconnu")
278 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
281 # On se met dans le repertoire ou se trouve le fichier de commandes
282 # pour trouver les eventuels fichiers include ou autres
283 # localises a cote du fichier de commandes
284 os.chdir(self.initialdir)
285 CONTEXT.unset_current_step()
286 J=self.cata[0].JdC(procedure=text,appli=self.appli,
287 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
289 rep_mat=self.appli.CONFIGURATION.rep_mat,
292 txt_exception = J.cr.get_mess_exception()
294 # des exceptions ont été levées à la création du JDC
295 # --> on affiche les erreurs mais pas le JDC
296 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
297 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
299 self.ShowJDC(J,self.JDCName)
300 self.appli.toolbar.active_boutons()
301 # si le JDC ne contient rien (vide), on retourne ici
302 if len(self.JDC.etapes) == 0 : return
303 # dans le cas où le JDC est invalide, on affiche son CR
304 if not self.JDC.isvalid():
305 self.appli.top.update()
306 self.visuCR(mode='JDC')
309 def GetLabelJDC(self,nb_jdc = 'absent'):
311 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
313 if nb_jdc == 'absent':
314 nb_jdc = len(self.nb.pagenames())
316 label_onglet = 'JDC'+`nb_jdc`
317 if label_onglet not in self.nb.pagenames() :
320 return self.GetLabelJDC(nb_jdc)
322 def saveasJDC(self,event=None):
324 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
325 donner le nom du fichier de sauvegarde
327 self.saveJDC(echo='oui')
329 def saveJDC(self,echo='non'):
331 Sauvegarde le JDC courant.
332 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
333 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
335 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
337 if not hasattr(self,'JDC') : return 0
338 format=self.appli.format_fichier.get()
339 if generator.plugins.has_key(format):
340 # Le generateur existe on l'utilise
341 g=generator.plugins[format]()
342 jdc_formate=g.gener(self.JDC,format='beautifie')
343 if format == 'homard':
344 self.jdc_homard=g.get_homard()
345 if not g.cr.estvide():
347 self.appli.affiche_infos("Erreur à la generation")
348 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
351 # Il n'existe pas c'est une erreur
352 self.appli.affiche_infos("Format %s non reconnu" % format)
353 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
355 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
357 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
358 return self.asknomsauvegardeJDC()
359 elif self.JDCDisplay_courant.fichier != None :
361 # Pour sauvegarde dans l etude si lancement depuis salome
362 if self.appli.salome != 0:
364 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
365 from panelsSalome import SALOME_UNIQUE_BASE_Panel
366 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
367 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
368 #PN Fin Ajout --> Salome
369 # le JDC a déjà un nom : on sauvegarde directement sans demander
370 # un autre nom au développeur
371 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
372 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
375 if self.appli.format_fichier.get() == 'homard':
376 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
377 self.JDCDisplay_courant.stop_modif()
378 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
381 def asknomsauvegardeJDC(self):
382 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
383 titre = "Sauvegarde d'un fichier de commandes "+self.code
384 if self.code == 'ASTER':
386 filtyp = ( ("ASTER", ".comm"),)
389 filtyp = ( (self.code, ".py"),)
390 sauvegarde = asksaveasfilename(title=titre,
391 defaultextension=defext,
393 initialdir = self.appli.CONFIGURATION.initialdir)
394 #initialdir = self.appli.CONFIGURATION.rep_user)
396 # PN ajout --> Salome
397 # Pour sauvegarde dans l etude si lancement depuis salome
398 if self.appli.salome != 0:
400 self.appli.salome.rangeInStudy(sauvegarde)
401 from panelsSalome import SALOME_UNIQUE_BASE_Panel
402 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
403 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
404 # PN fin ajout --> Salome
405 if not save_in_file(sauvegarde,self.jdc_fini) :
406 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
409 if self.appli.format_fichier.get() == 'homard':
410 self.save_homard(sauvegarde,self.jdc_homard)
411 self.JDCDisplay_courant.stop_modif()
412 self.appli.affiche_infos("Sauvegarde effectuée")
413 if sauvegarde != self.JDCDisplay_courant.fichier :
414 # l'utilisateur a sauvegardé le JDC sous un autre nom
415 self.JDCDisplay_courant.fichier = sauvegarde
416 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
422 def changeNomPage(self):
423 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
424 et recrée un autre onglet à la même place avec le bon nom
427 self.JDCDisplay_courant.jdc.nom = nom
428 nom_page = self.nb.getcurselection()
429 num_page = self.nb.index(nom_page)
430 tab = self.nb.tab(num_page)
431 tab.configure(text = nom)
433 def exitEFICAS(self,event=None):
435 Permet de sortir d'EFICAS en demandant à l'utilisateur
436 s'il veut sauvegarder les modifications en cours
438 liste = self.GetListeJDCaSauvegarder()
440 # Certains fichiers n'ont pas été sauvegardés ...
441 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
442 test = self.saveall(liste)
445 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
446 for JDCDisplay in self.liste_JDCDisplay:
447 JDCDisplay.jdc.supprime()
451 def GetListeJDCaSauvegarder(self) :
452 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
453 if not self.JDCDisplay_courant : return []
454 if len(self.liste_JDCDisplay) == 0 : return l
456 for JDCDisplay in self.liste_JDCDisplay:
457 if JDCDisplay.modified == 'o' :
461 def copy(self,event=None):
463 Lance la copie sur le JDC courant
465 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
467 def paste(self,event=None):
469 Lance le collage sur le JDC courant
471 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
473 def cut(self,event=None):
475 Lance le cut sur le JDC courant
477 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
481 Lance la suppression du noeud courant
483 if not self.JDCDisplay_courant : return
485 if self.JDCDisplay_courant.modified == 'n' :
486 self.JDCDisplay_courant.init_modif()
487 pere = self.JDCDisplay_courant.node_selected.parent
488 # Le noeud n'est pas au 1er niveau
489 if pere.parent.parent != None:
490 self.JDCDisplay_courant.node_selected.delete()
493 noeudselecte = self.JDCDisplay_courant.node_selected
494 parent = noeudselecte.parent
495 enfants = parent.children
496 index = enfants.index(noeudselecte)
497 self.JDCDisplay_courant.node_selected.delete()
499 enfants[index].select()
501 enfants[index-1].select()
502 except AttributeError:
505 def visuJDC_py(self):
507 Méthode permettant d'afficher dans une fenêtre à part l'écho au
508 format python du jdc courant
510 if not hasattr(self,'JDC') : return
511 jdc_fini = self.get_text_JDC('python')
512 if jdc_fini == None : return
514 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
519 Méthode permettant d'afficher dans une fenêtre à part l'écho au
520 format .comm ou .py du jdc courant
522 if not hasattr(self,'JDC') : return
523 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
524 format=self.appli.format_fichier.get()
525 self.jdc_fini = self.get_text_JDC(format)
526 if self.jdc_fini == None : return
527 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
529 def get_text_JDC(self,format):
530 if generator.plugins.has_key(format):
531 # Le generateur existe on l'utilise
532 g=generator.plugins[format]()
533 jdc_formate=g.gener(self.JDC,format='beautifie')
534 if not g.cr.estvide():
536 self.appli.affiche_infos("Erreur à la generation")
537 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
542 # Il n'existe pas c'est une erreur
543 self.appli.affiche_infos("Format %s non reconnu" % format)
544 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
549 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
550 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
551 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
553 if not self.JDCDisplay_courant : return
555 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
556 if cle_doc == None : return
557 cle_doc = string.replace(cle_doc,'.','')
558 cle_doc = string.replace(cle_doc,'-','')
559 commande = self.appli.CONFIGURATION.exec_acrobat
560 nom_fichier = cle_doc+".pdf"
561 rep_fichier = cle_doc[0:2]
562 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
564 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
565 elif os.name == 'posix':
566 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
567 pid = os.system(script)
568 except AttributeError:
569 traceback.print_exc()
572 def visu_a_plat(self,event=None):
574 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
576 if not hasattr(self,'JDC') : return
577 titre = 'fichier '+ self.JDCName + ' à plat '
578 self.jdc_fini = self.get_text_JDC('aplat')
579 if self.jdc_fini == None : return
580 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
582 def visu_txt_brut_JDC(self,event=None):
584 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
586 if not hasattr(self,'JDC') : return
587 titre = "fichier de commandes utilisateur"
588 #texte = self.JDC.procedure
590 if self.JDCDisplay_courant.fichier == None:
591 self.appli.affiche_infos("Pas de fichier initial")
592 showerror("Impossible de visualiser le fichier initial",
593 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
595 f=open(self.JDCDisplay_courant.fichier,'r')
598 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
600 def affichage_fichier_ini(self):
602 Affichage des valeurs des paramètres relus par Eficas
604 self.appli.CONFIGURATION.affichage_fichier_ini()
606 def saveall(self,liste):
608 Sauvegarde tous les JDC contenus dans liste
611 for JDCDisplay in liste :
612 self.JDC = JDCDisplay.jdc
613 test = test * self.saveJDC(echo = 'non')
616 def save_homard(self,nom,texte):
617 file_homard=nom+'.conf_homard'
619 f=open(file_homard,'w')
625 print "Pb a la sauvegarde sous le format homard"
626 if self.appli.salome != 0:
628 self.appli.salome.rangeInStudy(file_homard)
630 # ---------------------------------------------------------------------------
631 # Méthodes liées aux mots-clés inconnus
632 # ---------------------------------------------------------------------------
634 def mc_inconnus(self):
635 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
636 o = fenetre_mc_inconnus(l_mc)
637 l = o.wait_new_list()
638 #print "mc_inconnus_new_list: ",l
639 #CCAR: Il n' y a pas de retour vers le JDC
641 def aideEFICAS(self,event=None):
642 AIDE.go(master=self.parent)
644 def update_jdc_courant(self):
645 self.JDCDisplay_courant.update()