Salome HOME
version 19 mars
[tools/eficas.git] / Ihm / I_MCSIMP.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013   EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 import types,string
21 import traceback
22 from copy import copy
23 from repr import Repr
24 from Extensions.i18n import tr
25 from Extensions.eficas_exception import EficasException
26 myrepr = Repr()
27 myrepr.maxstring = 100
28 myrepr.maxother = 100
29
30 from Noyau.N_utils import repr_float
31 import Validation
32 import CONNECTOR
33
34 # Attention : les classes ASSD,.... peuvent etre surchargees
35 # dans le package Accas. Il faut donc prendre des precautions si
36 # on utilise les classes du Noyau pour faire des tests (isxxxx, ...)
37 # Si on veut creer des objets comme des CO avec les classes du noyau
38 # ils n'auront pas les conportements des autres packages (pb!!!)
39 # Il vaut mieux les importer d'Accas mais probleme d'import circulaire,
40 # on ne peut pas les importer au debut.
41 # On fait donc un import local quand c'est necessaire (peut occasionner
42 # des pbs de prformance).
43 from Noyau.N_ASSD import ASSD,assd
44 from Noyau.N_GEOM import GEOM,geom
45 from Noyau.N_CO import CO
46 import Accas
47 # fin attention
48
49 from Extensions import parametre
50 from Extensions import param2
51 import I_OBJECT
52 import CONNECTOR
53 from I_VALIDATOR import ValError,listProto
54
55 class MCSIMP(I_OBJECT.OBJECT):
56
57
58   def isvalid(self,cr='non'):
59       if self.state == 'unchanged':
60         return self.valid
61       for type_permis in self.definition.type:
62           if hasattr(type_permis, "__class__") and type_permis.__class__.__name__ == 'Matrice':
63              self.monType=type_permis
64              return self.valideMatrice(cr=cr)
65       return Validation.V_MCSIMP.MCSIMP.isvalid(self,cr=cr)
66
67   def GetNomConcept(self):
68       p=self
69       while p.parent :
70          try :
71             nomconcept=p.get_sdname()
72             return nomconcept
73          except:
74             try :
75                nomconcept= p.object.get_sdname()
76                return nomconcept
77             except :
78                pass
79          p=p.parent
80       return ""
81
82   def GetText(self):
83     """
84         Retourne le texte a afficher dans l'arbre representant la valeur de l'objet
85         pointe par self
86     """
87
88     if self.valeur == None : 
89       return None
90     elif type(self.valeur) == types.FloatType : 
91       # Traitement d'un flottant isole
92       txt = str(self.valeur)
93       clefobj=self.GetNomConcept()
94       if self.jdc.appli.appliEficas.dict_reels.has_key(clefobj):
95         if self.jdc.appli.appliEficas.dict_reels[clefobj].has_key(self.valeur):
96            txt=self.jdc.appli.appliEficas.dict_reels[clefobj][self.valeur]
97     elif type(self.valeur) in (types.ListType,types.TupleType) :
98       # Traitement des listes
99       txt='('
100       sep=''
101       for val in self.valeur:
102         if type(val) == types.FloatType : 
103            clefobj=self.GetNomConcept()
104            if self.jdc.appli.appliEficas.dict_reels.has_key(clefobj):
105               if self.jdc.appli.appliEficas.dict_reels[clefobj].has_key(val):
106                  txt=txt + sep +self.jdc.appli.appliEficas.dict_reels[clefobj][val]
107               else :
108                  txt=txt + sep + str(val)
109            else :
110               txt=txt + sep + str(val)
111         else: 
112            txt = txt + sep+ str(val)
113         if len(txt) > 200:
114             #ligne trop longue, on tronque
115             txt=txt+" ..."
116             break
117         sep=','
118       txt=txt+')'
119     else:
120       # Traitement des autres cas
121       txt = str(self.valeur)
122
123     # txt peut etre une longue chaine sur plusieurs lignes.
124     # Il est possible de tronquer cette chaine au premier \n et 
125     # de limiter la longueur de la chaine a 30 caracteres. Cependant
126     # ceci provoque une perte d'information pour l'utilisateur
127     # Pour le moment on retourne la chaine telle que
128     return txt
129
130   def getval(self):
131     """ 
132        Retourne une chaine de caractere representant la valeur de self 
133     """
134     val=self.valeur
135     if type(val) == types.FloatType : 
136       clefobj=self.GetNomConcept()
137       if self.jdc.appli.appliEficas.dict_reels.has_key(clefobj):
138         if self.jdc.appli.appliEficas.appliEficas.dict_reels[clefobj].has_key(val):
139            return self.jdc.appli.appliEficas.dict_reels[clefobj][val]
140     if type(val) != types.TupleType :
141       try:
142         return val.get_name()
143       except:
144         return val
145     else :
146       s='( '
147       for item in val :
148         try :
149           s=s+item.get_name()+','
150         except:
151           s=s+`item`+','
152       s=s+' )'
153       return s
154
155   def wait_bool(self):
156       for typ in self.definition.type:
157           try :
158             if typ == types.BooleanType: return True
159           except :
160             pass
161       return False
162
163   def wait_co(self):
164     """
165         Methode booleenne qui retourne 1 si l'objet attend un objet ASSD 
166         qui n'existe pas encore (type CO()), 0 sinon
167     """
168     for typ in self.definition.type:
169       if type(typ) == types.ClassType or isinstance(typ,type):
170         if issubclass(typ,CO) :
171            return 1
172     return 0
173
174   def wait_assd(self):
175     """ 
176         Methode booleenne qui retourne 1 si le MCS attend un objet de type ASSD 
177         ou derive, 0 sinon
178     """
179     for typ in self.definition.type:
180       if type(typ) == types.ClassType or isinstance(typ,type):
181         if issubclass(typ,ASSD) and not issubclass(typ,GEOM):
182           return 1
183     return 0
184
185   def wait_assd_or_geom(self):
186     """ 
187          Retourne 1 si le mot-cle simple attend un objet de type
188          assd, ASSD, geom ou GEOM
189          Retourne 0 dans le cas contraire
190     """
191     for typ in self.definition.type:
192       if type(typ) == types.ClassType or isinstance(typ,type):
193         if typ.__name__ in ("GEOM","ASSD","geom","assd") or issubclass(typ,GEOM) :
194           return 1
195     return 0
196
197   def wait_geom(self):
198     """ 
199          Retourne 1 si le mot-cle simple attend un objet de type GEOM
200          Retourne 0 dans le cas contraire
201     """
202     for typ in self.definition.type:
203       if type(typ) == types.ClassType or isinstance(typ,type):
204         if issubclass(typ,GEOM) : return 1
205     return 0
206
207
208   def wait_TXM(self):
209     """ 
210          Retourne 1 si le mot-cle simple attend un objet de type TXM
211          Retourne 0 dans le cas contraire
212     """
213     for typ in self.definition.type:
214       if typ == 'TXM' :return 1
215     return 0
216
217   def get_liste_valeurs(self):
218     """
219     """
220     if self.valeur == None:
221       return []
222     elif type(self.valeur) == types.TupleType:
223       return list(self.valeur)
224     elif type(self.valeur) == types.ListType:
225       return self.valeur
226     else:
227       return [self.valeur]
228
229   def isoblig(self):
230     return self.definition.statut=='o'
231
232   def isImmuable(self):
233     return self.definition.statut=='i'
234
235
236   def valid_val(self,valeur):
237       """
238         Verifie que la valeur passee en argument (valeur) est valide
239         sans modifier la valeur courante 
240       """
241       lval=listProto.adapt(valeur)
242       if lval is None:
243          valid=0
244          mess=tr("None n'est pas une valeur autorisee")
245       else:
246          try:
247             for val in lval:
248                 self.typeProto.adapt(val)
249                 self.intoProto.adapt(val)
250             self.cardProto.adapt(lval)
251             if self.definition.validators:
252                 self.definition.validators.convert(lval)
253             valid,mess=1,""
254          except ValError as e:
255             mess=str(e)
256             valid=0
257       return valid,mess
258
259   def valid_valeur(self,new_valeur):
260       """
261         Verifie que la valeur passee en argument (new_valeur) est valide
262         sans modifier la valeur courante (evite d'utiliser set_valeur et est plus performant)
263       """
264       validite,mess=self.valid_val(new_valeur)
265       return validite
266
267   def valid_valeur_partielle(self,new_valeur):
268       """
269         Verifie que la valeur passee en argument (new_valeur) est une liste partiellement valide
270         sans modifier la valeur courante du mot cle
271       """
272       validite=1
273       try:
274           for val in new_valeur:
275               self.typeProto.adapt(val)
276               self.intoProto.adapt(val)
277               #on ne verifie pas la cardinalite
278               if self.definition.validators:
279                   validite=self.definition.validators.valide_liste_partielle(new_valeur)
280       except ValError as e:
281           validite=0
282
283       return validite
284
285   def update_condition_bloc(self):
286       """ Met a jour les blocs conditionnels dependant du mot cle simple self
287       """
288       if self.definition.position == 'global' : 
289          self.etape.deep_update_condition_bloc()
290       elif self.definition.position == 'global_jdc' :
291          self.jdc.deep_update_condition_bloc()
292       else:
293          self.parent.update_condition_bloc()
294
295   def set_valeur(self,new_valeur,evaluation='oui'):
296         #print "set_valeur",new_valeur
297         self.init_modif()
298         self.valeur = new_valeur
299         self.val = new_valeur
300         self.update_condition_bloc()
301         self.etape.modified()
302         self.fin_modif()
303         return 1
304
305   def eval_valeur(self,new_valeur):
306     """
307         Essaie d'evaluer new_valeur comme une SD, une declaration Python 
308         ou un EVAL: Retourne la valeur evaluee (ou None) et le test de reussite (1 ou 0)
309     """
310     sd = self.jdc.get_sd_avant_etape(new_valeur,self.etape)
311     #sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None)
312     #print sd
313     if sd is not None:
314       return sd,1
315     lsd = self.jdc.cherche_list_avant(self.etape,new_valeur) 
316     if lsd :
317       return lsd,1
318     else:
319       d={}
320       # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
321       d['EVAL']=Accas.EVAL
322       try :
323         objet = eval(new_valeur,d)
324         return objet,1
325       except Exception:
326         itparam=self.cherche_item_parametre(new_valeur)
327         if itparam:
328              return itparam,1
329         try :
330              object=eval(new_valeur.valeur,d)
331         except :
332              pass
333         if CONTEXT.debug : traceback.print_exc()
334         return None,0
335
336   def eval_val(self,new_valeur):
337     """
338        Tente d'evaluer new_valeur comme un objet du jdc (par appel a eval_val_item)
339        ou comme une liste de ces memes objets
340        Si new_valeur contient au moins un separateur (,), tente l'evaluation sur
341        la chaine splittee
342     """
343     if new_valeur in ('True','False') and 'TXM' in self.definition.type  :
344        valeur=self.eval_val_item(str(new_valeur))
345        return new_valeur
346     if type(new_valeur) in (types.ListType,types.TupleType):
347        valeurretour=[]
348        for item in new_valeur :
349           valeurretour.append(self.eval_val_item(item))
350        return valeurretour
351     else:
352        valeur=self.eval_val_item(new_valeur)
353        return valeur
354
355   def eval_val_item(self,new_valeur):
356     """
357        Tente d'evaluer new_valeur comme un concept, un parametre, un objet Python
358        Si c'est impossible retourne new_valeur inchange
359        argument new_valeur : string (nom de concept, de parametre, expression ou simple chaine)
360     """
361     if self.etape and self.etape.parent:
362        valeur=self.etape.parent.eval_in_context(new_valeur,self.etape)
363        return valeur
364     else:
365        try :
366            valeur = eval(val)
367            return valeur
368        except:
369            #traceback.print_exc()
370            return new_valeur
371            pass
372
373   def cherche_item_parametre (self,new_valeur):
374         try:
375           nomparam=new_valeur[0:new_valeur.find("[")]
376           indice=new_valeur[new_valeur.find(u"[")+1:new_valeur.find(u"]")]
377           for p in self.jdc.params:
378              if p.nom == nomparam :
379                 if int(indice) < len(p.get_valeurs()):
380                    itparam=parametre.ITEM_PARAMETRE(p,int(indice))
381                    return itparam
382           return None
383         except:
384           return None
385
386   def update_concept(self,sd):
387     if type(self.valeur) in (types.ListType,types.TupleType) :
388        if sd in self.valeur:
389          self.init_modif()
390          self.fin_modif()
391     else:
392        if sd == self.valeur:
393          self.init_modif()
394          self.fin_modif()
395
396   def delete_concept(self,sd):
397     """ 
398         Inputs :
399            - sd=concept detruit
400         Fonction :
401         Met a jour la valeur du mot cle simple suite a la disparition 
402         du concept sd
403         Attention aux matrices
404     """
405     if type(self.valeur) == types.TupleType :
406       if sd in self.valeur:
407         self.init_modif()
408         self.valeur=list(self.valeur)
409         self.valeur.remove(sd)
410         self.fin_modif()
411     elif type(self.valeur) == types.ListType:
412       if sd in self.valeur:
413         self.init_modif()
414         self.valeur.remove(sd)
415         self.fin_modif()
416     else:
417       if self.valeur == sd:
418         self.init_modif()
419         self.valeur=None
420         self.val=None
421         self.fin_modif()
422     # Glut Horrible pour les matrices ???
423     if sd.__class__.__name__== "variable":
424        for type_permis in self.definition.type:
425             if type(type_permis) == types.InstanceType:
426                if type_permis.__class__.__name__ == 'Matrice' :
427                    self.state="changed"
428                    self.isvalid()
429                   
430
431   def replace_concept(self,old_sd,sd):
432     """
433         Inputs :
434            - old_sd=concept remplace
435            - sd=nouveau concept
436         Fonction :
437         Met a jour la valeur du mot cle simple suite au remplacement 
438         du concept old_sd
439     """
440     #print "replace_concept",old_sd,sd
441     if type(self.valeur) == types.TupleType :
442       if old_sd in self.valeur:
443         self.init_modif()
444         self.valeur=list(self.valeur)
445         i=self.valeur.index(old_sd)
446         self.valeur[i]=sd
447         self.fin_modif()
448     elif type(self.valeur) == types.ListType:
449       if old_sd in self.valeur:
450         self.init_modif()
451         i=self.valeur.index(old_sd)
452         self.valeur[i]=sd
453         self.fin_modif()
454     else:
455       if self.valeur == old_sd:
456         self.init_modif()
457         self.valeur=sd
458         self.val=sd
459         self.fin_modif()
460
461   def set_valeur_co(self,nom_co):
462       """
463           Affecte a self l'objet de type CO et de nom nom_co
464       """
465       #print "set_valeur_co",nom_co
466       step=self.etape.parent
467       if nom_co == None or nom_co == '':
468          new_objet=None
469       else:
470          # Avant de creer un concept il faut s'assurer du contexte : step 
471          # courant
472          sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui')
473          if sd:
474             # Si un concept du meme nom existe deja dans la portee de l'etape
475             # on ne cree pas le concept
476             return 0,tr("un concept de meme nom existe deja")
477          # Il n'existe pas de concept de meme nom. On peut donc le creer 
478          # Il faut neanmoins que la methode NommerSdProd de step gere les 
479          # contextes en mode editeur
480          # Normalement la methode  du Noyau doit etre surchargee
481          # On declare l'etape du mot cle comme etape courante pour NommerSdprod
482          cs= CONTEXT.get_current_step()
483          CONTEXT.unset_current_step()
484          CONTEXT.set_current_step(step)
485          step.set_etape_context(self.etape)
486          new_objet = Accas.CO(nom_co)
487          CONTEXT.unset_current_step()
488          CONTEXT.set_current_step(cs)
489       self.init_modif()
490       self.valeur = new_objet
491       self.val = new_objet
492       # On force l'enregistrement de new_objet en tant que concept produit 
493       # de la macro en appelant get_type_produit avec force=1
494       self.etape.get_type_produit(force=1)
495       self.fin_modif()
496       step.reset_context()
497       #print "set_valeur_co",new_objet
498       return 1,tr("Concept cree")
499         
500   def verif_existence_sd(self):
501      """
502         Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
503         avant etape, sinon enleve la referea ces concepts
504      """
505      #print "verif_existence_sd"
506      # Attention : possible probleme avec include
507      # A priori il n'y a pas de raison de retirer les concepts non existants
508      # avant etape. En fait il s'agit uniquement eventuellement de ceux crees par une macro
509      l_sd_avant_etape = self.jdc.get_contexte_avant(self.etape).values()  
510      if type(self.valeur) in (types.TupleType,types.ListType) :
511        l=[]
512        for sd in self.valeur:
513          if isinstance(sd,ASSD) :
514             if sd in l_sd_avant_etape or self.etape.get_sdprods(sd.nom) is sd:
515                l.append(sd)
516          else:
517             l.append(sd)
518        if len(l) < len(self.valeur):
519           self.init_modif()
520           self.valeur=tuple(l)
521           self.fin_modif()
522      else:
523        if isinstance(self.valeur,ASSD) :
524           if self.valeur not in l_sd_avant_etape and self.etape.get_sdprods(self.valeur.nom) is None:
525              self.init_modif()
526              self.valeur = None
527              self.fin_modif()
528  
529   def get_min_max(self):
530      """
531      Retourne les valeurs min et max admissibles pour la valeur de self
532      """
533      return self.definition.min,self.definition.max
534
535
536   def get_type(self):
537      """
538      Retourne le type attendu par le mot-cle simple
539      """
540      return self.definition.type
541
542   def delete_mc_global(self):
543       """ Retire self des declarations globales
544       """
545       if self.definition.position == 'global' : 
546          etape = self.get_etape()
547          if etape :
548             del etape.mc_globaux[self.nom]
549       elif self.definition.position == 'global_jdc' :
550          del self.jdc.mc_globaux[self.nom]
551
552   def update_mc_global(self):
553      """
554         Met a jour les mots cles globaux enregistres dans l'etape parente
555         et dans le jdc parent.
556         Un mot cle simple peut etre global. 
557      """
558      if self.definition.position == 'global' :
559         etape = self.get_etape()
560         if etape :
561            etape.mc_globaux[self.nom]=self
562      elif self.definition.position == 'global_jdc' :
563         if self.jdc:
564            self.jdc.mc_globaux[self.nom]=self
565
566   def nbrColonnes(self):
567      genea = self.get_genealogie()
568      if "VALE_C" in genea and "DEFI_FONCTION" in genea : return 3
569      if "VALE" in genea and "DEFI_FONCTION" in genea : return 2
570      return 0
571
572   def valide_item(self,item):
573       """Valide un item isole. Cet item est candidata l'ajout a la liste existante"""
574       valid=1
575       try:
576           #on verifie le type
577           self.typeProto.adapt(item)
578           #on verifie les choix possibles
579           self.intoProto.adapt(item)
580           #on ne verifie pas la cardinalite
581           if self.definition.validators:
582               valid=self.definition.validators.verif_item(item)
583       except ValError as e:
584           #traceback.print_exc()
585           valid=0
586       return valid
587
588   def verif_type(self,item):
589       """Verifie le type d'un item de liste"""
590       try:
591           #on verifie le type
592           self.typeProto.adapt(item)
593           #on verifie les choix possibles
594           self.intoProto.adapt(item)
595           #on ne verifie pas la cardinalite mais on verifie les validateurs
596           if self.definition.validators:
597               valid=self.definition.validators.verif_item(item)
598           comment=""
599           valid=1
600       except ValError as e:
601           #traceback.print_exc()
602           comment=tr(e.__str__())
603           valid=0
604       return valid,comment
605
606   def valideMatrice(self,cr):
607        print "jjjjjjjjjjjjjjjj"
608        #Attention, la matrice contient comme dernier tuple l ordre des variables
609        if self.monType.methodeCalculTaille != None :
610            apply (MCSIMP.__dict__[self.monType.methodeCalculTaille],(self,))
611        try :
612        #if 1 :
613            ok=0
614            if len(self.valeur) == self.monType.nbLigs +1:
615               ok=1
616               for i in range(len(self.valeur) -1):
617                   if len(self.valeur[i])!= self.monType.nbCols:
618                      ok=0
619            if ok: 
620               self.set_valid(1)
621               return 1 
622        except :
623        #else :
624             pass
625        if cr == 'oui' :
626              self.cr.fatal(tr("La matrice n'est pas une matrice %(n_lign)d sur %(n_col)d", \
627              {'n_lign': self.monType.nbLigs, 'n_col': self.monType.nbCols}))
628        self.set_valid(0)
629        return 0
630
631   def NbDeVariables(self):
632        listeVariables=self.jdc.get_variables(self.etape)
633        self.monType.nbLigs=len(listeVariables)
634        self.monType.nbCols=len(listeVariables)
635       
636
637   def NbDeDistributions(self):
638        listeVariables=self.jdc.get_distributions(self.etape)
639        self.monType.nbLigs=len(listeVariables)
640        self.monType.nbCols=len(listeVariables)
641       
642 #--------------------------------------------------------------------------------
643  
644 #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation
645 # Elles doivent etre reintegrees des que possible
646
647
648   def verif_typeihm(self,val,cr='non'):
649       try :
650          val.eval()
651          return 1
652       except :
653          traceback.print_exc()
654          pass
655       return self.verif_type(val,cr)
656
657   def verif_typeliste(self,val,cr='non') :
658       verif=0
659       for v in val :
660         verif=verif+self.verif_typeihm(v,cr)
661       return verif
662
663   def init_modif_up(self):
664     Validation.V_MCSIMP.MCSIMP.init_modif_up(self)
665     CONNECTOR.Emit(self,"valid")