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