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 == 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):
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.rep_user
250 self.initialdir = self.appli.CONFIGURATION.initialdir
251 if file.__class__.__name__ in ('Event',):
254 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
255 defaultextension=".comm",
256 filetypes = filetypes,
257 initialdir = self.initialdir)
260 e=extension_fichier(file)
261 self.JDCName=stripPath(file)
262 self.initialdir = os.path.dirname(file)
265 #XXX CCAR: pour le moment mis en commentaire
266 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
268 format=self.appli.format_fichier.get()
269 # Il faut convertir le contenu du fichier en fonction du format
270 if convert.plugins.has_key(format):
271 # Le convertisseur existe on l'utilise
272 p=convert.plugins[format]()
274 text=p.convert('exec')
275 if not p.cr.estvide():
276 self.appli.affiche_infos("Erreur à la conversion")
278 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
279 texte = str(p.cr)).wait()
282 # Il n'existe pas c'est une erreur
283 self.appli.affiche_infos("Type de fichier non reconnu")
284 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
287 # On se met dans le repertoire ou se trouve le fichier de commandes
288 # pour trouver les eventuels fichiers include ou autres
289 # localises a cote du fichier de commandes
290 os.chdir(self.initialdir)
291 CONTEXT.unset_current_step()
292 J=self.cata[0].JdC(procedure=text,appli=self.appli,
293 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
295 rep_mat=self.appli.CONFIGURATION.rep_mat,
298 txt_exception = J.cr.get_mess_exception()
300 # des exceptions ont été levées à la création du JDC
301 # --> on affiche les erreurs mais pas le JDC
302 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
303 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
305 self.ShowJDC(J,self.JDCName)
306 self.appli.toolbar.active_boutons()
307 # si le JDC ne contient rien (vide), on retourne ici
308 if len(self.JDC.etapes) == 0 : return
309 # dans le cas où le JDC est invalide, on affiche son CR
310 if not self.JDC.isvalid():
311 self.appli.top.update()
312 self.visuCR(mode='JDC')
315 def GetLabelJDC(self,nb_jdc = 'absent'):
317 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
319 if nb_jdc == 'absent':
320 nb_jdc = len(self.nb.pagenames())
322 label_onglet = 'JDC'+`nb_jdc`
323 if label_onglet not in self.nb.pagenames() :
326 return self.GetLabelJDC(nb_jdc)
328 def saveasJDC(self,event=None):
330 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
331 donner le nom du fichier de sauvegarde
333 self.saveJDC(echo='oui')
335 def saveJDC(self,echo='non'):
337 Sauvegarde le JDC courant.
338 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
339 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
341 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
343 if not hasattr(self,'JDC') : return 0
344 format=self.appli.format_fichier.get()
345 if generator.plugins.has_key(format):
346 # Le generateur existe on l'utilise
347 g=generator.plugins[format]()
348 jdc_formate=g.gener(self.JDC,format='beautifie')
349 if format == 'homard':
350 self.jdc_homard=g.get_homard()
351 if not g.cr.estvide():
353 self.appli.affiche_infos("Erreur à la generation")
354 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
357 # Il n'existe pas c'est une erreur
358 self.appli.affiche_infos("Format %s non reconnu" % format)
359 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
361 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
363 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
364 return self.asknomsauvegardeJDC()
365 elif self.JDCDisplay_courant.fichier != None :
367 # Pour sauvegarde dans l etude si lancement depuis salome
368 if self.appli.salome != 0:
370 self.appli.salome.rangeInStudy(self.JDCDisplay_courant.fichier)
371 from panelsSalome import SALOME_UNIQUE_BASE_Panel
372 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
373 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
374 #PN Fin Ajout --> Salome
375 # le JDC a déjà un nom : on sauvegarde directement sans demander
376 # un autre nom au développeur
377 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
378 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
381 if self.appli.format_fichier.get() == 'homard':
382 self.save_homard(self.JDCDisplay_courant.fichier,self.jdc_homard)
383 self.JDCDisplay_courant.stop_modif()
384 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
387 def asknomsauvegardeJDC(self):
388 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
389 titre = "Sauvegarde d'un fichier de commandes "+self.code
390 if self.code == 'ASTER':
392 filtyp = ( ("ASTER", ".comm"),)
395 filtyp = ( (self.code, ".py"),)
396 sauvegarde = asksaveasfilename(title=titre,
397 defaultextension=defext,
399 initialdir = self.appli.CONFIGURATION.initialdir)
400 #initialdir = self.appli.CONFIGURATION.rep_user)
402 # PN ajout --> Salome
403 # Pour sauvegarde dans l etude si lancement depuis salome
404 if self.appli.salome != 0:
406 self.appli.salome.rangeInStudy(sauvegarde)
407 from panelsSalome import SALOME_UNIQUE_BASE_Panel
408 if len(SALOME_UNIQUE_BASE_Panel.dict_fichier_unite) > 0 :
409 self.appli.salome.creeConfigTxt(self.appli.CONFIGURATION.initialdir,SALOME_UNIQUE_BASE_Panel.dict_fichier_unite)
410 # PN fin ajout --> Salome
411 if not save_in_file(sauvegarde,self.jdc_fini) :
412 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
415 if self.appli.format_fichier.get() == 'homard':
416 self.save_homard(sauvegarde,self.jdc_homard)
417 self.JDCDisplay_courant.stop_modif()
418 self.appli.affiche_infos("Sauvegarde effectuée")
419 if sauvegarde != self.JDCDisplay_courant.fichier :
420 # l'utilisateur a sauvegardé le JDC sous un autre nom
421 self.JDCDisplay_courant.fichier = sauvegarde
422 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
428 def changeNomPage(self):
429 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
430 et recrée un autre onglet à la même place avec le bon nom
433 self.JDCDisplay_courant.jdc.nom = nom
434 nom_page = self.nb.getcurselection()
435 num_page = self.nb.index(nom_page)
436 tab = self.nb.tab(num_page)
437 tab.configure(text = nom)
439 def exitEFICAS(self,event=None):
441 Permet de sortir d'EFICAS en demandant à l'utilisateur
442 s'il veut sauvegarder les modifications en cours
444 liste = self.GetListeJDCaSauvegarder()
446 # Certains fichiers n'ont pas été sauvegardés ...
447 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
448 test = self.saveall(liste)
451 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
452 for JDCDisplay in self.liste_JDCDisplay:
453 JDCDisplay.jdc.supprime()
457 def GetListeJDCaSauvegarder(self) :
458 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
459 if not self.JDCDisplay_courant : return []
460 if len(self.liste_JDCDisplay) == 0 : return l
462 for JDCDisplay in self.liste_JDCDisplay:
463 if JDCDisplay.modified == 'o' :
467 def copy(self,event=None):
469 Lance la copie sur le JDC courant
471 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
473 def paste(self,event=None):
475 Lance le collage sur le JDC courant
477 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
479 def cut(self,event=None):
481 Lance le cut sur le JDC courant
483 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
487 Lance la suppression du noeud courant
489 if not self.JDCDisplay_courant : return
491 if self.JDCDisplay_courant.modified == 'n' :
492 self.JDCDisplay_courant.init_modif()
493 pere = self.JDCDisplay_courant.node_selected.parent
494 # Le noeud n'est pas au 1er niveau
495 if pere.parent.parent != None:
496 self.JDCDisplay_courant.node_selected.delete()
499 noeudselecte = self.JDCDisplay_courant.node_selected
500 parent = noeudselecte.parent
501 enfants = parent.children
502 index = enfants.index(noeudselecte)
503 self.JDCDisplay_courant.node_selected.delete()
505 enfants[index].select()
507 enfants[index-1].select()
508 except AttributeError:
511 def visuJDC_py(self,event=None):
513 Méthode permettant d'afficher dans une fenêtre à part l'écho au
514 format python du jdc courant
516 if not hasattr(self,'JDC') : return
517 jdc_fini = self.get_text_JDC('python')
518 if jdc_fini == None : return
520 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
525 Méthode permettant d'afficher dans une fenêtre à part l'écho au
526 format .comm ou .py du jdc courant
528 if not hasattr(self,'JDC') : return
529 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
530 format=self.appli.format_fichier.get()
531 self.jdc_fini = self.get_text_JDC(format)
532 if self.jdc_fini == None : return
533 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
535 def get_text_JDC(self,format):
536 if generator.plugins.has_key(format):
537 # Le generateur existe on l'utilise
538 g=generator.plugins[format]()
539 jdc_formate=g.gener(self.JDC,format='beautifie')
540 if not g.cr.estvide():
542 self.appli.affiche_infos("Erreur à la generation")
543 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
548 # Il n'existe pas c'est une erreur
549 self.appli.affiche_infos("Format %s non reconnu" % format)
550 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
555 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
556 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
557 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
559 if not self.JDCDisplay_courant : return
561 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
562 if cle_doc == None : return
563 cle_doc = string.replace(cle_doc,'.','')
564 cle_doc = string.replace(cle_doc,'-','')
565 commande = self.appli.CONFIGURATION.exec_acrobat
566 nom_fichier = cle_doc+".pdf"
567 rep_fichier = cle_doc[0:2]
568 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
570 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
571 elif os.name == 'posix':
572 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
573 pid = os.system(script)
574 except AttributeError:
575 traceback.print_exc()
578 def visu_a_plat(self,event=None):
580 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
582 if not hasattr(self,'JDC') : return
583 titre = 'fichier '+ self.JDCName + ' à plat '
584 self.jdc_fini = self.get_text_JDC('aplat')
585 if self.jdc_fini == None : return
586 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
588 def visu_txt_brut_JDC(self,event=None):
590 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
592 if not hasattr(self,'JDC') : return
593 titre = "fichier de commandes utilisateur"
594 #texte = self.JDC.procedure
596 if self.JDCDisplay_courant.fichier == None:
597 self.appli.affiche_infos("Pas de fichier initial")
598 showerror("Impossible de visualiser le fichier initial",
599 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
601 f=open(self.JDCDisplay_courant.fichier,'r')
604 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
606 def affichage_fichier_ini(self):
608 Affichage des valeurs des paramètres relus par Eficas
610 self.appli.CONFIGURATION.affichage_fichier_ini()
612 def saveall(self,liste):
614 Sauvegarde tous les JDC contenus dans liste
617 for JDCDisplay in liste :
618 self.JDC = JDCDisplay.jdc
619 test = test * self.saveJDC(echo = 'non')
622 def save_homard(self,nom,texte):
623 file_homard=nom+'.conf_homard'
625 f=open(file_homard,'w')
631 print "Pb a la sauvegarde sous le format homard"
632 if self.appli.salome != 0:
634 self.appli.salome.rangeInStudy(file_homard)
636 # ---------------------------------------------------------------------------
637 # Méthodes liées aux mots-clés inconnus
638 # ---------------------------------------------------------------------------
640 def mc_inconnus(self):
641 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
642 o = fenetre_mc_inconnus(l_mc)
643 l = o.wait_new_list()
644 #print "mc_inconnus_new_list: ",l
645 #CCAR: Il n' y a pas de retour vers le JDC
647 def aideEFICAS(self,event=None):
648 AIDE.go(master=self.parent)
650 def update_jdc_courant(self):
651 self.JDCDisplay_courant.update()