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):
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 #XXX CCAR: pour le moment mis en commentaire
165 #self.JDC.set_context()
166 if label_onglet == None :
167 label_onglet = self.GetLabelJDC()
168 self.nb.add(label_onglet,tab_text = nom,tab_width=20)
172 self.JDCDisplay_courant=JDCDISPLAY(self.JDC,nom,appli=self.appli,parent=self.nb.page(label_onglet))
174 self.liste_JDCDisplay.append(self.JDCDisplay_courant)
175 self.JDCDisplay_courant.modified='n'
176 self.JDCDisplay_courant.fichier=self.fileName
177 self.nb.selectpage(label_onglet)
178 self.nb.setnaturalsize()
179 texte = "Jeu de commandes :" + self.JDCName+" ouvert"
180 self.appli.affiche_infos(texte)
182 def closeJDC (self,event=None) :
184 Ferme le JDC courant et détruit l'onglet associé dans le notebook self.nb
186 if self.JDCDisplay_courant == None:
188 if self.JDCDisplay_courant.modified == 'o' :
189 message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
190 reponse = askyesno(title="Sauvegarde du jdc courant",
193 test = self.saveJDC()
195 self.appli.affiche_infos("Sauvegarde impossible")
197 self.JDCDisplay_courant.jdc.supprime()
198 self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
199 self.nb.delete(self.nb.getcurselection())
200 #XXX CCAR: pour le moment mis en commentaire
201 #self.JDC.unset_context()
204 index = self.nb.index(self.nb.getcurselection())
205 self.JDCDisplay_courant = self.liste_JDCDisplay[index]
206 self.JDC = self.JDCDisplay_courant.jdc
208 self.JDCDisplay_courant = None
209 self.appli.toolbar.inactive_boutons()
211 def visuCRJDC(self,event=None):
212 return self.visuCR(mode='JDC')
214 def visuCR(self,mode):
216 Méthode permettant l'affichage du rapport de validation
219 if not hasattr(self,'JDC') : return
220 titre="rapport de validation du jeu de commandes courant"
221 cr = self.JDC.report()
222 self.update_jdc_courant()
224 from Noyau.N_CR import CR
226 cr.debut = "Début rapport de validation du catalogue"
227 cr.fin = "Fin rapport de validation du catalogue"
228 titre="rapport de validation du catalogue"
229 if hasattr(self,'cata_ordonne_cr') :
230 cr.add(self.cata_ordonne_cr)
231 if hasattr(self,'cata_dev_ordonne_cr') :
232 cr.add(self.cata_dev_ordonne_cr)
233 for cata in self.cata:
234 if hasattr(cata,'JdC'):
235 cr.add(cata.JdC.report())
237 self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
239 def openJDC(self,file=None):
241 Demande à l'utilisateur quel JDC existant il veut ouvrir
243 if self.code == 'ASTER':
244 filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
245 elif self.code == 'HOMARD' :
246 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),("Tous",'*'))
248 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
249 if not hasattr(self,'initialdir'):
250 #self.initialdir = self.appli.CONFIGURATION.rep_user
251 self.initialdir = self.appli.CONFIGURATION.initialdir
252 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(file)
266 #XXX CCAR: pour le moment mis en commentaire
267 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
269 format=self.appli.format_fichier.get()
270 # Il faut convertir le contenu du fichier en fonction du format
271 if convert.plugins.has_key(format):
272 # Le convertisseur existe on l'utilise
273 p=convert.plugins[format]()
275 text=p.convert('exec',self.appli)
276 if not p.cr.estvide():
277 self.appli.affiche_infos("Erreur à la conversion")
279 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
280 texte = str(p.cr)).wait()
283 # Il n'existe pas c'est une erreur
284 self.appli.affiche_infos("Type de fichier non reconnu")
285 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
288 # On se met dans le repertoire ou se trouve le fichier de commandes
289 # pour trouver les eventuels fichiers include ou autres
290 # localises a cote du fichier de commandes
291 os.chdir(self.initialdir)
292 CONTEXT.unset_current_step()
293 J=self.cata[0].JdC(procedure=text,appli=self.appli,
294 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
296 rep_mat=self.appli.CONFIGURATION.rep_mat,
299 txt_exception = J.cr.get_mess_exception()
301 # des exceptions ont été levées à la création du JDC
302 # --> on affiche les erreurs mais pas le JDC
303 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
304 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
306 self.ShowJDC(J,self.JDCName)
307 self.appli.toolbar.active_boutons()
308 # si le JDC ne contient rien (vide), on retourne ici
309 if len(self.JDC.etapes) == 0 : return
310 # dans le cas où le JDC est invalide, on affiche son CR
311 if not self.JDC.isvalid():
312 self.appli.top.update()
313 self.visuCR(mode='JDC')
316 def GetLabelJDC(self,nb_jdc = 'absent'):
318 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
320 if nb_jdc == 'absent':
321 nb_jdc = len(self.nb.pagenames())
323 label_onglet = 'JDC'+`nb_jdc`
324 if label_onglet not in self.nb.pagenames() :
327 return self.GetLabelJDC(nb_jdc)
329 def saveasJDC(self,event=None):
331 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
332 donner le nom du fichier de sauvegarde
334 self.saveJDC(echo='oui')
336 def saveJDC(self,echo='non'):
338 Sauvegarde le JDC courant.
339 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
340 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
342 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
344 if not hasattr(self,'JDC') : return 0
345 format=self.appli.format_fichier.get()
346 if generator.plugins.has_key(format):
347 # Le generateur existe on l'utilise
348 g=generator.plugins[format]()
349 jdc_formate=g.gener(self.JDC,format='beautifie')
350 if format == 'homard':
351 self.jdc_homard=g.get_homard()
352 if not g.cr.estvide():
354 self.appli.affiche_infos("Erreur à la generation")
355 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
358 # Il n'existe pas c'est une erreur
359 self.appli.affiche_infos("Format %s non reconnu" % format)
360 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
362 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
364 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
365 return self.asknomsauvegardeJDC()
366 elif self.JDCDisplay_courant.fichier != None :
368 # Pour sauvegarde dans l etude si lancement depuis salome
369 if self.appli.salome != 0:
371 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
372 from panelsSalome import SALOME_UNIQUE_BASE_Panel
373 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
374 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
378 MyCLinit=eficasCL.CLinit()
383 #PN Fin Ajout --> Salome
384 # le JDC a déjà un nom : on sauvegarde directement sans demander
385 # un autre nom au développeur
386 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
387 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
390 if self.appli.format_fichier.get() == 'homard':
391 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
392 self.JDCDisplay_courant.stop_modif()
393 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
396 def asknomsauvegardeJDC(self):
397 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
398 titre = "Sauvegarde d'un fichier de commandes "+self.code
399 if self.code == 'ASTER':
401 filtyp = ( ("ASTER", ".comm"),)
404 filtyp = ( (self.code, ".py"),)
405 sauvegarde = asksaveasfilename(title=titre,
406 defaultextension=defext,
408 initialdir = self.appli.CONFIGURATION.initialdir)
409 #initialdir = self.appli.CONFIGURATION.rep_user)
411 # PN ajout --> Salome
412 # Pour sauvegarde dans l etude si lancement depuis salome
413 if self.appli.salome != 0:
415 self.appli.salome.rangeInStudy(sauvegarde)
416 from panelsSalome import SALOME_UNIQUE_BASE_Panel
417 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
418 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
422 MyCLinit=eficasCL.CLinit()
427 # PN fin ajout --> Salome
428 if not save_in_file(sauvegarde,self.jdc_fini) :
429 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
432 if self.appli.format_fichier.get() == 'homard':
433 self.save_homard(sauvegarde,self.jdc_homard)
434 self.JDCDisplay_courant.stop_modif()
435 self.appli.affiche_infos("Sauvegarde effectuée")
436 if sauvegarde != self.JDCDisplay_courant.fichier :
437 # l'utilisateur a sauvegardé le JDC sous un autre nom
438 self.JDCDisplay_courant.fichier = sauvegarde
439 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
445 def changeNomPage(self):
446 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
447 et recrée un autre onglet à la même place avec le bon nom
450 self.JDCDisplay_courant.jdc.nom = nom
451 nom_page = self.nb.getcurselection()
452 num_page = self.nb.index(nom_page)
453 tab = self.nb.tab(num_page)
454 tab.configure(text = nom)
456 def exitEFICAS(self,event=None):
458 Permet de sortir d'EFICAS en demandant à l'utilisateur
459 s'il veut sauvegarder les modifications en cours
461 liste = self.GetListeJDCaSauvegarder()
463 # Certains fichiers n'ont pas été sauvegardés ...
464 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
465 test = self.saveall(liste)
468 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
469 for JDCDisplay in self.liste_JDCDisplay:
470 JDCDisplay.jdc.supprime()
474 def GetListeJDCaSauvegarder(self) :
475 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
476 if not self.JDCDisplay_courant : return []
477 if len(self.liste_JDCDisplay) == 0 : return l
479 for JDCDisplay in self.liste_JDCDisplay:
480 if JDCDisplay.modified == 'o' :
484 def copy(self,event=None):
486 Lance la copie sur le JDC courant
488 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
490 def paste(self,event=None):
492 Lance le collage sur le JDC courant
494 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
496 def cut(self,event=None):
498 Lance le cut sur le JDC courant
500 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
504 Lance la suppression du noeud courant
506 if not self.JDCDisplay_courant : return
508 if self.JDCDisplay_courant.modified == 'n' :
509 self.JDCDisplay_courant.init_modif()
510 pere = self.JDCDisplay_courant.node_selected.parent
511 # Le noeud n'est pas au 1er niveau
512 if pere.parent.parent != None:
513 self.JDCDisplay_courant.node_selected.delete()
516 noeudselecte = self.JDCDisplay_courant.node_selected
517 parent = noeudselecte.parent
518 enfants = parent.children
519 index = enfants.index(noeudselecte)
520 self.JDCDisplay_courant.node_selected.delete()
522 enfants[index].select()
524 enfants[index-1].select()
525 except AttributeError:
528 def visuJDC_py(self,event=None):
530 Méthode permettant d'afficher dans une fenêtre à part l'écho au
531 format python du jdc courant
533 if not hasattr(self,'JDC') : return
534 jdc_fini = self.get_text_JDC('python')
535 if jdc_fini == None : return
537 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
542 Méthode permettant d'afficher dans une fenêtre à part l'écho au
543 format .comm ou .py du jdc courant
545 if not hasattr(self,'JDC') : return
546 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
547 format=self.appli.format_fichier.get()
548 self.jdc_fini = self.get_text_JDC(format)
549 if self.jdc_fini == None : return
550 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
552 def get_text_JDC(self,format):
553 if generator.plugins.has_key(format):
554 # Le generateur existe on l'utilise
555 g=generator.plugins[format]()
556 jdc_formate=g.gener(self.JDC,format='beautifie')
557 if not g.cr.estvide():
559 self.appli.affiche_infos("Erreur à la generation")
560 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
565 # Il n'existe pas c'est une erreur
566 self.appli.affiche_infos("Format %s non reconnu" % format)
567 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
572 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
573 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
574 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
576 if not self.JDCDisplay_courant : return
578 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
579 if cle_doc == None : return
580 cle_doc = string.replace(cle_doc,'.','')
581 cle_doc = string.replace(cle_doc,'-','')
582 commande = self.appli.CONFIGURATION.exec_acrobat
583 nom_fichier = cle_doc+".pdf"
584 rep_fichier = cle_doc[0:2]
585 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
587 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
588 elif os.name == 'posix':
589 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
590 pid = os.system(script)
591 except AttributeError:
592 traceback.print_exc()
595 def visu_a_plat(self,event=None):
597 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
599 if not hasattr(self,'JDC') : return
600 titre = 'fichier '+ self.JDCName + ' à plat '
601 self.jdc_fini = self.get_text_JDC('aplat')
602 if self.jdc_fini == None : return
603 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
605 def visu_txt_brut_JDC(self,event=None):
607 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
609 if not hasattr(self,'JDC') : return
610 titre = "fichier de commandes utilisateur"
611 #texte = self.JDC.procedure
613 if self.JDCDisplay_courant.fichier == None:
614 self.appli.affiche_infos("Pas de fichier initial")
615 showerror("Impossible de visualiser le fichier initial",
616 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
618 f=open(self.JDCDisplay_courant.fichier,'r')
621 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
623 def affichage_fichier_ini(self):
625 Affichage des valeurs des paramètres relus par Eficas
627 self.appli.CONFIGURATION.affichage_fichier_ini()
629 def saveall(self,liste):
631 Sauvegarde tous les JDC contenus dans liste
634 for JDCDisplay in liste :
635 self.JDC = JDCDisplay.jdc
636 test = test * self.saveJDC(echo = 'non')
639 def save_homard(self,nom,texte):
640 file_homard=nom+'.conf_homard'
642 f=open(file_homard,'w')
648 print "Pb a la sauvegarde sous le format homard"
649 if self.appli.salome != 0:
651 self.appli.salome.rangeInStudy(file_homard,"_CONF")
653 # ---------------------------------------------------------------------------
654 # Méthodes liées aux mots-clés inconnus
655 # ---------------------------------------------------------------------------
657 def mc_inconnus(self):
658 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
659 o = fenetre_mc_inconnus(l_mc)
660 l = o.wait_new_list()
661 #print "mc_inconnus_new_list: ",l
662 #CCAR: Il n' y a pas de retour vers le JDC
664 def aideEFICAS(self,event=None):
665 AIDE.go(master=self.parent)
667 def update_jdc_courant(self):
668 self.JDCDisplay_courant.update()