Salome HOME
92da9ad64ea7e72863e6ac16c4746c1f7646bde4
[tools/eficas.git] / Editeur / bureau.py
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.
8 #
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.
13 #
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.
17 #
18 #
19 # ======================================================================
20 """
21    Ce module contient la classe BUREAU qui gere les JDC ouverts
22 """
23 # Modules Python
24 import os,string
25 import traceback
26 import Pmw
27 from tkFileDialog import askopenfilename,asksaveasfilename
28 from tkMessageBox import showinfo,askyesno,showerror
29
30 # Modules Eficas
31 import splash
32 import prefs
33 import convert
34 import generator
35 from jdcdisplay import JDCDISPLAY
36 from utils import extension,stripPath,save_in_file
37 from widgets import Fenetre,Ask_Format_Fichier
38 from fenetre_mc_inconnus import fenetre_mc_inconnus
39
40 class BUREAU:
41    menu_defs=[
42               ('Fichier',[
43                            ('Nouveau','newJDC'),
44                            ('Ouvrir','openJDC'),
45                            ('Enregistrer','saveJDC'),
46                            ('Enregistrer sous','saveasJDC'),
47                            None,
48                            ('Fermer','closeJDC'),
49                            ('Quitter','exitEFICAS'),
50                          ]
51               ),
52               ('Edition',[
53                            ('Copier','copy'),
54                            ('Couper','cut'),
55                            ('Coller','paste'),
56                          ]
57               ),
58               ('Jeu de commandes',[
59                                    ('Rapport de validation','visuCRJDC'),
60                                    ('Fichier à plat','visu_a_plat'),
61                                    ('Fichier .py','visuJDC_py'),
62                                    ('Fichier source','visu_txt_brut_JDC'),
63                                    ('Paramètres Eficas','affichage_fichier_ini'),
64                                    ('Mots-clés inconnus','mc_inconnus'),
65                                   ]
66               ),
67              ]
68
69    button_defs  =      (('New24',"newJDC","Création d'un nouveau fichier",'always'),
70                         ('Open24',"openJDC","Ouverture d'un fichier existant",'always'),
71                         ('Save24',"saveJDC","Sauvegarde du fichier courant",'always'),
72                         ('Zoom24',"visuJDC","Visualisation du fichier de commandes",'always'),
73                         None,
74                         ('Copy24',"copy","Copie l'objet courant",'jdc'),
75                         ('Cut24',"cut","Coupe l'objet courant",'jdc'),
76                         ('Paste24',"paste","Colle l'objet copié après l'objet courant",'jdc'),
77                         None,
78                         ('Delete24',"delete","Supprime l'objet courant",'jdc'),
79                         ('Help24',"view_doc","Documentation de l'objet courant",'jdc')
80                        )
81    try:
82       menu_defs=prefs.menu_defs['bureau']
83    except:
84       pass
85    try:
86       button_defs=prefs.button_defs['bureau']
87    except:
88       pass
89
90    def __init__(self,appli,parent):
91       self.parent=parent
92       self.appli=appli
93       splash._splash.configure(text = "Création du bureau")
94       self.nb = Pmw.NoteBook(self.parent,raisecommand=self.selectJDC)
95       self.nb.pack(fill='both',expand=1)
96       self.JDCDisplay_courant=None
97       self.fileName=None
98       self.liste_JDCDisplay=[]
99       self.cree_cataitem()
100
101    def cree_cataitem(self):
102       """
103           On récupère dans l'extension readercata les variables 
104           qui servent par la suite pour la création des JDC
105       """
106       self.cataitem=self.appli.readercata.cataitem
107       self.cata=self.appli.readercata.cata
108       self.cata_ordonne_dico=self.appli.readercata.cata_ordonne_dico
109       self.code=self.appli.readercata.code
110       self.version_code=self.appli.readercata.version_code
111       self.fic_cata=self.appli.readercata.fic_cata
112
113    def selectJDC(self,event=None):
114       """
115           Cette méthode est appelée chaque fois que l'on sélectionne 
116           l'onglet d'un JDC dans le NoteBook des JDC.
117           Elle permet de stocker dans les variable self.JDC et 
118           self.JDCDisplay_courant les valeurs concernant le JDC courant
119       """
120       if len(self.liste_JDCDisplay) == 0 : return
121       #if self.JDCDisplay_courant : self.JDCDisplay_courant.jdc.unset_context()
122       numero_jdc = self.nb.index(self.nb.getcurselection())
123       self.JDCDisplay_courant = self.liste_JDCDisplay[numero_jdc]
124       self.JDC = self.JDCDisplay_courant.jdc
125       #self.JDC.set_context()
126       self.JDCName = self.JDC.nom
127
128    def newJDC(self):
129       """
130           Initialise un nouveau JDC vierge
131       """
132       self.appli.statusbar.reset_affichage_infos()
133
134       CONTEXT.unset_current_step()
135       J=self.cata[0].JdC(cata=self.cata,
136                          cata_ord_dico=self.cata_ordonne_dico,
137                          appli=self.appli)
138       self.JDCName=J.nom
139       self.fileName=None
140       self.ShowJDC(J,self.JDCName)
141       self.appli.toolbar.active_boutons()
142
143    def ShowJDC(self,JDC,nom,label_onglet=None):
144       """
145           Lance l'affichage du JDC cad création du JDCDisplay
146           Rajoute le JDCDisplay à la liste des JDCDisplay si label_onglet == None cad si on crée
147           bien un nouveau JDCDisplay et non si on remplace (renommage de l'onglet)
148       """
149       self.JDC=JDC
150       self.JDCName = self.JDC.nom = nom
151       #XXX CCAR: pour le moment mis en commentaire
152       #self.JDC.set_context()
153       if label_onglet == None :
154           label_onglet = self.GetLabelJDC()
155           self.nb.add(label_onglet,tab_text = nom,tab_width=20)
156           new = 'oui'
157       else :
158           new = 'non'
159       self.JDCDisplay_courant=JDCDISPLAY(self.JDC,nom,appli=self.appli,parent=self.nb.page(label_onglet))
160       if new == 'oui':
161           self.liste_JDCDisplay.append(self.JDCDisplay_courant)
162       self.JDCDisplay_courant.modified='n'
163       self.JDCDisplay_courant.fichier=self.fileName
164       self.nb.selectpage(label_onglet)
165       self.nb.setnaturalsize()
166       texte = "Jeu de commandes :" + self.JDCName+" ouvert"
167       self.appli.affiche_infos(texte)
168
169    def closeJDC (self) :
170       """
171       Ferme le JDC courant et détruit l'onglet associé dans le notebook self.nb
172       """
173       if self.JDCDisplay_courant.modified == 'o' :
174           message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
175           reponse = askyesno(title="Sauvegarde du jdc courant",
176                              message=message)
177           if reponse :
178               test = self.saveJDC()
179               if test == 0 :
180                   self.appli.affiche_infos("Sauvegarde impossible")
181                   return
182       self.JDCDisplay_courant.jdc.supprime()
183       self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
184       self.nb.delete(self.nb.getcurselection())
185       #XXX CCAR: pour le moment mis en commentaire
186       #self.JDC.unset_context()
187       self.JDC = None
188       try:
189           index = self.nb.index(self.nb.getcurselection())
190           self.JDCDisplay_courant = self.liste_JDCDisplay[index]
191           self.JDC = self.JDCDisplay_courant.jdc
192       except:
193           self.JDCDisplay_courant = None
194           self.appli.toolbar.inactive_boutons()
195
196    def visuCRJDC(self):
197       return self.visuCR(mode='JDC')
198
199    def visuCR(self,mode):
200       """
201       Méthode permettant l'affichage du rapport de validation
202       """
203       if mode == 'JDC':
204           if not hasattr(self,'JDC') : return
205           titre="rapport de validation du jeu de commandes courant"
206           cr = self.JDC.report()
207       elif mode == 'CATA':
208           from Noyau.N_CR import CR
209           cr = CR()
210           cr.debut = "Début rapport de validation du catalogue"
211           cr.fin = "Fin rapport de validation du catalogue"
212           titre="rapport de validation du catalogue"
213           if hasattr(self,'cata_ordonne_cr') :
214               cr.add(self.cata_ordonne_cr)
215           if hasattr(self,'cata_dev_ordonne_cr') :
216               cr.add(self.cata_dev_ordonne_cr)
217           for cata in self.cata:
218               if hasattr(cata,'JdC'):
219                   cr.add(cata.JdC.report())
220       texte_cr = str(cr)
221       self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
222
223    def openJDC(self,file=None):
224       """
225           Demande à l'utilisateur quel JDC existant il veut ouvrir
226       """
227       if self.code == 'ASTER':
228           filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
229       else:
230           filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
231       if not hasattr(self,'initialdir'):
232          self.initialdir = self.appli.CONFIGURATION.rep_user
233       if not file :
234           file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
235                                  defaultextension=".comm",
236                                  filetypes = filetypes,
237                                  initialdir = self.initialdir)
238       if file != '':
239           self.fileName = file
240           e=extension(file)
241           self.JDCName=stripPath(file)
242           self.initialdir = os.path.dirname(file)
243       else :
244           return
245       #XXX CCAR: pour le moment mis en commentaire
246       #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
247
248       format=self.appli.format_fichier.get()
249       # Il faut convertir le contenu du fichier en fonction du format
250       if convert.plugins.has_key(format):
251          # Le convertisseur existe on l'utilise
252          p=convert.plugins[format]()
253          p.readfile(file)
254          text=p.convert('exec')
255          if not p.cr.estvide(): 
256             self.appli.affiche_infos("Erreur à la conversion")
257             Fenetre(self.appli,
258                     titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
259                     texte = str(p.cr)).wait()
260             return
261       else:
262          # Il n'existe pas c'est une erreur
263          self.appli.affiche_infos("Type de fichier non reconnu")
264          showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
265          return
266
267       # On se met dans le repertoire ou se trouve le fichier de commandes
268       # pour trouver les eventuels fichiers include ou autres
269       # localises a cote du fichier de commandes
270       os.chdir(self.initialdir)
271       CONTEXT.unset_current_step()
272       J=self.cata[0].JdC(procedure=text,appli=self.appli,
273                          cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
274                          nom = self.JDCName)
275       J.analyse()
276       txt_exception = J.cr.get_mess_exception()
277       if txt_exception :
278           # des exceptions ont été levées à la création du JDC 
279           # --> on affiche les erreurs mais pas le JDC
280           self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
281           showerror("Erreur fatale au chargement d'un fichier",txt_exception)
282       else:
283           self.ShowJDC(J,self.JDCName)
284           self.appli.toolbar.active_boutons()
285           # si le JDC ne contient rien (vide), on retourne ici
286           if len(self.JDC.etapes) == 0 : return
287           # dans le cas où le JDC est invalide, on affiche son CR
288           cr = self.JDC.report()
289           if not cr.estvide() : 
290              self.appli.top.update()
291              self.visuCR(mode='JDC')
292
293
294    def GetLabelJDC(self,nb_jdc = 'absent'):
295       """
296       Retourne le label de l'onglet du NoteBook associé au JDC à afficher
297       """
298       if nb_jdc == 'absent':
299           nb_jdc = len(self.nb.pagenames())
300       nb_jdc = nb_jdc+1
301       label_onglet = 'JDC'+`nb_jdc`
302       if label_onglet not in self.nb.pagenames() :
303           return label_onglet
304       else :
305           return self.GetLabelJDC(nb_jdc)
306
307    def saveasJDC(self):
308       """ 
309            Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
310            donner le nom du fichier de sauvegarde 
311       """
312       self.saveJDC(echo='oui')
313
314    def saveJDC(self,echo='non'):
315       """ 
316           Sauvegarde le JDC courant.
317           Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
318           Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il 
319                             veut sauver le JDC
320           Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
321       """
322       if not hasattr(self,'JDC') : return 0
323       format=self.appli.format_fichier.get()
324       if generator.plugins.has_key(format):
325          # Le generateur existe on l'utilise
326          g=generator.plugins[format]()
327          jdc_formate=g.gener(self.JDC,format='beautifie')
328          if not g.cr.estvide():
329             print g.cr
330             self.appli.affiche_infos("Erreur à la generation")
331             showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
332             return
333       else:
334          # Il n'existe pas c'est une erreur
335          self.appli.affiche_infos("Format %s non reconnu" % format)
336          showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
337          return
338       self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
339
340       if echo =='oui' or self.JDCDisplay_courant.fichier == None:
341           return self.asknomsauvegardeJDC()
342       elif self.JDCDisplay_courant.fichier != None :
343           # le JDC a déjà un nom : on sauvegarde directement sans demander
344           # un autre nom au développeur
345           if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
346               showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
347               return 0
348           else :
349               self.JDCDisplay_courant.stop_modif()
350               self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
351               return 1
352
353    def asknomsauvegardeJDC(self):
354       """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
355       titre = "Sauvegarde d'un fichier de commandes "+self.code
356       if self.code == 'ASTER':
357           defext = ".comm"
358           filtyp = ( ("ASTER", ".comm"),)
359       else :
360           defext = ".py"
361           filtyp = ( (self.code, ".py"),)
362       sauvegarde = asksaveasfilename(title=titre,
363                                      defaultextension=defext,
364                                      filetypes = filtyp,
365                                      initialdir = self.appli.CONFIGURATION.rep_user)
366       if sauvegarde != '':
367           if not save_in_file(sauvegarde,self.jdc_fini) :
368               showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
369               return 0
370           else :
371               self.JDCDisplay_courant.stop_modif()
372               self.appli.affiche_infos("Sauvegarde effectuée")
373               if sauvegarde != self.JDCDisplay_courant.fichier :
374                   # l'utilisateur a sauvegardé le JDC sous un autre nom
375                   self.JDCDisplay_courant.fichier = sauvegarde
376                   self.JDCName = self.JDC.nom = stripPath(sauvegarde)
377                   self.changeNomPage()
378               return 1
379       else :
380           return 0
381
382    def changeNomPage(self):
383       """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
384           et recrée un autre onglet à la même place avec le bon nom 
385       """
386       nom = self.JDCName
387       self.JDCDisplay_courant.jdc.nom = nom
388       nom_page = self.nb.getcurselection()
389       num_page = self.nb.index(nom_page)
390       tab = self.nb.tab(num_page)
391       tab.configure(text = nom)
392
393    def exitEFICAS(self):
394       """
395           Permet de sortir d'EFICAS en demandant à l'utilisateur
396           s'il veut sauvegarder les modifications en cours
397       """
398       liste = self.GetListeJDCaSauvegarder()
399       if liste != [] :
400           # Certains fichiers n'ont pas été sauvegardés ...
401           if askyesno("Enregistrer modifications","Enregister les modifications ?") :
402               test = self.saveall(liste)
403               if test != 1 :
404                   return
405       if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
406           for JDCDisplay in self.liste_JDCDisplay:
407               JDCDisplay.jdc.supprime()
408           self.appli.quit()
409           return
410
411    def GetListeJDCaSauvegarder(self) :
412       """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
413       if not self.JDCDisplay_courant : return []
414       if len(self.liste_JDCDisplay) == 0 : return l
415       l = []
416       for JDCDisplay in self.liste_JDCDisplay:
417           if JDCDisplay.modified == 'o' :
418               l.append(JDCDisplay)
419       return l
420
421    def copy(self):
422       """
423           Lance la copie sur le JDC courant
424       """
425       if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
426
427    def paste(self):
428       """
429            Lance le collage sur le JDC courant
430       """
431       if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
432
433    def cut(self):
434       """
435          Lance le cut sur le JDC courant
436       """
437       if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
438
439    def delete(self):
440       """
441           Lance la suppression du noeud courant
442       """
443       if not self.JDCDisplay_courant : return
444       try:
445           if self.JDCDisplay_courant.modified == 'n' : 
446              self.JDCDisplay_courant.init_modif()
447           pere = self.JDCDisplay_courant.node_selected.parent
448           self.JDCDisplay_courant.node_selected.delete()
449           pere.select()
450       except AttributeError:
451           pass
452
453    def visuJDC_py(self):
454       """ 
455           Méthode permettant d'afficher dans une fenêtre à part l'écho au 
456             format python du jdc courant 
457       """
458       if not hasattr(self,'JDC') : return
459       jdc_fini = self.get_text_JDC('python')
460       if jdc_fini == None : return
461       Fenetre(self.appli,
462               titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
463               texte = jdc_fini)
464
465    def visuJDC(self):
466       """ 
467           Méthode permettant d'afficher dans une fenêtre à part l'écho au 
468             format .comm ou .py du jdc courant 
469       """
470       if not hasattr(self,'JDC') : return
471       titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
472       format=self.appli.format_fichier.get()
473       self.jdc_fini = self.get_text_JDC(format)
474       if self.jdc_fini == None : return
475       self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
476
477    def get_text_JDC(self,format):
478       if generator.plugins.has_key(format):
479          # Le generateur existe on l'utilise
480          g=generator.plugins[format]()
481          jdc_formate=g.gener(self.JDC,format='beautifie')
482          if not g.cr.estvide():
483             print g.cr
484             self.appli.affiche_infos("Erreur à la generation")
485             showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
486             return
487          else:
488             return jdc_formate
489       else:
490          # Il n'existe pas c'est une erreur
491          self.appli.affiche_infos("Format %s non reconnu" % format)
492          showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
493          return
494
495    def view_doc(self):
496       """
497           Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
498           - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
499           - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
500       """
501       if not self.JDCDisplay_courant : return
502       try:
503           cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
504           if cle_doc == None : return
505           cle_doc = string.replace(cle_doc,'.','')
506           cle_doc = string.replace(cle_doc,'-','')
507           commande = self.appli.CONFIGURATION.exec_acrobat
508           nom_fichier = cle_doc+".pdf"
509           rep_fichier = cle_doc[0:2]
510           fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
511           if os.name == 'nt':
512               os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
513           elif os.name == 'posix':
514               script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
515               pid = os.system(script)
516       except AttributeError:
517           traceback.print_exc()
518           pass
519
520    def visu_a_plat(self):
521       """ 
522           Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant 
523       """
524       if not hasattr(self,'JDC') : return
525       titre = 'fichier '+ self.JDCName + ' à plat '
526       self.jdc_fini = self.get_text_JDC('aplat')
527       if self.jdc_fini == None : return
528       self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
529
530    def visu_txt_brut_JDC(self):
531       """
532            Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
533       """
534       if not hasattr(self,'JDC') : return
535       titre = "fichier de commandes utilisateur"
536       #texte = self.JDC.procedure
537       #if texte == None:
538       if self.JDCDisplay_courant.fichier == None:
539             self.appli.affiche_infos("Pas de fichier initial")
540             showerror("Impossible de visualiser le fichier initial",
541                       "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
542             return
543       f=open(self.JDCDisplay_courant.fichier,'r')
544       texte=f.read()
545       f.close()
546       self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
547
548    def affichage_fichier_ini(self):
549       """
550            Affichage des valeurs des paramètres relus par Eficas
551       """
552       self.appli.CONFIGURATION.affichage_fichier_ini()
553
554    def saveall(self,liste):
555       """ 
556            Sauvegarde tous les JDC contenus dans liste 
557       """
558       test = 1
559       for JDCDisplay in liste :
560           self.JDC = JDCDisplay.jdc
561           test = test * self.saveJDC(echo = 'non')
562       return test
563
564
565 # ---------------------------------------------------------------------------
566 #                       Méthodes liées aux mots-clés inconnus
567 # ---------------------------------------------------------------------------
568
569    def mc_inconnus(self):
570       l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
571       o = fenetre_mc_inconnus(l_mc)
572       l = o.wait_new_list()
573       print "mc_inconnus_new_list: ",l
574       #CCAR: Il n' y a pas de retour vers le JDC
575