Salome HOME
gestion des listes et label sur 2
[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.homo=='constant'
234
235   def isInformation(self):
236     return self.definition.homo=='information'
237
238
239
240   def valid_val(self,valeur):
241       """
242         Verifie que la valeur passee en argument (valeur) est valide
243         sans modifier la valeur courante 
244       """
245       lval=listProto.adapt(valeur)
246       if lval is None:
247          valid=0
248          mess=tr("None n'est pas une valeur autorisee")
249       else:
250          try:
251             for val in lval:
252                 self.typeProto.adapt(val)
253                 self.intoProto.adapt(val)
254             self.cardProto.adapt(lval)
255             if self.definition.validators:
256                 self.definition.validators.convert(lval)
257             valid,mess=1,""
258          except ValError as e:
259             mess=str(e)
260             valid=0
261       return valid,mess
262
263   def valid_valeur(self,new_valeur):
264       """
265         Verifie que la valeur passee en argument (new_valeur) est valide
266         sans modifier la valeur courante (evite d'utiliser set_valeur et est plus performant)
267       """
268       validite,mess=self.valid_val(new_valeur)
269       return validite
270
271   def valid_valeur_partielle(self,new_valeur):
272       """
273         Verifie que la valeur passee en argument (new_valeur) est une liste partiellement valide
274         sans modifier la valeur courante du mot cle
275       """
276       validite=1
277       try:
278           for val in new_valeur:
279               self.typeProto.adapt(val)
280               self.intoProto.adapt(val)
281               #on ne verifie pas la cardinalite
282               if self.definition.validators:
283                   validite=self.definition.validators.valide_liste_partielle(new_valeur)
284       except ValError as e:
285           validite=0
286
287       return validite
288
289   def update_condition_bloc(self):
290       """ Met a jour les blocs conditionnels dependant du mot cle simple self
291       """
292       if self.definition.position == 'global' : 
293          self.etape.deep_update_condition_bloc()
294       elif self.definition.position == 'global_jdc' :
295          self.jdc.deep_update_condition_bloc()
296       else:
297          self.parent.update_condition_bloc()
298
299   def set_valeur(self,new_valeur,evaluation='oui'):
300         #print "set_valeur",new_valeur
301         self.init_modif()
302         self.valeur = new_valeur
303         self.val = new_valeur
304         self.update_condition_bloc()
305         self.etape.modified()
306         self.fin_modif()
307         return 1
308
309   def eval_valeur(self,new_valeur):
310     """
311         Essaie d'evaluer new_valeur comme une SD, une declaration Python 
312         ou un EVAL: Retourne la valeur evaluee (ou None) et le test de reussite (1 ou 0)
313     """
314     sd = self.jdc.get_sd_avant_etape(new_valeur,self.etape)
315     #sd = self.jdc.get_contexte_avant(self.etape).get(new_valeur,None)
316     #print sd
317     if sd is not None:
318       return sd,1
319     lsd = self.jdc.cherche_list_avant(self.etape,new_valeur) 
320     if lsd :
321       return lsd,1
322     else:
323       d={}
324       # On veut EVAL avec tous ses comportements. On utilise Accas. Perfs ??
325       d['EVAL']=Accas.EVAL
326       try :
327         objet = eval(new_valeur,d)
328         return objet,1
329       except Exception:
330         itparam=self.cherche_item_parametre(new_valeur)
331         if itparam:
332              return itparam,1
333         try :
334              object=eval(new_valeur.valeur,d)
335         except :
336              pass
337         if CONTEXT.debug : traceback.print_exc()
338         return None,0
339
340   def eval_val(self,new_valeur):
341     """
342        Tente d'evaluer new_valeur comme un objet du jdc (par appel a eval_val_item)
343        ou comme une liste de ces memes objets
344        Si new_valeur contient au moins un separateur (,), tente l'evaluation sur
345        la chaine splittee
346     """
347     if new_valeur in ('True','False') and 'TXM' in self.definition.type  :
348        valeur=self.eval_val_item(str(new_valeur))
349        return new_valeur
350     if type(new_valeur) in (types.ListType,types.TupleType):
351        valeurretour=[]
352        for item in new_valeur :
353           valeurretour.append(self.eval_val_item(item))
354        return valeurretour
355     else:
356        valeur=self.eval_val_item(new_valeur)
357        return valeur
358
359   def eval_val_item(self,new_valeur):
360     """
361        Tente d'evaluer new_valeur comme un concept, un parametre, un objet Python
362        Si c'est impossible retourne new_valeur inchange
363        argument new_valeur : string (nom de concept, de parametre, expression ou simple chaine)
364     """
365     if self.etape and self.etape.parent:
366        valeur=self.etape.parent.eval_in_context(new_valeur,self.etape)
367        return valeur
368     else:
369        try :
370            valeur = eval(val)
371            return valeur
372        except:
373            #traceback.print_exc()
374            return new_valeur
375            pass
376
377   def cherche_item_parametre (self,new_valeur):
378         try:
379           nomparam=new_valeur[0:new_valeur.find("[")]
380           indice=new_valeur[new_valeur.find(u"[")+1:new_valeur.find(u"]")]
381           for p in self.jdc.params:
382              if p.nom == nomparam :
383                 if int(indice) < len(p.get_valeurs()):
384                    itparam=parametre.ITEM_PARAMETRE(p,int(indice))
385                    return itparam
386           return None
387         except:
388           return None
389
390   def update_concept(self,sd):
391     if type(self.valeur) in (types.ListType,types.TupleType) :
392        if sd in self.valeur:
393          self.init_modif()
394          self.fin_modif()
395     else:
396        if sd == self.valeur:
397          self.init_modif()
398          self.fin_modif()
399
400   def delete_concept(self,sd):
401     """ 
402         Inputs :
403            - sd=concept detruit
404         Fonction :
405         Met a jour la valeur du mot cle simple suite a la disparition 
406         du concept sd
407         Attention aux matrices
408     """
409     if type(self.valeur) == types.TupleType :
410       if sd in self.valeur:
411         self.init_modif()
412         self.valeur=list(self.valeur)
413         self.valeur.remove(sd)
414         self.fin_modif()
415     elif type(self.valeur) == types.ListType:
416       if sd in self.valeur:
417         self.init_modif()
418         self.valeur.remove(sd)
419         self.fin_modif()
420     else:
421       if self.valeur == sd:
422         self.init_modif()
423         self.valeur=None
424         self.val=None
425         self.fin_modif()
426     # Glut Horrible pour les matrices ???
427     if sd.__class__.__name__== "variable":
428        for type_permis in self.definition.type:
429             if type(type_permis) == types.InstanceType:
430                if type_permis.__class__.__name__ == 'Matrice' :
431                    self.state="changed"
432                    self.isvalid()
433                   
434
435   def replace_concept(self,old_sd,sd):
436     """
437         Inputs :
438            - old_sd=concept remplace
439            - sd=nouveau concept
440         Fonction :
441         Met a jour la valeur du mot cle simple suite au remplacement 
442         du concept old_sd
443     """
444     #print "replace_concept",old_sd,sd
445     if type(self.valeur) == types.TupleType :
446       if old_sd in self.valeur:
447         self.init_modif()
448         self.valeur=list(self.valeur)
449         i=self.valeur.index(old_sd)
450         self.valeur[i]=sd
451         self.fin_modif()
452     elif type(self.valeur) == types.ListType:
453       if old_sd in self.valeur:
454         self.init_modif()
455         i=self.valeur.index(old_sd)
456         self.valeur[i]=sd
457         self.fin_modif()
458     else:
459       if self.valeur == old_sd:
460         self.init_modif()
461         self.valeur=sd
462         self.val=sd
463         self.fin_modif()
464
465   def set_valeur_co(self,nom_co):
466       """
467           Affecte a self l'objet de type CO et de nom nom_co
468       """
469       #print "set_valeur_co",nom_co
470       step=self.etape.parent
471       if nom_co == None or nom_co == '':
472          new_objet=None
473       else:
474          # Avant de creer un concept il faut s'assurer du contexte : step 
475          # courant
476          sd= step.get_sd_autour_etape(nom_co,self.etape,avec='oui')
477          if sd:
478             # Si un concept du meme nom existe deja dans la portee de l'etape
479             # on ne cree pas le concept
480             return 0,tr("un concept de meme nom existe deja")
481          # Il n'existe pas de concept de meme nom. On peut donc le creer 
482          # Il faut neanmoins que la methode NommerSdProd de step gere les 
483          # contextes en mode editeur
484          # Normalement la methode  du Noyau doit etre surchargee
485          # On declare l'etape du mot cle comme etape courante pour NommerSdprod
486          cs= CONTEXT.get_current_step()
487          CONTEXT.unset_current_step()
488          CONTEXT.set_current_step(step)
489          step.set_etape_context(self.etape)
490          new_objet = Accas.CO(nom_co)
491          CONTEXT.unset_current_step()
492          CONTEXT.set_current_step(cs)
493       self.init_modif()
494       self.valeur = new_objet
495       self.val = new_objet
496       # On force l'enregistrement de new_objet en tant que concept produit 
497       # de la macro en appelant get_type_produit avec force=1
498       self.etape.get_type_produit(force=1)
499       self.fin_modif()
500       step.reset_context()
501       #print "set_valeur_co",new_objet
502       return 1,tr("Concept cree")
503         
504   def verif_existence_sd(self):
505      """
506         Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
507         avant etape, sinon enleve la referea ces concepts
508      """
509      #print "verif_existence_sd"
510      # Attention : possible probleme avec include
511      # A priori il n'y a pas de raison de retirer les concepts non existants
512      # avant etape. En fait il s'agit uniquement eventuellement de ceux crees par une macro
513      l_sd_avant_etape = self.jdc.get_contexte_avant(self.etape).values()  
514      if type(self.valeur) in (types.TupleType,types.ListType) :
515        l=[]
516        for sd in self.valeur:
517          if isinstance(sd,ASSD) :
518             if sd in l_sd_avant_etape or self.etape.get_sdprods(sd.nom) is sd:
519                l.append(sd)
520          else:
521             l.append(sd)
522        if len(l) < len(self.valeur):
523           self.init_modif()
524           self.valeur=tuple(l)
525           self.fin_modif()
526      else:
527        if isinstance(self.valeur,ASSD) :
528           if self.valeur not in l_sd_avant_etape and self.etape.get_sdprods(self.valeur.nom) is None:
529              self.init_modif()
530              self.valeur = None
531              self.fin_modif()
532  
533   def get_min_max(self):
534      """
535      Retourne les valeurs min et max admissibles pour la valeur de self
536      """
537      return self.definition.min,self.definition.max
538
539
540   def get_type(self):
541      """
542      Retourne le type attendu par le mot-cle simple
543      """
544      return self.definition.type
545
546   def delete_mc_global(self):
547       """ Retire self des declarations globales
548       """
549       if self.definition.position == 'global' : 
550          etape = self.get_etape()
551          if etape :
552             del etape.mc_globaux[self.nom]
553       elif self.definition.position == 'global_jdc' :
554          del self.jdc.mc_globaux[self.nom]
555
556   def update_mc_global(self):
557      """
558         Met a jour les mots cles globaux enregistres dans l'etape parente
559         et dans le jdc parent.
560         Un mot cle simple peut etre global. 
561      """
562      if self.definition.position == 'global' :
563         etape = self.get_etape()
564         if etape :
565            etape.mc_globaux[self.nom]=self
566      elif self.definition.position == 'global_jdc' :
567         if self.jdc:
568            self.jdc.mc_globaux[self.nom]=self
569
570   def nbrColonnes(self):
571      genea = self.get_genealogie()
572      if "VALE_C" in genea and "DEFI_FONCTION" in genea : return 3
573      if "VALE" in genea and "DEFI_FONCTION" in genea : return 2
574      return 0
575
576   def valide_item(self,item):
577       """Valide un item isole. Cet item est candidata l'ajout a la liste existante"""
578       valid=1
579       try:
580           #on verifie le type
581           self.typeProto.adapt(item)
582           #on verifie les choix possibles
583           self.intoProto.adapt(item)
584           #on ne verifie pas la cardinalite
585           if self.definition.validators:
586               valid=self.definition.validators.verif_item(item)
587       except ValError as e:
588           #traceback.print_exc()
589           valid=0
590       return valid
591
592   def verif_type(self,item):
593       """Verifie le type d'un item de liste"""
594       try:
595           #on verifie le type
596           self.typeProto.adapt(item)
597           #on verifie les choix possibles
598           self.intoProto.adapt(item)
599           #on ne verifie pas la cardinalite mais on verifie les validateurs
600           if self.definition.validators:
601               valid=self.definition.validators.verif_item(item)
602           comment=""
603           valid=1
604       except ValError as e:
605           #traceback.print_exc()
606           comment=tr(e.__str__())
607           valid=0
608       return valid,comment
609
610   def valideMatrice(self,cr):
611        #Attention, la matrice contient comme dernier tuple l ordre des variables
612        if self.monType.methodeCalculTaille != None :
613            apply (MCSIMP.__dict__[self.monType.methodeCalculTaille],(self,))
614        try :
615        #if 1 :
616            ok=0
617            if len(self.valeur) == self.monType.nbLigs +1:
618               ok=1
619               for i in range(len(self.valeur) -1):
620                   if len(self.valeur[i])!= self.monType.nbCols:
621                      ok=0
622            if ok: 
623               self.set_valid(1)
624               return 1 
625        except :
626        #else :
627             pass
628        if cr == 'oui' :
629              self.cr.fatal(tr("La matrice n'est pas une matrice %(n_lign)d sur %(n_col)d", \
630              {'n_lign': self.monType.nbLigs, 'n_col': self.monType.nbCols}))
631        self.set_valid(0)
632        return 0
633
634   def NbDeVariables(self):
635        listeVariables=self.jdc.get_variables(self.etape)
636        self.monType.nbLigs=len(listeVariables)
637        self.monType.nbCols=len(listeVariables)
638       
639
640   def NbDeDistributions(self):
641        listeVariables=self.jdc.get_distributions(self.etape)
642        self.monType.nbLigs=len(listeVariables)
643        self.monType.nbCols=len(listeVariables)
644       
645 #--------------------------------------------------------------------------------
646  
647 #ATTENTION SURCHARGE : toutes les methodes ci apres sont des surcharges du Noyau et de Validation
648 # Elles doivent etre reintegrees des que possible
649
650
651   def verif_typeihm(self,val,cr='non'):
652       try :
653          val.eval()
654          return 1
655       except :
656          traceback.print_exc()
657          pass
658       return self.verif_type(val,cr)
659
660   def verif_typeliste(self,val,cr='non') :
661       verif=0
662       for v in val :
663         verif=verif+self.verif_typeihm(v,cr)
664       return verif
665
666   def init_modif_up(self):
667     Validation.V_MCSIMP.MCSIMP.init_modif_up(self)
668     CONNECTOR.Emit(self,"valid")