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 #cr = self.JDC.report()
306 #if not cr.estvide() :
307 self.appli.top.update()
308 self.visuCR(mode='JDC')
311 def GetLabelJDC(self,nb_jdc = 'absent'):
313 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
315 if nb_jdc == 'absent':
316 nb_jdc = len(self.nb.pagenames())
318 label_onglet = 'JDC'+`nb_jdc`
319 if label_onglet not in self.nb.pagenames() :
322 return self.GetLabelJDC(nb_jdc)
324 def saveasJDC(self,event=None):
326 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
327 donner le nom du fichier de sauvegarde
329 self.saveJDC(echo='oui')
331 def saveJDC(self,echo='non'):
333 Sauvegarde le JDC courant.
334 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
335 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
337 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
339 if not hasattr(self,'JDC') : return 0
340 format=self.appli.format_fichier.get()
341 if generator.plugins.has_key(format):
342 # Le generateur existe on l'utilise
343 g=generator.plugins[format]()
344 jdc_formate=g.gener(self.JDC,format='beautifie')
345 if format == 'homard':
346 self.jdc_homard=g.get_homard()
347 if not g.cr.estvide():
349 self.appli.affiche_infos("Erreur à la generation")
350 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
353 # Il n'existe pas c'est une erreur
354 self.appli.affiche_infos("Format %s non reconnu" % format)
355 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
357 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
359 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
360 return self.asknomsauvegardeJDC()
361 elif self.JDCDisplay_courant.fichier != None :
363 # Pour sauvegarde dans l etude si lancement depuis salome
364 if self.appli.salome != 0:
366 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
367 from panelsSalome import SALOME_UNIQUE_BASE_Panel
368 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
369 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
370 #PN Fin Ajout --> Salome
371 # le JDC a déjà un nom : on sauvegarde directement sans demander
372 # un autre nom au développeur
373 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
374 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
377 if self.appli.format_fichier.get() == 'homard':
378 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
379 self.JDCDisplay_courant.stop_modif()
380 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
383 def asknomsauvegardeJDC(self):
384 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
385 titre = "Sauvegarde d'un fichier de commandes "+self.code
386 if self.code == 'ASTER':
388 filtyp = ( ("ASTER", ".comm"),)
391 filtyp = ( (self.code, ".py"),)
392 sauvegarde = asksaveasfilename(title=titre,
393 defaultextension=defext,
395 initialdir = self.appli.CONFIGURATION.initialdir)
396 #initialdir = self.appli.CONFIGURATION.rep_user)
398 # PN ajout --> Salome
399 # Pour sauvegarde dans l etude si lancement depuis salome
400 if self.appli.salome != 0:
402 self.appli.salome.rangeInStudy(sauvegarde)
403 from panelsSalome import SALOME_UNIQUE_BASE_Panel
404 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
405 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
406 # PN fin ajout --> Salome
407 if not save_in_file(sauvegarde,self.jdc_fini) :
408 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
411 if self.appli.format_fichier.get() == 'homard':
412 self.save_homard(sauvegarde,self.jdc_homard)
413 self.JDCDisplay_courant.stop_modif()
414 self.appli.affiche_infos("Sauvegarde effectuée")
415 if sauvegarde != self.JDCDisplay_courant.fichier :
416 # l'utilisateur a sauvegardé le JDC sous un autre nom
417 self.JDCDisplay_courant.fichier = sauvegarde
418 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
424 def changeNomPage(self):
425 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
426 et recrée un autre onglet à la même place avec le bon nom
429 self.JDCDisplay_courant.jdc.nom = nom
430 nom_page = self.nb.getcurselection()
431 num_page = self.nb.index(nom_page)
432 tab = self.nb.tab(num_page)
433 tab.configure(text = nom)
435 def exitEFICAS(self,event=None):
437 Permet de sortir d'EFICAS en demandant à l'utilisateur
438 s'il veut sauvegarder les modifications en cours
440 liste = self.GetListeJDCaSauvegarder()
442 # Certains fichiers n'ont pas été sauvegardés ...
443 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
444 test = self.saveall(liste)
447 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
448 for JDCDisplay in self.liste_JDCDisplay:
449 JDCDisplay.jdc.supprime()
453 def GetListeJDCaSauvegarder(self) :
454 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
455 if not self.JDCDisplay_courant : return []
456 if len(self.liste_JDCDisplay) == 0 : return l
458 for JDCDisplay in self.liste_JDCDisplay:
459 if JDCDisplay.modified == 'o' :
463 def copy(self,event=None):
465 Lance la copie sur le JDC courant
467 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
469 def paste(self,event=None):
471 Lance le collage sur le JDC courant
473 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
475 def cut(self,event=None):
477 Lance le cut sur le JDC courant
479 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
483 Lance la suppression du noeud courant
485 if not self.JDCDisplay_courant : return
487 if self.JDCDisplay_courant.modified == 'n' :
488 self.JDCDisplay_courant.init_modif()
489 pere = self.JDCDisplay_courant.node_selected.parent
490 # Le noeud n'est pas au 1er niveau
491 if pere.parent.parent != None:
492 self.JDCDisplay_courant.node_selected.delete()
495 noeudselecte = self.JDCDisplay_courant.node_selected
496 parent = noeudselecte.parent
497 enfants = parent.children
498 index = enfants.index(noeudselecte)
499 self.JDCDisplay_courant.node_selected.delete()
501 enfants[index].select()
503 enfants[index-1].select()
504 except AttributeError:
507 def visuJDC_py(self):
509 Méthode permettant d'afficher dans une fenêtre à part l'écho au
510 format python du jdc courant
512 if not hasattr(self,'JDC') : return
513 jdc_fini = self.get_text_JDC('python')
514 if jdc_fini == None : return
516 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
521 Méthode permettant d'afficher dans une fenêtre à part l'écho au
522 format .comm ou .py du jdc courant
524 if not hasattr(self,'JDC') : return
525 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
526 format=self.appli.format_fichier.get()
527 self.jdc_fini = self.get_text_JDC(format)
528 if self.jdc_fini == None : return
529 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
531 def get_text_JDC(self,format):
532 if generator.plugins.has_key(format):
533 # Le generateur existe on l'utilise
534 g=generator.plugins[format]()
535 jdc_formate=g.gener(self.JDC,format='beautifie')
536 if not g.cr.estvide():
538 self.appli.affiche_infos("Erreur à la generation")
539 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
544 # Il n'existe pas c'est une erreur
545 self.appli.affiche_infos("Format %s non reconnu" % format)
546 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
551 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
552 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
553 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
555 if not self.JDCDisplay_courant : return
557 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
558 if cle_doc == None : return
559 cle_doc = string.replace(cle_doc,'.','')
560 cle_doc = string.replace(cle_doc,'-','')
561 commande = self.appli.CONFIGURATION.exec_acrobat
562 nom_fichier = cle_doc+".pdf"
563 rep_fichier = cle_doc[0:2]
564 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
566 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
567 elif os.name == 'posix':
568 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
569 pid = os.system(script)
570 except AttributeError:
571 traceback.print_exc()
574 def visu_a_plat(self,event=None):
576 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
578 if not hasattr(self,'JDC') : return
579 titre = 'fichier '+ self.JDCName + ' à plat '
580 self.jdc_fini = self.get_text_JDC('aplat')
581 if self.jdc_fini == None : return
582 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
584 def visu_txt_brut_JDC(self,event=None):
586 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
588 if not hasattr(self,'JDC') : return
589 titre = "fichier de commandes utilisateur"
590 #texte = self.JDC.procedure
592 if self.JDCDisplay_courant.fichier == None:
593 self.appli.affiche_infos("Pas de fichier initial")
594 showerror("Impossible de visualiser le fichier initial",
595 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
597 f=open(self.JDCDisplay_courant.fichier,'r')
600 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
602 def affichage_fichier_ini(self):
604 Affichage des valeurs des paramètres relus par Eficas
606 self.appli.CONFIGURATION.affichage_fichier_ini()
608 def saveall(self,liste):
610 Sauvegarde tous les JDC contenus dans liste
613 for JDCDisplay in liste :
614 self.JDC = JDCDisplay.jdc
615 test = test * self.saveJDC(echo = 'non')
618 def save_homard(self,nom,texte):
619 file_homard=nom+'.conf_homard'
621 f=open(file_homard,'w')
627 print "Pb a la sauvegarde sous le format homard"
628 if self.appli.salome != 0:
630 self.appli.salome.rangeInStudy(file_homard)
632 # ---------------------------------------------------------------------------
633 # Méthodes liées aux mots-clés inconnus
634 # ---------------------------------------------------------------------------
636 def mc_inconnus(self):
637 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
638 o = fenetre_mc_inconnus(l_mc)
639 l = o.wait_new_list()
640 #print "mc_inconnus_new_list: ",l
641 #CCAR: Il n' y a pas de retour vers le JDC
643 def aideEFICAS(self,event=None):
644 AIDE.go(master=self.parent)
646 def update_jdc_courant(self):
647 self.JDCDisplay_courant.update()