Salome HOME
fin portage python 3
[tools/eficas.git] / Ihm / I_MCCOMPO.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 """
21 """
22 from __future__ import absolute_import
23 from __future__ import print_function
24 import string,types,sys
25 from copy import copy
26 import traceback
27
28 import Validation
29 from Extensions.i18n import tr
30 from Noyau.N_MCSIMP import MCSIMP
31 from Noyau.N_MCFACT import MCFACT
32 from Noyau.N_MCBLOC import MCBLOC
33 from Noyau.N_MCLIST import MCList
34 from . import I_OBJECT
35
36 from . import CONNECTOR
37
38 class MCCOMPO(I_OBJECT.OBJECT):
39   def getlabeltext(self):
40     """ 
41        Retourne le label de self 
42        utilise pour l'affichage dans l'arbre
43     """
44     return self.nom
45
46   def get_liste_mc_ordonnee(self,liste,dico):
47     """
48        Retourne la liste ordonnee (suivant le catalogue) des mots-cles
49        d'une entite composee dont le chemin complet est donne sous forme
50        d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
51        il faut encore rearranger cette liste (certains mots-cles deja
52        presents ne doivent plus etre proposes, regles ...)
53     """
54     return self.filtre_liste_mc(self.get_liste_mc_ordonnee_brute(liste,dico))
55
56   def get_liste_mc_ordonnee_brute(self,liste,dico):
57     """
58        Retourne la liste ordonnee (suivant le catalogue) BRUTE des mots-cles
59        d'une entite composee dont le chemin complet est donne sous forme
60        d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
61     """
62     for arg in liste:
63         objet_cata = dico[arg]
64         dico=objet_cata.entites
65         l=[]
66         specifique=0
67         for obj in list(dico.keys()) :
68             if not(hasattr(dico[obj],'cache')) or dico[obj].cache==0 :
69                l.append(obj)
70             else :
71                specifique=1
72         if specifique == 1 : return l    
73     return objet_cata.ordre_mc
74
75   def filtre_liste_mc(self,liste_brute):
76     """ 
77        Cette methode est appelee par EFICAS afin de presenter a 
78        l'utilisateur la liste des enfants possibles de self actualisee 
79        en fonction du contexte de self. En clair, sont supprimes de la
80        liste des possibles (fournie par la definition), les mots-cles
81        exclus par les regles de self et les mots-cles ne pouvant plus 
82        etre repetes
83     """
84     liste = copy(liste_brute)
85     liste_mc_presents = self.liste_mc_presents()
86     # on enleve les mots-cles non permis par les regles
87     for regle in self.definition.regles:
88        # la methode purge_liste est a developper pour chaque regle qui
89        # influe sur la liste de choix a proposer a l'utilisateur
90        # --> EXCLUS,UN_PARMI,PRESENT_ABSENT
91        liste = regle.purge_liste(liste,liste_mc_presents)
92     # on enleve les mots-cles dont l'occurrence est deja atteinte
93     liste_copy = copy(liste)
94     for k in liste_copy:
95       objet = self.get_child(k,restreint = 'oui')
96       if objet != None :
97         # l'objet est deja present : il faut distinguer plusieurs cas
98         if isinstance(objet,MCSIMP):
99           # un mot-cle simple ne peut pas etre repete
100           liste.remove(k)
101         elif isinstance(objet,MCBLOC):
102           # un bloc conditionnel ne doit pas apparaitre dans la liste de choix
103           liste.remove(k)
104         elif isinstance(objet,MCFACT):
105           # un mot-cle facteur ne peut pas etre repete plus de self.max fois
106           if objet.definition.max == 1:
107             liste.remove(k)
108         elif isinstance(objet,MCList):
109           try :
110             nb_occur_maxi = objet[0].definition.max
111             if len(objet) >= nb_occur_maxi:
112               liste.remove(k)
113           except:
114             pass
115         else :
116           #XXX CCAR : les MCNUPLET ne sont pas traites
117           if CONTEXT.debug : print('   ',k,' est un objet de type inconnu :',type(objet))
118       else :
119         # l'objet est absent : on enleve de la liste les blocs
120         if self.definition.entites[k].statut=='c' :
121           liste.remove(k)
122         if self.definition.entites[k].label=='BLOC':
123           liste.remove(k)
124     # Pour corriger les exces qui pourraient etre commis dans la methode purge_liste
125     # des regles, on essaie de compenser comme suit :
126     # on ajoute les mots cles facteurs presents dont l'occurence n'est pas atteinte
127     for k in liste_mc_presents:
128       if k in liste:continue
129       objet = self.get_child(k,restreint = 'oui')
130       if isinstance(objet,MCFACT):
131           # un mot-cle facteur ne peut pas etre repete plus de self.max fois
132           if objet.definition.max > 1:
133              liste.append(k)
134       elif isinstance(objet,MCList):
135           nb_occur_maxi = objet[0].definition.max
136           if len(objet) < nb_occur_maxi:
137               liste.append(k)
138     return liste
139
140   def liste_mc_presents(self):
141     """ 
142        Retourne la liste des noms des mots-cles fils de self presents construite
143        a partir de self.mc_liste 
144     """
145     l=[]
146     for v in self.mc_liste:
147       k=v.nom
148       l.append(k)
149     return l
150
151   def get_index_child(self,nom_fils):
152       """
153         Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils
154         Permet de savoir a quelle position il faut ajouter un nouveau mot-cle
155       """
156       cata_ordonne = self.jdc.cata_ordonne_dico
157       liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(self.get_genealogie(),cata_ordonne)
158       liste_noms_mc_presents = self.liste_mc_presents()
159       index=0
160       for nom in liste_noms_mc_ordonnee:
161           if nom == nom_fils:break
162           if nom not in liste_noms_mc_presents :continue
163           index=index+1
164       return index
165           
166   def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
167     """
168         Retourne liste_mc_a_ordonner ordonnee suivant l'ordre 
169         donne par liste_noms_mc_ordonnee
170     """
171     liste = []
172     # on transforme liste_a_ordonner en un dictionnaire (plus facile a consulter)
173     d_mc = {}
174     for mc in liste_mc_a_ordonner:
175       d_mc[mc.nom]=mc
176     # on construit la liste des objets ordonnes
177     for nom_mc in liste_noms_mc_ordonnee:
178       if nom_mc in d_mc:
179         liste.append(d_mc.get(nom_mc))
180     # on la retourne
181     return liste
182
183   def suppentite(self,objet) :
184     """ 
185         Supprime le fils 'objet' de self : 
186         Retourne 1 si la suppression a pu etre effectuee,
187         Retourne 0 dans le cas contraire
188     """
189     if not objet in self.mc_liste:
190        # Impossible de supprimer objet. Il n'est pas dans mc_liste
191        return 0
192
193     self.init_modif()
194     self.mc_liste.remove(objet)
195     CONNECTOR.Emit(self,"supp",objet)
196     objet.delete_mc_global()
197     objet.update_condition_bloc()
198     objet.supprime()
199     self.etape.modified()
200     self.fin_modif()
201     return 1
202
203   def isoblig(self):
204       return 0
205
206   def addentite(self,name,pos=None):
207       """ 
208           Ajoute le mot-cle name a la liste des mots-cles de
209           l'objet MCCOMPOSE
210       """
211       self.init_modif()
212       if type(name)==bytes :
213         # on est en mode creation d'un motcle 
214         if self.ispermis(name) == 0 : return 0
215         objet=self.definition.entites[name](val=None,nom=name,parent=self)
216       else :
217         # dans ce cas on est en mode copie d'un motcle
218         objet = name
219         # Appel de la methode qui fait le menage dans les references
220         # sur les concepts produits (verification que les concepts existent
221         # dans le contexte de la commande courante).
222         objet.verif_existence_sd()
223
224       # On verifie que l'ajout d'objet est autorise
225       if self.ispermis(objet) == 0:
226         self.jdc.appli.affiche_alerte(tr("Erreur"),
227                                       tr("L'objet %(v_1)s ne peut  etre un fils de %(v_2)s",\
228                                       {'v_1': objet.nom, 'v_2': self.nom}))
229         self.fin_modif()
230         return 0
231
232       # On cherche s'il existe deja un mot cle de meme nom
233       old_obj = self.get_child(objet.nom,restreint = 'oui')
234       if not old_obj :
235          # on normalize l'objet
236          objet=objet.normalize()
237          # Le mot cle n'existe pas encore. On l'ajoute a la position
238          # demandee (pos)
239          if pos == None :
240            self.mc_liste.append(objet)
241          else :
242            self.mc_liste.insert(pos,objet)
243          # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
244          objet.reparent(self)
245          CONNECTOR.Emit(self,"add",objet)
246          objet.update_mc_global()
247          objet.update_condition_bloc()
248          self.fin_modif()
249          return objet
250       else:
251          # Le mot cle existe deja. Si le mot cle est repetable,
252          # on cree une liste d'objets. Dans le cas contraire,
253          # on emet un message d'erreur.
254          if not old_obj.isrepetable():
255             self.jdc.appli.affiche_alerte(tr("Erreur"),tr("L'objet %s ne peut pas etre repete", objet.nom))
256             self.fin_modif()
257             return 0
258          else:
259             # une liste d'objets de meme type existe deja
260             old_obj.addentite(objet)
261             self.fin_modif()
262             return old_obj
263
264   def ispermis(self,fils):
265     """ 
266         Retourne 1 si l'objet de nom nom_fils 
267         est bien permis, cad peut bien etre un fils de self, 
268         Retourne 0 sinon 
269     """
270     if type(fils) == bytes :
271       # on veut juste savoir si self peut avoir un fils de nom 'fils'
272       if fils in self.definition.entites:
273         return 1
274       else :
275         return 0
276     elif type(fils) == types.InstanceType:
277       # fils est un objet (commande,mcf,mclist)
278       # on est dans le cas d'une tentative de copie de l'objet
279       # on veut savoir si l'objet peut bien etre un fils de self :
280       # la verification du nom de suffit pas (plusieurs commandes
281       # ont le meme mot-cle facteur AFFE ... et c'est l'utilisateur
282       # qui choisit le pere d'ou un risque d'erreur)
283       if not fils.nom in self.definition.entites:
284         return 0
285       else:
286         if fils.parent.nom != self.nom : return 0
287       return 1
288
289   def update_concept(self,sd):
290     for child in self.mc_liste :
291         child.update_concept(sd)
292
293   def delete_concept(self,sd):
294     """ 
295         Inputs :
296            - sd=concept detruit
297         Fonction :
298         Mettre a jour les fils de l objet suite a la disparition du
299         concept sd
300         Seuls les mots cles simples MCSIMP font un traitement autre que 
301         de transmettre aux fils
302     """
303     for child in self.mc_liste :
304       child.delete_concept(sd)
305
306   def replace_concept(self,old_sd,sd):
307     """
308         Inputs :
309            - old_sd=concept remplace
310            - sd = nouveau concept
311         Fonction :
312         Mettre a jour les fils de l objet suite au remplacement  du
313         concept old_sd
314     """
315     for child in self.mc_liste :
316       child.replace_concept(old_sd,sd)
317
318   def get_liste_mc_inconnus(self):
319      """
320      Retourne la liste des mots-cles inconnus dans self
321      """
322      l_mc = []
323      if self.reste_val != {}:
324         for k,v in self.reste_val.items() :
325             l_mc.append([self,k,v])
326      for child in self.mc_liste :
327         if child.isvalid() : continue
328         l_child = child.get_liste_mc_inconnus()
329         for mc in l_child:
330            l = [self]
331            l.extend(mc)
332            l_mc.append(l)
333      return l_mc
334
335   def deep_update_condition_bloc(self):
336      """
337         Parcourt l'arborescence des mcobject et realise l'update 
338         des blocs conditionnels par appel de la methode update_condition_bloc
339      """
340      self._update_condition_bloc()
341      for mcobj in self.mc_liste:
342         if hasattr(mcobj,"deep_update_condition_bloc"):
343            mcobj.deep_update_condition_bloc()
344
345   def update_condition_bloc(self):
346      """
347         Realise l'update des blocs conditionnels fils de self
348         et propage au parent
349      """
350      self._update_condition_bloc()
351      if self.parent:self.parent.update_condition_bloc()
352
353   def _update_condition_bloc(self):
354      """
355         Realise l'update des blocs conditionnels fils de self
356      """
357      dict = self.cree_dict_condition(self.mc_liste,condition=1)
358      for k,v in self.definition.entites.items():
359         if v.label != 'BLOC' :continue
360         globs= self.jdc and self.jdc.condition_context or {}
361         bloc=self.get_child(k,restreint = 'oui')
362         presence=v.verif_presence(dict,globs)
363         if presence and not bloc:
364            # le bloc doit etre present
365            # mais le bloc n'est pas present et il doit etre cree
366            #print "AJOUT BLOC",k
367            pos=self.get_index_child(k)
368            self.addentite(k,pos)
369         if not presence and bloc:
370            # le bloc devrait etre absent
371            # le bloc est present : il faut l'enlever
372            #print "SUPPRESSION BLOC",k,bloc
373            self.suppentite(bloc)
374
375   def verif_condition_bloc(self):
376     """ 
377         Evalue les conditions de tous les blocs fils possibles 
378         (en fonction du catalogue donc de la definition) de self
379         et retourne deux listes :
380           - la premiere contient les noms des blocs a rajouter
381           - la seconde contient les noms des blocs a supprimer
382     """
383     liste_ajouts = []
384     liste_retraits = []
385     dict = self.cree_dict_condition(self.mc_liste,condition=1)
386     for k,v in self.definition.entites.items():
387       if v.label=='BLOC' :
388         globs= self.jdc and self.jdc.condition_context or {}
389         if v.verif_presence(dict,globs):
390           # le bloc doit etre present
391           if not self.get_child(k,restreint = 'oui'):
392             # le bloc n'est pas present et il doit etre cree
393             liste_ajouts.append(k)
394         else :
395           # le bloc doit etre absent
396           if self.get_child(k,restreint = 'oui'):
397             # le bloc est present : il faut l'enlever
398             liste_retraits.append(k)
399     return liste_ajouts,liste_retraits
400
401   def verif_existence_sd(self):
402      """
403         Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
404         avant etape, sinon enleve la reference a ces concepts
405      """
406      for motcle in self.mc_liste :
407          motcle.verif_existence_sd()
408
409   def update_mc_global(self):
410      """
411         Met a jour les mots cles globaux enregistres dans l'etape parente 
412         et dans le jdc parent.
413         Un mot cle compose ne peut pas etre global. Il se contente de passer
414         la requete a ses fils.
415      """
416      for motcle in self.mc_liste :
417          motcle.update_mc_global()
418
419   def delete_mc_global(self):
420      for motcle in self.mc_liste :
421          motcle.delete_mc_global()
422      try :
423          motcle.update_mc_global()
424      except :
425          pass
426
427   def init_modif_up(self):
428     Validation.V_MCCOMPO.MCCOMPO.init_modif_up(self)
429     CONNECTOR.Emit(self,"valid")
430