Salome HOME
5b72e6b305374d5cd078c9853eecc92d74313f74
[tools/eficas.git] / Editeur / readercata.py
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.
9 #
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.
14 #
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.
18 #
19 #
20 # ======================================================================
21 """
22     Ce module sert à lire un catalogue et à construire
23     un objet CataItem pour Eficas.
24     Il s'appuie sur la classe READERCATA
25 """
26 # Modules Python
27 import time
28 import os,sys,py_compile
29 import traceback
30 import cPickle
31 import Pmw
32
33 # Modules Eficas
34 import prefs
35 import splash
36 import fontes
37 import analyse_catalogue
38 from Noyau.N_CR import CR
39 from widgets import showinfo,showerror
40 from widgets import Fenetre
41 from utils import init_rep_cata_dev
42
43 #import catabrowser
44 import autre_analyse_cata
45 import uiinfo
46
47 class READERCATA:
48
49    menu_defs=[
50               ('Catalogue',[
51                            ("Rapport de validation catalogue",'visuCRCATA'),
52                          ]
53               )
54              ]
55
56    button_defs=[]
57
58    def __init__(self,appli,parent):
59       self.appli=appli
60       self.parent=parent
61       self.code=self.appli.code
62       self.appli.format_fichier.set('python')
63       self.version_code=self.appli.version_code
64       self.fic_cata=None
65       self.OpenCata()
66       self.cataitem=None
67
68    def OpenCata(self):
69       """ 
70           Ouvre le catalogue standard du code courant, cad le catalogue présent
71           dans le répertoire Cata 
72       """
73       message1 = "Compilation des fichiers Eficas \n\n Veuillez patienter ..."
74       if self.appli.test == 0 :
75          splash._splash.configure(text = message1)
76       self.configure_barre(4)
77
78       liste_cata_possibles=[]
79       for catalogue in self.appli.CONFIGURATION.catalogues:
80           if catalogue[0] == self.code :
81              liste_cata_possibles.append(catalogue)
82
83       if len(liste_cata_possibles)==0:
84           showerror("Import du catalogue","Pas de catalogue defini pour le code %s" % self.code)
85           self.appli.quit()
86           sys.exit(1)
87
88       if self.version_code is not None:
89           # La version a ete fixee
90           for cata in liste_cata_possibles:
91              if self.version_code == cata[1]:
92                 self.fic_cata = cata[2]
93                 self.appli.format_fichier.set(cata[3])
94       elif len(liste_cata_possibles)==1:
95           self.fic_cata = liste_cata_possibles[0][2]
96           self.code = self.appli.CONFIGURATION.catalogues[0][0]
97           self.version_code = liste_cata_possibles[0][1]
98           self.appli.format_fichier.set(liste_cata_possibles[0][3])
99       else:
100           # plusieurs catalogues sont disponibles : il faut demander à l'utilisateur
101           # lequel il veut utiliser ...
102           self.ask_choix_catalogue()
103
104       if self.fic_cata == None :
105           print "Pas de catalogue pour code %s, version %s" %(self.code,self.version_code)
106           sys.exit(0)
107
108       # détermination de fic_cata_c et fic_cata_p
109       self.fic_cata_c = self.fic_cata + 'c'
110       self.fic_cata_p = os.path.splitext(self.fic_cata)[0]+'_pickled.py'
111
112       #if self.appli.test == 0 :
113       #   splash._splash.configure(text = "Debut compil cata: %d s" % time.clock())
114       # compilation éventuelle du catalogue
115       #test = self.compile_cata(self.fic_cata,self.fic_cata_c)
116       #self.update_barre()
117       #if self.appli.test == 0 :
118       #   splash._splash.configure(text = "Fin compil cata: %d s" % time.clock())
119       #if not test : showerror("Compilation catalogue","Impossible de compiler le catalogue %s" %self.fic_cata)
120
121       # import du catalogue
122       if self.appli.test == 0 :
123          splash._splash.configure(text = "Debut import_cata: %d s" % time.clock())
124       self.cata = self.import_cata(self.fic_cata)
125       self.update_barre()
126       if self.appli.test == 0 :
127          splash._splash.configure(text = "Fin import_cata: %d s" % time.clock())
128       if not self.cata : showerror("Import du catalogue","Impossible d'importer le catalogue %s" %self.fic_cata)
129
130       #
131       # analyse du catalogue (ordre des mots-clés)
132       #
133       if self.appli.test == 0 :
134          splash._splash.configure(text = "Debut Retrouve_Ordre: %d s" % time.clock())
135       # Retrouve_Ordre_Cata_Standard fait une analyse textuelle du catalogue
136       # remplacé par Retrouve_Ordre_Cata_Standard_autre qui utilise une numerotation
137       # des mots clés à la création
138       #self.Retrouve_Ordre_Cata_Standard()
139       self.Retrouve_Ordre_Cata_Standard_autre()
140       self.update_barre()
141       if self.appli.test == 0 :
142          splash._splash.configure(text = "Fin Retrouve_Ordre: %d s" % time.clock())
143       #
144       # analyse des données liées à l'IHM : UIinfo
145       #
146       uiinfo.traite_UIinfo(self.cata)
147       self.update_barre()
148
149       #
150       # traitement des clefs documentaires
151       #
152       self.traite_clefs_documentaires()
153
154       # chargement et analyse des catalogues développeur (le cas échéant)
155       #
156       if self.appli.CONFIGURATION.isdeveloppeur == 'OUI' :
157           init_rep_cata_dev(self.fic_cata,self.appli.CONFIGURATION.path_cata_dev)
158           fic_cata_dev = os.path.join(self.appli.CONFIGURATION.path_cata_dev,'cata_developpeur.py')
159           if os.path.isfile(fic_cata_dev):
160               # il y a bien un catalogue développeur : il faut récupérer le module_object associé ...
161               test = self.compile_cata(fic_cata_dev,fic_cata_dev+'c')
162               if not test :
163                   showinfo("Compilation catalogue développeur",
164                            "Erreur dans la compilation du catalogue développeur")
165                   self.cata = (self.cata,)
166               else:
167                   self.cata_dev =self.import_cata(fic_cata_dev)
168                   #self.Retrouve_Ordre_Cata_Developpeur()
169                   self.Retrouve_Ordre_Cata_Developpeur_autre()
170                   self.cata = (self.cata,self.cata_dev)
171           else:
172               self.cata = (self.cata,)
173       else:
174           self.cata = (self.cata,)
175
176    def import_cata(self,cata):
177       """ 
178           Réalise l'import du catalogue dont le chemin d'accès est donné par cata
179       """
180       if self.appli.test == 0 :
181          splash._splash.configure(text = "Chargement du catalogue")
182       nom_cata = os.path.splitext(os.path.basename(cata))[0]
183       rep_cata = os.path.dirname(cata)
184       sys.path[:0] = [rep_cata]
185       try :
186           o=__import__(nom_cata)
187           return o
188       except Exception,e:
189           traceback.print_exc()
190           return 0
191
192    def Retrouve_Ordre_Cata_Standard_autre(self):
193       """ 
194           Construit une structure de données dans le catalogue qui permet
195           à EFICAS de retrouver l'ordre des mots-clés dans le texte du catalogue.
196           Pour chaque entité du catlogue on crée une liste de nom ordre_mc qui
197           contient le nom des mots clés dans le bon ordre
198       """ 
199       self.cata_ordonne_dico,self.appli.liste_simp_reel=autre_analyse_cata.analyse_catalogue(self.cata)
200
201    def Retrouve_Ordre_Cata_Standard(self):
202       """ 
203           Retrouve l'ordre des mots-clés dans le catalogue, cad :
204            - si ce dernier a été modifié, relance l'analyse du catalogue pour déterminer
205                l'ordre des mots-clés dans le catalogue
206            - s'il n'a pas été modifié, relie le fichier pickle 
207       """
208       time1 = os.path.getmtime(self.fic_cata)
209       try :
210           time2 = os.path.getmtime(self.fic_cata_p)
211       except:
212           time2 = 0
213       if time2 > time1 :
214           # l'objet catalogue n'a pas été modifié depuis le dernier "pickle"
215           self.Get_Ordre_Cata()
216       else :
217           # le catalogue a été modifié depuis le dernier "pickle" :
218           # il faut retrouver l'ordre du catalogue et refaire pickle
219           self.Get_Ordre_Cata(mode='cata')
220       self.appli.affiche_infos("Catalogue standard chargé")
221
222    def Retrouve_Ordre_Cata_Developpeur(self):
223       """ 
224           Retrouve l'ordre des mots-clés dans le catalogue, cad :
225           - si ce dernier a été modifié, relance l'analyse du catalogue pour déterminer
226             l'ordre des mots-clés dans le catalogue
227           - s'il n'a pas été modifié, relie le fichier pickle 
228       """
229       if self.code != 'ASTER' : return
230       fic_cata = os.path.join(self.appli.CONFIGURATION.path_cata_dev,'cata_developpeur.py')
231       message="Chargement catalogue développeur présent dans :\n %s..." % self.appli.CONFIGURATION.path_cata_dev
232       if self.appli.test == 0 :
233          splash._splash.configure(text = message,barre='oui')
234       cata_dev_ordonne = analyse_cata.analyse_catalogue(self,self.fic_cata)
235       self.cata_dev_ordonne_cr = cata_dev_ordonne.cr
236       cata_dev_ordonne_dico = cata_dev_ordonne.entites
237       self.cata_ordonne_dico.update(cata_dev_ordonne_dico)
238       self.appli.affiche_infos(" catalogue(s) développeur(s) chargé(s)" )
239
240    def Retrouve_Ordre_Cata_Developpeur_autre(self):
241       """
242           Retrouve l'ordre des mots-clés dans le catalogue, cad :
243           - si ce dernier a été modifié, relance l'analyse du catalogue pour déterminer
244             l'ordre des mots-clés dans le catalogue
245           - s'il n'a pas été modifié, relie le fichier pickle
246       """
247       if self.code != 'ASTER' : return
248       message="Chargement catalogue développeur présent dans :\n %s..." % self.appli.CONFIGURATION.path_cata_dev
249       if self.appli.test == 0 :
250          splash._splash.configure(text = message,barre='oui')
251       cata_dev_ordonne_dico,self.appli.liste_simp_reel=autre_analyse_cata.analyse_catalogue(self.cata)
252       self.cata_ordonne_dico.update(cata_dev_ordonne_dico)
253       self.appli.affiche_infos(" catalogue(s) développeur(s) chargé(s)" )
254
255    def Get_Ordre_Cata(self,mode='pickle'):
256       """ 
257           Retrouve l'ordre du catalogue :
258             - mode='pickle ': tente de relire le fichier pickle et sinon lance l'analyse du catalogue
259             - mode='cata'   : force l'analyse du catalogue directement sans relire le pickle
260       """
261       if mode == 'pickle' :
262           try:
263               f = open(self.fic_cata_p)
264               u = cPickle.Unpickler(f)
265               if self.appli.test == 0 :
266                  splash._splash.configure(text = "Analyse du catalogue")
267               self.cata_ordonne_dico = u.load()
268               f.close()
269           except :
270               # on peut ne pas arriver à relire le fichier pickle s'il a été altéré
271               # ou (le plus probable) s'il a été créé sous un autre OS
272               self.Get_Ordre_Cata(mode='cata')
273       elif mode == 'cata':
274           if self.appli.test == 0 :
275               splash._splash.configure(text = "Analyse du catalogue",barre='oui')
276           cata_ordonne = analyse_catalogue.analyse_catalogue(self,self.fic_cata)
277           self.cata_ordonne_cr = cata_ordonne.cr
278           self.cata_ordonne_dico = cata_ordonne.entites
279           splash._splash.configure(text = "Sauvegarde des informations sur le catalogue")
280           f = open(self.fic_cata_p,'w+')
281           p = cPickle.Pickler(f)
282           p.dump(self.cata_ordonne_dico)
283           f.close()
284       else :
285           raise Exception("Appel à un mode inconnu de Get_Ordre_Cata : %s" % mode)
286           return
287
288    def ask_choix_catalogue(self):
289       """
290       Ouvre une fenêtre de sélection du catalogue dans le cas où plusieurs
291       ont été définis dans Accas/editeur.ini
292       """
293       # construction du dictionnaire et de la liste des catalogues
294       self.dico_catalogues = {}
295       defaut = None
296       for catalogue in self.appli.CONFIGURATION.catalogues:
297           if catalogue[0] == self.code :
298               self.dico_catalogues[catalogue[1]] = catalogue
299               if len(catalogue) == 5 :
300                   if catalogue[4]=='defaut' : defaut = catalogue[1]
301       liste_choix = self.dico_catalogues.keys()
302       liste_choix.sort()
303       # test si plusieurs catalogues ou non
304       if len(liste_choix) == 0:
305           showerror("Aucun catalogue déclaré pour %s" %self.code)
306           self.appli.quit()
307           sys.exit(1)
308       elif len(liste_choix) == 1:
309           self.fic_cata = self.dico_catalogues[liste_choix[0]][2]
310           self.version_code = liste_choix[0]
311           return
312       # création d'une boîte de dialogue modale
313       self.fenetre_choix_cata = Pmw.Dialog(splash._splash, #avec self.parent, ne marche pas sous Windows
314                                            buttons=('OK','ANNULER'),
315                                            defaultbutton = 'OK',
316                                            title = "Choix d'une version du code %s" %self.code,
317                                            command = self.chooseCata)
318       # construction des radioboutons
319       label = `len(liste_choix)`+' versions du code %s sont disponibles\n' %self.code
320       label = label + 'Veuillez choisir celle avec laquelle vous souhaitez travailler :'
321       self.radiobutton = Pmw.RadioSelect(self.fenetre_choix_cata.interior(),
322                                          buttontype='radiobutton',
323                                          labelpos = 'w',
324                                          label_text = label,
325                                          label_font = fontes.standard,
326                                          orient='vertical')
327       for choix in liste_choix :
328           self.radiobutton.add(choix)
329       if defaut == None :
330           # aucun catalogue par défaut n'a été spécifié dans Accas/editeur.ini
331           defaut = liste_choix[0]
332       self.radiobutton.invoke(defaut)
333       self.radiobutton.pack(fill='x',padx=10,pady=10)
334       # centrage de la fenêtre
335       self.fenetre_choix_cata.activate(geometry='centerscreenalways')
336
337    def chooseCata(self,txt):
338       """ 
339           Méthode activée lorsque l'utilisateur a fait son choix et cliqué sur 'OK' ou sur 'ANNULER'
340       """
341       if txt == 'OK' :
342           version_cata = self.radiobutton.getcurselection()
343           self.fic_cata = self.dico_catalogues[version_cata][2]
344           self.version_code = version_cata
345           self.appli.format_fichier.set(self.dico_catalogues[version_cata][3])
346           self.fenetre_choix_cata.destroy()
347       else:
348           self.parent.destroy()
349
350    def compile_cata(self,cata,catac):
351       """ 
352            Teste si le catalogue a bien besoin d'être recompilé et si oui, le compile et
353            affiche un message dans le splash . Retourne 1 si la compilation s'est bien déroulée,
354            0 sinon.
355       """
356       time1 = os.path.getmtime(cata)
357       try:
358           time2 = os.path.getmtime(catac)
359       except:
360           time2 = 0
361       if time1 > time2:
362           try:
363               # le catalogue doit être recompilé avant d'être importé
364               if self.appli.test == 0 :
365                  splash._splash.configure(text="Compilation du catalogue\nCela peut prendre plusieurs secondes ...")
366               py_compile.compile(cata)
367           except:
368               return 0
369       return 1
370
371
372 #--------------------------------------------------------------------------------
373 # Méthodes concernant la barre de progression lors de l'analyse du catalogue
374 #--------------------------------------------------------------------------------
375
376    def configure_barre(self,nbcommandes):
377       """ Configure la barre de progression en lui passant comme paramètre le
378           nombre de commandes du catalogue qui lui sert à déterminer la longueur de son incrément """
379       try:
380           if self.appli.test == 0 :
381              splash._splash.configure(barre='oui',ratio = nbcommandes)
382       except:
383           pass
384
385    def update_barre(self):
386       """ Update la position de la barre de progression : la fait progresser de son incrément """
387       try:
388           if self.appli.test == 0 :
389              splash._splash.update_barre()
390       except:
391           pass
392
393    def visuCRCATA(self):
394       """
395       Méthode permettant l'affichage du rapport de validation
396       """
397       cr = CR( debut = "Début rapport de validation du catalogue",
398                fin = "Fin rapport de validation du catalogue")
399       titre="rapport de validation du catalogue"
400       if hasattr(self,'cata_ordonne_cr') :
401           cr.add(self.cata_ordonne_cr)
402       if hasattr(self,'cata_dev_ordonne_cr') :
403           cr.add(self.cata_dev_ordonne_cr)
404       for cata in self.cata:
405           if hasattr(cata,'JdC'):
406               cr.add(cata.JdC.report())
407       texte_cr = str(cr)
408       self.visu_texte_cr = Fenetre(self.appli,titre=titre,texte=texte_cr)
409
410
411    def traite_clefs_documentaires(self):
412       try:
413         self.fic_cata_clef=os.path.splitext(self.fic_cata_c)[0]+'_clefs_docu'
414         f=open(self.fic_cata_clef)
415       except:
416         #print "Pas de fichier associé contenant des clefs documentaires"
417         return
418
419       dict_clef_docu={}
420       for l in f.readlines():
421           clef=l.split(':')[0]
422           docu=l.split(':')[1]
423           docu=docu[0:-1]
424           dict_clef_docu[clef]=docu
425       for oper in self.cata.JdC.commandes:
426            if dict_clef_docu.has_key(oper.nom):
427               oper.docu=dict_clef_docu[oper.nom]