Salome HOME
menage
[tools/eficas.git] / Editeur / Objecttreeitem.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 # import généraux
23 import types,string,os,glob,imp,sys
24 from repr import Repr
25 from copy import copy,deepcopy
26
27 # import du chargeur de composants
28 from comploader import make_objecttreeitem
29 from Ihm import CONNECTOR
30 from Extensions.i18n import tr
31 from Extensions.eficas_exception import EficasException
32
33 myrepr = Repr()
34 myrepr.maxstring = 100
35 myrepr.maxother = 100
36
37 class TreeItem:
38
39     """Abstract class representing tree items.
40
41     Methods should typically be overridden, otherwise a default action
42     is used.
43
44     """
45     # itemNode est une factory qui doit retourner un objet de la classe Node
46     # ou dérivé de cette classe.
47     # Le widget arbre utilisera cet objet comme noeud associé au tree item.
48     # Par defaut, utilise la classe Node de base
49     # La signature de la factory est la suivante :
50     # itemNode(treeOrNode,item,command,rmenu)
51     # ou treeOrNode est le noeud parent, item est l'item associé
52     # command est une fonction python appelée sur sélection graphique
53     # du noeud et rmenu est une fonction python appelée sur click droit sur le noeud
54     itemNode=None
55
56     def __init__(self):
57         """Constructor.  Do whatever you need to do."""
58
59     def GetText(self):
60         """Return text string to display."""
61
62     def GetLabelText(self):
63         """Return label text string to display in front of text (if any)."""
64
65     expandable = None
66
67     def _IsExpandable(self):
68         """Do not override!  Called by TreeNode."""
69         if self.expandable is None:
70             self.expandable = self.IsExpandable()
71         return self.expandable
72
73     def IsExpandable(self):
74         """Return whether there are subitems."""
75         return 1
76
77     def _GetSubList(self):
78         """Do not override!  Called by TreeNode."""
79         if not self.IsExpandable():
80             return []
81         sublist = self.GetSubList()
82         if not sublist:
83             self.expandable = 0
84         return sublist
85
86     def IsEditable(self):
87         """Return whether the item's text may be edited."""
88
89     def SetText(self, text):
90         """Change the item's text (if it is editable)."""
91
92     def GetIconName(self):
93         """Return name of icon to be displayed normally."""
94
95     def GetSelectedIconName(self):
96         """Return name of icon to be displayed when selected."""
97
98     def GetSubList(self):
99         """Return list of items forming sublist."""
100
101     def OnDoubleClick(self):
102         """Called on a double-click on the item."""
103
104 class Delegate:
105     def __init__(self, delegate=None):
106         self.object = delegate
107         self.__cache = {}
108
109     def setdelegate(self, delegate):
110         self.resetcache()
111         self.object = delegate
112
113     def getdelegate(self):
114         return self.object
115
116     def __getattr__(self, name):
117         attr = getattr(self.object, name) # May raise AttributeError
118         setattr(self, name, attr)
119         self.__cache[name] = attr
120         return attr
121
122     def resetcache(self):
123         for key in self.__cache.keys():
124             try:
125                 delattr(self, key)
126             except AttributeError:
127                 pass
128         self.__cache.clear()
129
130     def cachereport(self):
131         keys = self.__cache.keys()
132         keys.sort()
133         #print keys
134
135
136 class ObjectTreeItem(TreeItem,Delegate):
137     def __init__(self, appli, labeltext, object, setfunction=None):
138         self.labeltext = labeltext
139         self.appli = appli
140         # L'objet délegué est stocké dans l'attribut object
141         # L'objet associé à l'item est stocké dans l'attribut _object
142         # Il peut etre obtenu par appel à la méthode getObject
143         # Attention : le délégué peut etre différent de l'objet associé (MCLIST)
144         # Dans le cas d'une MCListe de longueur 1, l'objet associé est la MCListe
145         # et l'objet délégué est le MCFACT (object = _object.data[0])
146         Delegate.__init__(self,object)
147         # On cache l'objet initial (pour destruction eventuelle
148         # ultérieure)
149         self._object = object
150         self.setfunction = setfunction
151         self.expandable = 1
152         self.sublist=[]
153         self.init()
154
155     def init(self):
156         return
157
158     def getObject(self):
159         return self._object
160
161     def connect(self,channel,callable,args):
162         """ Connecte la fonction callable (avec arguments args) à l'item self sur le 
163             canal channel
164         """
165         #print self,channel,callable,args
166         CONNECTOR.Connect(self._object,channel,callable,args)
167         CONNECTOR.Connect(self.object, channel,callable,args)
168
169     def copy(self):
170         """
171         Crée un item copie de self
172         """
173         object = self._object.copy()
174         appli = copy(self.appli)
175         labeltext = copy(self.labeltext)
176         fonction = deepcopy(self.setfunction)
177         item = make_objecttreeitem(appli,labeltext,object,fonction)
178         return item
179     
180     def isactif(self):
181         if hasattr(self.object,'actif'):
182             return self.object.actif
183         else:
184             return 1
185     
186     def update(self,item):
187         """
188           Met a jour l'item courant a partir d'un autre item passe en argument
189           Ne fait rien par defaut
190         """
191         pass
192
193     def GetLabelText(self):
194         """ Retourne 3 valeurs :
195         - le texte à afficher dans le noeud représentant l'item
196         - la fonte dans laquelle afficher ce texte
197         - la couleur du texte
198         """
199         # None --> fonte et couleur par défaut
200         return self.labeltext,None,None
201
202     def get_nature(self) :
203         """ 
204             Retourne la nature de l'item et de l'objet
205         """ 
206         return self.object.nature
207
208     def get_regles(self):
209         """ retourne les règles de l'objet pointé par self """
210         return self.object.get_regles()
211     
212     def get_liste_mc_presents(self):
213         """ Retourne la liste des mots-clés fils de l'objet pointé par self """
214         return self.object.liste_mc_presents()
215     
216     def get_val(self):
217         """ Retourne le nom de la valeur de l'objet pointé par self dans le cas
218             où celle-ci est un objet (ASSD) """
219         return self.object.getval()
220     
221     def get_definition(self):
222         """ 
223            Retourne l'objet definition de l'objet pointé par self 
224         """
225         return self.object.definition
226
227     def get_liste_mc_ordonnee(self,liste,dico):
228         """ retourne la liste ordonnée (suivant le catalogue) brute des mots-clés
229             d'une entité composée dont le chemin complet est donné sous forme
230             d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
231             il faut encore réarranger cette liste (certains mots-clés déjà
232             présents ne doivent plus être proposés, règles ...)"""
233         return self.object.get_liste_mc_ordonnee(liste,dico)
234
235     def get_liste_mc_ordonnee_brute(self,liste,dico):
236         """
237         retourne la liste ordonnée (suivant le catalogue) BRUTE des mots-clés
238         d'une entité composée dont le chemin complet est donné sous forme
239         d'une liste du type :ETAPE + MCFACT ou MCBLOC + ...
240         """
241         return self.object.get_liste_mc_ordonnee_brute(liste,dico)
242    
243     def get_genealogie(self):
244         """
245         Retourne la liste des noms des ascendants (noms de MCSIMP,MCFACT,MCBLOC ou ETAPE)
246         de l'objet pointé par self
247         """
248         return self.object.get_genealogie()
249
250     def get_index_child(self,nom_fils):
251         """
252         Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils
253         Nécessaire pour savoir à quelle position dans la liste des fils il faut ajouter
254         le nouveau mot-clé
255         """
256         return self.object.get_index_child(nom_fils)
257
258     def get_index_child_old(self,nom_fils):
259         """
260         Retourne l'index dans la liste des fils de self du nouveau fils de nom nom_fils
261         Nécessaire pour savoir à quelle position dans la liste des fils il faut ajouter
262         le nouveau mot-clé
263         """
264         liste_noms_mc_ordonnee = self.get_liste_mc_ordonnee_brute(self.get_genealogie(),self.get_jdc().cata_ordonne_dico)
265         liste_noms_mc_presents = self.object.liste_mc_presents()
266         l=[]
267         for nom in liste_noms_mc_ordonnee:
268             if nom in liste_noms_mc_presents or nom == nom_fils:
269                 l.append(nom)
270         # l contient les anciens mots-clés + le nouveau dans l'ordre
271         return l.index(nom_fils)
272         
273     def append_child(self,name,pos=None):
274         """
275           Permet d'ajouter un item fils à self
276         """
277         if pos == 'first':
278             index = 0
279         elif pos == 'last':
280             index = len(self.liste_mc_presents())
281         elif type(pos) == types.IntType :
282             # la position est fixée 
283             index = pos
284         elif type(pos) == types.InstanceType:
285             # pos est un item. Il faut inserer name apres pos
286             index = self.get_index(pos) +1
287         elif type(name) == types.InstanceType:
288             index = self.get_index_child(name.nom)
289         else:
290             index = self.get_index_child(name)
291         return self.addobject(name,index)
292
293     def append_brother(self,name,pos='after'):
294         """
295         Permet d'ajouter un frère à self
296         par défaut on l'ajoute après self
297         """
298         index = self._object.parent.get_index(self.getObject())
299         if pos == 'before':
300             index = index
301         elif pos == 'after':
302             index = index +1
303         else:
304             print (tr("%d n'est pas un index valide pour append_brother", pos))
305             return
306         return self.parent.addobject(name,index)
307
308     def get_nom_etape(self):
309         """Retourne le nom de self """
310         return self.object.get_nom_etape()
311
312     def get_copie_objet(self):
313         """ Retourne une copie de l'objet pointé par self """
314         return self.object.copy()
315     
316     def get_position(self):
317         """ Retourne la valeur de l'attribut position de l'objet pointé par self """
318         definition = self.get_definition()
319         try:
320             return getattr(definition,'position')
321         except AttributeError:
322             return 'local'
323         
324     def get_nom(self):
325         """ Retourne le nom de l'objet pointé par self """
326         return self.object.nom
327
328     def get_jdc(self):
329         """ Retourne le jdc auquel appartient l'objet pointé par self """
330         return self.object.jdc
331     
332     def get_valeur(self):
333         """ Retourne la valeur de l'objet pointé par self """
334         return self.object.valeur
335
336     def get_cr(self):
337         """ Retourne le compte-rendu CR de self """
338         return self.object.report()
339
340     def get_objet_commentarise(self):
341         """
342         Cette méthode retourne un objet commentarisé
343         représentatif de self.object
344         --> à surcharger par les différents items
345         """
346         raise EficasException("MESSAGE AU DEVELOPPEUR : il faut \
347                                  surcharger la methode get_objet_commentarise() \
348                                  pour la classe %s", self.__class__.__name__)
349         
350     def isvalid(self):
351         """ Retourne 1 si l'objet pointé par self est valide, 0 sinon"""
352         return self.object.isvalid()
353
354     def iscopiable(self):
355         """
356         Retourne 1 si l'objet est copiable, 0 sinon
357         Par défaut retourne 0
358         """
359         return 0
360     
361     def get_mc_presents(self):
362         """ Retourne le dictionnaire des mots-clés présents de l'objet pointé par self """
363         return self.object.dict_mc_presents()
364
365     def verif_condition_regles(self,l_mc_presents):
366         return self.object.verif_condition_regles(l_mc_presents)
367
368     def get_fr(self):
369         """ Retourne le fr de l'objet pointé par self """
370         try:
371             return self.object.get_fr()
372         except:
373             return ""
374
375     def get_docu(self):
376         """ Retourne la clé de doc de l'objet pointé par self """
377         return self.object.get_docu()
378
379     def set_valeur(self,new_valeur):
380         """ Remplace la valeur de l'objet pointé par self par new_valeur """
381         return self.object.set_valeur(new_valeur)
382         
383     def GetText(self):
384         return myrepr.repr(self.object)
385     
386     def GetIconName(self):
387         if not self.IsExpandable():
388             return "python"
389
390     def IsEditable(self):
391         return self.setfunction is not None
392
393     def SetText(self, text):
394         try:
395             value = eval(text)
396             self.setfunction(value)
397         except:
398             pass
399 # Modif de ma part CCar : je ne comprend pas a quoi ca sert
400 # ca parait meme incorrect
401       #  else:
402       #      self.object = value
403
404     def IsExpandable(self):
405         return 1
406         
407     def GetSubList(self):
408         keys = dir(self.object)
409         sublist = []
410         for key in keys:
411             try:
412                 value = getattr(self.object, key)
413             except AttributeError:
414                 continue
415             item = make_objecttreeitem(
416                 self.appli,
417                 str(key) + " =",
418                 value,
419                 lambda value, key=key, object=self.object:
420                     setattr(object, key, value))
421             sublist.append(item)
422         return sublist
423
424     def wait_fichier_init(self):
425         """ Retourne 1 si l'object pointé par self attend un fichier d'initialisation
426         (ex: macros POURSUITE et INCLUDE de Code_Aster), 0 SINON """
427         return self.object.definition.fichier_ini
428
429     def make_objecttreeitem(self,appli,labeltext, object, setfunction=None):
430         """
431            Cette methode, globale pour les objets de type item, permet de construire et de retourner un objet
432            de type item associé à l'object passé en argument.
433         """
434         return make_objecttreeitem(appli,labeltext,object,setfunction)
435
436     #def __del__(self):
437     #    print "__del__",self
438
439 class AtomicObjectTreeItem(ObjectTreeItem):
440     def IsExpandable(self):
441         return 0
442
443 class SequenceTreeItem(ObjectTreeItem):
444     def IsExpandable(self):
445         return len(self._object) > 0
446
447     def __len__(self) :
448         return len(self._object)
449    
450     def keys(self):
451         return range(len(self._object))
452
453     def GetIconName(self):
454         if self._object.isvalid():
455           return "ast-green-los"
456         elif self._object.isoblig():
457           return "ast-red-los"
458         else:
459           return "ast-yel-los"
460
461     def ajout_possible(self):
462         return self._object.ajout_possible()
463
464     def get_index(self,child):
465         """ Retourne le numéro de child dans la liste des enfants de self """
466         return self._object.get_index(child.getObject())
467
468     def GetText(self):
469       return  "    "
470
471     def additem(self,obj,pos):
472         self._object.insert(pos,obj)
473         item = self.make_objecttreeitem(self.appli, obj.nom + ":", obj)
474         return item
475
476     def suppitem(self,item):
477         try :
478             self._object.remove(item.getObject())
479             # la liste peut être retournée vide !
480             message = "Mot-clef " + item.getObject().nom + " supprime"
481             self.appli.affiche_infos(message)
482             return 1
483         except:
484             return 0
485
486     def GetSubList(self):
487         isublist=iter(self.sublist)
488         liste=self._object.data
489         iliste=iter(liste)
490         self.sublist=[]
491
492         while(1):
493            old_obj=obj=None
494            for item in isublist:
495               old_obj=item.getObject()
496               if old_obj in liste:break
497
498            for obj in iliste:
499               if obj is old_obj:break
500               # nouvel objet : on cree un nouvel item
501               def setfunction(value, object=obj):
502                   object=value
503               it = self.make_objecttreeitem(self.appli, obj.nom + " : ", obj, setfunction)
504               self.sublist.append(it)
505            if old_obj is None and obj is None:break
506            if old_obj is obj: self.sublist.append(item)
507         return self.sublist