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()
111 def cree_cataitem(self):
113 On récupère dans l'appli_composant readercata les variables
114 qui servent par la suite pour la création des JDC
116 self.cataitem=self.appli.readercata.cataitem
117 self.cata=self.appli.readercata.cata
118 self.cata_ordonne_dico=self.appli.readercata.cata_ordonne_dico
119 self.code=self.appli.readercata.code
120 self.version_code=self.appli.readercata.version_code
121 self.fic_cata=self.appli.readercata.fic_cata
123 def selectJDC(self,event=None):
125 Cette méthode est appelée chaque fois que l'on sélectionne
126 l'onglet d'un JDC dans le NoteBook des JDC.
127 Elle permet de stocker dans les variable self.JDC et
128 self.JDCDisplay_courant les valeurs concernant le JDC courant
130 if len(self.liste_JDCDisplay) == 0 : return
131 #if self.JDCDisplay_courant : self.JDCDisplay_courant.jdc.unset_context()
132 numero_jdc = self.nb.index(self.nb.getcurselection())
133 self.JDCDisplay_courant = self.liste_JDCDisplay[numero_jdc]
134 self.JDC = self.JDCDisplay_courant.jdc
135 #self.JDC.set_context()
136 self.JDCName = self.JDC.nom
138 def newJDC(self,event=None):
140 Initialise un nouveau JDC vierge
142 self.appli.statusbar.reset_affichage_infos()
144 CONTEXT.unset_current_step()
145 J=self.cata[0].JdC(cata=self.cata,
146 cata_ord_dico=self.cata_ordonne_dico,
148 rep_mat=self.appli.CONFIGURATION.rep_mat,
152 self.ShowJDC(J,self.JDCName)
153 self.appli.toolbar.active_boutons()
155 def ShowJDC(self,JDC,nom,label_onglet=None):
157 Lance l'affichage du JDC cad création du JDCDisplay
158 Rajoute le JDCDisplay à la liste des JDCDisplay si label_onglet == None cad si on crée
159 bien un nouveau JDCDisplay et non si on remplace (renommage de l'onglet)
162 self.JDCName = self.JDC.nom = nom
163 #XXX CCAR: pour le moment mis en commentaire
164 #self.JDC.set_context()
165 if label_onglet == None :
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.modified == 'o' :
186 message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
187 reponse = askyesno(title="Sauvegarde du jdc courant",
190 test = self.saveJDC()
192 self.appli.affiche_infos("Sauvegarde impossible")
194 self.JDCDisplay_courant.jdc.supprime()
195 self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
196 self.nb.delete(self.nb.getcurselection())
197 #XXX CCAR: pour le moment mis en commentaire
198 #self.JDC.unset_context()
201 index = self.nb.index(self.nb.getcurselection())
202 self.JDCDisplay_courant = self.liste_JDCDisplay[index]
203 self.JDC = self.JDCDisplay_courant.jdc
205 self.JDCDisplay_courant = None
206 self.appli.toolbar.inactive_boutons()
208 def visuCRJDC(self,event=None):
209 return self.visuCR(mode='JDC')
211 def visuCR(self,mode):
213 Méthode permettant l'affichage du rapport de validation
216 if not hasattr(self,'JDC') : return
217 titre="rapport de validation du jeu de commandes courant"
218 cr = self.JDC.report()
219 self.update_jdc_courant()
221 from Noyau.N_CR import CR
223 cr.debut = "Début rapport de validation du catalogue"
224 cr.fin = "Fin rapport de validation du catalogue"
225 titre="rapport de validation du catalogue"
226 if hasattr(self,'cata_ordonne_cr') :
227 cr.add(self.cata_ordonne_cr)
228 if hasattr(self,'cata_dev_ordonne_cr') :
229 cr.add(self.cata_dev_ordonne_cr)
230 for cata in self.cata:
231 if hasattr(cata,'JdC'):
232 cr.add(cata.JdC.report())
234 self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
236 def openJDC(self,file=None):
238 Demande à l'utilisateur quel JDC existant il veut ouvrir
240 if self.code == 'ASTER':
241 filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
242 elif self.code == 'HOMARD' :
243 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),("Tous",'*'))
245 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
246 if not hasattr(self,'initialdir'):
247 #self.initialdir = self.appli.CONFIGURATION.rep_user
248 self.initialdir = self.appli.CONFIGURATION.initialdir
249 if file.__class__.__name__ in ('Event',):
252 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
253 defaultextension=".comm",
254 filetypes = filetypes,
255 initialdir = self.initialdir)
258 e=extension_fichier(file)
259 self.JDCName=stripPath(file)
260 self.initialdir = os.path.dirname(file)
263 #XXX CCAR: pour le moment mis en commentaire
264 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
266 format=self.appli.format_fichier.get()
267 # Il faut convertir le contenu du fichier en fonction du format
268 if convert.plugins.has_key(format):
269 # Le convertisseur existe on l'utilise
270 p=convert.plugins[format]()
272 text=p.convert('exec')
273 if not p.cr.estvide():
274 self.appli.affiche_infos("Erreur à la conversion")
276 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
277 texte = str(p.cr)).wait()
280 # Il n'existe pas c'est une erreur
281 self.appli.affiche_infos("Type de fichier non reconnu")
282 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
285 # On se met dans le repertoire ou se trouve le fichier de commandes
286 # pour trouver les eventuels fichiers include ou autres
287 # localises a cote du fichier de commandes
288 os.chdir(self.initialdir)
289 CONTEXT.unset_current_step()
290 J=self.cata[0].JdC(procedure=text,appli=self.appli,
291 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
293 rep_mat=self.appli.CONFIGURATION.rep_mat,
296 txt_exception = J.cr.get_mess_exception()
298 # des exceptions ont été levées à la création du JDC
299 # --> on affiche les erreurs mais pas le JDC
300 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
301 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
303 self.ShowJDC(J,self.JDCName)
304 self.appli.toolbar.active_boutons()
305 # si le JDC ne contient rien (vide), on retourne ici
306 if len(self.JDC.etapes) == 0 : return
307 # dans le cas où le JDC est invalide, on affiche son CR
308 if not self.JDC.isvalid():
309 self.appli.top.update()
310 self.visuCR(mode='JDC')
313 def GetLabelJDC(self,nb_jdc = 'absent'):
315 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
317 if nb_jdc == 'absent':
318 nb_jdc = len(self.nb.pagenames())
320 label_onglet = 'JDC'+`nb_jdc`
321 if label_onglet not in self.nb.pagenames() :
324 return self.GetLabelJDC(nb_jdc)
326 def saveasJDC(self,event=None):
328 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
329 donner le nom du fichier de sauvegarde
331 self.saveJDC(echo='oui')
333 def saveJDC(self,echo='non'):
335 Sauvegarde le JDC courant.
336 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
337 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
339 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
341 if not hasattr(self,'JDC') : return 0
342 format=self.appli.format_fichier.get()
343 if generator.plugins.has_key(format):
344 # Le generateur existe on l'utilise
345 g=generator.plugins[format]()
346 jdc_formate=g.gener(self.JDC,format='beautifie')
347 if format == 'homard':
348 self.jdc_homard=g.get_homard()
349 if not g.cr.estvide():
351 self.appli.affiche_infos("Erreur à la generation")
352 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
355 # Il n'existe pas c'est une erreur
356 self.appli.affiche_infos("Format %s non reconnu" % format)
357 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
359 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
361 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
362 return self.asknomsauvegardeJDC()
363 elif self.JDCDisplay_courant.fichier != None :
365 # Pour sauvegarde dans l etude si lancement depuis salome
366 if self.appli.salome != 0:
368 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
369 from panelsSalome import SALOME_UNIQUE_BASE_Panel
370 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
371 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
372 #PN Fin Ajout --> Salome
373 # le JDC a déjà un nom : on sauvegarde directement sans demander
374 # un autre nom au développeur
375 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
376 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
379 if self.appli.format_fichier.get() == 'homard':
380 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
381 self.JDCDisplay_courant.stop_modif()
382 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
385 def asknomsauvegardeJDC(self):
386 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
387 titre = "Sauvegarde d'un fichier de commandes "+self.code
388 if self.code == 'ASTER':
390 filtyp = ( ("ASTER", ".comm"),)
393 filtyp = ( (self.code, ".py"),)
394 sauvegarde = asksaveasfilename(title=titre,
395 defaultextension=defext,
397 initialdir = self.appli.CONFIGURATION.initialdir)
398 #initialdir = self.appli.CONFIGURATION.rep_user)
400 # PN ajout --> Salome
401 # Pour sauvegarde dans l etude si lancement depuis salome
402 if self.appli.salome != 0:
404 self.appli.salome.rangeInStudy(sauvegarde)
405 from panelsSalome import SALOME_UNIQUE_BASE_Panel
406 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
407 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
408 # PN fin ajout --> Salome
409 if not save_in_file(sauvegarde,self.jdc_fini) :
410 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
413 if self.appli.format_fichier.get() == 'homard':
414 self.save_homard(sauvegarde,self.jdc_homard)
415 self.JDCDisplay_courant.stop_modif()
416 self.appli.affiche_infos("Sauvegarde effectuée")
417 if sauvegarde != self.JDCDisplay_courant.fichier :
418 # l'utilisateur a sauvegardé le JDC sous un autre nom
419 self.JDCDisplay_courant.fichier = sauvegarde
420 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
426 def changeNomPage(self):
427 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
428 et recrée un autre onglet à la même place avec le bon nom
431 self.JDCDisplay_courant.jdc.nom = nom
432 nom_page = self.nb.getcurselection()
433 num_page = self.nb.index(nom_page)
434 tab = self.nb.tab(num_page)
435 tab.configure(text = nom)
437 def exitEFICAS(self,event=None):
439 Permet de sortir d'EFICAS en demandant à l'utilisateur
440 s'il veut sauvegarder les modifications en cours
442 liste = self.GetListeJDCaSauvegarder()
444 # Certains fichiers n'ont pas été sauvegardés ...
445 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
446 test = self.saveall(liste)
449 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
450 for JDCDisplay in self.liste_JDCDisplay:
451 JDCDisplay.jdc.supprime()
455 def GetListeJDCaSauvegarder(self) :
456 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
457 if not self.JDCDisplay_courant : return []
458 if len(self.liste_JDCDisplay) == 0 : return l
460 for JDCDisplay in self.liste_JDCDisplay:
461 if JDCDisplay.modified == 'o' :
465 def copy(self,event=None):
467 Lance la copie sur le JDC courant
469 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
471 def paste(self,event=None):
473 Lance le collage sur le JDC courant
475 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
477 def cut(self,event=None):
479 Lance le cut sur le JDC courant
481 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
485 Lance la suppression du noeud courant
487 if not self.JDCDisplay_courant : return
489 if self.JDCDisplay_courant.modified == 'n' :
490 self.JDCDisplay_courant.init_modif()
491 pere = self.JDCDisplay_courant.node_selected.parent
492 # Le noeud n'est pas au 1er niveau
493 if pere.parent.parent != None:
494 self.JDCDisplay_courant.node_selected.delete()
497 noeudselecte = self.JDCDisplay_courant.node_selected
498 parent = noeudselecte.parent
499 enfants = parent.children
500 index = enfants.index(noeudselecte)
501 self.JDCDisplay_courant.node_selected.delete()
503 enfants[index].select()
505 enfants[index-1].select()
506 except AttributeError:
509 def visuJDC_py(self):
511 Méthode permettant d'afficher dans une fenêtre à part l'écho au
512 format python du jdc courant
514 if not hasattr(self,'JDC') : return
515 jdc_fini = self.get_text_JDC('python')
516 if jdc_fini == None : return
518 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
523 Méthode permettant d'afficher dans une fenêtre à part l'écho au
524 format .comm ou .py du jdc courant
526 if not hasattr(self,'JDC') : return
527 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
528 format=self.appli.format_fichier.get()
529 self.jdc_fini = self.get_text_JDC(format)
530 if self.jdc_fini == None : return
531 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
533 def get_text_JDC(self,format):
534 if generator.plugins.has_key(format):
535 # Le generateur existe on l'utilise
536 g=generator.plugins[format]()
537 jdc_formate=g.gener(self.JDC,format='beautifie')
538 if not g.cr.estvide():
540 self.appli.affiche_infos("Erreur à la generation")
541 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
546 # Il n'existe pas c'est une erreur
547 self.appli.affiche_infos("Format %s non reconnu" % format)
548 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
553 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
554 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
555 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
557 if not self.JDCDisplay_courant : return
559 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
560 if cle_doc == None : return
561 cle_doc = string.replace(cle_doc,'.','')
562 cle_doc = string.replace(cle_doc,'-','')
563 commande = self.appli.CONFIGURATION.exec_acrobat
564 nom_fichier = cle_doc+".pdf"
565 rep_fichier = cle_doc[0:2]
566 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
568 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
569 elif os.name == 'posix':
570 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
571 pid = os.system(script)
572 except AttributeError:
573 traceback.print_exc()
576 def visu_a_plat(self,event=None):
578 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
580 if not hasattr(self,'JDC') : return
581 titre = 'fichier '+ self.JDCName + ' à plat '
582 self.jdc_fini = self.get_text_JDC('aplat')
583 if self.jdc_fini == None : return
584 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
586 def visu_txt_brut_JDC(self,event=None):
588 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
590 if not hasattr(self,'JDC') : return
591 titre = "fichier de commandes utilisateur"
592 #texte = self.JDC.procedure
594 if self.JDCDisplay_courant.fichier == None:
595 self.appli.affiche_infos("Pas de fichier initial")
596 showerror("Impossible de visualiser le fichier initial",
597 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
599 f=open(self.JDCDisplay_courant.fichier,'r')
602 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
604 def affichage_fichier_ini(self):
606 Affichage des valeurs des paramètres relus par Eficas
608 self.appli.CONFIGURATION.affichage_fichier_ini()
610 def saveall(self,liste):
612 Sauvegarde tous les JDC contenus dans liste
615 for JDCDisplay in liste :
616 self.JDC = JDCDisplay.jdc
617 test = test * self.saveJDC(echo = 'non')
620 def save_homard(self,nom,texte):
621 file_homard=nom+'.conf_homard'
623 f=open(file_homard,'w')
629 print "Pb a la sauvegarde sous le format homard"
630 if self.appli.salome != 0:
632 self.appli.salome.rangeInStudy(file_homard)
634 # ---------------------------------------------------------------------------
635 # Méthodes liées aux mots-clés inconnus
636 # ---------------------------------------------------------------------------
638 def mc_inconnus(self):
639 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
640 o = fenetre_mc_inconnus(l_mc)
641 l = o.wait_new_list()
642 #print "mc_inconnus_new_list: ",l
643 #CCAR: Il n' y a pas de retour vers le JDC
645 def aideEFICAS(self,event=None):
646 AIDE.go(master=self.parent)
648 def update_jdc_courant(self):
649 self.JDCDisplay_courant.update()