2 Ce module contient la classe BUREAU qui gere les JDC ouverts
8 from tkFileDialog import askopenfilename,asksaveasfilename
9 from tkMessageBox import showinfo,askyesno,showerror
16 from jdcdisplay import JDCDISPLAY
17 from utils import extension,stripPath,save_in_file
18 from widgets import Fenetre,Ask_Format_Fichier
19 from fenetre_mc_inconnus import fenetre_mc_inconnus
26 ('Enregistrer','saveJDC'),
27 ('Enregistrer sous','saveasJDC'),
29 ('Fermer','closeJDC'),
30 ('Quitter','exitEFICAS'),
40 ('Rapport de validation','visuCRJDC'),
41 ('Fichier à plat','visu_a_plat'),
42 ('Fichier .py','visuJDC_py'),
43 ('Fichier source','visu_txt_brut_JDC'),
44 ('Paramètres Eficas','affichage_fichier_ini'),
45 ('Mots-clés inconnus','mc_inconnus'),
50 button_defs = (('New24',"newJDC","Création d'un nouveau fichier",'always'),
51 ('Open24',"openJDC","Ouverture d'un fichier existant",'always'),
52 ('Save24',"saveJDC","Sauvegarde du fichier courant",'always'),
53 ('Zoom24',"visuJDC","Visualisation du fichier de commandes",'always'),
55 ('Copy24',"copy","Copie l'objet courant",'jdc'),
56 ('Cut24',"cut","Coupe l'objet courant",'jdc'),
57 ('Paste24',"paste","Colle l'objet copié après l'objet courant",'jdc'),
59 ('Delete24',"delete","Supprime l'objet courant",'jdc'),
60 ('Help24',"view_doc","Documentation de l'objet courant",'jdc')
63 menu_defs=prefs.menu_defs['bureau']
67 button_defs=prefs.button_defs['bureau']
71 def __init__(self,appli,parent):
74 splash._splash.configure(text = "Création du bureau")
75 self.nb = Pmw.NoteBook(self.parent,raisecommand=self.selectJDC)
76 self.nb.pack(fill='both',expand=1)
77 self.JDCDisplay_courant=None
79 self.liste_JDCDisplay=[]
82 def cree_cataitem(self):
84 On récupère dans l'extension readercata les variables
85 qui servent par la suite pour la création des JDC
87 self.cataitem=self.appli.readercata.cataitem
88 self.cata=self.appli.readercata.cata
89 self.cata_ordonne_dico=self.appli.readercata.cata_ordonne_dico
90 self.code=self.appli.readercata.code
91 self.version_code=self.appli.readercata.version_code
92 self.fic_cata=self.appli.readercata.fic_cata
94 def selectJDC(self,event=None):
96 Cette méthode est appelée chaque fois que l'on sélectionne
97 l'onglet d'un JDC dans le NoteBook des JDC.
98 Elle permet de stocker dans les variable self.JDC et
99 self.JDCDisplay_courant les valeurs concernant le JDC courant
101 if len(self.liste_JDCDisplay) == 0 : return
102 #if self.JDCDisplay_courant : self.JDCDisplay_courant.jdc.unset_context()
103 numero_jdc = self.nb.index(self.nb.getcurselection())
104 self.JDCDisplay_courant = self.liste_JDCDisplay[numero_jdc]
105 self.JDC = self.JDCDisplay_courant.jdc
106 #self.JDC.set_context()
107 self.JDCName = self.JDC.nom
111 Initialise un nouveau JDC vierge
113 self.appli.statusbar.reset_affichage_infos()
115 CONTEXT.unset_current_step()
116 J=self.cata[0].JdC(cata=self.cata,
117 cata_ord_dico=self.cata_ordonne_dico,
121 self.ShowJDC(J,self.JDCName)
122 self.appli.toolbar.active_boutons()
124 def ShowJDC(self,JDC,nom,label_onglet=None):
126 Lance l'affichage du JDC cad création du JDCDisplay
127 Rajoute le JDCDisplay à la liste des JDCDisplay si label_onglet == None cad si on crée
128 bien un nouveau JDCDisplay et non si on remplace (renommage de l'onglet)
131 self.JDCName = self.JDC.nom = nom
132 #XXX CCAR: pour le moment mis en commentaire
133 #self.JDC.set_context()
134 if label_onglet == None :
135 label_onglet = self.GetLabelJDC()
136 self.nb.add(label_onglet,tab_text = nom,tab_width=20)
140 self.JDCDisplay_courant=JDCDISPLAY(self.JDC,nom,appli=self.appli,parent=self.nb.page(label_onglet))
142 self.liste_JDCDisplay.append(self.JDCDisplay_courant)
143 self.JDCDisplay_courant.modified='n'
144 self.JDCDisplay_courant.fichier=self.fileName
145 self.nb.selectpage(label_onglet)
146 self.nb.setnaturalsize()
147 texte = "Jeu de commandes :" + self.JDCName+" ouvert"
148 self.appli.affiche_infos(texte)
150 def closeJDC (self) :
152 Ferme le JDC courant et détruit l'onglet associé dans le notebook self.nb
154 if self.JDCDisplay_courant.modified == 'o' :
155 message = "Voulez-vous sauvegarder le jeu de commandes "+self.JDC.nom+" courant ?"
156 reponse = askyesno(title="Sauvegarde du jdc courant",
159 test = self.saveJDC()
161 self.appli.affiche_infos("Sauvegarde impossible")
163 self.JDCDisplay_courant.jdc.supprime()
164 self.liste_JDCDisplay.remove(self.JDCDisplay_courant)
165 self.nb.delete(self.nb.getcurselection())
166 #XXX CCAR: pour le moment mis en commentaire
167 #self.JDC.unset_context()
170 index = self.nb.index(self.nb.getcurselection())
171 self.JDCDisplay_courant = self.liste_JDCDisplay[index]
172 self.JDC = self.JDCDisplay_courant.jdc
174 self.JDCDisplay_courant = None
175 self.appli.toolbar.inactive_boutons()
178 return self.visuCR(mode='JDC')
180 def visuCR(self,mode):
182 Méthode permettant l'affichage du rapport de validation
185 if not hasattr(self,'JDC') : return
186 titre="rapport de validation du jeu de commandes courant"
187 cr = self.JDC.report()
189 from Noyau.N_CR import CR
191 cr.debut = "Début rapport de validation du catalogue"
192 cr.fin = "Fin rapport de validation du catalogue"
193 titre="rapport de validation du catalogue"
194 if hasattr(self,'cata_ordonne_cr') :
195 cr.add(self.cata_ordonne_cr)
196 if hasattr(self,'cata_dev_ordonne_cr') :
197 cr.add(self.cata_dev_ordonne_cr)
198 for cata in self.cata:
199 if hasattr(cata,'JdC'):
200 cr.add(cata.JdC.report())
202 self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
204 def openJDC(self,file=None):
206 Demande à l'utilisateur quel JDC existant il veut ouvrir
208 if self.code == 'ASTER':
209 filetypes = ( ("format "+self.appli.format_fichier.get(), ".comm"),("Tous",'*'))
211 filetypes = ( ("format "+self.appli.format_fichier.get(), ".py"),)
212 if not hasattr(self,'initialdir'):
213 self.initialdir = self.appli.CONFIGURATION.rep_user
215 file = askopenfilename(title="Ouverture d'un fichier de commandes Aster",
216 defaultextension=".comm",
217 filetypes = filetypes,
218 initialdir = self.initialdir)
222 self.JDCName=stripPath(file)
223 self.initialdir = os.path.dirname(file)
226 #XXX CCAR: pour le moment mis en commentaire
227 #if self.JDCDisplay_courant:self.JDCDisplay_courant.jdc.unset_context()
229 format=self.appli.format_fichier.get()
230 # Il faut convertir le contenu du fichier en fonction du format
231 if convert.plugins.has_key(format):
232 # Le convertisseur existe on l'utilise
233 p=convert.plugins[format]()
235 text=p.convert('exec')
236 if not p.cr.estvide():
237 self.appli.affiche_infos("Erreur à la conversion")
239 titre="compte-rendu d'erreurs, EFICAS ne sait pas convertir ce fichier",
240 texte = str(p.cr)).wait()
243 # Il n'existe pas c'est une erreur
244 self.appli.affiche_infos("Type de fichier non reconnu")
245 showerror("Type de fichier non reconnu","EFICAS ne sait pas ouvrir ce type de fichier")
248 # On se met dans le repertoire ou se trouve le fichier de commandes
249 # pour trouver les eventuels fichiers include ou autres
250 # localises a cote du fichier de commandes
251 os.chdir(self.initialdir)
252 CONTEXT.unset_current_step()
253 J=self.cata[0].JdC(procedure=text,appli=self.appli,
254 cata=self.cata,cata_ord_dico=self.cata_ordonne_dico,
257 txt_exception = J.cr.get_mess_exception()
259 # des exceptions ont été levées à la création du JDC
260 # --> on affiche les erreurs mais pas le JDC
261 self.appli.affiche_infos("Erreur fatale au chargement de %s" %file)
262 showerror("Erreur fatale au chargement d'un fichier",txt_exception)
264 self.ShowJDC(J,self.JDCName)
265 self.appli.toolbar.active_boutons()
266 # si le JDC ne contient rien (vide), on retourne ici
267 if len(self.JDC.etapes) == 0 : return
268 # dans le cas où le JDC est invalide, on affiche son CR
269 cr = self.JDC.report()
270 if not cr.estvide() :
271 self.appli.top.update()
272 self.visuCR(mode='JDC')
275 def GetLabelJDC(self,nb_jdc = 'absent'):
277 Retourne le label de l'onglet du NoteBook associé au JDC à afficher
279 if nb_jdc == 'absent':
280 nb_jdc = len(self.nb.pagenames())
282 label_onglet = 'JDC'+`nb_jdc`
283 if label_onglet not in self.nb.pagenames() :
286 return self.GetLabelJDC(nb_jdc)
290 Sauvegarde le JDC courant en demandant impérativement à l'utilisateur de
291 donner le nom du fichier de sauvegarde
293 self.saveJDC(echo='oui')
295 def saveJDC(self,echo='non'):
297 Sauvegarde le JDC courant.
298 Retourne 1 si la sauvegarde s'est bien faite, 0 sinon.
299 Si echo = 'oui' : interactif (l'utilisateur donne le nom sous lequel il
301 Si echo = 'non' : muet (sauvegarde le JDC dans JDC.procedure)
303 if not hasattr(self,'JDC') : return 0
304 format=self.appli.format_fichier.get()
305 if generator.plugins.has_key(format):
306 # Le generateur existe on l'utilise
307 g=generator.plugins[format]()
308 jdc_formate=g.gener(self.JDC,format='beautifie')
309 if not g.cr.estvide():
311 self.appli.affiche_infos("Erreur à la generation")
312 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
315 # Il n'existe pas c'est une erreur
316 self.appli.affiche_infos("Format %s non reconnu" % format)
317 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC")
319 self.jdc_fini = string.replace(jdc_formate,'\r\n','\n')
321 if echo =='oui' or self.JDCDisplay_courant.fichier == None:
322 return self.asknomsauvegardeJDC()
323 elif self.JDCDisplay_courant.fichier != None :
324 # le JDC a déjà un nom : on sauvegarde directement sans demander
325 # un autre nom au développeur
326 if not save_in_file(self.JDCDisplay_courant.fichier,self.jdc_fini) :
327 showinfo("Erreur","Problème à la sauvegarde du fichier :" + `self.JDCDisplay_courant.fichier`)
330 self.JDCDisplay_courant.stop_modif()
331 self.appli.affiche_infos("sauvegarde de "+`self.JDCDisplay_courant.fichier`+" effectuée")
334 def asknomsauvegardeJDC(self):
335 """ Demande à l'utilsateur le nom sous lequel il veut sauvegarder le JDC courant """
336 titre = "Sauvegarde d'un fichier de commandes "+self.code
337 if self.code == 'ASTER':
339 filtyp = ( ("ASTER", ".comm"),)
342 filtyp = ( (self.code, ".py"),)
343 sauvegarde = asksaveasfilename(title=titre,
344 defaultextension=defext,
346 initialdir = self.appli.CONFIGURATION.rep_user)
348 if not save_in_file(sauvegarde,self.jdc_fini) :
349 showinfo("Erreur","Problème à la sauvegarde du fichier "+`sauvegarde`)
352 self.JDCDisplay_courant.stop_modif()
353 self.appli.affiche_infos("Sauvegarde effectuée")
354 if sauvegarde != self.JDCDisplay_courant.fichier :
355 # l'utilisateur a sauvegardé le JDC sous un autre nom
356 self.JDCDisplay_courant.fichier = sauvegarde
357 self.JDCName = self.JDC.nom = stripPath(sauvegarde)
363 def changeNomPage(self):
364 """ Change le nom de l'onglet contenant le JDC courant : en fait détruit l'actuel
365 et recrée un autre onglet à la même place avec le bon nom
368 self.JDCDisplay_courant.jdc.nom = nom
369 nom_page = self.nb.getcurselection()
370 num_page = self.nb.index(nom_page)
371 tab = self.nb.tab(num_page)
372 tab.configure(text = nom)
374 def exitEFICAS(self):
376 Permet de sortir d'EFICAS en demandant à l'utilisateur
377 s'il veut sauvegarder les modifications en cours
379 liste = self.GetListeJDCaSauvegarder()
381 # Certains fichiers n'ont pas été sauvegardés ...
382 if askyesno("Enregistrer modifications","Enregister les modifications ?") :
383 test = self.saveall(liste)
386 if askyesno ("Quitter","Voulez-vous vraiment quitter l'application ?") :
387 for JDCDisplay in self.liste_JDCDisplay:
388 JDCDisplay.jdc.supprime()
392 def GetListeJDCaSauvegarder(self) :
393 """ Retourne parmi la liste de tous les JDC ouverts la liste de ceux qui ont été modifiés """
394 if not self.JDCDisplay_courant : return []
395 if len(self.liste_JDCDisplay) == 0 : return l
397 for JDCDisplay in self.liste_JDCDisplay:
398 if JDCDisplay.modified == 'o' :
404 Lance la copie sur le JDC courant
406 if self.JDCDisplay_courant : self.JDCDisplay_courant.doCopy()
410 Lance le collage sur le JDC courant
412 if self.JDCDisplay_courant : self.JDCDisplay_courant.doPaste()
416 Lance le cut sur le JDC courant
418 if self.JDCDisplay_courant: self.JDCDisplay_courant.doCut()
422 Lance la suppression du noeud courant
424 if not self.JDCDisplay_courant : return
426 if self.JDCDisplay_courant.modified == 'n' :
427 self.JDCDisplay_courant.init_modif()
428 pere = self.JDCDisplay_courant.node_selected.parent
429 self.JDCDisplay_courant.node_selected.delete()
431 except AttributeError:
434 def visuJDC_py(self):
436 Méthode permettant d'afficher dans une fenêtre à part l'écho au
437 format python du jdc courant
439 if not hasattr(self,'JDC') : return
440 jdc_fini = self.get_text_JDC('python')
441 if jdc_fini == None : return
443 titre = 'fichier '+ self.JDCName + ' à la syntaxe Python',
448 Méthode permettant d'afficher dans une fenêtre à part l'écho au
449 format .comm ou .py du jdc courant
451 if not hasattr(self,'JDC') : return
452 titre = 'fichier '+ self.JDCName + ' à la syntaxe '+ self.code
453 format=self.appli.format_fichier.get()
454 self.jdc_fini = self.get_text_JDC(format)
455 if self.jdc_fini == None : return
456 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
458 def get_text_JDC(self,format):
459 if generator.plugins.has_key(format):
460 # Le generateur existe on l'utilise
461 g=generator.plugins[format]()
462 jdc_formate=g.gener(self.JDC,format='beautifie')
463 if not g.cr.estvide():
465 self.appli.affiche_infos("Erreur à la generation")
466 showerror("Erreur à la generation","EFICAS ne sait pas convertir ce JDC")
471 # Il n'existe pas c'est une erreur
472 self.appli.affiche_infos("Format %s non reconnu" % format)
473 showerror("Format %s non reconnu" % format,"EFICAS ne sait pas convertir le JDC en format %s "% format)
478 Permet d'ouvrir le fichier doc U de la commande au format pdf avec Acrobat Reader
479 - Ne fonctionne pas sous UNIX (chemin d'accès Acrobat Reader)
480 - indication du chemin d'accès aux fichiers pdf à revoir : trop statique
482 if not self.JDCDisplay_courant : return
484 cle_doc = self.JDCDisplay_courant.node_selected.item.get_docu()
485 if cle_doc == None : return
486 cle_doc = string.replace(cle_doc,'.','')
487 cle_doc = string.replace(cle_doc,'-','')
488 commande = self.appli.CONFIGURATION.exec_acrobat
489 nom_fichier = cle_doc+".pdf"
490 rep_fichier = cle_doc[0:2]
491 fichier = os.path.abspath(os.path.join(self.appli.CONFIGURATION.path_doc,rep_fichier,nom_fichier))
493 os.spawnv(os.P_NOWAIT,commande,(commande,fichier,))
494 elif os.name == 'posix':
495 script ="#!/usr/bin/sh \n%s %s&" %(commande,fichier)
496 pid = os.system(script)
497 except AttributeError:
498 traceback.print_exc()
501 def visu_a_plat(self):
503 Méthode permettant d'afficher dans une fenêtre à part l'écho 'à plat' du jdc courant
505 if not hasattr(self,'JDC') : return
506 titre = 'fichier '+ self.JDCName + ' à plat '
507 self.jdc_fini = self.get_text_JDC('aplat')
508 if self.jdc_fini == None : return
509 self.visu_fichier_cmd = Fenetre(self.appli,titre=titre,texte = self.jdc_fini)
511 def visu_txt_brut_JDC(self):
513 Méthode permettant d'afficher le jeu de commandes tel qu'il a été passé au JDC
515 if not hasattr(self,'JDC') : return
516 titre = "fichier de commandes utilisateur"
517 #texte = self.JDC.procedure
519 if self.JDCDisplay_courant.fichier == None:
520 self.appli.affiche_infos("Pas de fichier initial")
521 showerror("Impossible de visualiser le fichier initial",
522 "EFICAS ne peut visualiser le fichier initial.\nIl s'agit d'un nouveau JDC")
524 f=open(self.JDCDisplay_courant.fichier,'r')
527 self.visu_texte_JDC = Fenetre(self.appli,titre=titre,texte=texte)
529 def affichage_fichier_ini(self):
531 Affichage des valeurs des paramètres relus par Eficas
533 self.appli.CONFIGURATION.affichage_fichier_ini()
535 def saveall(self,liste):
537 Sauvegarde tous les JDC contenus dans liste
540 for JDCDisplay in liste :
541 self.JDC = JDCDisplay.jdc
542 test = test * self.saveJDC(echo = 'non')
546 # ---------------------------------------------------------------------------
547 # Méthodes liées aux mots-clés inconnus
548 # ---------------------------------------------------------------------------
550 def mc_inconnus(self):
551 l_mc = self.JDCDisplay_courant.jdc.get_liste_mc_inconnus()
552 o = fenetre_mc_inconnus(l_mc)
553 l = o.wait_new_list()