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():
356 self.appli.affiche_infos("Erreur à la generation")
357 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
360 # Il n'existe pas c'est une erreur
361 self.appli.affiche_infos("Format %s non reconnu" % format)
362 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
364 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
366 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
367 return self.asknomsauvegardeJDC()
368 elif self.JDCDisplay_courant.fichier != None :
370 # Pour sauvegarde dans l etude si lancement depuis salome
371 if self.appli.salome != 0:
373 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
374 from panelsSalome import SALOME_UNIQUE_BASE_Panel
375 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
376 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
380 MyCLinit=eficasCL.CLinit()
385 #PN Fin Ajout --> Salome
386 # le JDC a déjà un nom : on sauvegarde directement sans demander
387 # un autre nom au développeur
388 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
389 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
392 if self.appli.format_fichier.get() == 'homard':
393 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
394 self.JDCDisplay_courant.stop_modif()
395 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
398 def asknomsauvegardeJDC(self):
399 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
400 titre = "Sauvegarde d'un fichier de commandes "+self.code
401 if self.code == 'ASTER':
403 filtyp = ( ("ASTER", ".comm"),)
406 filtyp = ( (self.code, ".py"),)
407 sauvegarde = asksaveasfilename(title=titre,
408 defaultextension=defext,
410 initialdir = self.appli.CONFIGURATION.initialdir)
411 #initialdir = self.appli.CONFIGURATION.rep_user)
413 # PN ajout --> Salome
414 # Pour sauvegarde dans l etude si lancement depuis salome
415 if self.appli.salome != 0:
417 self.appli.salome.rangeInStudy(sauvegarde)
418 from panelsSalome import SALOME_UNIQUE_BASE_Panel
419 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
420 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
424 MyCLinit=eficasCL.CLinit()
429 # PN fin ajout --> Salome
430 if not save_in_file(sauvegarde,self.jdc_fini) :
431 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
434 if self.appli.format_fichier.get() == 'homard':
435 self.save_homard(sauvegarde,self.jdc_homard)
436 self.JDCDisplay_courant.stop_modif()
437 self.appli.affiche_infos("Sauvegarde effectuée")
438 if sauvegarde != self.JDCDisplay_courant.fichier :
439 # l'utilisateur a sauvegardé le JDC sous un autre nom
440 self.JDCDisplay_courant.fichier = sauvegarde
441 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
447 def changeNomPage(self):
448 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
449 et recrée un autre onglet à la même place avec le bon nom
452 self.JDCDisplay_courant.jdc.nom = nom
453 nom_page = self.nb.getcurselection()
454 num_page = self.nb.index(nom_page)
455 tab = self.nb.tab(num_page)
456 tab.configure(text = nom)
458 def exitEFICAS(self,event=None):
460 Permet de sortir d'EFICAS en demandant à l'utilisateur
461 s'il veut sauvegarder les modifications en cours
463 liste = self.GetListeJDCaSauvegarder()
465 # Certains fichiers n'ont pas été sauvegardés ...
466 if askyesno("Enregistrer modifications","Enregistrer les modifications ?") :
467 test = self.saveall(liste)
470 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
471 for JDCDisplay in self.liste_JDCDisplay:
472 JDCDisplay.jdc.supprime()
476 def GetListeJDCaSauvegarder(self) :
477 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
478 if not self.JDCDisplay_courant : return []
479 if len(self.liste_JDCDisplay) == 0 : return l
481 for JDCDisplay in self.liste_JDCDisplay:
482 if JDCDisplay.modified == 'o' :
486 def copy(self,event=None):
488 Lance la copie sur le JDC courant
490 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
492 def paste(self,event=None):
494 Lance le collage sur le JDC courant
496 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
498 def cut(self,event=None):
500 Lance le cut sur le JDC courant
502 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
506 Lance la suppression du noeud courant
508 if not self.JDCDisplay_courant : return
510 if self.JDCDisplay_courant.modified == 'n' :
511 self.JDCDisplay_courant.init_modif()
512 pere = self.JDCDisplay_courant.node_selected.parent
513 # Le noeud n'est pas au 1er niveau
514 if pere.parent.parent != None:
515 self.JDCDisplay_courant.node_selected.delete()
518 noeudselecte = self.JDCDisplay_courant.node_selected
519 parent = noeudselecte.parent
520 enfants = parent.children
521 index = enfants.index(noeudselecte)
522 self.JDCDisplay_courant.node_selected.delete()
524 enfants[index].select()
526 enfants[index-1].select()
527 except AttributeError:
530 def visuJDC_py(self,event=None):
532 Méthode permettant d'afficher dans une fenêtre à part l'écho au
533 format python du jdc courant
535 if not hasattr(self,'JDC') : return
536 jdc_fini = self.get_text_JDC('python')
537 if jdc_fini == None : return
539 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
544 Méthode permettant d'afficher dans une fenêtre à part l'écho au
545 format .comm ou .py du jdc courant
547 if not hasattr(self,'JDC') : return
548 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
549 format=self.appli.format_fichier.get()
550 self.jdc_fini = self.get_text_JDC(format)
551 if self.jdc_fini == None : return
552 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
554 def get_text_JDC(self,format):
555 if generator.plugins.has_key(format):
556 # Le generateur existe on l'utilise
557 g=generator.plugins[format]()
558 jdc_formate=g.gener(self.JDC,format='beautifie')
559 if not g.cr.estvide():
561 self.appli.affiche_infos("Erreur à la generation")
562 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
567 # Il n'existe pas c'est une erreur
568 self.appli.affiche_infos("Format %s non reconnu" % format)
569 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
574 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
575 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
576 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
578 if not self.JDCDisplay_courant : return
580 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
581 if cle_doc == None : return
582 cle_doc = string.replace(cle_doc,'.','')
583 cle_doc = string.replace(cle_doc,'-','')
584 commande = self.appli.CONFIGURATION.exec_acrobat
585 nom_fichier = cle_doc+".pdf"
586 rep_fichier = cle_doc[0:2]
587 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
589 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
590 elif os.name == 'posix':
591 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
592 pid = os.system(script)
593 except AttributeError:
594 traceback.print_exc()
597 def visu_a_plat(self,event=None):
599 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
601 if not hasattr(self,'JDC') : return
602 titre = 'fichier '+ self.JDCName + ' à plat '
603 self.jdc_fini = self.get_text_JDC('aplat')
604 if self.jdc_fini == None : return
605 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
607 def visu_txt_brut_JDC(self,event=None):
609 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
611 if not hasattr(self,'JDC') : return
612 titre = "fichier de commandes utilisateur"
613 #texte = self.JDC.procedure
615 if self.JDCDisplay_courant.fichier == None:
616 self.appli.affiche_infos("Pas de fichier initial")
617 showerror("Impossible de visualiser le fichier initial",
618 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
620 f=open(self.JDCDisplay_courant.fichier,'r')
623 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
625 def affichage_fichier_ini(self):
627 Affichage des valeurs des paramètres relus par Eficas
629 self.appli.CONFIGURATION.affichage_fichier_ini()
631 def saveall(self,liste):
633 Sauvegarde tous les JDC contenus dans liste
636 for JDCDisplay in liste :
637 self.JDC = JDCDisplay.jdc
638 test = test * self.saveJDC(echo = 'non')
641 def save_homard(self,nom,texte):
642 file_homard=nom+'.conf_homard'
644 f=open(file_homard,'w')
650 print "Pb a la sauvegarde sous le format homard"
651 if self.appli.salome != 0:
653 self.appli.salome.rangeInStudy(file_homard,"_CONF")
655 # ---------------------------------------------------------------------------
656 # Méthodes liées aux mots-clés inconnus
657 # ---------------------------------------------------------------------------
659 def mc_inconnus(self):
660 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
661 o = fenetre_mc_inconnus(l_mc)
662 l = o.wait_new_list()
663 #print "mc_inconnus_new_list: ",l
664 #CCAR: Il n' y a pas de retour vers le JDC
666 def aideEFICAS(self,event=None):
667 AIDE.go(master=self.parent)
669 def update_jdc_courant(self):
670 self.JDCDisplay_courant.update()