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