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