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 tkFileDialog import askopenfilename,asksaveasfilename
28 from tkMessageBox 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
46 ('Enregistrer','saveJDC'),
47 ('Enregistrer sous','saveasJDC'),
49 ('Fermer','closeJDC'),
50 ('Quitter','exitEFICAS'),
60 ('Rapport de validation','visuCRJDC'),
61 ('Fichier à plat','visu_a_plat'),
62 ('Fichier .py','visuJDC_py'),
63 ('Fichier source','visu_txt_brut_JDC'),
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
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) :
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()
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
243 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
244 defaultextension=".comm",
245 filetypes = filetypes,
246 initialdir = self.initialdir)
249 e=extension_fichier(file)
250 self.JDCName=stripPath(file)
251 self.initialdir = os.path.dirname(file)
254 #XXX CCAR: pour le moment mis en commentaire
255 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
257 format=self.appli.format_fichier.get()
258 # Il faut convertir le contenu du fichier en fonction du format
259 if convert.plugins.has_key(format):
260 # Le convertisseur existe on l'utilise
261 p=convert.plugins[format]()
263 text=p.convert('exec')
264 if not p.cr.estvide():
265 self.appli.affiche_infos("Erreur à la conversion")
267 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
268 texte = str(p.cr)).wait()
271 # Il n'existe pas c'est une erreur
272 self.appli.affiche_infos("Type de fichier non reconnu")
273 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
276 # On se met dans le repertoire ou se trouve le fichier de commandes
277 # pour trouver les eventuels fichiers include ou autres
278 # localises a cote du fichier de commandes
279 os.chdir(self.initialdir)
280 CONTEXT.unset_current_step()
281 J=self.cata[0].JdC(procedure=text,appli=self.appli,
282 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
284 rep_mat=self.appli.CONFIGURATION.rep_mat,
287 txt_exception = J.cr.get_mess_exception()
289 # des exceptions ont été levées à la création du JDC
290 # --> on affiche les erreurs mais pas le JDC
291 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
292 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
294 self.ShowJDC(J,self.JDCName)
295 self.appli.toolbar.active_boutons()
296 # si le JDC ne contient rien (vide), on retourne ici
297 if len(self.JDC.etapes) == 0 : return
298 # dans le cas où le JDC est invalide, on affiche son CR
299 if not self.JDC.isvalid():
300 #cr = self.JDC.report()
301 #if not cr.estvide() :
302 self.appli.top.update()
303 self.visuCR(mode='JDC')
306 def GetLabelJDC(self,nb_jdc = 'absent'):
308 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
310 if nb_jdc == 'absent':
311 nb_jdc = len(self.nb.pagenames())
313 label_onglet = 'JDC'+`nb_jdc`
314 if label_onglet not in self.nb.pagenames() :
317 return self.GetLabelJDC(nb_jdc)
321 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
322 donner le nom du fichier de sauvegarde
324 self.saveJDC(echo='oui')
326 def saveJDC(self,echo='non'):
328 Sauvegarde le JDC courant.
329 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
330 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
332 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
334 if not hasattr(self,'JDC') : return 0
335 format=self.appli.format_fichier.get()
336 if generator.plugins.has_key(format):
337 # Le generateur existe on l'utilise
338 g=generator.plugins[format]()
339 jdc_formate=g.gener(self.JDC,format='beautifie')
340 if not g.cr.estvide():
342 self.appli.affiche_infos("Erreur à la generation")
343 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
346 # Il n'existe pas c'est une erreur
347 self.appli.affiche_infos("Format %s non reconnu" % format)
348 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
350 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
352 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
353 return self.asknomsauvegardeJDC()
354 elif self.JDCDisplay_courant.fichier != None :
355 # le JDC a déjà un nom : on sauvegarde directement sans demander
356 # un autre nom au développeur
357 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
358 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
361 self.JDCDisplay_courant.stop_modif()
362 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
365 def asknomsauvegardeJDC(self):
366 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
367 titre = "Sauvegarde d'un fichier de commandes "+self.code
368 if self.code == 'ASTER':
370 filtyp = ( ("ASTER", ".comm"),)
373 filtyp = ( (self.code, ".py"),)
374 sauvegarde = asksaveasfilename(title=titre,
375 defaultextension=defext,
377 initialdir = self.appli.CONFIGURATION.initialdir)
378 #initialdir = self.appli.CONFIGURATION.rep_user)
380 if not save_in_file(sauvegarde,self.jdc_fini) :
381 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
384 self.JDCDisplay_courant.stop_modif()
385 self.appli.affiche_infos("Sauvegarde effectuée")
386 if sauvegarde != self.JDCDisplay_courant.fichier :
387 # l'utilisateur a sauvegardé le JDC sous un autre nom
388 self.JDCDisplay_courant.fichier = sauvegarde
389 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
395 def changeNomPage(self):
396 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
397 et recrée un autre onglet à la même place avec le bon nom
400 self.JDCDisplay_courant.jdc.nom = nom
401 nom_page = self.nb.getcurselection()
402 num_page = self.nb.index(nom_page)
403 tab = self.nb.tab(num_page)
404 tab.configure(text = nom)
406 def exitEFICAS(self):
408 Permet de sortir d'EFICAS en demandant à l'utilisateur
409 s'il veut sauvegarder les modifications en cours
411 liste = self.GetListeJDCaSauvegarder()
413 # Certains fichiers n'ont pas été sauvegardés ...
414 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
415 test = self.saveall(liste)
418 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
419 for JDCDisplay in self.liste_JDCDisplay:
420 JDCDisplay.jdc.supprime()
424 def GetListeJDCaSauvegarder(self) :
425 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
426 if not self.JDCDisplay_courant : return []
427 if len(self.liste_JDCDisplay) == 0 : return l
429 for JDCDisplay in self.liste_JDCDisplay:
430 if JDCDisplay.modified == 'o' :
436 Lance la copie sur le JDC courant
438 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
442 Lance le collage sur le JDC courant
444 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
448 Lance le cut sur le JDC courant
450 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
454 Lance la suppression du noeud courant
456 if not self.JDCDisplay_courant : return
458 if self.JDCDisplay_courant.modified == 'n' :
459 self.JDCDisplay_courant.init_modif()
460 pere = self.JDCDisplay_courant.node_selected.parent
461 self.JDCDisplay_courant.node_selected.delete()
463 except AttributeError:
466 def visuJDC_py(self):
468 Méthode permettant d'afficher dans une fenêtre à part l'écho au
469 format python du jdc courant
471 if not hasattr(self,'JDC') : return
472 jdc_fini = self.get_text_JDC('python')
473 if jdc_fini == None : return
475 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
480 Méthode permettant d'afficher dans une fenêtre à part l'écho au
481 format .comm ou .py du jdc courant
483 if not hasattr(self,'JDC') : return
484 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
485 format=self.appli.format_fichier.get()
486 self.jdc_fini = self.get_text_JDC(format)
487 if self.jdc_fini == None : return
488 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
490 def get_text_JDC(self,format):
491 if generator.plugins.has_key(format):
492 # Le generateur existe on l'utilise
493 g=generator.plugins[format]()
494 jdc_formate=g.gener(self.JDC,format='beautifie')
495 if not g.cr.estvide():
497 self.appli.affiche_infos("Erreur à la generation")
498 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
503 # Il n'existe pas c'est une erreur
504 self.appli.affiche_infos("Format %s non reconnu" % format)
505 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
510 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
511 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
512 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
514 if not self.JDCDisplay_courant : return
516 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
517 if cle_doc == None : return
518 cle_doc = string.replace(cle_doc,'.','')
519 cle_doc = string.replace(cle_doc,'-','')
520 commande = self.appli.CONFIGURATION.exec_acrobat
521 nom_fichier = cle_doc+".pdf"
522 rep_fichier = cle_doc[0:2]
523 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
525 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
526 elif os.name == 'posix':
527 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
528 pid = os.system(script)
529 except AttributeError:
530 traceback.print_exc()
533 def visu_a_plat(self):
535 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
537 if not hasattr(self,'JDC') : return
538 titre = 'fichier '+ self.JDCName + ' à plat '
539 self.jdc_fini = self.get_text_JDC('aplat')
540 if self.jdc_fini == None : return
541 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
543 def visu_txt_brut_JDC(self):
545 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
547 if not hasattr(self,'JDC') : return
548 titre = "fichier de commandes utilisateur"
549 #texte = self.JDC.procedure
551 if self.JDCDisplay_courant.fichier == None:
552 self.appli.affiche_infos("Pas de fichier initial")
553 showerror("Impossible de visualiser le fichier initial",
554 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
556 f=open(self.JDCDisplay_courant.fichier,'r')
559 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
561 def affichage_fichier_ini(self):
563 Affichage des valeurs des paramètres relus par Eficas
565 self.appli.CONFIGURATION.affichage_fichier_ini()
567 def saveall(self,liste):
569 Sauvegarde tous les JDC contenus dans liste
572 for JDCDisplay in liste :
573 self.JDC = JDCDisplay.jdc
574 test = test * self.saveJDC(echo = 'non')
578 # ---------------------------------------------------------------------------
579 # Méthodes liées aux mots-clés inconnus
580 # ---------------------------------------------------------------------------
582 def mc_inconnus(self):
583 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
584 o = fenetre_mc_inconnus(l_mc)
585 l = o.wait_new_list()
586 #print "mc_inconnus_new_list: ",l
587 #CCAR: Il n' y a pas de retour vers le JDC
589 def aideEFICAS(self):
590 AIDE.go(master=self.parent)
592 def update_jdc_courant(self):
593 self.JDCDisplay_courant.update()