Salome HOME
*** empty log message ***
[tools/eficas.git] / Ihm / I_MCSIMP.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 import types,string
22 import traceback
23 from copy import copy
24 from repr import Repr
25 myrepr = Repr()
26 myrepr.maxstring = 100
27 myrepr.maxother = 100
28
29 from Noyau.N_utils import repr_float
30 import Validation
31 import CONNECTOR
32
33 # Attention : les classes ASSD,.... peuvent etre surchargées
34 # dans le package Accas. Il faut donc prendre des précautions si
35 # on utilise les classes du Noyau pour faire des tests (isxxxx, ...)
36 # Si on veut créer des objets comme des CO avec les classes du noyau
37 # ils n'auront pas les conportements des autres packages (pb!!!)
38 # Il vaut mieux les importer d'Accas mais problème d'import circulaire,
39 # on ne peut pas les importer au début.
40 # On fait donc un import local quand c'est nécessaire (peut occasionner
41 # des pbs de prformance).
42 from Noyau.N_ASSD import ASSD,assd
43 from Noyau.N_GEOM import GEOM,geom
44 from Noyau.N_CO import CO
45 import Accas
46 # fin attention
47
48 from Extensions import parametre
49 from Extensions import param2
50 import I_OBJECT
51 import CONNECTOR
52 from I_VALIDATOR import ValError,listProto
53
54 class MCSIMP(I_OBJECT.OBJECT):
55
56   def GetNomConcept(self):
57       p=self
58       while p.parent :
59          try :
60             nomconcept=p.get_sdname()
61             return nomconcept
62          except:
63             try :
64                nomconcept= p.object.get_sdname()
65                return nomconcept
66             except :
67                pass
68          p=p.parent
69       return ""
70
71   def GetText(self):
72     """
73         Retourne le texte à afficher dans l'arbre représentant la valeur de l'objet
74         pointé par self
75     """
76
77     if self.valeur == None : 
78       return None
79     elif type(self.valeur) == types.FloatType : 
80       # Traitement d'un flottant isolé
81       txt = str(self.valeur)
82       clefobj=self.GetNomConcept()
83       if self.jdc.appli.dict_reels.has_key(clefobj):
84         if self.jdc.appli.dict_reels[clefobj].has_key(self.valeur):
85            txt=self.jdc.appli.dict_reels[clefobj][self.valeur]
86     elif type(self.valeur) in (types.ListType,types.TupleType) :
87       # Traitement des listes
88       txt='('
89       sep=''
90       for val in self.valeur:
91         if type(val) == types.FloatType : 
92            clefobj=self.GetNomConcept()
93            if self.jdc.appli.dict_reels.has_key(clefobj):
94               if self.jdc.appli.dict_reels[clefobj].has_key(val):
95                  txt=txt + sep +self.jdc.appli.dict_reels[clefobj][val]
96               else :
97                  txt=txt + sep + str(val)
98            else :
99               txt=txt + sep + str(val)
100         else: 
101            txt = txt + sep+ str(val)
102         if len(txt) > 200:
103             #ligne trop longue, on tronque
104             txt=txt+" ..."
105             break
106         sep=','
107       txt=txt+')'
108     else:
109       # Traitement des autres cas
110       txt = str(self.valeur)
111
112     # txt peut etre une longue chaine sur plusieurs lignes.
113     # Il est possible de tronquer cette chaine au premier \n et 
114     # de limiter la longueur de la chaine a 30 caracteres. Cependant
115     # ceci provoque une perte d'information pour l'utilisateur
116     # Pour le moment on retourne la chaine telle que
117     return txt
118
119   def getval(self):
120     """ 
121        Retourne une chaîne de caractère représentant la valeur de self 
122     """
123     val=self.valeur
124     if type(val) == types.FloatType : 
125       clefobj=self.GetNomConcept()
126       if self.jdc.appli.dict_reels.has_key(clefobj):
127         if self.jdc.appli.dict_reels[clefobj].has_key(val):
128            return self.jdc.appli.dict_reels[clefobj][val]
129     if type(val) != types.TupleType :
130       try:
131         return val.get_name()
132       except:
133         return val
134     else :
135       s='( '
136       for item in val :
137         try :
138           s=s+item.get_name()+','
139         except:
140           s=s+`item`+','
141       s=s+' )'
142       return s
143
144   def wait_co(self):
145     """
146         Méthode booléenne qui retourne 1 si l'objet attend un objet ASSD 
147         qui n'existe pas encore (type CO()), 0 sinon
148     """
149     for typ in self.definition.type:
150       if type(typ) == types.ClassType or isinstance(typ,type):
151         if issubclass(typ,CO) :
152            return 1
153     return 0
154
155   def wait_assd(self):
156     """ 
157         Méthode booléenne qui retourne 1 si le MCS attend un objet de type ASSD 
158         ou dérivé, 0 sinon
159     """
160     for typ in self.definition.type:
161       if type(typ) == types.ClassType or isinstance(typ,type):
162         if issubclass(typ,ASSD) and not issubclass(typ,GEOM):
163           return 1
164     return 0
165
166   def wait_assd_or_geom(self):
167     """ 
168          Retourne 1 si le mot-clé simple attend un objet de type
169          assd, ASSD, geom ou GEOM
170          Retourne 0 dans le cas contraire
171     """
172     for typ in self.definition.type:
173       if type(typ) == types.ClassType or isinstance(typ,type):
174         if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) :
175           return 1
176     return 0
177
178   def wait_geom(self):
179     """ 
180          Retourne 1 si le mot-clé simple attend un objet de type GEOM
181          Retourne 0 dans le cas contraire
182     """
183     for typ in self.definition.type:
184       if type(typ) == types.ClassType or isinstance(typ,type):
185         if issubclass(typ,GEOM) : return 1
186     return 0
187
188   def wait_TXM(self):
189     """ 
190          Retourne 1 si le mot-clé simple attend un objet de type TXM
191          Retourne 0 dans le cas contraire
192     """
193     for typ in self.definition.type:
194       if typ == 'TXM' :return 1
195     return 0
196
197   def get_liste_valeurs(self):
198     """
199     """
200     if self.valeur == None:
201       return []
202     elif type(self.valeur) == types.TupleType:
203       return list(self.valeur)
204     elif type(self.valeur) == types.ListType:
205       return self.valeur
206     else:
207       return [self.valeur]
208
209   def isoblig(self):
210     return self.definition.statut=='o'
211
212   def valid_val(self,valeur):
213       """
214         Verifie que la valeur passee en argument (valeur) est valide
215         sans modifier la valeur courante 
216       """
217       lval=listProto.adapt(valeur)
218       if lval is None:
219          valid=0
220          mess="None n'est pas une valeur autorisée"
221       else:
222          try:
223             for val in lval:
224                 self.typeProto.adapt(val)
225                 self.intoProto.adapt(val)
226             self.cardProto.adapt(lval)
227             if self.definition.validators:
228                 self.definition.validators.convert(lval)
229             valid,mess=1,""
230          except ValError,e:
231             mess=str(e)
232             valid=0
233       return valid,mess
234
235   def valid_valeur(self,new_valeur):
236       """
237         Verifie que la valeur passee en argument (new_valeur) est valide
238         sans modifier la valeur courante (evite d'utiliser set_valeur et est plus performant)
239       """
240       validite,mess=self.valid_val(new_valeur)
241       return validite
242
243   def valid_valeur_partielle(self,new_valeur):
244       """
245         Verifie que la valeur passee en argument (new_valeur) est une liste partiellement valide
246         sans modifier la valeur courante du mot cle
247       """
248       validite=1
249       try:
250           for val in new_valeur:
251               self.typeProto.adapt(val)
252               self.intoProto.adapt(val)
253               #on ne verifie pas la cardinalité
254               if self.definition.validators:
255                   validite=self.definition.validators.valide_liste_partielle(new_valeur)
256       except ValError,e:
257           validite=0
258
259       return validite
260
261   def update_condition_bloc(self):
262       """ Met a jour les blocs conditionnels dependant du mot cle simple self
263       """
264       if self.definition.position == 'global' : 
265          self.etape.deep_update_condition_bloc()
266       elif self.definition.position == 'global_jdc' :
267          self.jdc.deep_update_condition_bloc()
268       else:
269          self.parent.update_condition_bloc()
270
271   def set_valeur(self,new_valeur,evaluation='oui'):
272         #print "set_valeur",new_valeur
273         self.init_modif()
274         self.valeur = new_valeur
275         self.val = new_valeur
276         self.update_condition_bloc()
277         self.fin_modif()
278         return 1
279
280   def eval_valeur(self,new_valeur):
281     """
282         Essaie d'évaluer new_valeur comme une SD, une déclaration Python 
283         ou un EVAL: Retourne la valeur évaluée (ou None) et le test de réussite (1 ou 0)
284     """
285     sd = self.jdc.get_sd_avant_etape(new_valeur,self.etape)
286     #sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None)
287     #print sd
288     if sd is not None:
289       return sd,1
290     lsd = self.jdc.cherche_list_avant(self.etape,new_valeur) 
291     if lsd :
292       return lsd,1
293     else:
294       d={}
295       # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
296       d['EVAL']=Accas.EVAL
297       try :
298         objet = eval(new_valeur,d)
299         return objet,1
300       except Exception:
301         itparam=self.cherche_item_parametre(new_valeur)
302         if itparam:
303              return itparam,1
304         try :
305              object=eval(new_valeur.valeur,d)
306         except :
307              pass
308         if CONTEXT.debug : traceback.print_exc()
309         return None,0
310
311   def eval_val(self,new_valeur):
312     """
313        Tente d'evaluer new_valeur comme un objet du jdc (par appel a eval_val_item)
314        ou comme une liste de ces memes objets
315        Si new_valeur contient au moins un separateur (,), tente l'evaluation sur
316        la chaine splittee
317     """
318     if type(new_valeur) in (types.ListType,types.TupleType):
319        valeurretour=[]
320        for item in new_valeur :
321           valeurretour.append(self.eval_val_item(item))
322        return valeurretour
323     else:
324        valeur=self.eval_val_item(new_valeur)
325        return valeur
326
327   def eval_val_item(self,new_valeur):
328     """
329        Tente d'evaluer new_valeur comme un concept, un parametre, un objet Python
330        Si c'est impossible retourne new_valeur inchange
331        argument new_valeur : string (nom de concept, de parametre, expression ou simple chaine)
332     """
333     if self.etape and self.etape.parent:
334        valeur=self.etape.parent.eval_in_context(new_valeur,self.etape)
335        return valeur
336     else:
337        try :
338            valeur = eval(val)
339            return valeur
340        except:
341            #traceback.print_exc()
342            return new_valeur
343            pass
344
345   def cherche_item_parametre (self,new_valeur):
346         try:
347           nomparam=new_valeur[0:new_valeur.find("[")]
348           indice=new_valeur[new_valeur.find("[")+1:new_valeur.find("]")]
349           for p in self.jdc.params:
350              if p.nom == nomparam :
351                 if int(indice) < len(p.get_valeurs()):
352                    itparam=parametre.ITEM_PARAMETRE(p,int(indice))
353                    return itparam
354           return None
355         except:
356           return None
357
358   def update_concept(self,sd):
359     if type(self.valeur) in (types.ListType,types.TupleType) :
360        if sd in self.valeur:self.fin_modif()
361     else:
362        if sd == self.valeur:self.fin_modif()
363
364   def delete_concept(self,sd):
365     """ 
366         Inputs :
367            - sd=concept detruit
368         Fonction :
369         Met a jour la valeur du mot cle simple suite à la disparition 
370         du concept sd
371     """
372     #print "delete_concept",sd
373     if type(self.valeur) == types.TupleType :
374       if sd in self.valeur:
375         self.init_modif()
376         self.valeur=list(self.valeur)
377         self.valeur.remove(sd)
378         self.fin_modif()
379     elif type(self.valeur) == types.ListType:
380       if sd in self.valeur:
381         self.init_modif()
382         self.valeur.remove(sd)
383         self.fin_modif()
384     else:
385       if self.valeur == sd:
386         self.init_modif()
387         self.valeur=None
388         self.val=None
389         self.fin_modif()
390
391   def replace_concept(self,old_sd,sd):
392     """
393         Inputs :
394            - old_sd=concept remplacé
395            - sd=nouveau concept
396         Fonction :
397         Met a jour la valeur du mot cle simple suite au remplacement 
398         du concept old_sd
399     """
400     #print "replace_concept",old_sd,sd
401     if type(self.valeur) == types.TupleType :
402       if old_sd in self.valeur:
403         self.init_modif()
404         self.valeur=list(self.valeur)
405         i=self.valeur.index(old_sd)
406         self.valeur[i]=sd
407         self.fin_modif()
408     elif type(self.valeur) == types.ListType:
409       if old_sd in self.valeur:
410         self.init_modif()
411         i=self.valeur.index(old_sd)
412         self.valeur[i]=sd
413         self.fin_modif()
414     else:
415       if self.valeur == old_sd:
416         self.init_modif()
417         self.valeur=sd
418         self.val=sd
419         self.fin_modif()
420
421   def set_valeur_co(self,nom_co):
422       """
423           Affecte à self l'objet de type CO et de nom nom_co
424       """
425       #print "set_valeur_co",nom_co
426       step=self.etape.parent
427       if nom_co == None or nom_co == '':
428          new_objet=None
429       else:
430          # Avant de créer un concept il faut s'assurer du contexte : step 
431          # courant
432          sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui')
433          if sd:
434             # Si un concept du meme nom existe deja dans la portée de l'étape
435             # on ne crée pas le concept
436             return 0,"un concept de meme nom existe deja"
437          # Il n'existe pas de concept de meme nom. On peut donc le créer 
438          # Il faut néanmoins que la méthode NommerSdProd de step gère les 
439          # contextes en mode editeur
440          # Normalement la méthode  du Noyau doit etre surchargée
441          # On déclare l'étape du mot clé comme etape courante pour NommerSdprod
442          cs= CONTEXT.get_current_step()
443          CONTEXT.unset_current_step()
444          CONTEXT.set_current_step(step)
445          step.set_etape_context(self.etape)
446          new_objet = Accas.CO(nom_co)
447          CONTEXT.unset_current_step()
448          CONTEXT.set_current_step(cs)
449       self.init_modif()
450       self.valeur = new_objet
451       self.val = new_objet
452       # On force l'enregistrement de new_objet en tant que concept produit 
453       # de la macro en appelant get_type_produit avec force=1
454       self.etape.get_type_produit(force=1)
455       self.fin_modif()
456       step.reset_context()
457       #print "set_valeur_co",new_objet
458       return 1,"Concept créé"
459         
460   def verif_existence_sd(self):
461      """
462         Vérifie que les structures de données utilisées dans self existent bien dans le contexte
463         avant étape, sinon enlève la référence à ces concepts
464      """
465      #print "verif_existence_sd"
466      # Attention : possible probleme avec include
467      # A priori il n'y a pas de raison de retirer les concepts non existants
468      # avant etape. En fait il s'agit uniquement eventuellement de ceux crees par une macro
469      l_sd_avant_etape = self.jdc.get_contexte_avant(self.etape).values()  
470      if type(self.valeur) in (types.TupleType,types.ListType) :
471        l=[]
472        for sd in self.valeur:
473          if isinstance(sd,ASSD) :
474             if sd in l_sd_avant_etape or self.etape.get_sdprods(sd.nom) is sd:
475                l.append(sd)
476          else:
477             l.append(sd)
478        if len(l) < len(self.valeur):
479           self.init_modif()
480           self.valeur=tuple(l)
481           self.fin_modif()
482      else:
483        if isinstance(self.valeur,ASSD) :
484           if self.valeur not in l_sd_avant_etape and self.etape.get_sdprods(self.valeur.nom) is None:
485              self.init_modif()
486              self.valeur = None
487              self.fin_modif()
488  
489   def get_min_max(self):
490      """
491      Retourne les valeurs min et max admissibles pour la valeur de self
492      """
493      return self.definition.min,self.definition.max
494
495
496   def get_type(self):
497      """
498      Retourne le type attendu par le mot-clé simple
499      """
500      return self.definition.type
501
502   def delete_mc_global(self):
503       """ Retire self des declarations globales
504       """
505       if self.definition.position == 'global' : 
506          etape = self.get_etape()
507          if etape :
508             del etape.mc_globaux[self.nom]
509       elif self.definition.position == 'global_jdc' :
510          del self.jdc.mc_globaux[self.nom]
511
512   def update_mc_global(self):
513      """
514         Met a jour les mots cles globaux enregistrés dans l'étape parente
515         et dans le jdc parent.
516         Un mot cle simple peut etre global. 
517      """
518      if self.definition.position == 'global' :
519         etape = self.get_etape()
520         if etape :
521            etape.mc_globaux[self.nom]=self
522      elif self.definition.position == 'global_jdc' :
523         if self.jdc:
524            self.jdc.mc_globaux[self.nom]=self
525
526   def nbrColonnes(self):
527      genea = self.get_genealogie()
528      if "VALE_C" in genea and "DEFI_FONCTION" in genea : return 3
529      if "VALE" in genea and "DEFI_FONCTION" in genea : return 2
530      return 0
531
532   def valide_item(self,item):
533       """Valide un item isolé. Cet item est candidat à l'ajout à la liste existante"""
534       valid=1
535       try:
536           #on verifie le type
537           self.typeProto.adapt(item)
538           #on verifie les choix possibles
539           self.intoProto.adapt(item)
540           #on ne verifie pas la cardinalité
541           if self.definition.validators:
542               valid=self.definition.validators.verif_item(item)
543       except ValError,e:
544           #traceback.print_exc()
545           valid=0
546       return valid
547
548   def verif_type(self,item):
549       """Verifie le type d'un item de liste"""
550       try:
551           #on verifie le type
552           self.typeProto.adapt(item)
553           #on verifie les choix possibles
554           self.intoProto.adapt(item)
555           #on ne verifie pas la cardinalité mais on verifie les validateurs
556           if self.definition.validators:
557               valid=self.definition.validators.verif_item(item)
558           comment=""
559           valid=1
560       except ValError,e:
561           #traceback.print_exc()
562           comment=str(e)
563           valid=0
564       return valid,comment
565
566 #--------------------------------------------------------------------------------
567  
568 #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation
569 # Elles doivent etre reintegrees des que possible
570
571
572   def verif_typeihm(self,val,cr='non'):
573       try :
574          val.eval()
575          return 1
576       except :
577          traceback.print_exc()
578          pass
579       return self.verif_type(val,cr)
580
581   def verif_typeliste(self,val,cr='non') :
582       verif=0
583       for v in val :
584         verif=verif+self.verif_typeihm(v,cr)
585       return verif
586
587   def init_modif_up(self):
588     Validation.V_MCSIMP.MCSIMP.init_modif_up(self)
589     CONNECTOR.Emit(self,"valid")