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 import string,types,sys
26 from Extensions.i18n import tr
27 from Noyau.N_MCLIST import MCList
28 from Noyau.N_MCSIMP import MCSIMP
29 from Noyau.N_MCFACT import MCFACT
30 from Noyau.N_MCBLOC import MCBLOC
36 class MCCOMPO(I_OBJECT.OBJECT):
37 def getlabeltext(self):
39 Retourne le label de self
40 utilise pour l'affichage dans l'arbre
44 def get_liste_mc_ordonnee(self,liste,dico):
46 Retourne la liste ordonnee (suivant le catalogue) des mots-cles
47 d'une entite composee dont le chemin complet est donne sous forme
48 d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
49 il faut encore rearranger cette liste (certains mots-cles deja
50 presents ne doivent plus etre proposes, regles ...)
52 return self.filtre_liste_mc(self.get_liste_mc_ordonnee_brute(liste,dico))
54 def get_liste_mc_ordonnee_brute(self,liste,dico):
56 Retourne la liste ordonnee (suivant le catalogue) BRUTE des mots-cles
57 d'une entite composee dont le chemin complet est donne sous forme
58 d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
61 objet_cata = dico[arg]
62 dico=objet_cata.entites
65 for obj in dico.keys() :
66 if not(hasattr(dico[obj],'cache')) or dico[obj].cache==0 :
70 if specifique == 1 : return l
71 return objet_cata.ordre_mc
73 def filtre_liste_mc(self,liste_brute):
75 Cette methode est appelee par EFICAS afin de presenter a
76 l'utilisateur la liste des enfants possibles de self actualisee
77 en fonction du contexte de self. En clair, sont supprimes de la
78 liste des possibles (fournie par la definition), les mots-cles
79 exclus par les regles de self et les mots-cles ne pouvant plus
82 liste = copy(liste_brute)
83 liste_mc_presents = self.liste_mc_presents()
84 # on enleve les mots-cles non permis par les regles
85 for regle in self.definition.regles:
86 # la methode purge_liste est a developper pour chaque regle qui
87 # influe sur la liste de choix a proposer a l'utilisateur
88 # --> EXCLUS,UN_PARMI,PRESENT_ABSENT
89 liste = regle.purge_liste(liste,liste_mc_presents)
90 # on enleve les mots-cles dont l'occurrence est deja atteinte
91 liste_copy = copy(liste)
93 objet = self.get_child(k,restreint = 'oui')
95 # l'objet est deja present : il faut distinguer plusieurs cas
96 if isinstance(objet,MCSIMP):
97 # un mot-cle simple ne peut pas etre repete
99 elif isinstance(objet,MCBLOC):
100 # un bloc conditionnel ne doit pas apparaitre dans la liste de choix
102 elif isinstance(objet,MCFACT):
103 # un mot-cle facteur ne peut pas etre repete plus de self.max fois
104 if objet.definition.max == 1:
106 elif isinstance(objet,MCList):
108 nb_occur_maxi = objet[0].definition.max
109 if len(objet) >= nb_occur_maxi:
114 #XXX CCAR : les MCNUPLET ne sont pas traites
115 if CONTEXT.debug : print ' ',k,' est un objet de type inconnu :',type(objet)
117 # l'objet est absent : on enleve de la liste les blocs
118 if self.definition.entites[k].statut=='c' :
120 if self.definition.entites[k].label=='BLOC':
122 # Pour corriger les exces qui pourraient etre commis dans la methode purge_liste
123 # des regles, on essaie de compenser comme suit :
124 # on ajoute les mots cles facteurs presents dont l'occurence n'est pas atteinte
125 for k in liste_mc_presents:
126 if k in liste:continue
127 objet = self.get_child(k,restreint = 'oui')
128 if isinstance(objet,MCFACT):
129 # un mot-cle facteur ne peut pas etre repete plus de self.max fois
130 if objet.definition.max > 1:
132 elif isinstance(objet,MCList):
133 nb_occur_maxi = objet[0].definition.max
134 if len(objet) < nb_occur_maxi:
138 def liste_mc_presents(self):
140 Retourne la liste des noms des mots-cles fils de self presents construite
141 a partir de self.mc_liste
144 for v in self.mc_liste:
149 def get_index_child(self,nom_fils):
151 Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils
152 Permet de savoir a quelle position il faut ajouter un nouveau mot-cle
154 cata_ordonne = self.jdc.cata_ordonne_dico
155 liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(self.get_genealogie(),cata_ordonne)
156 liste_noms_mc_presents = self.liste_mc_presents()
158 for nom in liste_noms_mc_ordonnee:
159 if nom == nom_fils:break
160 if nom not in liste_noms_mc_presents :continue
164 def ordonne_liste_mc(self,liste_mc_a_ordonner,liste_noms_mc_ordonnee):
166 Retourne liste_mc_a_ordonner ordonnee suivant l'ordre
167 donne par liste_noms_mc_ordonnee
170 # on transforme liste_a_ordonner en un dictionnaire (plus facile a consulter)
172 for mc in liste_mc_a_ordonner:
174 # on construit la liste des objets ordonnes
175 for nom_mc in liste_noms_mc_ordonnee:
176 if d_mc.has_key(nom_mc):
177 liste.append(d_mc.get(nom_mc))
181 def suppentite(self,objet) :
183 Supprime le fils 'objet' de self :
184 Retourne 1 si la suppression a pu etre effectuee,
185 Retourne 0 dans le cas contraire
187 if not objet in self.mc_liste:
188 # Impossible de supprimer objet. Il n'est pas dans mc_liste
192 self.mc_liste.remove(objet)
193 CONNECTOR.Emit(self,"supp",objet)
194 objet.delete_mc_global()
195 objet.update_condition_bloc()
197 self.etape.modified()
204 def addentite(self,name,pos=None):
206 Ajoute le mot-cle name a la liste des mots-cles de
210 if type(name)==types.StringType :
211 # on est en mode creation d'un motcle
212 if self.ispermis(name) == 0 : return 0
213 objet=self.definition.entites[name](val=None,nom=name,parent=self)
215 # dans ce cas on est en mode copie d'un motcle
217 # Appel de la methode qui fait le menage dans les references
218 # sur les concepts produits (verification que les concepts existent
219 # dans le contexte de la commande courante).
220 objet.verif_existence_sd()
222 # On verifie que l'ajout d'objet est autorise
223 if self.ispermis(objet) == 0:
224 self.jdc.appli.affiche_alerte(tr("Erreur"),
225 tr("L'objet %(v_1)s ne peut etre un fils de %(v_2)s",\
226 {'v_1': objet.nom, 'v_2': self.nom}))
230 # On cherche s'il existe deja un mot cle de meme nom
231 old_obj = self.get_child(objet.nom,restreint = 'oui')
233 # on normalize l'objet
234 objet=objet.normalize()
235 # Le mot cle n'existe pas encore. On l'ajoute a la position
238 self.mc_liste.append(objet)
240 self.mc_liste.insert(pos,objet)
241 # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
243 CONNECTOR.Emit(self,"add",objet)
244 objet.update_mc_global()
245 objet.update_condition_bloc()
249 # Le mot cle existe deja. Si le mot cle est repetable,
250 # on cree une liste d'objets. Dans le cas contraire,
251 # on emet un message d'erreur.
252 if not old_obj.isrepetable():
253 self.jdc.appli.affiche_alerte(tr("Erreur"),tr("L'objet %s ne peut pas etre repete", objet.nom))
257 # une liste d'objets de meme type existe deja
258 old_obj.addentite(objet)
262 def ispermis(self,fils):
264 Retourne 1 si l'objet de nom nom_fils
265 est bien permis, cad peut bien etre un fils de self,
268 if type(fils) == types.StringType :
269 # on veut juste savoir si self peut avoir un fils de nom 'fils'
270 if self.definition.entites.has_key(fils):
274 elif type(fils) == types.InstanceType:
275 # fils est un objet (commande,mcf,mclist)
276 # on est dans le cas d'une tentative de copie de l'objet
277 # on veut savoir si l'objet peut bien etre un fils de self :
278 # la verification du nom de suffit pas (plusieurs commandes
279 # ont le meme mot-cle facteur AFFE ... et c'est l'utilisateur
280 # qui choisit le pere d'ou un risque d'erreur)
281 if not self.definition.entites.has_key(fils.nom):
284 if fils.parent.nom != self.nom : return 0
287 def update_concept(self,sd):
288 for child in self.mc_liste :
289 child.update_concept(sd)
291 def delete_concept(self,sd):
296 Mettre a jour les fils de l objet suite a la disparition du
298 Seuls les mots cles simples MCSIMP font un traitement autre que
299 de transmettre aux fils
301 for child in self.mc_liste :
302 child.delete_concept(sd)
304 def replace_concept(self,old_sd,sd):
307 - old_sd=concept remplace
308 - sd = nouveau concept
310 Mettre a jour les fils de l objet suite au remplacement du
313 for child in self.mc_liste :
314 child.replace_concept(old_sd,sd)
316 def get_liste_mc_inconnus(self):
318 Retourne la liste des mots-cles inconnus dans self
321 if self.reste_val != {}:
322 for k,v in self.reste_val.items() :
323 l_mc.append([self,k,v])
324 for child in self.mc_liste :
325 if child.isvalid() : continue
326 l_child = child.get_liste_mc_inconnus()
333 def deep_update_condition_bloc(self):
335 Parcourt l'arborescence des mcobject et realise l'update
336 des blocs conditionnels par appel de la methode update_condition_bloc
338 self._update_condition_bloc()
339 for mcobj in self.mc_liste:
340 if hasattr(mcobj,"deep_update_condition_bloc"):
341 mcobj.deep_update_condition_bloc()
343 def update_condition_bloc(self):
345 Realise l'update des blocs conditionnels fils de self
348 self._update_condition_bloc()
349 if self.parent:self.parent.update_condition_bloc()
351 def _update_condition_bloc(self):
353 Realise l'update des blocs conditionnels fils de self
355 dict = self.cree_dict_condition(self.mc_liste,condition=1)
356 for k,v in self.definition.entites.items():
357 if v.label != 'BLOC' :continue
358 globs= self.jdc and self.jdc.condition_context or {}
359 bloc=self.get_child(k,restreint = 'oui')
360 presence=v.verif_presence(dict,globs)
361 if presence and not bloc:
362 # le bloc doit etre present
363 # mais le bloc n'est pas present et il doit etre cree
364 #print "AJOUT BLOC",k
365 pos=self.get_index_child(k)
366 self.addentite(k,pos)
367 if not presence and bloc:
368 # le bloc devrait etre absent
369 # le bloc est present : il faut l'enlever
370 #print "SUPPRESSION BLOC",k,bloc
371 self.suppentite(bloc)
373 def verif_condition_bloc(self):
375 Evalue les conditions de tous les blocs fils possibles
376 (en fonction du catalogue donc de la definition) de self
377 et retourne deux listes :
378 - la premiere contient les noms des blocs a rajouter
379 - la seconde contient les noms des blocs a supprimer
383 dict = self.cree_dict_condition(self.mc_liste,condition=1)
384 for k,v in self.definition.entites.items():
386 globs= self.jdc and self.jdc.condition_context or {}
387 if v.verif_presence(dict,globs):
388 # le bloc doit etre present
389 if not self.get_child(k,restreint = 'oui'):
390 # le bloc n'est pas present et il doit etre cree
391 liste_ajouts.append(k)
393 # le bloc doit etre absent
394 if self.get_child(k,restreint = 'oui'):
395 # le bloc est present : il faut l'enlever
396 liste_retraits.append(k)
397 return liste_ajouts,liste_retraits
399 def verif_existence_sd(self):
401 Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
402 avant etape, sinon enleve la reference a ces concepts
404 for motcle in self.mc_liste :
405 motcle.verif_existence_sd()
407 def update_mc_global(self):
409 Met a jour les mots cles globaux enregistres dans l'etape parente
410 et dans le jdc parent.
411 Un mot cle compose ne peut pas etre global. Il se contente de passer
412 la requete a ses fils.
414 for motcle in self.mc_liste :
415 motcle.update_mc_global()
417 def delete_mc_global(self):
418 for motcle in self.mc_liste :
419 motcle.delete_mc_global()
421 motcle.update_mc_global()
425 def init_modif_up(self):
426 Validation.V_MCCOMPO.MCCOMPO.init_modif_up(self)
427 CONNECTOR.Emit(self,"valid")