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(procedure="",appli=self.appli,
147 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
148 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.initialdir
251 if file.__class__.__name__ in ('Event',):
255 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
256 defaultextension=".comm",
257 filetypes = filetypes,
258 initialdir = self.initialdir)
261 e=extension_fichier(file)
262 self.JDCName=stripPath(file)
263 self.initialdir = os.path.dirname(os.path.abspath(file))
267 format=self.appli.format_fichier.get()
268 # Il faut convertir le contenu du fichier en fonction du format
269 if convert.plugins.has_key(format):
270 # Le convertisseur existe on l'utilise
271 p=convert.plugins[format]()
273 text=p.convert('exec',self.appli)
274 if not p.cr.estvide():
275 self.appli.affiche_infos("Erreur à la conversion")
277 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
278 texte = str(p.cr)).wait()
281 # Il n'existe pas c'est une erreur
282 self.appli.affiche_infos("Type de fichier non reconnu")
283 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
286 # On se met dans le repertoire ou se trouve le fichier de commandes
287 # pour trouver les eventuels fichiers include ou autres
288 # localises a cote du fichier de commandes
289 os.chdir(self.initialdir)
290 CONTEXT.unset_current_step()
291 J=self.cata[0].JdC(procedure=text,appli=self.appli,
292 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
294 rep_mat=self.appli.CONFIGURATION.rep_mat,
296 if units is not None:
297 J.recorded_units=units
298 J.old_recorded_units=units
301 txt_exception = J.cr.get_mess_exception()
303 # des exceptions ont été levées à la création du JDC
304 # --> on affiche les erreurs mais pas le JDC
305 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
306 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
308 self.ShowJDC(J,self.JDCName)
309 self.appli.toolbar.active_boutons()
310 # si le JDC ne contient rien (vide), on retourne ici
311 if len(self.JDC.etapes) == 0 : return
312 # dans le cas où le JDC est invalide, on affiche son CR
313 if not self.JDC.isvalid():
314 self.appli.top.update()
315 self.visuCR(mode='JDC')
318 def GetLabelJDC(self,nb_jdc = 'absent'):
320 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
322 if nb_jdc == 'absent':
323 nb_jdc = len(self.nb.pagenames())
325 label_onglet = 'JDC'+`nb_jdc`
326 if label_onglet not in self.nb.pagenames() :
329 return self.GetLabelJDC(nb_jdc)
331 def saveasJDC(self,event=None):
333 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
334 donner le nom du fichier de sauvegarde
336 self.saveJDC(echo='oui')
338 def saveJDC(self,echo='non'):
340 Sauvegarde le JDC courant.
341 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
342 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
344 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
346 if not hasattr(self,'JDC') : return 0
347 format=self.appli.format_fichier.get()
348 if generator.plugins.has_key(format):
349 # Le generateur existe on l'utilise
350 g=generator.plugins[format]()
351 jdc_formate=g.gener(self.JDC,format='beautifie')
352 if format == 'homard':
353 self.jdc_homard=g.get_homard()
354 if not g.cr.estvide():
355 self.appli.affiche_infos("Erreur à la generation")
356 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
359 # Il n'existe pas c'est une erreur
360 self.appli.affiche_infos("Format %s non reconnu" % format)
361 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
363 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
365 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
366 return self.asknomsauvegardeJDC()
367 elif self.JDCDisplay_courant.fichier != None :
369 # Pour sauvegarde dans l etude si lancement depuis salome
370 if self.appli.salome != 0:
372 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
373 from panelsSalome import SALOME_UNIQUE_BASE_Panel
374 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
375 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
379 MyCLinit=eficasCL.CLinit()
384 #PN Fin Ajout --> Salome
385 # le JDC a déjà un nom : on sauvegarde directement sans demander
386 # un autre nom au développeur
387 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
388 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
391 if self.appli.format_fichier.get() == 'homard':
392 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
393 self.JDCDisplay_courant.stop_modif()
394 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
397 def asknomsauvegardeJDC(self):
398 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
399 titre = "Sauvegarde d'un fichier de commandes "+self.code
400 if self.code == 'ASTER':
402 filtyp = ( ("ASTER", ".comm"),)
405 filtyp = ( (self.code, ".py"),)
406 sauvegarde = asksaveasfilename(title=titre,
407 defaultextension=defext,
409 initialdir = self.appli.CONFIGURATION.initialdir)
410 #initialdir = self.appli.CONFIGURATION.rep_user)
412 # PN ajout --> Salome
413 # Pour sauvegarde dans l etude si lancement depuis salome
414 if self.appli.salome != 0:
416 self.appli.salome.rangeInStudy(sauvegarde)
417 from panelsSalome import SALOME_UNIQUE_BASE_Panel
418 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
419 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
423 MyCLinit=eficasCL.CLinit()
428 # PN fin ajout --> Salome
429 if not save_in_file(sauvegarde,self.jdc_fini) :
430 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
433 if self.appli.format_fichier.get() == 'homard':
434 self.save_homard(sauvegarde,self.jdc_homard)
435 self.JDCDisplay_courant.stop_modif()
436 self.appli.affiche_infos("Sauvegarde effectuée")
437 if sauvegarde != self.JDCDisplay_courant.fichier :
438 # l'utilisateur a sauvegardé le JDC sous un autre nom
439 self.JDCDisplay_courant.fichier = sauvegarde
440 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
446 def changeNomPage(self):
447 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
448 et recrée un autre onglet à la même place avec le bon nom
451 self.JDCDisplay_courant.jdc.nom = nom
452 nom_page = self.nb.getcurselection()
453 num_page = self.nb.index(nom_page)
454 tab = self.nb.tab(num_page)
455 tab.configure(text = nom)
457 def exitEFICAS(self,event=None):
459 Permet de sortir d'EFICAS en demandant à l'utilisateur
460 s'il veut sauvegarder les modifications en cours
462 liste = self.GetListeJDCaSauvegarder()
464 # Certains fichiers n'ont pas été sauvegardés ...
465 if askyesno("Enregistrer modifications","Enregistrer les modifications ?") :
466 test = self.saveall(liste)
469 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
470 for JDCDisplay in self.liste_JDCDisplay:
471 JDCDisplay.jdc.supprime()
475 def GetListeJDCaSauvegarder(self) :
476 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
477 if not self.JDCDisplay_courant : return []
478 if len(self.liste_JDCDisplay) == 0 : return l
480 for JDCDisplay in self.liste_JDCDisplay:
481 if JDCDisplay.modified == 'o' :
485 def copy(self,event=None):
487 Lance la copie sur le JDC courant
489 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
491 def paste(self,event=None):
493 Lance le collage sur le JDC courant
495 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
497 def cut(self,event=None):
499 Lance le cut sur le JDC courant
501 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
505 Lance la suppression du noeud courant
507 if not self.JDCDisplay_courant : return
508 if self.JDCDisplay_courant.modified == 'n' :
509 self.JDCDisplay_courant.init_modif()
510 self.JDCDisplay_courant.node_selected.delete()
512 def visuJDC_py(self,event=None):
514 Méthode permettant d'afficher dans une fenêtre à part l'écho au
515 format python du jdc courant
517 if not hasattr(self,'JDC') : return
518 jdc_fini = self.get_text_JDC('python')
519 if jdc_fini == None : return
521 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
526 Méthode permettant d'afficher dans une fenêtre à part l'écho au
527 format .comm ou .py du jdc courant
529 if not hasattr(self,'JDC') : return
530 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
531 format=self.appli.format_fichier.get()
532 self.jdc_fini = self.get_text_JDC(format)
533 if self.jdc_fini == None : return
534 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
536 def get_text_JDC(self,format):
537 if generator.plugins.has_key(format):
538 # Le generateur existe on l'utilise
539 g=generator.plugins[format]()
540 jdc_formate=g.gener(self.JDC,format='beautifie')
541 if not g.cr.estvide():
542 self.appli.affiche_infos("Erreur à la generation")
543 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
548 # Il n'existe pas c'est une erreur
549 self.appli.affiche_infos("Format %s non reconnu" % format)
550 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
555 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
556 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
557 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
559 if not self.JDCDisplay_courant : return
561 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
562 if cle_doc == None : return
563 cle_doc = string.replace(cle_doc,'.','')
564 cle_doc = string.replace(cle_doc,'-','')
565 commande = self.appli.CONFIGURATION.exec_acrobat
566 nom_fichier = cle_doc+".pdf"
567 rep_fichier = cle_doc[0:2]
568 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
570 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
571 elif os.name == 'posix':
572 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
573 pid = os.system(script)
574 except AttributeError:
575 traceback.print_exc()
578 def visu_a_plat(self,event=None):
580 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
582 if not hasattr(self,'JDC') : return
583 titre = 'fichier '+ self.JDCName + ' à plat '
584 self.jdc_fini = self.get_text_JDC('aplat')
585 if self.jdc_fini == None : return
586 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
588 def visu_txt_brut_JDC(self,event=None):
590 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
592 if not hasattr(self,'JDC') : return
593 titre = "fichier de commandes utilisateur"
594 #texte = self.JDC.procedure
596 if self.JDCDisplay_courant.fichier == None:
597 self.appli.affiche_infos("Pas de fichier initial")
598 showerror("Impossible de visualiser le fichier initial",
599 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
601 f=open(self.JDCDisplay_courant.fichier,'r')
604 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
606 def affichage_fichier_ini(self):
608 Affichage des valeurs des paramètres relus par Eficas
610 self.appli.CONFIGURATION.affichage_fichier_ini()
612 def saveall(self,liste):
614 Sauvegarde tous les JDC contenus dans liste
617 for JDCDisplay in liste :
618 self.JDC = JDCDisplay.jdc
619 test = test * self.saveJDC(echo = 'non')
622 def save_homard(self,nom,texte):
623 file_homard=nom+'.conf_homard'
625 f=open(file_homard,'w')
631 print "Pb a la sauvegarde sous le format homard"
632 if self.appli.salome != 0:
634 self.appli.salome.rangeInStudy(file_homard,"_CONF")
636 # ---------------------------------------------------------------------------
637 # Méthodes liées aux mots-clés inconnus
638 # ---------------------------------------------------------------------------
640 def mc_inconnus(self):
641 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
642 o = fenetre_mc_inconnus(l_mc)
643 l = o.wait_new_list()
644 #print "mc_inconnus_new_list: ",l
645 #CCAR: Il n' y a pas de retour vers le JDC
647 def aideEFICAS(self,event=None):
648 AIDE.go(master=self.parent)
650 def update_jdc_courant(self):
651 self.JDCDisplay_courant.update()