Salome HOME
updated copyright message
[modules/kernel.git] / src / KERNEL_PY / kernel / studyedit.py
index c11a8b33b5e596b705ef275867c41aee0f20da4a..ad6cb485553bde361ecfc53e09ba090dae06b6c8 100644 (file)
@@ -1,6 +1,4 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -33,115 +31,84 @@ This module provides a new class :class:`StudyEditor` to complement
 
 import re
 
-import salome
-from salome.kernel.logger import Logger
 from salome.kernel import termcolor
-logger = Logger("salome.kernel.studyedit", color = termcolor.PURPLE)
+from salome.kernel.logger import Logger
+
+
+logger = Logger("salome.kernel.studyedit", color=termcolor.PURPLE)
 
-_editors = {}
 _DEFAULT_CONTAINER = "FactoryServer"
 
-## Return the ID of the active study. In GUI mode, this function is equivalent
-#  to salome.sg.getActiveStudyId(). Outside GUI, it returns <b> salome.myStudyId </b>
-#  variable.
-#  \ingroup studyedit
-def getActiveStudyId():
-    """
-    Return the ID of the active study. In GUI mode, this function is equivalent
-    to ``salome.sg.getActiveStudyId()``. Outside GUI, it returns
-    ``salome.myStudyId`` variable.
-    """
-    salome.salome_init()
-    # Warning: we don't use salome.getActiveStudy() here because it doesn't
-    # work properly when called from Salome modules (multi-study interpreter
-    # issue)
-    if salome.hasDesktop():
-        return salome.sg.getActiveStudyId()
-    else:
-        return salome.myStudyId
-
-def getActiveStudy():
-    return getStudyFromStudyId(getActiveStudyId())
-
-def getStudyFromStudyId(studyId):
-    salome.salome_init()
-    study = salome.myStudyManager.GetStudyByID(studyId)
-    return study
-
-def getStudyIdFromStudy(study):
-    studyId = study._get_StudyId()
-    return studyId
-
-## Return a \b StudyEditor instance to edit the study with ID studyId. 
-#  If \b studyId is \b None, return an editor for the current study.
-#  \ingroup studyedit
-def getStudyEditor(studyId = None):
-    """
-    Return a :class:`StudyEditor` instance to edit the study with ID
-    `studyId`. If `studyId` is :const:`None`, return an editor for the current
-    study.
-    """
-    if studyId is None:
-        studyId = getActiveStudyId()
-    if not _editors.has_key(studyId):
-        _editors[studyId] = StudyEditor(studyId)
-    return _editors[studyId]
 
 ## This class provides utility methods to complement \b Study and
 #  \b StudyBuilder classes. Those methods may be moved in those classes
-#  in the future. The parameter \b studyId defines the ID of the study to
-#  edit. If it is \em None, the edited study will be the current study.
+#  in the future.
 #  The preferred way to get a StudyEditor object is through the method
-#  \b getStudyEditor which allows to reuse existing instances.
+#  \b getStudyEditor which allows to reuse existing instance or through
+#  the global module attribute \b EDITOR.
 #
-#  \param studyId This instance attribute contains the ID of the edited study. 
-#  This attribute should not be modified.
+#  \param lcc This instance attribute provides access to the SALOME life cycle
+#  CORBA service.
 #
-#  \param study This instance attribute contains the underlying \b Study object.
-#  It can be used to access the study but the attribute itself should not
+#  \param study This instance attribute provides access to the \b Study object.
+#  It can be used to access the study but the attribute itself cannot
 #  be modified.
 #
-#  \param builder This instance attribute contains the underlying \b StudyBuilder
+#  \param builder This instance attribute provides access to the \b StudyBuilder
 #  object. It can be used to edit the study but the attribute itself
-#  should not be modified.
+#  cannot be modified.
 #  \ingroup studyedit
 class StudyEditor:
     """
     This class provides utility methods to complement :class:`Study` and
     :class:`StudyBuilder` classes. Those methods may be moved in those classes
-    in the future. The parameter `studyId` defines the ID of the study to
-    edit. If it is :const:`None`, the edited study will be the current study.
+    in the future.
     The preferred way to get a StudyEditor object is through the method
     :meth:`getStudyEditor` which allows to reuse existing instances.
 
-    .. attribute:: studyId
+    .. attribute:: lcc
     
-       This instance attribute contains the ID of the edited study. This
-       attribute should not be modified.
+       This instance attribute provides access to the SALOME life cycle
+       CORBA service.
 
     .. attribute:: study
     
-       This instance attribute contains the underlying :class:`Study` object.
-       It can be used to access the study but the attribute itself should not
+       This instance attribute provides access to the :class:`Study` object.
+       It can be used to access the study but the attribute itself cannot
        be modified.
 
     .. attribute:: builder
 
-       This instance attribute contains the underlying :class:`StudyBuilder`
+       This instance attribute provides access to the :class:`StudyBuilder`
        object. It can be used to edit the study but the attribute itself
-       should not be modified.
+       cannot be modified.
 
     """
-    def __init__(self, studyId = None):
+
+    @property
+    def study(self):
+        """Attribute that provides access to the study."""
+        import salome
+        salome.salome_init()
+        if salome.myStudy is None:
+            raise Exception("Study doesn't exist")
+        return salome.myStudy
+
+    @property
+    def builder(self):
+        """Attribute that provides access to the study builder."""
+        import salome
+        salome.salome_init()
+        if salome.myStudy is None:
+            raise Exception("Study doesn't exist")
+        return salome.myStudy.NewBuilder()
+
+    @property
+    def lcc(self):
+        """Attribute that providess access to the SALOME life cycle CORBA service."""
+        import salome
         salome.salome_init()
-        if studyId is None:
-            studyId = getActiveStudyId()
-        self.studyId = studyId
-        self.study = salome.myStudyManager.GetStudyByID(studyId)
-        if self.study is None:
-            raise Exception("Can't create StudyEditor object: "
-                            "Study %d doesn't exist" % studyId)
-        self.builder = self.study.NewBuilder()
+        return salome.lcc
 
     ## Find a component corresponding to the Salome module \b moduleName in
     #  the study. If none is found, create a new component and associate it
@@ -220,7 +187,7 @@ class StudyEditor:
             #attr = self.builder.FindOrCreateAttribute( sComponent, "AttributeParameter" )
             #attr.SetString( "ENGINE_NAME", engineName )
 
-            engine = salome.lcc.FindOrLoadComponent(containerName, moduleName)
+            engine = self.lcc.FindOrLoadComponent(containerName, moduleName)
             if engine is None:
                 raise Exception("Cannot load engine %s in container %s. See "
                                 "logs of container %s for more details." %
@@ -243,8 +210,8 @@ class StudyEditor:
         # engine name will be stored separately from the module name.
         #attr = self.builder.FindOrCreateAttribute( sComponent, "AttributeParameter" )
         #engineName = attr.GetString( "ENGINE_NAME" )
-        engine = salome.lcc.FindOrLoadComponent(containerName,
-                                                sComponent.GetComment())
+        engine = self.lcc.FindOrLoadComponent(containerName,
+                                              sComponent.GetComment())
         if engine is None:
             raise Exception("Cannot load component %s in container %s. See "
                             "logs of container %s for more details." %
@@ -314,12 +281,12 @@ class StudyEditor:
         while childIterator.More() and foundItem is None:
             childItem = childIterator.Value()
             if childItem and \
-               (name is None or childItem.GetName() == name) and \
+               (name is None or self.getName(childItem) == name) and \
                (fileType is None or \
                 self.getFileType(childItem) == fileType) and \
                (fileName is None or \
                 self.getFileName(childItem) == fileName) and \
-               (comment is None or childItem.GetComment() == comment) and \
+               (comment is None or self.getComment(childItem) == comment) and \
                (icon is None or \
                 self.getIcon(childItem) == icon) and \
                (IOR is None or childItem.GetIOR() == IOR) and \
@@ -338,19 +305,19 @@ class StudyEditor:
     #  \return new SObject created in the study.
     #
     #  See \b setItem() for the description of the other parameters.
-    def createItem(self, fatherItem, name, fileType = None, fileName = None,
-                   comment = None, icon = None, IOR = None, typeId = None):
+    def createItem(self, fatherItem, name, fileType=None, fileName=None,
+                   comment=None, icon=None, IOR=None, typeId=None):
         """
         Create a new object named `name` under `fatherItem` in the study, with
         the given attributes. If an object named `name` already exists under
         the father object, the new object is created with a new name `name_X`
         where X is the first available index.
-        
+
         :type  fatherItem: SObject
         :param fatherItem: item under which the new item will be added.
-                
+
         :return: new SObject created in the study
-        
+
         See :meth:`setItem` for the description of the other parameters.
         """
         aSObject = self.builder.NewObject(fatherItem)
@@ -365,11 +332,10 @@ class StudyEditor:
             aSObj = aChildIterator.Value()
             aChildIterator.Next()
             aName = aSObj.GetName()
-            if re.match(aNameRE,aName):
+            if re.match(aNameRE, aName):
                 aTmp = aName[aLength:]
-                if re.match(anIdRE,aTmp):
-                    import string
-                    anId = string.atol(aTmp[1:])
+                if re.match(anIdRE, aTmp):
+                    anId = int(aTmp[1:])
                     if aMaxId < anId:
                         aMaxId = anId
                         pass
@@ -379,16 +345,16 @@ class StudyEditor:
                     pass
                 pass
             pass
-        
+
         aMaxId = aMaxId + 1
         aName = name
         if aMaxId > 0:
             aName = aName + aDelim + str(aMaxId)
             pass
-        
+
         self.setItem(aSObject, aName, fileType, fileName, comment, icon,
                      IOR, typeId)
-    
+
         return aSObject
 
     ## Modify the attributes of an item in the study. Unspecified attributes
@@ -396,16 +362,16 @@ class StudyEditor:
     #
     #  \param item (SObject) item to modify.
     #
-    #  \param name (string) item name (attribute \b AttributeName).
+    #  \param name (string or unicode) item name (attribute \b AttributeName).
     #
-    #  \param fileType (string) item file type (attribute \b AttributeFileType).
+    #  \param fileType (string or unicode) item file type (attribute \b AttributeFileType).
     #
-    #  \param fileName (string) item file name (attribute \b AttributeExternalFileDef).
+    #  \param fileName (string or unicode) item file name (attribute \b AttributeExternalFileDef).
     #
-    #  \param comment (string) item comment (attribute \b AttributeComment). Note that
+    #  \param comment (string or unicode) item comment (attribute \b AttributeComment). Note that
     #  this attribute will appear in the \b Value column in the object browser.
     #
-    #  \param icon (string) item icon name (attribute \b AttributePixMap).
+    #  \param icon (string or unicode) item icon name (attribute \b AttributePixMap).
     #
     #  \param IOR (string) IOR of a CORBA object associated with the item
     #  (attribute \b AttributeIOR).
@@ -420,22 +386,22 @@ class StudyEditor:
         :type  item: SObject
         :param item: item to modify.
 
-        :type  name: string
+        :type  name: string or unicode
         :param name: item name (attribute 'AttributeName').
 
-        :type  fileType: string
+        :type  fileType: string or unicode
         :param fileType: item file type (attribute 'AttributeFileType').
 
-        :type  fileName: string
+        :type  fileName: string or unicode
         :param fileName: item file name (attribute
                          'AttributeExternalFileDef').
 
-        :type  comment: string
+        :type  comment: string or unicode
         :param comment: item comment (attribute 'AttributeComment'). Note that
                         this attribute will appear in the 'Value' column in
                         the object browser.
 
-        :type  icon: string
+        :type  icon: string or unicode
         :param icon: item icon name (attribute 'AttributePixMap').
 
         :type  IOR: string
@@ -449,19 +415,18 @@ class StudyEditor:
                      "comment=%s, icon=%s, IOR=%s" %
                      (item.GetID(), name, fileType, fileName, comment,
                       icon, IOR))
-        # Explicit cast is necessary for unicode to string conversion
         if name is not None:
-            self.builder.SetName(item, str(name))
+            self.setName(item, name)
         if fileType is not None:
             self.setFileType(item, fileType)
         if fileName is not None:
             self.setFileName(item, fileName)
         if comment is not None:
-            self.builder.SetComment(item, str(comment))
+            self.setComment(item, comment)
         if icon is not None:
             self.setIcon(item, icon)
         if IOR is not None:
-            self.builder.SetIOR(item, str(IOR))
+            self.builder.SetIOR(item, IOR)
         if typeId is not None:
             self.setTypeId(item, typeId)
 
@@ -496,7 +461,7 @@ class StudyEditor:
             else:
                 self.builder.RemoveObject(item)
             ok = True
-        except:
+        except Exception:
             ok = False
         return ok
 
@@ -538,6 +503,22 @@ class StudyEditor:
                      IOR, typeId)
         return sObj
 
+    ## Return the name of the object sObject
+    def getName(self, sObject):
+        return sObject.GetName()
+
+    ## Set the name of the object sObject
+    def setName(self, sObject, name):
+        self.builder.SetName(sObject, name)
+
+    ## Return the comment of the object sObject
+    def getComment(self, sObject):
+        return sObject.GetComment()
+
+    ## Set the comment of the object sObject
+    def setComment(self, sObject, comment):
+        self.builder.SetComment(sObject, comment)
+
     ## Return the value of the attribute named \b attributeName on the object
     #  sObject, or \b default if the attribute doesn't exist.
     def getAttributeValue(self, sObject, attributeName, default = None):
@@ -595,8 +576,8 @@ class StudyEditor:
         Set the attribute "AttributeFileType" of the object `sObject` to the
         value `value`.
         """
-        # Explicit cast is necessary for unicode to string conversion
-        self.setAttributeValue(sObject, "AttributeFileType", str(value))
+        self.setAttributeValue(sObject, "AttributeFileType",
+                               value)
 
     ## Return the value of the attribute "AttributeExternalFileDef" of the
     #  object sObject, or an empty string if it is not set.
@@ -614,9 +595,8 @@ class StudyEditor:
         Set the attribute "AttributeExternalFileDef" of the object `sObject`
         to the value `value`.
         """
-        # Explicit cast is necessary for unicode to string conversion
         self.setAttributeValue(sObject, "AttributeExternalFileDef",
-                               str(value))
+                               value)
 
     ## Return the value of the attribute "AttributePixMap" of the object
     #  sObject, or an empty string if it is not set.
@@ -639,5 +619,19 @@ class StudyEditor:
         value `value`.
         """
         attr = self.builder.FindOrCreateAttribute(sObject, "AttributePixMap")
-        # Explicit cast is necessary for unicode to string conversion
-        attr.SetPixMap(str(value))
+        attr.SetPixMap(value)
+
+## Singleton study editor instance.
+#  \ingroup studyedit
+EDITOR = StudyEditor()
+"""Singleton study editor instance."""
+
+## Return a \b StudyEditor instance to edit the study. 
+#  \deprecated This function is kept for backward compatibility. Use \a EDITOR instead.
+#  \ingroup studyedit
+def getStudyEditor():
+    """
+    Return a :class:`StudyEditor` instance to edit the study.
+    """
+    global EDITOR
+    return EDITOR