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 if self.appli.test == 0 :
100 splash._splash.configure(text = "Création du bureau")
101 self.nb = Pmw.NoteBook(self.parent,raisecommand=self.selectJDC)
102 self.nb.pack(fill='both',expand=1)
103 self.JDCDisplay_courant=None
105 self.liste_JDCDisplay=[]
108 def cree_cataitem(self):
110 On récupère dans l'appli_composant readercata les variables
111 qui servent par la suite pour la création des JDC
113 self.cataitem=self.appli.readercata.cataitem
114 self.cata=self.appli.readercata.cata
115 self.cata_ordonne_dico=self.appli.readercata.cata_ordonne_dico
116 self.code=self.appli.readercata.code
117 self.version_code=self.appli.readercata.version_code
118 self.fic_cata=self.appli.readercata.fic_cata
120 def selectJDC(self,event=None):
122 Cette méthode est appelée chaque fois que l'on sélectionne
123 l'onglet d'un JDC dans le NoteBook des JDC.
124 Elle permet de stocker dans les variable self.JDC et
125 self.JDCDisplay_courant les valeurs concernant le JDC courant
127 if len(self.liste_JDCDisplay) == 0 : return
128 #if self.JDCDisplay_courant : self.JDCDisplay_courant.jdc.unset_context()
129 numero_jdc = self.nb.index(self.nb.getcurselection())
130 self.JDCDisplay_courant = self.liste_JDCDisplay[numero_jdc]
131 self.JDC = self.JDCDisplay_courant.jdc
132 #self.JDC.set_context()
133 self.JDCName = self.JDC.nom
135 def newJDC(self,event=None):
137 Initialise un nouveau JDC vierge
139 self.appli.statusbar.reset_affichage_infos()
141 CONTEXT.unset_current_step()
142 J=self.cata[0].JdC(cata=self.cata,
143 cata_ord_dico=self.cata_ordonne_dico,
145 rep_mat=self.appli.CONFIGURATION.rep_mat,
149 self.ShowJDC(J,self.JDCName)
150 self.appli.toolbar.active_boutons()
152 def ShowJDC(self,JDC,nom,label_onglet=None):
154 Lance l'affichage du JDC cad création du JDCDisplay
155 Rajoute le JDCDisplay à la liste des JDCDisplay si label_onglet == None cad si on crée
156 bien un nouveau JDCDisplay et non si on remplace (renommage de l'onglet)
159 self.JDCName = self.JDC.nom = nom
160 #XXX CCAR: pour le moment mis en commentaire
161 #self.JDC.set_context()
162 if label_onglet == None :
163 label_onglet = self.GetLabelJDC()
164 self.nb.add(label_onglet,tab_text = nom,tab_width=20)
168 self.JDCDisplay_courant=JDCDISPLAY(self.JDC,nom,appli=self.appli,parent=self.nb.page(label_onglet))
170 self.liste_JDCDisplay.append(self.JDCDisplay_courant)
171 self.JDCDisplay_courant.modified='n'
172 self.JDCDisplay_courant.fichier=self.fileName
173 self.nb.selectpage(label_onglet)
174 self.nb.setnaturalsize()
175 texte = "Jeu de commandes :" + self.JDCName+" ouvert"
176 self.appli.affiche_infos(texte)
178 def closeJDC (self,event=None) :
180 Ferme le JDC courant et détruit l'onglet associé dans le notebook self.nb
182 if self.JDCDisplay_courant.modified == 'o' :
183 message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
184 reponse = askyesno(title="Sauvegarde du jdc courant",
187 test = self.saveJDC()
189 self.appli.affiche_infos("Sauvegarde impossible")
191 self.JDCDisplay_courant.jdc.supprime()
192 self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
193 self.nb.delete(self.nb.getcurselection())
194 #XXX CCAR: pour le moment mis en commentaire
195 #self.JDC.unset_context()
198 index = self.nb.index(self.nb.getcurselection())
199 self.JDCDisplay_courant = self.liste_JDCDisplay[index]
200 self.JDC = self.JDCDisplay_courant.jdc
202 self.JDCDisplay_courant = None
203 self.appli.toolbar.inactive_boutons()
205 def visuCRJDC(self,event=None):
206 return self.visuCR(mode='JDC')
208 def visuCR(self,mode):
210 Méthode permettant l'affichage du rapport de validation
213 if not hasattr(self,'JDC') : return
214 titre="rapport de validation du jeu de commandes courant"
215 cr = self.JDC.report()
216 self.update_jdc_courant()
218 from Noyau.N_CR import CR
220 cr.debut = "Début rapport de validation du catalogue"
221 cr.fin = "Fin rapport de validation du catalogue"
222 titre="rapport de validation du catalogue"
223 if hasattr(self,'cata_ordonne_cr') :
224 cr.add(self.cata_ordonne_cr)
225 if hasattr(self,'cata_dev_ordonne_cr') :
226 cr.add(self.cata_dev_ordonne_cr)
227 for cata in self.cata:
228 if hasattr(cata,'JdC'):
229 cr.add(cata.JdC.report())
231 self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
233 def openJDC(self,file=None):
235 Demande à l'utilisateur quel JDC existant il veut ouvrir
237 if self.code == 'ASTER':
238 filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
239 elif self.code == 'HOMARD' :
240 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),("Tous",'*'))
242 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
243 if not hasattr(self,'initialdir'):
244 #self.initialdir = self.appli.CONFIGURATION.rep_user
245 self.initialdir = self.appli.CONFIGURATION.initialdir
246 if file.__class__.__name__ in ('Event',):
249 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
250 defaultextension=".comm",
251 filetypes = filetypes,
252 initialdir = self.initialdir)
255 e=extension_fichier(file)
256 self.JDCName=stripPath(file)
257 self.initialdir = os.path.dirname(file)
260 #XXX CCAR: pour le moment mis en commentaire
261 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
263 format=self.appli.format_fichier.get()
264 # Il faut convertir le contenu du fichier en fonction du format
265 if convert.plugins.has_key(format):
266 # Le convertisseur existe on l'utilise
267 p=convert.plugins[format]()
269 text=p.convert('exec')
270 if not p.cr.estvide():
271 self.appli.affiche_infos("Erreur à la conversion")
273 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
274 texte = str(p.cr)).wait()
277 # Il n'existe pas c'est une erreur
278 self.appli.affiche_infos("Type de fichier non reconnu")
279 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
282 # On se met dans le repertoire ou se trouve le fichier de commandes
283 # pour trouver les eventuels fichiers include ou autres
284 # localises a cote du fichier de commandes
285 os.chdir(self.initialdir)
286 CONTEXT.unset_current_step()
287 J=self.cata[0].JdC(procedure=text,appli=self.appli,
288 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
290 rep_mat=self.appli.CONFIGURATION.rep_mat,
293 txt_exception = J.cr.get_mess_exception()
295 # des exceptions ont été levées à la création du JDC
296 # --> on affiche les erreurs mais pas le JDC
297 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
298 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
300 self.ShowJDC(J,self.JDCName)
301 self.appli.toolbar.active_boutons()
302 # si le JDC ne contient rien (vide), on retourne ici
303 if len(self.JDC.etapes) == 0 : return
304 # dans le cas où le JDC est invalide, on affiche son CR
305 if not self.JDC.isvalid():
306 self.appli.top.update()
307 self.visuCR(mode='JDC')
310 def GetLabelJDC(self,nb_jdc = 'absent'):
312 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
314 if nb_jdc == 'absent':
315 nb_jdc = len(self.nb.pagenames())
317 label_onglet = 'JDC'+`nb_jdc`
318 if label_onglet not in self.nb.pagenames() :
321 return self.GetLabelJDC(nb_jdc)
323 def saveasJDC(self,event=None):
325 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
326 donner le nom du fichier de sauvegarde
328 self.saveJDC(echo='oui')
330 def saveJDC(self,echo='non'):
332 Sauvegarde le JDC courant.
333 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
334 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
336 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
338 if not hasattr(self,'JDC') : return 0
339 format=self.appli.format_fichier.get()
340 if generator.plugins.has_key(format):
341 # Le generateur existe on l'utilise
342 g=generator.plugins[format]()
343 jdc_formate=g.gener(self.JDC,format='beautifie')
344 if format == 'homard':
345 self.jdc_homard=g.get_homard()
346 if not g.cr.estvide():
348 self.appli.affiche_infos("Erreur à la generation")
349 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
352 # Il n'existe pas c'est une erreur
353 self.appli.affiche_infos("Format %s non reconnu" % format)
354 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
356 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
358 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
359 return self.asknomsauvegardeJDC()
360 elif self.JDCDisplay_courant.fichier != None :
362 # Pour sauvegarde dans l etude si lancement depuis salome
363 if self.appli.salome != 0:
365 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
366 from panelsSalome import SALOME_UNIQUE_BASE_Panel
367 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
368 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
369 #PN Fin Ajout --> Salome
370 # le JDC a déjà un nom : on sauvegarde directement sans demander
371 # un autre nom au développeur
372 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
373 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
376 if self.appli.format_fichier.get() == 'homard':
377 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
378 self.JDCDisplay_courant.stop_modif()
379 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
382 def asknomsauvegardeJDC(self):
383 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
384 titre = "Sauvegarde d'un fichier de commandes "+self.code
385 if self.code == 'ASTER':
387 filtyp = ( ("ASTER", ".comm"),)
390 filtyp = ( (self.code, ".py"),)
391 sauvegarde = asksaveasfilename(title=titre,
392 defaultextension=defext,
394 initialdir = self.appli.CONFIGURATION.initialdir)
395 #initialdir = self.appli.CONFIGURATION.rep_user)
397 # PN ajout --> Salome
398 # Pour sauvegarde dans l etude si lancement depuis salome
399 if self.appli.salome != 0:
401 self.appli.salome.rangeInStudy(sauvegarde)
402 from panelsSalome import SALOME_UNIQUE_BASE_Panel
403 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
404 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
405 # PN fin ajout --> Salome
406 if not save_in_file(sauvegarde,self.jdc_fini) :
407 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
410 if self.appli.format_fichier.get() == 'homard':
411 self.save_homard(sauvegarde,self.jdc_homard)
412 self.JDCDisplay_courant.stop_modif()
413 self.appli.affiche_infos("Sauvegarde effectuée")
414 if sauvegarde != self.JDCDisplay_courant.fichier :
415 # l'utilisateur a sauvegardé le JDC sous un autre nom
416 self.JDCDisplay_courant.fichier = sauvegarde
417 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
423 def changeNomPage(self):
424 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
425 et recrée un autre onglet à la même place avec le bon nom
428 self.JDCDisplay_courant.jdc.nom = nom
429 nom_page = self.nb.getcurselection()
430 num_page = self.nb.index(nom_page)
431 tab = self.nb.tab(num_page)
432 tab.configure(text = nom)
434 def exitEFICAS(self,event=None):
436 Permet de sortir d'EFICAS en demandant à l'utilisateur
437 s'il veut sauvegarder les modifications en cours
439 liste = self.GetListeJDCaSauvegarder()
441 # Certains fichiers n'ont pas été sauvegardés ...
442 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
443 test = self.saveall(liste)
446 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
447 for JDCDisplay in self.liste_JDCDisplay:
448 JDCDisplay.jdc.supprime()
452 def GetListeJDCaSauvegarder(self) :
453 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
454 if not self.JDCDisplay_courant : return []
455 if len(self.liste_JDCDisplay) == 0 : return l
457 for JDCDisplay in self.liste_JDCDisplay:
458 if JDCDisplay.modified == 'o' :
462 def copy(self,event=None):
464 Lance la copie sur le JDC courant
466 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
468 def paste(self,event=None):
470 Lance le collage sur le JDC courant
472 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
474 def cut(self,event=None):
476 Lance le cut sur le JDC courant
478 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
482 Lance la suppression du noeud courant
484 if not self.JDCDisplay_courant : return
486 if self.JDCDisplay_courant.modified == 'n' :
487 self.JDCDisplay_courant.init_modif()
488 pere = self.JDCDisplay_courant.node_selected.parent
489 # Le noeud n'est pas au 1er niveau
490 if pere.parent.parent != None:
491 self.JDCDisplay_courant.node_selected.delete()
494 noeudselecte = self.JDCDisplay_courant.node_selected
495 parent = noeudselecte.parent
496 enfants = parent.children
497 index = enfants.index(noeudselecte)
498 self.JDCDisplay_courant.node_selected.delete()
500 enfants[index].select()
502 enfants[index-1].select()
503 except AttributeError:
506 def visuJDC_py(self):
508 Méthode permettant d'afficher dans une fenêtre à part l'écho au
509 format python du jdc courant
511 if not hasattr(self,'JDC') : return
512 jdc_fini = self.get_text_JDC('python')
513 if jdc_fini == None : return
515 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
520 Méthode permettant d'afficher dans une fenêtre à part l'écho au
521 format .comm ou .py du jdc courant
523 if not hasattr(self,'JDC') : return
524 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
525 format=self.appli.format_fichier.get()
526 self.jdc_fini = self.get_text_JDC(format)
527 if self.jdc_fini == None : return
528 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
530 def get_text_JDC(self,format):
531 if generator.plugins.has_key(format):
532 # Le generateur existe on l'utilise
533 g=generator.plugins[format]()
534 jdc_formate=g.gener(self.JDC,format='beautifie')
535 if not g.cr.estvide():
537 self.appli.affiche_infos("Erreur à la generation")
538 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
543 # Il n'existe pas c'est une erreur
544 self.appli.affiche_infos("Format %s non reconnu" % format)
545 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
550 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
551 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
552 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
554 if not self.JDCDisplay_courant : return
556 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
557 if cle_doc == None : return
558 cle_doc = string.replace(cle_doc,'.','')
559 cle_doc = string.replace(cle_doc,'-','')
560 commande = self.appli.CONFIGURATION.exec_acrobat
561 nom_fichier = cle_doc+".pdf"
562 rep_fichier = cle_doc[0:2]
563 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
565 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
566 elif os.name == 'posix':
567 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
568 pid = os.system(script)
569 except AttributeError:
570 traceback.print_exc()
573 def visu_a_plat(self,event=None):
575 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
577 if not hasattr(self,'JDC') : return
578 titre = 'fichier '+ self.JDCName + ' à plat '
579 self.jdc_fini = self.get_text_JDC('aplat')
580 if self.jdc_fini == None : return
581 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
583 def visu_txt_brut_JDC(self,event=None):
585 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
587 if not hasattr(self,'JDC') : return
588 titre = "fichier de commandes utilisateur"
589 #texte = self.JDC.procedure
591 if self.JDCDisplay_courant.fichier == None:
592 self.appli.affiche_infos("Pas de fichier initial")
593 showerror("Impossible de visualiser le fichier initial",
594 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
596 f=open(self.JDCDisplay_courant.fichier,'r')
599 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
601 def affichage_fichier_ini(self):
603 Affichage des valeurs des paramètres relus par Eficas
605 self.appli.CONFIGURATION.affichage_fichier_ini()
607 def saveall(self,liste):
609 Sauvegarde tous les JDC contenus dans liste
612 for JDCDisplay in liste :
613 self.JDC = JDCDisplay.jdc
614 test = test * self.saveJDC(echo = 'non')
617 def save_homard(self,nom,texte):
618 file_homard=nom+'.conf_homard'
620 f=open(file_homard,'w')
626 print "Pb a la sauvegarde sous le format homard"
627 if self.appli.salome != 0:
629 self.appli.salome.rangeInStudy(file_homard)
631 # ---------------------------------------------------------------------------
632 # Méthodes liées aux mots-clés inconnus
633 # ---------------------------------------------------------------------------
635 def mc_inconnus(self):
636 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
637 o = fenetre_mc_inconnus(l_mc)
638 l = o.wait_new_list()
639 #print "mc_inconnus_new_list: ",l
640 #CCAR: Il n' y a pas de retour vers le JDC
642 def aideEFICAS(self,event=None):
643 AIDE.go(master=self.parent)
645 def update_jdc_courant(self):
646 self.JDCDisplay_courant.update()