Salome HOME
Version initiale de EFICAS 1.2
[tools/eficas.git] / Editeur / readercata.py
1 """
2     Ce module sert à lire un catalogue et à construire
3     un objet CataItem pour Eficas.
4     Il s'appuie sur la classe READERCATA
5 """
6 # Modules Python
7 import os,sys,py_compile
8 import traceback
9 import cPickle
10 import Pmw
11 from tkMessageBox import showinfo,showerror
12
13 # Modules Eficas
14 import prefs
15 import splash
16 import fontes
17 import analyse_catalogue
18 from Noyau.N_CR import CR
19 from widgets import Fenetre
20
21 #import catabrowser
22
23 class READERCATA:
24
25    menu_defs=[
26               ('Catalogue',[
27                            ("Rapport de validation catalogue",'visuCRCATA'),
28                          ]
29               )
30              ]
31
32    button_defs=[]
33
34    def __init__(self,appli,parent):
35       self.appli=appli
36       self.parent=parent
37       self.code=self.appli.code
38       self.appli.format_fichier.set('python')
39       self.OpenCata()
40
41       self.cataitem=None
42       #XXX CCAR : Pour le moment je ne construis pas le CATAItem
43       #self.cataitem = catabrowser.CATAItem(self,"Catalogue "+self.code,
44                                            #self.cata,
45                                            #objet_cata_ordonne = self.cata_ordonne_dico)
46
47    def OpenCata(self):
48       """ 
49           Ouvre le catalogue standard du code courant, cad le catalogue présent
50           dans le répertoire Cata 
51       """
52       message1 = "Compilation des fichiers Eficas \n\n Veuillez patienter ..."
53       splash._splash.configure(text = message1)
54       if len(self.appli.CONFIGURATION.catalogues) == 1:
55           self.fic_cata = self.appli.CONFIGURATION.catalogues[0][2]
56           self.code = self.appli.CONFIGURATION.catalogues[0][0]
57           self.version_code = self.appli.CONFIGURATION.catalogues[0][1]
58           self.appli.format_fichier.set(self.appli.CONFIGURATION.catalogues[0][3])
59       elif len(self.appli.CONFIGURATION.catalogues) == 0:
60           # aucun catalogue défini dans le fichier Accas/editeur.ini
61           if self.code == 'ASTER' :
62               self.fic_cata = os.path.join(prefs.CODE_PATH,'Cata','cata.py')
63           elif self.code == 'SATURNE' :
64               self.fic_cata = os.path.join(prefs.CODE_PATH,'Cata','cata_saturne.py')
65           elif self.code == 'DESCARTES':
66               self.fic_cata = os.path.join(prefs.CODE_PATH,'Cata','cata_descartes.py')
67           else :
68               print 'Code inconnu'
69               sys.exit(0)
70       else:
71           # plusieurs catalogues sont disponibles : il faut demander à l'utilisateur
72           # lequel il veut utiliser ...
73           self.ask_choix_catalogue()
74       if self.fic_cata == None :
75           self.parent.destroy()
76           sys.exit(0)
77       # détermination de fic_cata_c et fic_cata_p
78       self.fic_cata_c = self.fic_cata + 'c'
79       self.fic_cata_p = os.path.splitext(self.fic_cata)[0]+'_pickled.py'
80       # compilation éventuelle du catalogue
81       test = self.compile_cata(self.fic_cata,self.fic_cata_c)
82       if not test : showerror("Compilation catalogue","Impossible de compiler le catalogue %s" %self.fic_cata)
83       # import du catalogue
84       self.cata = self.import_cata(self.fic_cata)
85       if not self.cata : showerror("Import du catalogue","Impossible d'importer le catalogue %s" %self.fic_cata)
86       # analyse du catalogue (ordre des mots-clés)
87       #XXX A priori ceci fait double emploi. Il faut d'abord calculer l'ordre
88       # puis fabriquer le CATAItem
89       #CCAR :self.catalo = catabrowser.CATAItem(self,"Catalogue",self.cata)
90       self.Retrouve_Ordre_Cata_Standard()
91       # chargement et analyse des catalogues développeur (le cas échéant)
92       if self.appli.CONFIGURATION.isdeveloppeur == 'OUI' :
93           init_rep_cata_dev(self.fic_cata,self.appli.CONFIGURATION.path_cata_dev)
94           fic_cata_dev = os.path.join(self.appli.CONFIGURATION.path_cata_dev,'cata_developpeur.py')
95           if os.path.isfile(fic_cata_dev):
96               # il y a bien un catalogue développeur : il faut récupérer le module_object associé ...
97               test = self.compile_cata(fic_cata_dev,fic_cata_dev+'c')
98               if not test :
99                   showinfo("Compilation catalogue développeur",
100                            "Erreur dans la compilation du catalogue développeur")
101                   self.cata = (self.cata,)
102               else:
103                   self.cata_dev =self.import_cata(fic_cata_dev)
104                   self.Retrouve_Ordre_Cata_Developpeur()
105                   self.cata = (self.cata,self.cata_dev)
106           else:
107               self.cata = (self.cata,)
108       else:
109           self.cata = (self.cata,)
110
111    def import_cata(self,cata):
112       """ 
113           Réalise l'import du catalogue dont le chemin d'accès est donné par cata
114       """
115       import imp
116       splash._splash.configure(text = "Chargement du catalogue")
117       nom_cata = os.path.splitext(os.path.basename(cata))[0]
118       rep_cata = os.path.dirname(cata)
119       sys.path[:0] = [rep_cata]
120       try :
121           f,p,d = imp.find_module(nom_cata)
122           o = imp.load_module(nom_cata,f,p,d)
123           return o
124       except Exception,e:
125           traceback.print_exc()
126           return 0
127
128    def Retrouve_Ordre_Cata_Standard(self):
129       """ 
130           Retrouve l'ordre des mots-clés dans le catalogue, cad :
131            - si ce dernier a été modifié, relance l'analyse du catalogue pour déterminer
132                l'ordre des mots-clés dans le catalogue
133            - s'il n'a pas été modifié, relie le fichier pickle 
134       """
135       time1 = os.path.getmtime(self.fic_cata)
136       try :
137           time2 = os.path.getmtime(self.fic_cata_p)
138       except:
139           time2 = 0
140       if time2 > time1 :
141           # l'objet catalogue n'a pas été modifié depuis le dernier "pickle"
142           self.Get_Ordre_Cata()
143       else :
144           # le catalogue a été modifié depuis le dernier "pickle" :
145           # il faut retrouver l'ordre du catalogue et refaire pickle
146           self.Get_Ordre_Cata(mode='cata')
147       self.appli.affiche_infos("Catalogue standard chargé")
148
149    def Get_Ordre_Cata(self,mode='pickle'):
150       """ 
151           Retrouve l'ordre du catalogue :
152             - mode='pickle ': tente de relire le fichier pickle et sinon lance l'analyse du catalogue
153             - mode='cata'   : force l'analyse du catalogue directement sans relire le pickle
154       """
155       if mode == 'pickle' :
156           try:
157               f = open(self.fic_cata_p)
158               u = cPickle.Unpickler(f)
159               splash._splash.configure(text = "Analyse du catalogue")
160               self.cata_ordonne_dico = u.load()
161               f.close()
162           except :
163               # on peut ne pas arriver à relire le fichier pickle s'il a été altéré
164               # ou (le plus probable) s'il a été créé sous un autre OS
165               self.Get_Ordre_Cata(mode='cata')
166       elif mode == 'cata':
167           splash._splash.configure(text = "Analyse du catalogue",barre='oui')
168           cata_ordonne = analyse_catalogue.analyse_catalogue(self,self.fic_cata)
169           self.cata_ordonne_cr = cata_ordonne.cr
170           self.cata_ordonne_dico = cata_ordonne.dico
171           splash._splash.configure(text = "Sauvegarde des informations sur le catalogue")
172           f = open(self.fic_cata_p,'w+')
173           p = cPickle.Pickler(f)
174           p.dump(self.cata_ordonne_dico)
175           f.close()
176       else :
177           raise Exception("Appel à un mode inconnu de Get_Ordre_Cata : %s" % mode)
178           return
179
180    def ask_choix_catalogue(self):
181       """
182       Ouvre une fenêtre de sélection du catalogue dans le cas où plusieurs
183       ont été définis dans Accas/editeur.ini
184       """
185       # construction du dictionnaire et de la liste des catalogues
186       self.dico_catalogues = {}
187       defaut = None
188       for catalogue in self.appli.CONFIGURATION.catalogues:
189           if catalogue[0] == self.code :
190               self.dico_catalogues[catalogue[1]] = catalogue
191               if len(catalogue) == 5 :
192                   if catalogue[4]=='defaut' : defaut = catalogue[1]
193       liste_choix = self.dico_catalogues.keys()
194       liste_choix.sort()
195       # test si plusieurs catalogues ou non
196       if len(liste_choix) == 0:
197           showerror("Aucun catalogue déclaré pour %s" %self.code)
198           self.quit()
199       elif len(liste_choix) == 1:
200           self.fic_cata = self.dico_catalogues[liste_choix[0]][2]
201           self.version_code = liste_choix[0]
202           return
203       # création d'une boîte de dialogue modale
204       self.fenetre_choix_cata = Pmw.Dialog(self.parent,
205                                            buttons=('OK','ANNULER'),
206                                            defaultbutton = 'OK',
207                                            title = "Choix d'une version du code %s" %self.code,
208                                            command = self.chooseCata)
209       # construction des radioboutons
210       label = `len(liste_choix)`+' versions du code %s sont disponibles\n' %self.code
211       label = label + 'Veuillez choisir celle avec laquelle vous souhaitez travailler :'
212       self.radiobutton = Pmw.RadioSelect(self.fenetre_choix_cata.interior(),
213                                          buttontype='radiobutton',
214                                          labelpos = 'w',
215                                          label_text = label,
216                                          label_font = fontes.standard,
217                                          orient='vertical')
218       for choix in liste_choix :
219           self.radiobutton.add(choix)
220       if defaut == None :
221           # aucun catalogue par défaut n'a été spécifié dans Accas/editeur.ini
222           defaut = liste_choix[0]
223       self.radiobutton.invoke(defaut)
224       self.radiobutton.pack(fill='x',padx=10,pady=10)
225       # centrage de la fenêtre
226       self.fenetre_choix_cata.activate(geometry='centerscreenalways')
227
228    def chooseCata(self,txt):
229       """ 
230           Méthode activée lorsque l'utilisateur a fait son choix et cliqué sur 'OK' ou sur 'ANNULER'
231       """
232       if txt == 'OK' :
233           version_cata = self.radiobutton.getcurselection()
234           self.fic_cata = self.dico_catalogues[version_cata][2]
235           self.version_code = version_cata
236           self.appli.format_fichier.set(self.dico_catalogues[version_cata][3])
237           self.fenetre_choix_cata.destroy()
238       else:
239           self.parent.destroy()
240
241    def compile_cata(self,cata,catac):
242       """ 
243            Teste si le catalogue a bien besoin d'être recompilé et si oui, le compile et
244            affiche un message dans le splash . Retourne 1 si la compilation s'est bien déroulée,
245            0 sinon.
246       """
247       time1 = os.path.getmtime(cata)
248       try:
249           time2 = os.path.getmtime(catac)
250       except:
251           time2 = 0
252       if time1 > time2:
253           try:
254               # le catalogue doit être recompilé avant d'être importé
255               splash._splash.configure(text="Compilation du catalogue\nCela peut prendre une trentaine de secondes ...")
256               py_compile.compile(cata)
257           except:
258               return 0
259       return 1
260
261
262 #--------------------------------------------------------------------------------
263 # Méthodes concernant la barre de progression lors de l'analyse du catalogue
264 #--------------------------------------------------------------------------------
265
266    def configure_barre(self,nbcommandes):
267       """ Configure la barre de progression en lui passant comme paramètre le
268           nombre de commandes du catalogue qui lui sert à déterminer la longueur de son incrément """
269       try:
270           splash._splash.configure(barre='oui',ratio = nbcommandes)
271       except:
272           pass
273
274    def update_barre(self):
275       """ Update la position de la barre de progression : la fait progresser de son incrément """
276       try:
277           splash._splash.update_barre()
278       except:
279           pass
280
281    def visuCRCATA(self):
282       """
283       Méthode permettant l'affichage du rapport de validation
284       """
285       cr = CR( debut = "Début rapport de validation du catalogue",
286                fin = "Fin rapport de validation du catalogue")
287       titre="rapport de validation du catalogue"
288       if hasattr(self,'cata_ordonne_cr') :
289           cr.add(self.cata_ordonne_cr)
290       if hasattr(self,'cata_dev_ordonne_cr') :
291           cr.add(self.cata_dev_ordonne_cr)
292       for cata in self.cata:
293           if hasattr(cata,'JdC'):
294               cr.add(cata.JdC.report())
295       texte_cr = str(cr)
296       self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
297