1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2013 EDF R&D
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.
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.
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
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 from __future__ import absolute_import
23 from __future__ import print_function
24 import string,types,sys
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
36 from . import CONNECTOR
38 class MCCOMPO(I_OBJECT.OBJECT):
39 def getlabeltext(self):
41 Retourne le label de self
42 utilise pour l'affichage dans l'arbre
46 def get_liste_mc_ordonnee(self,liste,dico):
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 ...)
54 return self.filtre_liste_mc(self.get_liste_mc_ordonnee_brute(liste,dico))
56 def get_liste_mc_ordonnee_brute(self,liste,dico):
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 + ...
63 objet_cata = dico[arg]
64 dico=objet_cata.entites
67 for obj in list(dico.keys()) :
68 if not(hasattr(dico[obj],'cache')) or dico[obj].cache==0 :
72 if specifique == 1 : return l
73 return objet_cata.ordre_mc
75 def filtre_liste_mc(self,liste_brute):
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
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)
95 objet = self.get_child(k,restreint = 'oui')
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
101 elif isinstance(objet,MCBLOC):
102 # un bloc conditionnel ne doit pas apparaitre dans la liste de choix
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:
108 elif isinstance(objet,MCList):
110 nb_occur_maxi = objet[0].definition.max
111 if len(objet) >= nb_occur_maxi:
116 #XXX CCAR : les MCNUPLET ne sont pas traites
117 if CONTEXT.debug : print(' ',k,' est un objet de type inconnu :',type(objet))
119 # l'objet est absent : on enleve de la liste les blocs
120 if self.definition.entites[k].statut=='c' :
122 if self.definition.entites[k].label=='BLOC':
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:
134 elif isinstance(objet,MCList):
135 nb_occur_maxi = objet[0].definition.max
136 if len(objet) < nb_occur_maxi:
140 def liste_mc_presents(self):
142 Retourne la liste des noms des mots-cles fils de self presents construite
143 a partir de self.mc_liste
146 for v in self.mc_liste:
151 def get_index_child(self,nom_fils):
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
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()
160 for nom in liste_noms_mc_ordonnee:
161 if nom == nom_fils:break
162 if nom not in liste_noms_mc_presents :continue
166 def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
168 Retourne liste_mc_a_ordonner ordonnee suivant l'ordre
169 donne par liste_noms_mc_ordonnee
172 # on transforme liste_a_ordonner en un dictionnaire (plus facile a consulter)
174 for mc in liste_mc_a_ordonner:
176 # on construit la liste des objets ordonnes
177 for nom_mc in liste_noms_mc_ordonnee:
179 liste.append(d_mc.get(nom_mc))
183 def suppentite(self,objet) :
185 Supprime le fils 'objet' de self :
186 Retourne 1 si la suppression a pu etre effectuee,
187 Retourne 0 dans le cas contraire
189 if not objet in self.mc_liste:
190 # Impossible de supprimer objet. Il n'est pas dans mc_liste
194 self.mc_liste.remove(objet)
195 CONNECTOR.Emit(self,"supp",objet)
196 objet.delete_mc_global()
197 objet.update_condition_bloc()
199 self.etape.modified()
206 def addentite(self,name,pos=None):
208 Ajoute le mot-cle name a la liste des mots-cles de
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)
217 # dans ce cas on est en mode copie d'un motcle
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()
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}))
232 # On cherche s'il existe deja un mot cle de meme nom
233 old_obj = self.get_child(objet.nom,restreint = 'oui')
235 # on normalize l'objet
236 objet=objet.normalize()
237 # Le mot cle n'existe pas encore. On l'ajoute a la position
240 self.mc_liste.append(objet)
242 self.mc_liste.insert(pos,objet)
243 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
245 CONNECTOR.Emit(self,"add",objet)
246 objet.update_mc_global()
247 objet.update_condition_bloc()
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))
259 # une liste d'objets de meme type existe deja
260 old_obj.addentite(objet)
264 def ispermis(self,fils):
266 Retourne 1 si l'objet de nom nom_fils
267 est bien permis, cad peut bien etre un fils de self,
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:
276 #elif type(fils) == types.InstanceType:
277 elif isinstance(fils,object):
278 # fils est un objet (commande,mcf,mclist)
279 # on est dans le cas d'une tentative de copie de l'objet
280 # on veut savoir si l'objet peut bien etre un fils de self :
281 # la verification du nom de suffit pas (plusieurs commandes
282 # ont le meme mot-cle facteur AFFE ... et c'est l'utilisateur
283 # qui choisit le pere d'ou un risque d'erreur)
284 if not fils.nom in self.definition.entites:
287 if fils.parent.nom != self.nom : return 0
290 def update_concept(self,sd):
291 for child in self.mc_liste :
292 child.update_concept(sd)
294 def delete_concept(self,sd):
299 Mettre a jour les fils de l objet suite a la disparition du
301 Seuls les mots cles simples MCSIMP font un traitement autre que
302 de transmettre aux fils
304 for child in self.mc_liste :
305 child.delete_concept(sd)
307 def replace_concept(self,old_sd,sd):
310 - old_sd=concept remplace
311 - sd = nouveau concept
313 Mettre a jour les fils de l objet suite au remplacement du
316 for child in self.mc_liste :
317 child.replace_concept(old_sd,sd)
319 def get_liste_mc_inconnus(self):
321 Retourne la liste des mots-cles inconnus dans self
324 if self.reste_val != {}:
325 for k,v in self.reste_val.items() :
326 l_mc.append([self,k,v])
327 for child in self.mc_liste :
328 if child.isvalid() : continue
329 l_child = child.get_liste_mc_inconnus()
336 def deep_update_condition_bloc(self):
338 Parcourt l'arborescence des mcobject et realise l'update
339 des blocs conditionnels par appel de la methode update_condition_bloc
341 self._update_condition_bloc()
342 for mcobj in self.mc_liste:
343 if hasattr(mcobj,"deep_update_condition_bloc"):
344 mcobj.deep_update_condition_bloc()
346 def update_condition_bloc(self):
348 Realise l'update des blocs conditionnels fils de self
351 self._update_condition_bloc()
352 if self.parent:self.parent.update_condition_bloc()
354 def _update_condition_bloc(self):
356 Realise l'update des blocs conditionnels fils de self
358 dict = self.cree_dict_condition(self.mc_liste,condition=1)
359 for k,v in self.definition.entites.items():
360 if v.label != 'BLOC' :continue
361 globs= self.jdc and self.jdc.condition_context or {}
362 bloc=self.get_child(k,restreint = 'oui')
363 presence=v.verif_presence(dict,globs)
364 if presence and not bloc:
365 # le bloc doit etre present
366 # mais le bloc n'est pas present et il doit etre cree
367 #print "AJOUT BLOC",k
368 pos=self.get_index_child(k)
369 self.addentite(k,pos)
370 if not presence and bloc:
371 # le bloc devrait etre absent
372 # le bloc est present : il faut l'enlever
373 #print "SUPPRESSION BLOC",k,bloc
374 self.suppentite(bloc)
376 def verif_condition_bloc(self):
378 Evalue les conditions de tous les blocs fils possibles
379 (en fonction du catalogue donc de la definition) de self
380 et retourne deux listes :
381 - la premiere contient les noms des blocs a rajouter
382 - la seconde contient les noms des blocs a supprimer
386 dict = self.cree_dict_condition(self.mc_liste,condition=1)
387 for k,v in self.definition.entites.items():
389 globs= self.jdc and self.jdc.condition_context or {}
390 if v.verif_presence(dict,globs):
391 # le bloc doit etre present
392 if not self.get_child(k,restreint = 'oui'):
393 # le bloc n'est pas present et il doit etre cree
394 liste_ajouts.append(k)
396 # le bloc doit etre absent
397 if self.get_child(k,restreint = 'oui'):
398 # le bloc est present : il faut l'enlever
399 liste_retraits.append(k)
400 return liste_ajouts,liste_retraits
402 def verif_existence_sd(self):
404 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
405 avant etape, sinon enleve la reference a ces concepts
407 for motcle in self.mc_liste :
408 motcle.verif_existence_sd()
410 def update_mc_global(self):
412 Met a jour les mots cles globaux enregistres dans l'etape parente
413 et dans le jdc parent.
414 Un mot cle compose ne peut pas etre global. Il se contente de passer
415 la requete a ses fils.
417 for motcle in self.mc_liste :
418 motcle.update_mc_global()
420 def delete_mc_global(self):
421 for motcle in self.mc_liste :
422 motcle.delete_mc_global()
424 motcle.update_mc_global()
428 def init_modif_up(self):
429 Validation.V_MCCOMPO.MCCOMPO.init_modif_up(self)
430 CONNECTOR.Emit(self,"valid")