]> SALOME platform Git repositories - tools/eficas.git/blob - Ihm/I_MCCOMPO.py
Salome HOME
update version
[tools/eficas.git] / Ihm / I_MCCOMPO.py
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 2007-2021   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 tr(self.nom)
45
46     def getListeMcOrdonnee(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.filtreListeMc(self.getListeMcOrdonneeBrute(liste,dico))
55
56     def getListeMcOrdonneeBrute(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 filtreListeMc(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         listeMcPresents = self.listeMcPresents()
86         # on enleve les mots-cles non permis par les regles
87         for regle in self.definition.regles:
88             # la methode purgeListe 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.purgeListe(liste,listeMcPresents)
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.getChild(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 purgeListe
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 listeMcPresents:
128             if k in liste:continue
129             objet = self.getChild(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 listeMcPresents(self):
141         """
142            Retourne la liste des noms des mots-cles fils de self presents construite
143            a partir de self.mcListe
144         """
145         l=[]
146         for v in self.mcListe:
147             k=v.nom
148             l.append(k)
149         return l
150
151     def getIndexChild(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.getListeMcOrdonneeBrute(self.getGenealogie(),cata_ordonne)
158         liste_noms_mc_presents = self.listeMcPresents()
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 chercheIndiceDsLeContenu(self,objet) :
167     # uniquement pour Pyxb
168     # ajoute la taille des les Blocs
169     # faut -il chercher plus loin ds les petits-enfants ?
170         if objet.nature == 'MCList' : objet=objet[0]
171         leRang=0
172         positionDsLaListe=0
173         try :
174             positionDsLaListe=self.mcListe.index(objet)
175             positionDsLaListeDeFactSiFact =0
176         except :
177             for mc in self.mcListe:
178                 if mc.nature == 'MCList':
179                     try :
180                         positionDsLaListeDeFactSiFact=mc.index(objet)
181                         break
182                     except :
183                         positionDsLaListe=positionDsLaListe+1
184                 else : positionDsLaListe=positionDsLaListe+1
185         i=0
186         while i < positionDsLaListe :
187             leRang= leRang + self.mcListe[i].longueurDsArbre()
188             i=i+1
189         leRang=leRang+positionDsLaListeDeFactSiFact
190         return leRang
191
192
193     def ordonneListeMc(self,listeMc_a_ordonner,liste_noms_mc_ordonnee):
194         """
195             Retourne listeMc_a_ordonner ordonnee suivant l'ordre
196             donne par liste_noms_mc_ordonnee
197         """
198         liste = []
199         # on transforme liste_a_ordonner en un dictionnaire (plus facile a consulter)
200         d_mc = {}
201         for mc in listeMc_a_ordonner:
202             d_mc[mc.nom]=mc
203         # on construit la liste des objets ordonnes
204         for nom_mc in liste_noms_mc_ordonnee:
205             if nom_mc in d_mc:
206                 liste.append(d_mc.get(nom_mc))
207         # on la retourne
208         return liste
209
210     def suppEntite(self,objet) :
211         """
212             Supprime le fils 'objet' de self :
213             Retourne 1 si la suppression a pu etre effectuee,
214             Retourne 0 dans le cas contraire
215         """
216         #print ('suppEntite', self.nom,objet.nom)
217         if not objet in self.mcListe:
218             # Impossible de supprimer objet. Il n'est pas dans mcListe
219             return 0
220
221         self.initModif()
222         objet.delObjPyxb()
223         objet.deleteRef()
224         self.mcListe.remove(objet)
225         CONNECTOR.Emit(self,"supp",objet)
226         objet.deleteMcGlobal()
227         objet.updateConditionBloc()
228         objet.supprime()
229         while self.etape.doitEtreRecalculee == True :
230             #print (' je suis dans le while')
231             self.etape.doitEtreRecalculee = False
232             self.etape.deepUpdateConditionBlocApresSuppression()
233         self.etape.modified()
234         self.finModif()
235         return 1
236
237     def isOblig(self):
238         return 0
239
240     def addEntite(self,name,pos=None):
241         """
242             Ajoute le mot-cle name a la liste des mots-cles de
243             l'objet MCCOMPOSE
244         """
245         #print ('addEntite', name, pos)
246         self.initModif()
247         if type(name)==bytes or type(name) == str :
248                 # on est en mode creation d'un motcle
249             if self.ispermis(name) == 0 : return 0
250             objet=self.definition.entites[name](val=None,nom=name,parent=self)
251         else :
252             # dans ce cas on est en mode copie d'un motcle
253             objet = name
254             # Appel de la methode qui fait le menage dans les references
255             # sur les concepts produits (verification que les concepts existent
256             # dans le contexte de la commande courante).
257             objet.verifExistenceSd()
258
259         # On verifie que l'ajout d'objet est autorise
260         if self.ispermis(objet) == 0:
261             self.jdc.editor.afficheAlerte(tr("Erreur"),
262                                           tr("L'objet %(v_1)s ne peut  etre un fils de %(v_2)s",\
263                                           {'v_1': objet.nom, 'v_2': self.nom}))
264             self.finModif()
265             return 0
266
267         # On cherche s'il existe deja un mot cle de meme nom
268         old_obj = self.getChild(objet.nom,restreint = 'oui')
269         if not old_obj :
270             # on normalize l'objet
271             objet=objet.normalize()
272             # Le mot cle n'existe pas encore. On l'ajoute a la position
273             # demandee (pos)
274             if pos == None :
275                 self.mcListe.append(objet)
276             else :
277                 self.mcListe.insert(pos,objet)
278             # Il ne faut pas oublier de reaffecter le parent d'obj (si copie)
279             objet.reparent(self)
280             if  self.cata.modeleMetier :
281                 if isinstance(objet,MCList): objet[0].addObjPyxb(self.chercheIndiceDsLeContenu(objet))
282                 else : objet.addObjPyxb(self.chercheIndiceDsLeContenu(objet))
283             CONNECTOR.Emit(self,"add",objet)
284             objet.updateMcGlobal()
285             objet.updateConditionBloc()
286             self.finModif()
287             return objet
288         else:
289             # Le mot cle existe deja. Si le mot cle est repetable,
290             # on cree une liste d'objets. Dans le cas contraire,
291             # on emet un message d'erreur.
292             if not old_obj.isRepetable():
293                 self.jdc.editor.afficheAlerte(tr("Erreur"),tr("L'objet %s ne peut pas etre repete", objet.nom))
294                 self.finModif()
295                 return 0
296             else:
297                 # une liste d'objets de meme type existe deja
298                 old_obj.addEntite(objet)
299                 if  self.cata.modeleMetier :
300                     if isinstance(objet,MCList): objet[0].addObjPyxb(self.chercheIndiceDsLeContenu(objet))
301                     else : objet.addObjPyxb(self.chercheIndiceDsLeContenu(objet))
302                 self.finModif()
303                 return old_obj
304
305     def ispermis(self,fils):
306         """
307             Retourne 1 si l'objet de nom nom_fils
308             est bien permis, cad peut bien etre un fils de self,
309             Retourne 0 sinon
310         """
311         if type(fils) == bytes or type(fils) == str  :
312         # on veut juste savoir si self peut avoir un fils de nom 'fils'
313             if fils in self.definition.entites:
314                 return 1
315             else :
316                 return 0
317         #elif type(fils) == types.InstanceType:
318         elif isinstance(fils,object):
319             # fils est un objet (commande,mcf,mclist)
320             # on est dans le cas d'une tentative de copie de l'objet
321             # on veut savoir si l'objet peut bien etre un fils de self :
322             # la verification du nom de suffit pas (plusieurs commandes
323             # ont le meme mot-cle facteur AFFE ... et c'est l'utilisateur
324             # qui choisit le pere d'ou un risque d'erreur)
325             if not fils.nom in self.definition.entites:
326                 return 0
327             else:
328                 if fils.parent.nom != self.nom : return 0
329             return 1
330
331     def updateConcept(self,sd):
332         for child in self.mcListe :
333             child.updateConcept(sd)
334
335     def deleteConcept(self,sd):
336         """
337             Inputs :
338                - sd=concept detruit
339             Fonction :
340             Mettre a jour les fils de l objet suite a la disparition du
341             concept sd
342             Seuls les mots cles simples MCSIMP font un traitement autre que
343             de transmettre aux fils
344         """
345         for child in self.mcListe :
346             child.deleteConcept(sd)
347
348     def replaceConcept(self,old_sd,sd):
349         """
350             Inputs :
351                - old_sd=concept remplace
352                - sd = nouveau concept
353             Fonction :
354             Mettre a jour les fils de l objet suite au remplacement  du
355             concept old_sd
356         """
357         for child in self.mcListe :
358             child.replaceConcept(old_sd,sd)
359
360     def getListeMcInconnus(self):
361         """
362         Retourne la liste des mots-cles inconnus dans self
363         """
364         l_mc = []
365         if self.reste_val != {}:
366             for k,v in self.reste_val.items() :
367                 l_mc.append([self,k,v])
368         for child in self.mcListe :
369             if child.isValid() : continue
370             l_child = child.getListeMcInconnus()
371             for mc in l_child:
372                 l = [self]
373                 l.extend(mc)
374                 l_mc.append(l)
375         return l_mc
376
377     def deepUpdateConditionBlocApresSuppression(self):
378         self._updateConditionBloc()
379         for mcobj in self.mcListe:
380             if mcobj.nature=="MCList" :
381                 for obj in mcobj :
382                     obj.deepUpdateConditionBlocApresSuppression()
383                     obj.state='modified'
384             elif hasattr(mcobj,"deepUpdateConditionBlocApresSuppression"):
385                 mcobj.deepUpdateConditionBlocApresSuppression()
386
387
388     def deepUpdateConditionBlocApresCreation(self):
389         # idem deepUpdateConditionBloc sauf qu on cherche les MC qui
390         # avait ete laisse de cote par la construction
391         # Comme on est en construction, on ne devrait pas avoir a detruire de bloc
392         # si on vient d un xml invalide, il faudra probablement traiter les blocs deja crees
393         # reste_val est au niveau du MCCompo, il faut donc tout parcourir
394         #print ('dans deepUpdateConditionBlocApresCreation pour', self.nom)
395         if self.reste_val != {} : self.buildMcApresGlobalEnCreation()
396         for mcobj in self.mcListe:
397             if mcobj.nature=="MCList" :
398                 for obj in mcobj :
399                     obj.deepUpdateConditionBlocApresCreation()
400                     obj.state='modified'
401             elif hasattr(mcobj,"deepUpdateConditionBlocApresCreation"):
402                 mcobj.deepUpdateConditionBlocApresCreation()
403             mcobj.state='modified'
404         self.state='modified'
405
406     def deepUpdateConditionBloc(self):
407         """
408            Parcourt l'arborescence des mcobject et realise l'update
409            des blocs conditionnels par appel de la methode updateConditionBloc
410         """
411         self._updateConditionBloc()
412         for mcobj in self.mcListe:
413             if hasattr(mcobj,"deepUpdateConditionBloc"):
414                 mcobj.deepUpdateConditionBloc()
415             mcobj.state='modified'
416         if self.nature == 'PROCEDURE' :
417             if self.doitEtreRecalculee :
418                 self.doitEtreRecalculee = False
419                 self.deepUpdateConditionBloc()
420
421     def updateConditionBloc(self):
422         """
423            Realise l'update des blocs conditionnels fils de self
424            et propage au parent
425         """
426         self._updateConditionBloc()
427         if self.parent:self.parent.updateConditionBloc()
428
429     def _updateConditionBloc(self):
430         """
431            Realise l'update des blocs conditionnels fils de self
432         """
433         dict = self.creeDictCondition(self.mcListe,condition=1)
434         doitEtreReecrit=False
435         for k,v in self.definition.entites.items():
436             if v.label != 'BLOC' :continue
437             globs= self.jdc and self.jdc.condition_context or {}
438             bloc=self.getChild(k,restreint = 'oui')
439             presence=v.verifPresence(dict,globs)
440             if presence and not bloc:
441                 # le bloc doit etre present
442                 # mais le bloc n'est pas present et il doit etre cree
443                 pos=self.getIndexChild(k)
444                 self.addEntite(k,pos)
445                 #print ("AJOUT",k,pos)
446             if not presence and bloc:
447                 # le bloc devrait etre absent
448                 # le bloc est present : il faut l'enlever
449                 #print ("SUPPRESSION BLOC",k,bloc)
450                 self.suppEntite(bloc)
451                 doitEtreReecrit=True
452
453     def verifConditionBloc(self):
454         """
455         2021 : obsolete ?
456             Evalue les conditions de tous les blocs fils possibles
457             (en fonction du catalogue donc de la definition) de self
458             et retourne deux listes :
459               - la premiere contient les noms des blocs a rajouter
460               - la seconde contient les noms des blocs a supprimer
461         """
462         liste_ajouts = []
463         liste_retraits = []
464         dict = self.creeDictCondition(self.mcListe,condition=1)
465         for k,v in self.definition.entites.items():
466             if v.label=='BLOC' :
467                 globs= self.jdc and self.jdc.condition_context or {}
468                 if v.verifPresence(dict,globs):
469             # le bloc doit etre present
470                     if not self.getChild(k,restreint = 'oui'):
471                 # le bloc n'est pas present et il doit etre cree
472                         liste_ajouts.append(k)
473                 else :
474                     # le bloc doit etre absent
475                     if self.getChild(k,restreint = 'oui'):
476                         # le bloc est present : il faut l'enlever
477                         liste_retraits.append(k)
478         return liste_ajouts,liste_retraits
479
480     def verifExistenceSd(self):
481         """
482            Verifie que les structures de donnees utilisees dans self existent bien dans le contexte
483            avant etape, sinon enleve la reference a ces concepts
484         """
485         for motcle in self.mcListe :
486             motcle.verifExistenceSd()
487
488     def updateMcGlobal(self):
489         """
490            Met a jour les mots cles globaux enregistres dans l'etape parente
491            et dans le jdc parent.
492            Un mot cle compose ne peut pas etre global. Il se contente de passer
493            la requete a ses fils.
494         """
495         for motcle in self.mcListe :
496             motcle.updateMcGlobal()
497
498     def deleteMcGlobal(self):
499         for motcle in self.mcListe :
500             motcle.deleteMcGlobal()
501         # PN : je ne comprends pas les 4 lignes suivantes
502         # du coup je les vire
503         # surtout en dehors dans le for ?
504         # 20201217
505         #try :
506         #    print (motcle)
507         #    motcle.updateMcGlobal()
508         #except :
509         #    pass
510
511     def supprimeUserAssd(self):
512         for objUserAssd in self.userASSDCrees:
513             objUserAssd.supprime(self)
514
515     def initModifUp(self):
516         Validation.V_MCCOMPO.MCCOMPO.initModifUp(self)
517         CONNECTOR.Emit(self,"valid")