]> SALOME platform Git repositories - modules/kernel.git/blob - src/KERNEL_PY/kernel/studyedit.py
Salome HOME
Merge tag 'V8_3_0a2' into ngr/python3_dev
[modules/kernel.git] / src / KERNEL_PY / kernel / studyedit.py
1 # Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Lesser General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 # Lesser General Public License for more details.
12 #
13 # You should have received a copy of the GNU Lesser General Public
14 # License along with this library; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 #
19
20 ## \defgroup studyedit studyedit
21 #  \{ 
22 #  \details
23 #  This module provides a new class \bStudyEditor to complement \bStudy
24 #  and \bStudyBuilder classes.
25 #  \}
26
27 """
28 This module provides a new class :class:`StudyEditor` to complement
29 :class:`Study` and :class:`StudyBuilder` classes.
30 """
31
32 import re
33
34 import salome
35 from salome.kernel.logger import Logger
36 from salome.kernel import termcolor
37 logger = Logger("salome.kernel.studyedit", color = termcolor.PURPLE)
38
39 _editors = {}
40 _DEFAULT_CONTAINER = "FactoryServer"
41
42 # The codec to use for strings that are displayed in Salome study tree is Latin-1
43 ENCODING_FOR_SALOME_STUDY = "iso-8859-1"
44
45 ## Return the ID of the active study. In GUI mode, this function is equivalent
46 #  to salome.sg.getActiveStudyId(). Outside GUI, it returns <b> salome.myStudyId </b>
47 #  variable.
48 #  \ingroup studyedit
49 def getActiveStudyId():
50     """
51     Return the ID of the active study. In GUI mode, this function is equivalent
52     to ``salome.sg.getActiveStudyId()``. Outside GUI, it returns
53     ``salome.myStudyId`` variable.
54     """
55     salome.salome_init()
56     # Warning: we don't use salome.getActiveStudy() here because it doesn't
57     # work properly when called from Salome modules (multi-study interpreter
58     # issue)
59     if salome.hasDesktop():
60         return salome.sg.getActiveStudyId()
61     else:
62         return salome.myStudyId
63
64 def getActiveStudy():
65     return getStudyFromStudyId(getActiveStudyId())
66
67 def getStudyFromStudyId(studyId):
68     salome.salome_init()
69     study = salome.myStudyManager.GetStudyByID(studyId)
70     return study
71
72 def getStudyIdFromStudy(study):
73     studyId = study._get_StudyId()
74     return studyId
75
76 ## Return a \b StudyEditor instance to edit the study with ID studyId. 
77 #  If \b studyId is \b None, return an editor for the current study.
78 #  \ingroup studyedit
79 def getStudyEditor(studyId = None):
80     """
81     Return a :class:`StudyEditor` instance to edit the study with ID
82     `studyId`. If `studyId` is :const:`None`, return an editor for the current
83     study.
84     """
85     if studyId is None:
86         studyId = getActiveStudyId()
87     if studyId not in _editors:
88         _editors[studyId] = StudyEditor(studyId)
89     return _editors[studyId]
90
91 ## This class provides utility methods to complement \b Study and
92 #  \b StudyBuilder classes. Those methods may be moved in those classes
93 #  in the future. The parameter \b studyId defines the ID of the study to
94 #  edit. If it is \em None, the edited study will be the current study.
95 #  The preferred way to get a StudyEditor object is through the method
96 #  \b getStudyEditor which allows to reuse existing instances.
97 #
98 #  \param studyId This instance attribute contains the ID of the edited study. 
99 #  This attribute should not be modified.
100 #
101 #  \param study This instance attribute contains the underlying \b Study object.
102 #  It can be used to access the study but the attribute itself should not
103 #  be modified.
104 #
105 #  \param builder This instance attribute contains the underlying \b StudyBuilder
106 #  object. It can be used to edit the study but the attribute itself
107 #  should not be modified.
108 #  \ingroup studyedit
109 class StudyEditor:
110     """
111     This class provides utility methods to complement :class:`Study` and
112     :class:`StudyBuilder` classes. Those methods may be moved in those classes
113     in the future. The parameter `studyId` defines the ID of the study to
114     edit. If it is :const:`None`, the edited study will be the current study.
115     The preferred way to get a StudyEditor object is through the method
116     :meth:`getStudyEditor` which allows to reuse existing instances.
117
118     .. attribute:: studyId
119     
120        This instance attribute contains the ID of the edited study. This
121        attribute should not be modified.
122
123     .. attribute:: study
124     
125        This instance attribute contains the underlying :class:`Study` object.
126        It can be used to access the study but the attribute itself should not
127        be modified.
128
129     .. attribute:: builder
130
131        This instance attribute contains the underlying :class:`StudyBuilder`
132        object. It can be used to edit the study but the attribute itself
133        should not be modified.
134
135     """
136     def __init__(self, studyId = None):
137         salome.salome_init()
138         if studyId is None:
139             studyId = getActiveStudyId()
140         self.studyId = studyId
141         self.study = salome.myStudyManager.GetStudyByID(studyId)
142         if self.study is None:
143             raise Exception("Can't create StudyEditor object: "
144                             "Study %d doesn't exist" % studyId)
145         self.builder = self.study.NewBuilder()
146
147     ## Find a component corresponding to the Salome module \b moduleName in
148     #  the study. If none is found, create a new component and associate it
149     #  with the corresponding engine (i.e. the engine named \b moduleName).
150     #  Note that in Salome 5, the module name and engine name must be
151     #  identical (every module must provide an engine with the same name).
152     #  In Salome 6 it will be possible to define a different name for the
153     #  engine.
154     #
155     #  \param moduleName (string) name of the module corresponding to the component
156     #  (the module name is the string value in the
157     #  attribute "AttributeComment" of the component)
158     #
159     #  \param componentName (string) name of the new component if created. 
160     #  If \b None, use \b moduleName instead.
161     #
162     #  \param icon (string) icon for the new component (attribute "AttributePixMap").
163     #
164     #  \param containerName (string) name of the container in which the engine should be
165     #  loaded.
166     #
167     #  \return the SComponent found or created.
168     def findOrCreateComponent(self, moduleName, componentName = None,
169                               icon = None, containerName = _DEFAULT_CONTAINER):
170         """
171         Find a component corresponding to the Salome module `moduleName` in
172         the study. If none is found, create a new component and associate it
173         with the corresponding engine (i.e. the engine named `moduleName`).
174         Note that in Salome 5, the module name and engine name must be
175         identical (every module must provide an engine with the same name).
176         In Salome 6 it will be possible to define a different name for the
177         engine.
178
179         :type  moduleName: string
180         :param moduleName: name of the module corresponding to the component
181                            (the module name is the string value in the
182                            attribute "AttributeComment" of the component)
183
184         :type  componentName: string
185         :param componentName: name of the new component if created. If
186                               :const:`None`, use `moduleName` instead.
187
188         :type  icon: string
189         :param icon: icon for the new component (attribute "AttributePixMap").
190
191         :type  containerName: string
192         :param containerName: name of the container in which the engine should be
193                               loaded.
194
195         :return: the SComponent found or created.
196
197         """
198         sComponent = self.study.FindComponent(moduleName)
199         if sComponent is None:
200             sComponent = self.builder.NewComponent(moduleName)
201             # Note that the NewComponent method set the "comment" attribute to the
202             # value of its argument (moduleName here)
203             if componentName is None:
204                 componentName = moduleName
205             self.builder.SetName(sComponent, componentName)
206             if icon is not None:
207                 # _MEM_ : This will be effective if and only if "moduleName"
208                 # really corresponds to the module name (as specified in the
209                 # SalomeApp.xml)
210                 self.setIcon(sComponent, icon)
211
212             # This part will stay inactive until Salome 6. In Salome 6, the
213             # engine name will be stored separately from the module name.
214             # An internal convention (in this class) is to store the name of the
215             # associated engine in the parameter attribute of the scomponent (so that
216             # it could be retrieved in a future usage of this scomponent, for example,
217             # for the need of the function loadComponentEngine). The comment attribute
218             # SHOULD NOT be used for this purpose  because it's used by the SALOME
219             # resources manager to identify the SALOME module and then localized
220             # the resource files
221             #attr = self.builder.FindOrCreateAttribute( sComponent, "AttributeParameter" )
222             #attr.SetString( "ENGINE_NAME", engineName )
223
224             engine = salome.lcc.FindOrLoadComponent(containerName, moduleName)
225             if engine is None:
226                 raise Exception("Cannot load engine %s in container %s. See "
227                                 "logs of container %s for more details." %
228                                 (moduleName, containerName, containerName))
229             self.builder.DefineComponentInstance(sComponent, engine)
230
231         return sComponent
232
233     ## Load the engine corresponding to \b sComponent in the container
234     #  \b containerName, associate the engine with the component and load the
235     #  CORBA objects of this component in the study.
236     def loadComponentEngine(self, sComponent,
237                             containerName = _DEFAULT_CONTAINER):
238         """
239         Load the engine corresponding to `sComponent` in the container
240         `containerName`, associate the engine with the component and load the
241         CORBA objects of this component in the study.
242         """
243         # This part will stay inactive until Salome 6. In Salome 6, the
244         # engine name will be stored separately from the module name.
245         #attr = self.builder.FindOrCreateAttribute( sComponent, "AttributeParameter" )
246         #engineName = attr.GetString( "ENGINE_NAME" )
247         engine = salome.lcc.FindOrLoadComponent(containerName,
248                                                 sComponent.GetComment())
249         if engine is None:
250             raise Exception("Cannot load component %s in container %s. See "
251                             "logs of container %s for more details." %
252                             (sComponent.GetComment(), containerName,
253                              containerName))
254         self.builder.LoadWith(sComponent, engine)
255
256     ## Get the CORBA object associated with the SObject \b item, eventually by
257     #  first loading it with the corresponding engine.
258     def getOrLoadObject(self, item):
259         """
260         Get the CORBA object associated with the SObject `item`, eventually by
261         first loading it with the corresponding engine.
262         """
263         object = item.GetObject()
264         if object is None: # the engine has not been loaded yet
265             sComponent = item.GetFatherComponent()
266             self.loadComponentEngine(sComponent)
267             object = item.GetObject()
268         return object
269
270     ## Find an object under \b fatherItem in the study with the given
271     #  attributes. Return the first one found if at least one exists,
272     #  otherwise create a new one with the given attributes and return it.
273     #
274     #  See \b setItem() for the description of the parameters.
275     def findOrCreateItem(self, fatherItem, name, fileType = None,
276                          fileName = None, comment = None, icon = None,
277                          IOR = None, typeId = None):
278         """
279         Find an object under `fatherItem` in the study with the given
280         attributes. Return the first one found if at least one exists,
281         otherwise create a new one with the given attributes and return it.
282         
283         See :meth:`setItem` for the description of the parameters.
284         """
285         sObject = self.findItem(fatherItem, name, fileType, fileName, comment,
286                                 icon, IOR, typeId)
287         if sObject is None:
288             sObject = self.createItem(fatherItem, name, fileType, fileName,
289                                       comment, icon, IOR, typeId)
290         return sObject
291
292     ## Find an item with given attributes under \b fatherItem in the study. If
293     #  none is found, return \b None. If several items correspond to
294     #  the parameters, only the first one is returned. The search is made
295     #  only on given parameters (i.e. not \b None). To look explicitly
296     #  for an empty attribute, use an empty string in the corresponding
297     #  parameter.
298     #    
299     #  See \b setItem() for the description of the parameters.
300     def findItem(self, fatherItem, name = None, fileType = None,
301                  fileName = None, comment = None, icon = None, IOR = None,
302                  typeId = None):
303         """
304         Find an item with given attributes under `fatherItem` in the study. If
305         none is found, return :const:`None`. If several items correspond to
306         the parameters, only the first one is returned. The search is made
307         only on given parameters (i.e. not :const:`None`). To look explicitly
308         for an empty attribute, use an empty string in the corresponding
309         parameter.
310         
311         See :meth:`setItem` for the description of the parameters.
312         """
313         foundItem = None;
314         childIterator = self.study.NewChildIterator(fatherItem)
315         while childIterator.More() and foundItem is None:
316             childItem = childIterator.Value()
317             if childItem and \
318                (name is None or self.getName(childItem) == name) and \
319                (fileType is None or \
320                 self.getFileType(childItem) == fileType) and \
321                (fileName is None or \
322                 self.getFileName(childItem) == fileName) and \
323                (comment is None or self.getComment(childItem) == comment) and \
324                (icon is None or \
325                 self.getIcon(childItem) == icon) and \
326                (IOR is None or childItem.GetIOR() == IOR) and \
327                (typeId is None or \
328                 self.getTypeId(childItem) == typeId):
329                 foundItem = childItem
330             childIterator.Next()
331         return foundItem
332
333     ## Create a new object named \b name under \b fatherItem in the study, with
334     #  the given attributes. If an object named \b name already exists under
335     #  the father object, the new object is created with a new name \b name_X
336     #  where X is the first available index.
337     #
338     #  param fatherItem (SObject) item under which the new item will be added.
339     #  \return new SObject created in the study.
340     #
341     #  See \b setItem() for the description of the other parameters.
342     def createItem(self, fatherItem, name, fileType = None, fileName = None,
343                    comment = None, icon = None, IOR = None, typeId = None):
344         """
345         Create a new object named `name` under `fatherItem` in the study, with
346         the given attributes. If an object named `name` already exists under
347         the father object, the new object is created with a new name `name_X`
348         where X is the first available index.
349         
350         :type  fatherItem: SObject
351         :param fatherItem: item under which the new item will be added.
352                 
353         :return: new SObject created in the study
354         
355         See :meth:`setItem` for the description of the other parameters.
356         """
357         aSObject = self.builder.NewObject(fatherItem)
358
359         aChildIterator = self.study.NewChildIterator(fatherItem)
360         aMaxId = -1
361         aLength = len(name)
362         aDelim = "_"
363         anIdRE = re.compile("^" + aDelim + "[0-9]+")
364         aNameRE = re.compile("^" + name)
365         while aChildIterator.More():
366             aSObj = aChildIterator.Value()
367             aChildIterator.Next()
368             aName = aSObj.GetName()
369             if re.match(aNameRE,aName):
370                 aTmp = aName[aLength:]
371                 if re.match(anIdRE,aTmp):
372                     import string
373                     anId = string.atol(aTmp[1:])
374                     if aMaxId < anId:
375                         aMaxId = anId
376                         pass
377                     pass
378                 elif aMaxId < 0:
379                     aMaxId = 0
380                     pass
381                 pass
382             pass
383         
384         aMaxId = aMaxId + 1
385         aName = name
386         if aMaxId > 0:
387             aName = aName + aDelim + str(aMaxId)
388             pass
389         
390         self.setItem(aSObject, aName, fileType, fileName, comment, icon,
391                      IOR, typeId)
392     
393         return aSObject
394
395     ## Modify the attributes of an item in the study. Unspecified attributes
396     #  (i.e. those set to \b None) are left unchanged.
397     #
398     #  \param item (SObject) item to modify.
399     #
400     #  \param name (string or unicode) item name (attribute \b AttributeName).
401     #
402     #  \param fileType (string or unicode) item file type (attribute \b AttributeFileType).
403     #
404     #  \param fileName (string or unicode) item file name (attribute \b AttributeExternalFileDef).
405     #
406     #  \param comment (string or unicode) item comment (attribute \b AttributeComment). Note that
407     #  this attribute will appear in the \b Value column in the object browser.
408     #
409     #  \param icon (string or unicode) item icon name (attribute \b AttributePixMap).
410     #
411     #  \param IOR (string) IOR of a CORBA object associated with the item
412     #  (attribute \b AttributeIOR).
413     #
414     #  \param typeId (integer) item type (attribute \b AttributeLocalID).
415     def setItem(self, item, name = None, fileType = None, fileName = None,
416                 comment = None, icon = None, IOR = None, typeId = None):
417         """
418         Modify the attributes of an item in the study. Unspecified attributes
419         (i.e. those set to :const:`None`) are left unchanged.
420
421         :type  item: SObject
422         :param item: item to modify.
423
424         :type  name: string or unicode
425         :param name: item name (attribute 'AttributeName').
426
427         :type  fileType: string or unicode
428         :param fileType: item file type (attribute 'AttributeFileType').
429
430         :type  fileName: string or unicode
431         :param fileName: item file name (attribute
432                          'AttributeExternalFileDef').
433
434         :type  comment: string or unicode
435         :param comment: item comment (attribute 'AttributeComment'). Note that
436                         this attribute will appear in the 'Value' column in
437                         the object browser.
438
439         :type  icon: string or unicode
440         :param icon: item icon name (attribute 'AttributePixMap').
441
442         :type  IOR: string
443         :param IOR: IOR of a CORBA object associated with the item
444                     (attribute 'AttributeIOR').
445
446         :type  typeId: integer
447         :param typeId: item type (attribute 'AttributeLocalID').
448         """
449         logger.debug("setItem (ID=%s): name=%s, fileType=%s, fileName=%s, "
450                      "comment=%s, icon=%s, IOR=%s" %
451                      (item.GetID(), name, fileType, fileName, comment,
452                       icon, IOR))
453         if name is not None:
454             self.setName(item, name)
455         if fileType is not None:
456             self.setFileType(item, fileType)
457         if fileName is not None:
458             self.setFileName(item, fileName)
459         if comment is not None:
460             self.setComment(item, comment)
461         if icon is not None:
462             self.setIcon(item, icon)
463         if IOR is not None:
464             self.builder.SetIOR(item, IOR)
465         if typeId is not None:
466             self.setTypeId(item, typeId)
467
468     ## Remove the given item from the study. Note that the items are never
469     #  really deleted. They just don't appear in the study anymore.
470     #
471     #  \param item (SObject) the item to be removed
472     #
473     #  \param withChildren (boolean) if \b True, also remove the children of item
474     #
475     #  \return \b True if the item was removed successfully, or 
476     #  \b False if an error happened.
477     def removeItem(self, item, withChildren = False ):
478         """
479         Remove the given item from the study. Note that the items are never
480         really deleted. They just don't appear in the study anymore.
481
482         :type  item: SObject
483         :param item: the item to be removed
484
485         :type  withChildren: boolean
486         :param withChildren: if :const:`True`, also remove the children of
487                              `item`
488
489         :return: :const:`True` if the item was removed successfully, or
490                  :const:`False` if an error happened.
491         """
492         ok = False
493         try:
494             if withChildren:
495                 self.builder.RemoveObjectWithChildren(item)
496             else:
497                 self.builder.RemoveObject(item)
498             ok = True
499         except:
500             ok = False
501         return ok
502
503     ## Find an item tagged \b tag under \b fatherItem in the study tree or
504     #  create it if there is none, then set its attributes.
505     #
506     #  \param fatherItem (SObject) item under which the tagged item will be looked for
507     #  and eventually created.
508     #
509     #  \param tag integer) tag of the item to look for.
510     #
511     #  \return the SObject at \b tag if found or created successfully, or
512     #  \b None if an error happened.
513     #    
514     #  See \b setItem() for the description of the other parameters.
515     def setItemAtTag(self, fatherItem, tag, name = None, fileType = None,
516                      fileName = None, comment = None, icon = None, IOR = None,
517                      typeId = None):
518         """
519         Find an item tagged `tag` under `fatherItem` in the study tree or
520         create it if there is none, then set its attributes.
521         
522         :type  fatherItem: SObject
523         :param fatherItem: item under which the tagged item will be looked for
524                            and eventually created.
525
526         :type  tag: integer
527         :param tag: tag of the item to look for.
528
529         :return: the SObject at `tag` if found or created successfully, or
530                  :const:`None` if an error happened.
531         
532         See :meth:`setItem` for the description of the other parameters.
533         """
534         found, sObj = fatherItem.FindSubObject(tag)
535         if not found:
536             sObj = self.builder.NewObjectToTag(fatherItem, tag)
537         self.setItem(sObj, name, fileType, fileName, comment, icon,
538                      IOR, typeId)
539         return sObj
540
541     ## Return the name of the object sObject
542     def getName(self, sObject):
543         val = sObject.GetName()
544         return str(val, ENCODING_FOR_SALOME_STUDY)
545
546     ## Set the name of the object sObject
547     def setName(self, sObject, name):
548         self.builder.SetName(sObject, name.encode(ENCODING_FOR_SALOME_STUDY))
549
550     ## Return the comment of the object sObject
551     def getComment(self, sObject):
552         val = sObject.GetComment()
553         return str(val, ENCODING_FOR_SALOME_STUDY)
554
555     ## Set the comment of the object sObject
556     def setComment(self, sObject, comment):
557         self.builder.SetComment(sObject, comment.encode(ENCODING_FOR_SALOME_STUDY))
558
559     ## Return the value of the attribute named \b attributeName on the object
560     #  sObject, or \b default if the attribute doesn't exist.
561     def getAttributeValue(self, sObject, attributeName, default = None):
562         """
563         Return the value of the attribute named `attributeName` on the object
564         `sObject`, or `default` if the attribute doesn't exist.
565         """
566         value = default
567         found, attr = self.builder.FindAttribute(sObject, attributeName)
568         if found:
569             value = attr.Value()
570         return value
571
572     ## Set the value of the attribute named \b attributeName on the object
573     #  sObject to the value \b attributeValue.
574     def setAttributeValue(self, sObject, attributeName, attributeValue):
575         """
576         Set the value of the attribute named `attributeName` on the object
577         `sObject` to the value `attributeValue`.
578         """        
579         attr = self.builder.FindOrCreateAttribute(sObject, attributeName)
580         attr.SetValue(attributeValue)
581
582     ## Return the value of the attribute "AttributeLocalID" of the object
583     #  sObject, or \b None if it is not set.
584     def getTypeId(self, sObject):
585         """
586         Return the value of the attribute "AttributeLocalID" of the object
587         `sObject`, or :const:`None` if it is not set.
588         """
589         return self.getAttributeValue(sObject, "AttributeLocalID")
590
591     ## Set the attribute "AttributeLocalID" of the object \b sObject to the
592     #  value \b value.
593     def setTypeId(self, sObject, value):
594         """
595         Set the attribute "AttributeLocalID" of the object `sObject` to the
596         value `value`.
597         """
598         self.setAttributeValue(sObject, "AttributeLocalID", value)
599
600     ## Return the value of the attribute "AttributeFileType" of the object
601     #  sObject, or an empty string if it is not set.
602     def getFileType(self, sObject):
603         """
604         Return the value of the attribute "AttributeFileType" of the object
605         `sObject`, or an empty string if it is not set.
606         """
607         val = self.getAttributeValue(sObject, "AttributeFileType", "")
608         return str(val, ENCODING_FOR_SALOME_STUDY)
609
610     ## Set the attribute "AttributeFileType" of the object sObject to the
611     #  value value.
612     def setFileType(self, sObject, value):
613         """
614         Set the attribute "AttributeFileType" of the object `sObject` to the
615         value `value`.
616         """
617         self.setAttributeValue(sObject, "AttributeFileType",
618                                value.encode(ENCODING_FOR_SALOME_STUDY))
619
620     ## Return the value of the attribute "AttributeExternalFileDef" of the
621     #  object sObject, or an empty string if it is not set.
622     def getFileName(self, sObject):
623         """
624         Return the value of the attribute "AttributeExternalFileDef" of the
625         object `sObject`, or an empty string if it is not set.
626         """
627         val = self.getAttributeValue(sObject, "AttributeExternalFileDef", "")
628         return str(val, ENCODING_FOR_SALOME_STUDY)
629
630     ## Set the attribute "AttributeExternalFileDef" of the object sObject
631     #  to the value value.
632     def setFileName(self, sObject, value):
633         """
634         Set the attribute "AttributeExternalFileDef" of the object `sObject`
635         to the value `value`.
636         """
637         self.setAttributeValue(sObject, "AttributeExternalFileDef",
638                                value.encode(ENCODING_FOR_SALOME_STUDY))
639
640     ## Return the value of the attribute "AttributePixMap" of the object
641     #  sObject, or an empty string if it is not set.
642     def getIcon(self, sObject):
643         """
644         Return the value of the attribute "AttributePixMap" of the object
645         `sObject`, or an empty string if it is not set.
646         """
647         value = ""
648         found, attr = self.builder.FindAttribute(sObject, "AttributePixMap")
649         if found and attr.HasPixMap():
650             value = attr.GetPixMap()
651         return str(value, ENCODING_FOR_SALOME_STUDY)
652
653     ## Set the attribute "AttributePixMap" of the object sObject to the
654     #  value value.
655     def setIcon(self, sObject, value):
656         """
657         Set the attribute "AttributePixMap" of the object `sObject` to the
658         value `value`.
659         """
660         attr = self.builder.FindOrCreateAttribute(sObject, "AttributePixMap")
661         attr.SetPixMap(value.encode(ENCODING_FOR_SALOME_STUDY))