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
47 ('Nouveau','newJDC','<Control-n>'),
48 ('Ouvrir','openJDC','<Control-o>'),
49 ('Enregistrer','saveJDC','<Control-e>'),
50 ('Enregistrer sous','saveasJDC','<Control-s>'),
52 ('Fermer','closeJDC','<Control-f>'),
53 ('Quitter','exitEFICAS','<Control-q>'),
57 ('Copier','copy','<Control-c>'),
58 ('Couper','cut','<Control-x>'),
59 ('Coller','paste','<Control-v>'),
63 ('Rapport de validation','visuCRJDC','<Control-r>'),
64 ('Fichier à plat','visu_a_plat','<Control-p>'),
65 ('Fichier .py','visuJDC_py'),
66 ('Fichier source','visu_txt_brut_JDC','<Control-b>'),
67 ('Paramètres Eficas','affichage_fichier_ini'),
68 ('Mots-clés inconnus','mc_inconnus'),
72 ('Aide EFICAS','aideEFICAS'),
77 button_defs = (('New24',"newJDC","Création d'un nouveau fichier",'always'),
78 ('Open24',"openJDC","Ouverture d'un fichier existant",'always'),
79 ('Save24',"saveJDC","Sauvegarde du fichier courant",'always'),
80 ('Zoom24',"visuJDC","Visualisation du fichier de commandes",'always'),
82 ('Copy24',"copy","Copie l'objet courant",'jdc'),
83 ('Cut24',"cut","Coupe l'objet courant",'jdc'),
84 ('Paste24',"paste","Colle l'objet copié après l'objet courant",'jdc'),
86 ('Delete24',"delete","Supprime l'objet courant",'jdc'),
87 ('Help24',"view_doc","Documentation de l'objet courant",'jdc')
90 menu_defs=prefs.menu_defs['bureau']
94 button_defs=prefs.button_defs['bureau']
98 def __init__(self,appli,parent):
101 if self.appli.test == 0 :
102 splash._splash.configure(text = "Création du bureau")
103 self.nb = Pmw.NoteBook(self.parent,raisecommand=self.selectJDC)
104 self.nb.pack(fill='both',expand=1)
105 self.JDCDisplay_courant=None
107 self.liste_JDCDisplay=[]
108 comploader.charger_composants()
112 def cree_cataitem(self):
114 On récupère dans l'appli_composant readercata les variables
115 qui servent par la suite pour la création des JDC
117 self.cataitem=self.appli.readercata.cataitem
118 self.cata=self.appli.readercata.cata
119 self.cata_ordonne_dico=self.appli.readercata.cata_ordonne_dico
120 self.code=self.appli.readercata.code
121 self.version_code=self.appli.readercata.version_code
122 self.fic_cata=self.appli.readercata.fic_cata
124 def selectJDC(self,event=None):
126 Cette méthode est appelée chaque fois que l'on sélectionne
127 l'onglet d'un JDC dans le NoteBook des JDC.
128 Elle permet de stocker dans les variable self.JDC et
129 self.JDCDisplay_courant les valeurs concernant le JDC courant
131 if len(self.liste_JDCDisplay) == 0 : return
132 #if self.JDCDisplay_courant : self.JDCDisplay_courant.jdc.unset_context()
133 numero_jdc = self.nb.index(self.nb.getcurselection())
134 self.JDCDisplay_courant = self.liste_JDCDisplay[numero_jdc]
135 self.JDC = self.JDCDisplay_courant.jdc
136 #self.JDC.set_context()
137 self.JDCName = self.JDC.nom
139 def newJDC(self,event=None):
141 Initialise un nouveau JDC vierge
143 self.appli.statusbar.reset_affichage_infos()
145 CONTEXT.unset_current_step()
146 J=self.cata[0].JdC(cata=self.cata,
147 cata_ord_dico=self.cata_ordonne_dico,
149 rep_mat=self.appli.CONFIGURATION.rep_mat,
153 self.ShowJDC(J,self.JDCName)
154 self.appli.toolbar.active_boutons()
156 def ShowJDC(self,JDC,nom,label_onglet=None,JDCDISPLAY=JDCDISPLAY):
158 Lance l'affichage du JDC cad création du JDCDisplay
159 Rajoute le JDCDisplay à la liste des JDCDisplay si label_onglet == None cad si on crée
160 bien un nouveau JDCDisplay et non si on remplace (renommage de l'onglet)
163 self.JDCName = self.JDC.nom = nom
164 if label_onglet == None :
165 # On veut un nouvel onglet
166 label_onglet = self.GetLabelJDC()
167 self.nb.add(label_onglet,tab_text = nom,tab_width=20)
171 self.JDCDisplay_courant=JDCDISPLAY(self.JDC,nom,appli=self.appli,parent=self.nb.page(label_onglet))
173 self.liste_JDCDisplay.append(self.JDCDisplay_courant)
174 self.JDCDisplay_courant.modified='n'
175 self.JDCDisplay_courant.fichier=self.fileName
176 self.nb.selectpage(label_onglet)
177 self.nb.setnaturalsize()
178 texte = "Jeu de commandes :" + self.JDCName+" ouvert"
179 self.appli.affiche_infos(texte)
181 def closeJDC (self,event=None) :
183 Ferme le JDC courant et détruit l'onglet associé dans le notebook self.nb
185 if self.JDCDisplay_courant == None:
187 if self.JDCDisplay_courant.modified == 'o' :
188 message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
189 reponse = askyesno(title="Sauvegarde du jdc courant",
192 test = self.saveJDC()
194 self.appli.affiche_infos("Sauvegarde impossible")
196 self.JDCDisplay_courant.jdc.supprime()
197 self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
198 self.nb.delete(self.nb.getcurselection())
199 #XXX CCAR: pour le moment mis en commentaire
200 #self.JDC.unset_context()
203 index = self.nb.index(self.nb.getcurselection())
204 self.JDCDisplay_courant = self.liste_JDCDisplay[index]
205 self.JDC = self.JDCDisplay_courant.jdc
207 self.JDCDisplay_courant = None
208 self.appli.toolbar.inactive_boutons()
210 def visuCRJDC(self,event=None):
211 return self.visuCR(mode='JDC')
213 def visuCR(self,mode):
215 Méthode permettant l'affichage du rapport de validation
218 if not hasattr(self,'JDC') : return
219 titre="rapport de validation du jeu de commandes courant"
220 cr = self.JDC.report()
221 self.update_jdc_courant()
223 from Noyau.N_CR import CR
225 cr.debut = "Début rapport de validation du catalogue"
226 cr.fin = "Fin rapport de validation du catalogue"
227 titre="rapport de validation du catalogue"
228 if hasattr(self,'cata_ordonne_cr') :
229 cr.add(self.cata_ordonne_cr)
230 if hasattr(self,'cata_dev_ordonne_cr') :
231 cr.add(self.cata_dev_ordonne_cr)
232 for cata in self.cata:
233 if hasattr(cata,'JdC'):
234 cr.add(cata.JdC.report())
236 self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
238 def openJDC(self,file=None,units=None):
240 Demande à l'utilisateur quel JDC existant il veut ouvrir
242 if self.code == 'ASTER':
243 filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
244 elif self.code == 'HOMARD' :
245 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),("Tous",'*'))
247 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
248 if not hasattr(self,'initialdir'):
249 #self.initialdir = self.appli.CONFIGURATION.rep_user
250 self.initialdir = self.appli.CONFIGURATION.initialdir
252 if file.__class__.__name__ in ('Event',):
256 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
257 defaultextension=".comm",
258 filetypes = filetypes,
259 initialdir = self.initialdir)
262 e=extension_fichier(file)
263 self.JDCName=stripPath(file)
264 self.initialdir = os.path.dirname(os.path.abspath(file))
268 format=self.appli.format_fichier.get()
269 # Il faut convertir le contenu du fichier en fonction du format
270 if convert.plugins.has_key(format):
271 # Le convertisseur existe on l'utilise
272 p=convert.plugins[format]()
274 text=p.convert('exec',self.appli)
275 if not p.cr.estvide():
276 self.appli.affiche_infos("Erreur à la conversion")
278 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
279 texte = str(p.cr)).wait()
282 # Il n'existe pas c'est une erreur
283 self.appli.affiche_infos("Type de fichier non reconnu")
284 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
287 # On se met dans le repertoire ou se trouve le fichier de commandes
288 # pour trouver les eventuels fichiers include ou autres
289 # localises a cote du fichier de commandes
290 os.chdir(self.initialdir)
291 CONTEXT.unset_current_step()
292 J=self.cata[0].JdC(procedure=text,appli=self.appli,
293 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
295 rep_mat=self.appli.CONFIGURATION.rep_mat,
297 if units is not None:
298 J.recorded_units=units
299 J.old_recorded_units=units
302 txt_exception = J.cr.get_mess_exception()
304 # des exceptions ont été levées à la création du JDC
305 # --> on affiche les erreurs mais pas le JDC
306 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
307 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
309 self.ShowJDC(J,self.JDCName)
310 self.appli.toolbar.active_boutons()
311 # si le JDC ne contient rien (vide), on retourne ici
312 if len(self.JDC.etapes) == 0 : return
313 # dans le cas où le JDC est invalide, on affiche son CR
314 if not self.JDC.isvalid():
315 self.appli.top.update()
316 self.visuCR(mode='JDC')
319 def GetLabelJDC(self,nb_jdc = 'absent'):
321 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
323 if nb_jdc == 'absent':
324 nb_jdc = len(self.nb.pagenames())
326 label_onglet = 'JDC'+`nb_jdc`
327 if label_onglet not in self.nb.pagenames() :
330 return self.GetLabelJDC(nb_jdc)
332 def saveasJDC(self,event=None):
334 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
335 donner le nom du fichier de sauvegarde
337 self.saveJDC(echo='oui')
339 def saveJDC(self,echo='non'):
341 Sauvegarde le JDC courant.
342 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
343 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
345 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
347 if not hasattr(self,'JDC') : return 0
348 format=self.appli.format_fichier.get()
349 if generator.plugins.has_key(format):
350 # Le generateur existe on l'utilise
351 g=generator.plugins[format]()
352 jdc_formate=g.gener(self.JDC,format='beautifie')
353 if format == 'homard':
354 self.jdc_homard=g.get_homard()
355 if not g.cr.estvide():
357 self.appli.affiche_infos("Erreur à la generation")
358 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
361 # Il n'existe pas c'est une erreur
362 self.appli.affiche_infos("Format %s non reconnu" % format)
363 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
365 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
367 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
368 return self.asknomsauvegardeJDC()
369 elif self.JDCDisplay_courant.fichier != None :
371 # Pour sauvegarde dans l etude si lancement depuis salome
372 if self.appli.salome != 0:
374 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
375 from panelsSalome import SALOME_UNIQUE_BASE_Panel
376 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
377 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
381 MyCLinit=eficasCL.CLinit()
386 #PN Fin Ajout --> Salome
387 # le JDC a déjà un nom : on sauvegarde directement sans demander
388 # un autre nom au développeur
389 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
390 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
393 if self.appli.format_fichier.get() == 'homard':
394 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
395 self.JDCDisplay_courant.stop_modif()
396 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
399 def asknomsauvegardeJDC(self):
400 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
401 titre = "Sauvegarde d'un fichier de commandes "+self.code
402 if self.code == 'ASTER':
404 filtyp = ( ("ASTER", ".comm"),)
407 filtyp = ( (self.code, ".py"),)
408 sauvegarde = asksaveasfilename(title=titre,
409 defaultextension=defext,
411 initialdir = self.appli.CONFIGURATION.initialdir)
412 #initialdir = self.appli.CONFIGURATION.rep_user)
414 # PN ajout --> Salome
415 # Pour sauvegarde dans l etude si lancement depuis salome
416 if self.appli.salome != 0:
418 self.appli.salome.rangeInStudy(sauvegarde)
419 from panelsSalome import SALOME_UNIQUE_BASE_Panel
420 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
421 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
425 MyCLinit=eficasCL.CLinit()
430 # PN fin ajout --> Salome
431 if not save_in_file(sauvegarde,self.jdc_fini) :
432 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
435 if self.appli.format_fichier.get() == 'homard':
436 self.save_homard(sauvegarde,self.jdc_homard)
437 self.JDCDisplay_courant.stop_modif()
438 self.appli.affiche_infos("Sauvegarde effectuée")
439 if sauvegarde != self.JDCDisplay_courant.fichier :
440 # l'utilisateur a sauvegardé le JDC sous un autre nom
441 self.JDCDisplay_courant.fichier = sauvegarde
442 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
448 def changeNomPage(self):
449 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
450 et recrée un autre onglet à la même place avec le bon nom
453 self.JDCDisplay_courant.jdc.nom = nom
454 nom_page = self.nb.getcurselection()
455 num_page = self.nb.index(nom_page)
456 tab = self.nb.tab(num_page)
457 tab.configure(text = nom)
459 def exitEFICAS(self,event=None):
461 Permet de sortir d'EFICAS en demandant à l'utilisateur
462 s'il veut sauvegarder les modifications en cours
464 liste = self.GetListeJDCaSauvegarder()
466 # Certains fichiers n'ont pas été sauvegardés ...
467 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
468 test = self.saveall(liste)
471 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
472 for JDCDisplay in self.liste_JDCDisplay:
473 JDCDisplay.jdc.supprime()
477 def GetListeJDCaSauvegarder(self) :
478 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
479 if not self.JDCDisplay_courant : return []
480 if len(self.liste_JDCDisplay) == 0 : return l
482 for JDCDisplay in self.liste_JDCDisplay:
483 if JDCDisplay.modified == 'o' :
487 def copy(self,event=None):
489 Lance la copie sur le JDC courant
491 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
493 def paste(self,event=None):
495 Lance le collage sur le JDC courant
497 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
499 def cut(self,event=None):
501 Lance le cut sur le JDC courant
503 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
507 Lance la suppression du noeud courant
509 if not self.JDCDisplay_courant : return
511 if self.JDCDisplay_courant.modified == 'n' :
512 self.JDCDisplay_courant.init_modif()
513 pere = self.JDCDisplay_courant.node_selected.parent
514 # Le noeud n'est pas au 1er niveau
515 if pere.parent.parent != None:
516 self.JDCDisplay_courant.node_selected.delete()
519 noeudselecte = self.JDCDisplay_courant.node_selected
520 parent = noeudselecte.parent
521 enfants = parent.children
522 index = enfants.index(noeudselecte)
523 self.JDCDisplay_courant.node_selected.delete()
525 enfants[index].select()
527 enfants[index-1].select()
528 except AttributeError:
531 def visuJDC_py(self,event=None):
533 Méthode permettant d'afficher dans une fenêtre à part l'écho au
534 format python du jdc courant
536 if not hasattr(self,'JDC') : return
537 jdc_fini = self.get_text_JDC('python')
538 if jdc_fini == None : return
540 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
545 Méthode permettant d'afficher dans une fenêtre à part l'écho au
546 format .comm ou .py du jdc courant
548 if not hasattr(self,'JDC') : return
549 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
550 format=self.appli.format_fichier.get()
551 self.jdc_fini = self.get_text_JDC(format)
552 if self.jdc_fini == None : return
553 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
555 def get_text_JDC(self,format):
556 if generator.plugins.has_key(format):
557 # Le generateur existe on l'utilise
558 g=generator.plugins[format]()
559 jdc_formate=g.gener(self.JDC,format='beautifie')
560 if not g.cr.estvide():
562 self.appli.affiche_infos("Erreur à la generation")
563 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
568 # Il n'existe pas c'est une erreur
569 self.appli.affiche_infos("Format %s non reconnu" % format)
570 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
575 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
576 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
577 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
579 if not self.JDCDisplay_courant : return
581 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
582 if cle_doc == None : return
583 cle_doc = string.replace(cle_doc,'.','')
584 cle_doc = string.replace(cle_doc,'-','')
585 commande = self.appli.CONFIGURATION.exec_acrobat
586 nom_fichier = cle_doc+".pdf"
587 rep_fichier = cle_doc[0:2]
588 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
590 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
591 elif os.name == 'posix':
592 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
593 pid = os.system(script)
594 except AttributeError:
595 traceback.print_exc()
598 def visu_a_plat(self,event=None):
600 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
602 if not hasattr(self,'JDC') : return
603 titre = 'fichier '+ self.JDCName + ' à plat '
604 self.jdc_fini = self.get_text_JDC('aplat')
605 if self.jdc_fini == None : return
606 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
608 def visu_txt_brut_JDC(self,event=None):
610 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
612 if not hasattr(self,'JDC') : return
613 titre = "fichier de commandes utilisateur"
614 #texte = self.JDC.procedure
616 if self.JDCDisplay_courant.fichier == None:
617 self.appli.affiche_infos("Pas de fichier initial")
618 showerror("Impossible de visualiser le fichier initial",
619 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
621 f=open(self.JDCDisplay_courant.fichier,'r')
624 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
626 def affichage_fichier_ini(self):
628 Affichage des valeurs des paramètres relus par Eficas
630 self.appli.CONFIGURATION.affichage_fichier_ini()
632 def saveall(self,liste):
634 Sauvegarde tous les JDC contenus dans liste
637 for JDCDisplay in liste :
638 self.JDC = JDCDisplay.jdc
639 test = test * self.saveJDC(echo = 'non')
642 def save_homard(self,nom,texte):
643 file_homard=nom+'.conf_homard'
645 f=open(file_homard,'w')
651 print "Pb a la sauvegarde sous le format homard"
652 if self.appli.salome != 0:
654 self.appli.salome.rangeInStudy(file_homard,"_CONF")
656 # ---------------------------------------------------------------------------
657 # Méthodes liées aux mots-clés inconnus
658 # ---------------------------------------------------------------------------
660 def mc_inconnus(self):
661 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
662 o = fenetre_mc_inconnus(l_mc)
663 l = o.wait_new_list()
664 #print "mc_inconnus_new_list: ",l
665 #CCAR: Il n' y a pas de retour vers le JDC
667 def aideEFICAS(self,event=None):
668 AIDE.go(master=self.parent)
670 def update_jdc_courant(self):
671 self.JDCDisplay_courant.update()