1 # CONFIGURATION MANAGEMENT OF EDF VERSION
2 # ======================================================================
3 # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG
4 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
5 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
6 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR
7 # (AT YOUR OPTION) ANY LATER VERSION.
9 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT
10 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF
11 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU
12 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.
14 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE
15 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,
16 # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.
19 # ======================================================================
21 Ce module contient la classe BUREAU qui gere les JDC ouverts
27 from widgets import askopenfilename,asksaveasfilename
28 from widgets import showinfo,askyesno,showerror
36 from jdcdisplay import JDCDISPLAY
37 from utils import extension_fichier,stripPath,save_in_file
38 from widgets import Fenetre,Ask_Format_Fichier
39 from fenetre_mc_inconnus import fenetre_mc_inconnus
44 ('Nouveau','newJDC','<Control-n>'),
45 ('Ouvrir','openJDC','<Control-o>'),
46 ('Enregistrer','saveJDC','<Control-e>'),
47 ('Enregistrer sous','saveasJDC''<Control-s>'),
49 ('Fermer','closeJDC','<Control-f>'),
50 ('Quitter','exitEFICAS','<Control-q>'),
54 ('Copier','copy','<Control-c>'),
55 ('Couper','cut','<Control-x>'),
56 ('Coller','paste','<Control-v>'),
60 ('Rapport de validation','visuCRJDC','<Control-r>'),
61 ('Fichier à plat','visu_a_plat','<Control-p>'),
62 ('Fichier .py','visuJDC_py'),
63 ('Fichier source','visu_txt_brut_JDC','<Control-b>'),
64 ('Paramètres Eficas','affichage_fichier_ini'),
65 ('Mots-clés inconnus','mc_inconnus'),
69 ('Aide EFICAS','aideEFICAS'),
74 button_defs = (('New24',"newJDC","Création d'un nouveau fichier",'always'),
75 ('Open24',"openJDC","Ouverture d'un fichier existant",'always'),
76 ('Save24',"saveJDC","Sauvegarde du fichier courant",'always'),
77 ('Zoom24',"visuJDC","Visualisation du fichier de commandes",'always'),
79 ('Copy24',"copy","Copie l'objet courant",'jdc'),
80 ('Cut24',"cut","Coupe l'objet courant",'jdc'),
81 ('Paste24',"paste","Colle l'objet copié après l'objet courant",'jdc'),
83 ('Delete24',"delete","Supprime l'objet courant",'jdc'),
84 ('Help24',"view_doc","Documentation de l'objet courant",'jdc')
87 menu_defs=prefs.menu_defs['bureau']
91 button_defs=prefs.button_defs['bureau']
95 def __init__(self,appli,parent):
98 splash._splash.configure(text = "Création du bureau")
99 self.nb = Pmw.NoteBook(self.parent,raisecommand=self.selectJDC)
100 self.nb.pack(fill='both',expand=1)
101 self.JDCDisplay_courant=None
103 self.liste_JDCDisplay=[]
106 def cree_cataitem(self):
108 On récupère dans l'appli_composant readercata les variables
109 qui servent par la suite pour la création des JDC
111 self.cataitem=self.appli.readercata.cataitem
112 self.cata=self.appli.readercata.cata
113 self.cata_ordonne_dico=self.appli.readercata.cata_ordonne_dico
114 self.code=self.appli.readercata.code
115 self.version_code=self.appli.readercata.version_code
116 self.fic_cata=self.appli.readercata.fic_cata
118 def selectJDC(self,event=None):
120 Cette méthode est appelée chaque fois que l'on sélectionne
121 l'onglet d'un JDC dans le NoteBook des JDC.
122 Elle permet de stocker dans les variable self.JDC et
123 self.JDCDisplay_courant les valeurs concernant le JDC courant
125 if len(self.liste_JDCDisplay) == 0 : return
126 #if self.JDCDisplay_courant : self.JDCDisplay_courant.jdc.unset_context()
127 numero_jdc = self.nb.index(self.nb.getcurselection())
128 self.JDCDisplay_courant = self.liste_JDCDisplay[numero_jdc]
129 self.JDC = self.JDCDisplay_courant.jdc
130 #self.JDC.set_context()
131 self.JDCName = self.JDC.nom
133 def newJDC(self,event=None):
135 Initialise un nouveau JDC vierge
137 self.appli.statusbar.reset_affichage_infos()
139 CONTEXT.unset_current_step()
140 J=self.cata[0].JdC(cata=self.cata,
141 cata_ord_dico=self.cata_ordonne_dico,
143 rep_mat=self.appli.CONFIGURATION.rep_mat,
147 self.ShowJDC(J,self.JDCName)
148 self.appli.toolbar.active_boutons()
150 def ShowJDC(self,JDC,nom,label_onglet=None):
152 Lance l'affichage du JDC cad création du JDCDisplay
153 Rajoute le JDCDisplay à la liste des JDCDisplay si label_onglet == None cad si on crée
154 bien un nouveau JDCDisplay et non si on remplace (renommage de l'onglet)
157 self.JDCName = self.JDC.nom = nom
158 #XXX CCAR: pour le moment mis en commentaire
159 #self.JDC.set_context()
160 if label_onglet == None :
161 label_onglet = self.GetLabelJDC()
162 self.nb.add(label_onglet,tab_text = nom,tab_width=20)
166 self.JDCDisplay_courant=JDCDISPLAY(self.JDC,nom,appli=self.appli,parent=self.nb.page(label_onglet))
168 self.liste_JDCDisplay.append(self.JDCDisplay_courant)
169 self.JDCDisplay_courant.modified='n'
170 self.JDCDisplay_courant.fichier=self.fileName
171 self.nb.selectpage(label_onglet)
172 self.nb.setnaturalsize()
173 texte = "Jeu de commandes :" + self.JDCName+" ouvert"
174 self.appli.affiche_infos(texte)
176 def closeJDC (self,event=None) :
178 Ferme le JDC courant et détruit l'onglet associé dans le notebook self.nb
180 if self.JDCDisplay_courant.modified == 'o' :
181 message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
182 reponse = askyesno(title="Sauvegarde du jdc courant",
185 test = self.saveJDC()
187 self.appli.affiche_infos("Sauvegarde impossible")
189 self.JDCDisplay_courant.jdc.supprime()
190 self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
191 self.nb.delete(self.nb.getcurselection())
192 #XXX CCAR: pour le moment mis en commentaire
193 #self.JDC.unset_context()
196 index = self.nb.index(self.nb.getcurselection())
197 self.JDCDisplay_courant = self.liste_JDCDisplay[index]
198 self.JDC = self.JDCDisplay_courant.jdc
200 self.JDCDisplay_courant = None
201 self.appli.toolbar.inactive_boutons()
203 def visuCRJDC(self,event=None):
204 return self.visuCR(mode='JDC')
206 def visuCR(self,mode):
208 Méthode permettant l'affichage du rapport de validation
211 if not hasattr(self,'JDC') : return
212 titre="rapport de validation du jeu de commandes courant"
213 cr = self.JDC.report()
214 self.update_jdc_courant()
216 from Noyau.N_CR import CR
218 cr.debut = "Début rapport de validation du catalogue"
219 cr.fin = "Fin rapport de validation du catalogue"
220 titre="rapport de validation du catalogue"
221 if hasattr(self,'cata_ordonne_cr') :
222 cr.add(self.cata_ordonne_cr)
223 if hasattr(self,'cata_dev_ordonne_cr') :
224 cr.add(self.cata_dev_ordonne_cr)
225 for cata in self.cata:
226 if hasattr(cata,'JdC'):
227 cr.add(cata.JdC.report())
229 self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
231 def openJDC(self,file=None):
233 Demande à l'utilisateur quel JDC existant il veut ouvrir
235 if self.code == 'ASTER':
236 filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
238 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
239 if not hasattr(self,'initialdir'):
240 #self.initialdir = self.appli.CONFIGURATION.rep_user
241 self.initialdir = self.appli.CONFIGURATION.initialdir
242 if file.__class__.__name__ in ('Event',):
245 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
246 defaultextension=".comm",
247 filetypes = filetypes,
248 initialdir = self.initialdir)
251 e=extension_fichier(file)
252 self.JDCName=stripPath(file)
253 self.initialdir = os.path.dirname(file)
256 #XXX CCAR: pour le moment mis en commentaire
257 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
259 format=self.appli.format_fichier.get()
260 # Il faut convertir le contenu du fichier en fonction du format
261 if convert.plugins.has_key(format):
262 # Le convertisseur existe on l'utilise
263 p=convert.plugins[format]()
265 text=p.convert('exec')
266 if not p.cr.estvide():
267 self.appli.affiche_infos("Erreur à la conversion")
269 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
270 texte = str(p.cr)).wait()
273 # Il n'existe pas c'est une erreur
274 self.appli.affiche_infos("Type de fichier non reconnu")
275 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
278 # On se met dans le repertoire ou se trouve le fichier de commandes
279 # pour trouver les eventuels fichiers include ou autres
280 # localises a cote du fichier de commandes
281 os.chdir(self.initialdir)
282 CONTEXT.unset_current_step()
283 J=self.cata[0].JdC(procedure=text,appli=self.appli,
284 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
286 rep_mat=self.appli.CONFIGURATION.rep_mat,
289 txt_exception = J.cr.get_mess_exception()
291 # des exceptions ont été levées à la création du JDC
292 # --> on affiche les erreurs mais pas le JDC
293 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
294 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
296 self.ShowJDC(J,self.JDCName)
297 self.appli.toolbar.active_boutons()
298 # si le JDC ne contient rien (vide), on retourne ici
299 if len(self.JDC.etapes) == 0 : return
300 # dans le cas où le JDC est invalide, on affiche son CR
301 if not self.JDC.isvalid():
302 #cr = self.JDC.report()
303 #if not cr.estvide() :
304 self.appli.top.update()
305 self.visuCR(mode='JDC')
308 def GetLabelJDC(self,nb_jdc = 'absent'):
310 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
312 if nb_jdc == 'absent':
313 nb_jdc = len(self.nb.pagenames())
315 label_onglet = 'JDC'+`nb_jdc`
316 if label_onglet not in self.nb.pagenames() :
319 return self.GetLabelJDC(nb_jdc)
321 def saveasJDC(self,event=None):
323 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
324 donner le nom du fichier de sauvegarde
326 self.saveJDC(echo='oui')
328 def saveJDC(self,echo='non'):
330 Sauvegarde le JDC courant.
331 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
332 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
334 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
336 if not hasattr(self,'JDC') : return 0
337 format=self.appli.format_fichier.get()
338 if generator.plugins.has_key(format):
339 # Le generateur existe on l'utilise
340 g=generator.plugins[format]()
341 jdc_formate=g.gener(self.JDC,format='beautifie')
342 if not g.cr.estvide():
344 self.appli.affiche_infos("Erreur à la generation")
345 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
348 # Il n'existe pas c'est une erreur
349 self.appli.affiche_infos("Format %s non reconnu" % format)
350 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
352 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
354 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
355 return self.asknomsauvegardeJDC()
356 elif self.JDCDisplay_courant.fichier != None :
358 # Pour sauvegarde dans l etude si lancement depuis salome
359 if self.appli.salome != 0:
361 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
362 from panelsSalome import SALOME_UNIQUE_BASE_Panel
363 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
364 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
365 #PN Fin Ajout --> Salome
366 # le JDC a déjà un nom : on sauvegarde directement sans demander
367 # un autre nom au développeur
368 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
369 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
372 self.JDCDisplay_courant.stop_modif()
373 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
376 def asknomsauvegardeJDC(self):
377 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
378 titre = "Sauvegarde d'un fichier de commandes "+self.code
379 if self.code == 'ASTER':
381 filtyp = ( ("ASTER", ".comm"),)
384 filtyp = ( (self.code, ".py"),)
385 sauvegarde = asksaveasfilename(title=titre,
386 defaultextension=defext,
388 initialdir = self.appli.CONFIGURATION.initialdir)
389 #initialdir = self.appli.CONFIGURATION.rep_user)
391 # PN ajout --> Salome
392 # Pour sauvegarde dans l etude si lancement depuis salome
393 if self.appli.salome != 0:
395 self.appli.salome.rangeInStudy(sauvegarde)
396 from panelsSalome import SALOME_UNIQUE_BASE_Panel
397 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
398 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
399 # PN fin ajout --> Salome
400 if not save_in_file(sauvegarde,self.jdc_fini) :
401 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
404 self.JDCDisplay_courant.stop_modif()
405 self.appli.affiche_infos("Sauvegarde effectuée")
406 if sauvegarde != self.JDCDisplay_courant.fichier :
407 # l'utilisateur a sauvegardé le JDC sous un autre nom
408 self.JDCDisplay_courant.fichier = sauvegarde
409 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
415 def changeNomPage(self):
416 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
417 et recrée un autre onglet à la même place avec le bon nom
420 self.JDCDisplay_courant.jdc.nom = nom
421 nom_page = self.nb.getcurselection()
422 num_page = self.nb.index(nom_page)
423 tab = self.nb.tab(num_page)
424 tab.configure(text = nom)
426 def exitEFICAS(self,event=None):
428 Permet de sortir d'EFICAS en demandant à l'utilisateur
429 s'il veut sauvegarder les modifications en cours
431 liste = self.GetListeJDCaSauvegarder()
433 # Certains fichiers n'ont pas été sauvegardés ...
434 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
435 test = self.saveall(liste)
438 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
439 for JDCDisplay in self.liste_JDCDisplay:
440 JDCDisplay.jdc.supprime()
444 def GetListeJDCaSauvegarder(self) :
445 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
446 if not self.JDCDisplay_courant : return []
447 if len(self.liste_JDCDisplay) == 0 : return l
449 for JDCDisplay in self.liste_JDCDisplay:
450 if JDCDisplay.modified == 'o' :
454 def copy(self,event=None):
456 Lance la copie sur le JDC courant
458 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
460 def paste(self,event=None):
462 Lance le collage sur le JDC courant
464 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
466 def cut(self,event=None):
468 Lance le cut sur le JDC courant
470 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
474 Lance la suppression du noeud courant
476 if not self.JDCDisplay_courant : return
478 if self.JDCDisplay_courant.modified == 'n' :
479 self.JDCDisplay_courant.init_modif()
480 pere = self.JDCDisplay_courant.node_selected.parent
481 # Le noeud n'est pas au 1er niveau
482 if pere.parent.parent != None:
483 self.JDCDisplay_courant.node_selected.delete()
486 noeudselecte = self.JDCDisplay_courant.node_selected
487 parent = noeudselecte.parent
488 enfants = parent.children
489 index = enfants.index(noeudselecte)
490 self.JDCDisplay_courant.node_selected.delete()
492 enfants[index].select()
494 enfants[index-1].select()
495 except AttributeError:
498 def visuJDC_py(self):
500 Méthode permettant d'afficher dans une fenêtre à part l'écho au
501 format python du jdc courant
503 if not hasattr(self,'JDC') : return
504 jdc_fini = self.get_text_JDC('python')
505 if jdc_fini == None : return
507 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
512 Méthode permettant d'afficher dans une fenêtre à part l'écho au
513 format .comm ou .py du jdc courant
515 if not hasattr(self,'JDC') : return
516 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
517 format=self.appli.format_fichier.get()
518 self.jdc_fini = self.get_text_JDC(format)
519 if self.jdc_fini == None : return
520 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
522 def get_text_JDC(self,format):
523 if generator.plugins.has_key(format):
524 # Le generateur existe on l'utilise
525 g=generator.plugins[format]()
526 jdc_formate=g.gener(self.JDC,format='beautifie')
527 if not g.cr.estvide():
529 self.appli.affiche_infos("Erreur à la generation")
530 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
535 # Il n'existe pas c'est une erreur
536 self.appli.affiche_infos("Format %s non reconnu" % format)
537 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
542 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
543 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
544 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
546 if not self.JDCDisplay_courant : return
548 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
549 if cle_doc == None : return
550 cle_doc = string.replace(cle_doc,'.','')
551 cle_doc = string.replace(cle_doc,'-','')
552 commande = self.appli.CONFIGURATION.exec_acrobat
553 nom_fichier = cle_doc+".pdf"
554 rep_fichier = cle_doc[0:2]
555 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
557 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
558 elif os.name == 'posix':
559 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
560 pid = os.system(script)
561 except AttributeError:
562 traceback.print_exc()
565 def visu_a_plat(self,event=None):
567 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
569 if not hasattr(self,'JDC') : return
570 titre = 'fichier '+ self.JDCName + ' à plat '
571 self.jdc_fini = self.get_text_JDC('aplat')
572 if self.jdc_fini == None : return
573 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
575 def visu_txt_brut_JDC(self,event=None):
577 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
579 if not hasattr(self,'JDC') : return
580 titre = "fichier de commandes utilisateur"
581 #texte = self.JDC.procedure
583 if self.JDCDisplay_courant.fichier == None:
584 self.appli.affiche_infos("Pas de fichier initial")
585 showerror("Impossible de visualiser le fichier initial",
586 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
588 f=open(self.JDCDisplay_courant.fichier,'r')
591 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
593 def affichage_fichier_ini(self):
595 Affichage des valeurs des paramètres relus par Eficas
597 self.appli.CONFIGURATION.affichage_fichier_ini()
599 def saveall(self,liste):
601 Sauvegarde tous les JDC contenus dans liste
604 for JDCDisplay in liste :
605 self.JDC = JDCDisplay.jdc
606 test = test * self.saveJDC(echo = 'non')
610 # ---------------------------------------------------------------------------
611 # Méthodes liées aux mots-clés inconnus
612 # ---------------------------------------------------------------------------
614 def mc_inconnus(self):
615 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
616 o = fenetre_mc_inconnus(l_mc)
617 l = o.wait_new_list()
618 #print "mc_inconnus_new_list: ",l
619 #CCAR: Il n' y a pas de retour vers le JDC
621 def aideEFICAS(self,event=None):
622 AIDE.go(master=self.parent)
624 def update_jdc_courant(self):
625 self.JDCDisplay_courant.update()