src/daSalome/Makefile
src/daSalome/daGUI/Makefile
src/daSalome/daGUI/daGuiImpl/Makefile
+ src/daSalome/daGUI/daEficasWrapper/Makefile
+ src/daSalome/daGUI/daEficasWrapper/eficasWrapper.py
bin/Makefile
bin/qtEficas_datassim_study.py
])
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
#
-SUBDIRS = daGuiImpl
+SUBDIRS = daGuiImpl daEficasWrapper
include $(top_srcdir)/adm_local/make_common_starter.am
--- /dev/null
+# Copyright (C) 2010 EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+include $(top_srcdir)/adm_local/make_common_starter.am
+
+mypkgpythondir =$(salomepythondir)/daEficasWrapper
+
+mypkgpython_PYTHON = \
+ eficasWrapper.py \
+ __init__.py \
+ datassimEficasWrapper.py
+
+EXTRA_DIST = eficasWrapper.py.in
+
+
+
--- /dev/null
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2010 EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from eficasWrapper import *
+import sys
+
+# Configuration de l'installation
+my_path = os.path.dirname(os.path.abspath(__file__))
+DATASSIM_INSTALL_DIR = my_path + "/../daEficas"
+sys.path[:0]=[DATASSIM_INSTALL_DIR]
+
+#
+# ================================================
+# Specialization of the EficasWrapper for DATASSIM
+# ================================================
+#
+class DatassimEficasWrapper(EficasWrapper):
+ def __init__(self, parent, code="DATASSIM"):
+ EficasWrapper.__init__(self, parent, code)
+
+ def fileSave(self):
+ """
+ @overload
+ """
+ qtEficas.Appli.fileSave(self)
+ self.notifyObserver(EficasEvent.EVENT_TYPES.SAVE)
+
+ def fileSaveAs(self):
+ """
+ @overload
+ """
+ qtEficas.Appli.fileSaveAs(self)
+ self.notifyObserver(EficasEvent.EVENT_TYPES.SAVE)
+
+ def getCurrentFileName(self):
+ index = self.viewmanager.myQtab.currentIndex()
+ print index
+ rtn = ""
+ if index > 0 :
+ rtn = self.viewmanager.myQtab.tabText(index)
+ return rtn
--- /dev/null
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2010 EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+__author__="aribes/gboulant"
+
+# HACK - Pour l'instant
+import logging
+logging.basicConfig(level=logging.DEBUG, format='%(levelname)-8s %(message)s')
+logger = logging.getLogger()
+
+class DevelException(Exception):
+ def __init__(self, message):
+ """Canonical constructor"""
+ Exception.__init__(self,message)
+
+#
+# ==============================================================================
+# Interface of an eficas observer (for implementing the subject/observer pattern)
+# ==============================================================================
+#
+from daGuiImpl.enumerate import Enumerate
+class EficasObserver:
+ """
+ This class specifies the interface of an eficas observer. See example at the
+ bottom of this file.
+ """
+ def processEficasEvent(self, eficasWrapper, eficasEvent):
+ """
+ This function should be implemented in the concrete Observer.
+ @param eficasWrapper the instance of the source EficasWrapper
+ @param eficasEvent the emitted event (instance of EficasEvent)
+ """
+ raise DevelException("processEficasEvent not implemented yet")
+
+class EficasEvent:
+ EVENT_TYPES=Enumerate([
+ 'CLOSE',
+ 'SAVE'
+ ])
+
+ def __init__(self,eventType,callbackId=None):
+ """
+ Creates an eficas event to be used by an EficasWrapper to notify an
+ EficasObserver.
+
+ The eventType depends of the context of creation. It specify the nature
+ of the event inside EficasWrapper that triggers the creation of this instance.
+
+ The callbackId is an object used by the EficasObserver to map the
+ notification (this received event) with the initial event (callback)
+ This object can be anything and has to be defined through a convention
+ that both the EficasWrapper and the EficasObserver can understand.
+ Typically, the eficas observer set the callback id to the eficas wrapper
+ before running the asynchronous show. Then, when an event is raised by
+ the eficas wrapper toward its observer, it embeds the callback id so that
+ the observer can match the received event to the initial trigger context.
+
+ @param the eventType to be choosen in the EVENT_TYPES
+ @param callbackId an arbitrary data object
+ """
+ if not self.EVENT_TYPES.isValid(eventType):
+ raise DevelException("The event type "+str(eventType)+" is not defined")
+
+ self.eventType = eventType
+ self.callbackId = callbackId
+
+#
+# ==============================================================================
+# Definition of an Eficas wrapper for integration to the SALOME framework
+# This wrapper is not specific to the OMA context and is intended not to be.
+# ==============================================================================
+#
+eficasPath = '@EFICAS_DIR@'
+import os
+if os.environ.has_key( "EFICAS_ROOT"):
+ eficasPath = os.environ["EFICAS_ROOT"]
+import sys
+sys.path[:0]=[eficasPath,
+ os.path.join( eficasPath,'Editeur'),
+ os.path.join( eficasPath,'UiQT4'),
+ ]
+
+import Editeur
+from InterfaceQT4 import qtEficas
+
+class EficasWrapper(qtEficas.Appli):
+
+ def __init__(self, parent, code , fichier=None, module="Eficas", version=None, salome=0):
+
+ self.__codetype = code
+ self.__jdc = None
+
+ # variables for the notification procedure
+ self.__observer = None
+ self.__callbackId = None
+
+ # The convention is that the python pref associated to the code are in
+ # a folder whose name is the code name with lower letters but the
+ # first that is in capital letter.
+ pathCode=code[0]+code[1:].lower()
+ sys.path[:0]=[os.path.join(eficasPath,pathCode)]
+
+ if Editeur.__dict__.has_key( 'session' ):
+ from Editeur import session
+ eficasArg = []
+ eficasArg += sys.argv
+ if fichier:
+ eficasArg += [ fichier ]
+ if version:
+ eficasArg += [ "-c", version ]
+ else :
+ print "noversion"
+ session.parse( eficasArg )
+
+ qtEficas.Appli.__init__( self,code=code,salome=salome,parent=parent)
+
+ def setCodeType(self,code):
+ self.__codetype = code
+
+ def setJdc(self, value, name=None):
+ self.__jdc = value
+ if self.__jdc is None:
+ editor = self.viewmanager.getEditor()
+ editor.fichier = os.path.abspath(unicode("/tmp/eficasfile.comm"))
+ else:
+ fichier = os.path.abspath(unicode("/tmp/eficasfile.comm"))
+ f = open(fichier,'w')
+ f.write(self.__jdc)
+ f.close()
+ editor=self.viewmanager.getEditor( fichier,units=None)
+
+ # _TODO_ set the name and indicate that it's not used to ask a filename
+ #index=self.viewmanager.myQtab.currentIndex()
+ #self.viewmanager.myQtab.setTabText(index,fileName)
+
+ def getJdc(self):
+ # First update the jdc attribute and return the value
+ self.__jdc = self.__getJdcText()
+ return self.__jdc
+
+ # ==========================================================================
+ # Function for the notification interface between an EficasWrapper an an
+ # EficasObserver.
+ #
+ def addObserver(self, observer):
+ """
+ In fact, only one observer may be defined for the moment.
+ """
+ try:
+ observer.processEficasEvent
+ except:
+ raise DevelException("the argument should implement the function processEficasEvent")
+ self.__observer = observer
+
+ def notifyObserver(self, eventType):
+ eficasEvent = EficasEvent(eventType, self.getCallbackId())
+ self.__observer.processEficasEvent(self, eficasEvent)
+
+ def setCallbackId(self, callbackId):
+ """
+ This function should be used to define the callback identifier that
+ will be used by the observer to map the notifcation event with the source
+ event.
+ @param callbackId Any object to be used in the notification interface
+ """
+ self.__callbackId = callbackId
+
+ def getCallbackId(self):
+ return self.__callbackId
+
+ # ==========================================================================
+ # Functions to handle the Eficas callback functions
+ #
+ def closeEvent(self,event):
+ """
+ This method is a notification function called at the end of the eficas
+ processes quit/exit.
+ This close event has to be overload to handle the management of data
+ saving process, and to prevent the application from bug when reopen
+ eficas after a first close operation inside SALOME.
+ @overload
+ """
+ logger.debug("#### Handle closeEvent")
+
+ # Get the data and notify the observers of the event
+ # _TODO_ get data
+ self.notifyObserver(EficasEvent.EVENT_TYPES.CLOSE)
+ self.fileCloseAll()
+
+ # This is to prevent from bug when reopen eficas after a first close
+ # operation inside SALOME.
+ import InterfaceQT4.readercata
+ if hasattr(InterfaceQT4.readercata,'reader') :
+ del InterfaceQT4.readercata.reader
+ event.accept()
+
+
+ def fileSave(self):
+ """
+ @overload
+ """
+ logger.debug("This is my fileSave")
+ # Notify the observers of the event
+ self.notifyObserver(EficasEvent.EVENT_TYPES.SAVE)
+
+ qtEficas.Appli.fileSave(self)
+
+
+ def fileSaveAs(self):
+ """
+ @overload
+ """
+ logger.debug("This is my fileSaveAs")
+ self.fileSave()
+
+ def fileClose(self):
+ """
+ @overload
+ """
+ logger.debug("This is my fileClose")
+ qtEficas.Appli.fileClose(self)
+
+ def fileCloseAll(self):
+ """
+ @overload
+ """
+ logger.debug("This is my fileCloseAll")
+ qtEficas.Appli.fileCloseAll(self)
+
+ # ==========================================================================
+ # helper functions
+ #
+ def __getJdcText(self):
+ """
+ This function returns the current jdc in text format.
+ """
+ index=self.viewmanager.myQtab.currentIndex()
+ if index < 0 : return
+
+ editor=self.viewmanager.dict_editors[index]
+ format = self.format_fichier
+ strSource = str( editor.get_text_JDC(format) )
+ return strSource
+
+ def displayNew(self):
+ self.fileNew()
+ self.show()
+
+ # ==========================================================================
+ # Test functions ...
+ #
+ def __displayData(self, textjdc):
+ index=self.viewmanager.myQtab.currentIndex()
+ if index < 0 : return
+
+ editor=self.viewmanager.dict_editors[index]
+
+ jdc=editor.readercata.cata[0].JdC(procedure=textjdc,appli=editor,cata=editor.readercata.cata,cata_ord_dico=editor.readercata.cata_ordonne_dico,nom="JDC name",rep_mat=editor.CONFIGURATION.rep_mat)
+ self.viewmanager.getEditor("toto.com",jdc)
+
+
__init__.py \
DATASSIMGUI_impl.py \
datassimGuiManager.py \
+ datassimGuiHelper.py \
+ datassimModuleHelper.py \
+ datassimStudyEditor.py \
+ studyedit.py \
enumerate.py
--- /dev/null
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2010 EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+__author__="aribes/gboulant"
+
+import salome
+# Get SALOME PyQt interface
+import SalomePyQt
+__sgPyQt = SalomePyQt.SalomePyQt()
+
+import datassimModuleHelper
+from PyQt4 import QtGui,QtCore
+
+def waitCursor():
+ QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
+
+def restoreCursor():
+ QtGui.QApplication.restoreOverrideCursor()
+
+def gui_warning(parent, msg="An error occurs" ):
+ """
+ This function displays a message dialog box displaying the specified message.
+ """
+ QtGui.QMessageBox.warning( parent, "Alerte", msg)
+
+def getActiveStudyId():
+ """
+ This function returns the id of the active study. The concept of active study
+ makes sens only in the GUI context.
+ """
+ return __sgPyQt.getStudyId()
+
+
+def getActiveStudy():
+ """
+ This function returns the active study reference. The concept of active study
+ makes sens only in the GUI context.
+ """
+ studyId = getActiveStudyId()()
+ study = datassimModuleHelper.getStudyManager().GetStudyByID( studyId )
+ return study
+
+def refreshObjectBrowser():
+ """
+ Refresh the graphical representation of the SALOME study, in case where the
+ GUI is working.
+ """
+ if salome.sg is not None:
+ salome.sg.updateObjBrowser(0)
+
+def getSelectedItem(salomeStudyId=getActiveStudyId()):
+ """
+ Get the current selection. If more than one item are selected, the
+ only first is considered. The object is return (not the id).
+ The item can be of any type, no control is done in this function.
+ """
+ if salome.sg is None:
+ raise Exception("GuiHelper.getSelectedItem can't be used without the GUI context")
+
+ salomeStudy = datassimModuleHelper.getStudyManager().GetStudyByID( salomeStudyId )
+
+ item = None
+ listEntries=salome.sg.getAllSelected()
+ if len(listEntries) >= 1:
+ entry = listEntries[0]
+ item = salomeStudy.FindObjectID( entry )
+
+ return item
+
+def getAllSelected(salomeStudyId):
+ """
+ Returns all selected items in the specified study.
+ """
+ if salome.sg is None:
+ raise OmaException("getSelectedItem can't be used without the GUI context", OmaException.TYPES.DEVEL)
+
+ study = datassimModuleHelper.getStudyManager().GetStudyByID( salomeStudyId )
+ selcount = salome.sg.SelectedCount()
+ seltypes = {}
+ for i in range( selcount ):
+ __incObjToMap( seltypes, datassimModuleHelper.getObjectID( study, salome.sg.getSelected( i ) ) )
+ pass
+ return selcount, seltypes
+
+def __incObjToMap( m, id ):
+ """
+ Increment object counter in the specified map.
+ Not to be used outside this module.
+ """
+ if id not in m: m[id] = 0
+ m[id] += 1
+ pass
+
+def getDesktop():
+ """
+ Returns the active Desktop. Usefull to set the relative position of a dialog box
+ """
+ return __sgPyQt.getDesktop()
+
+def warning(msg):
+ """
+ This function displays a message dialog box displaying the specified message.
+ """
+ gui_warning(getDesktop(),msg)
sgPyQt = SalomePyQt.SalomePyQt()
from daGuiImpl.enumerate import Enumerate
+from daEficasWrapper.datassimEficasWrapper import DatassimEficasWrapper
+from daEficasWrapper.eficasWrapper import EficasObserver
+from daEficasWrapper.eficasWrapper import EficasEvent
+import datassimGuiHelper
+import datassimStudyEditor
+
#
# ==============================================================================
# Classes to manage the building of UI components
sgPyQt.createMenu(a, mid)
sgPyQt.createTool(a, tid)
-class DatassimGuiActionImpl():
+class DatassimGuiActionImpl(EficasObserver):
"""
This class implements the ui actions concerning the management of oma study
cases.
"""
- __dlgNewStudyCase = None
__dlgEficasWrapper = None
def __init__(self):
# This dialog is created once so that it can be recycled for each call
# to newOmaCase().
#self.__dlgNewStudyCase = DlgNewStudyCase()
- #self.__dlgEficasWrapper = OmaEficasWrapper(parent=SalomePyQt.SalomePyQt().getDesktop())
+ self.__dlgEficasWrapper = DatassimEficasWrapper(parent=SalomePyQt.SalomePyQt().getDesktop())
+ self.__dlgEficasWrapper.addObserver(self)
# ==========================================================================
# Processing of ui actions
def newDatassimCase(self):
print "newDatassimCase"
+ salomeStudyId = datassimGuiHelper.getActiveStudyId()
+ salomeStudyItem = datassimStudyEditor.addInStudy(salomeStudyId, "newDatassimCase")
+ datassimGuiHelper.refreshObjectBrowser()
+ callbackId = [salomeStudyId, salomeStudyItem]
+ self.__dlgEficasWrapper.setCallbackId(callbackId)
+ self.__dlgEficasWrapper.displayNew()
+
+ # ==========================================================================
+ # Processing notifications from eficas
+ #
+ __processOptions={
+ EficasEvent.EVENT_TYPES.CLOSE : "_processEficasCloseEvent",
+ EficasEvent.EVENT_TYPES.SAVE : "_processEficasSaveEvent"
+ }
+ def processEficasEvent(self, eficasWrapper, eficasEvent):
+ """
+ Implementation of the interface EficasObserver. The implementation is a
+ switch on the possible types of events defined in EficasEvent.EVENT_TYPES.
+ @overload
+ """
+ functionName = self.__processOptions.get(eficasEvent.eventType, lambda : "_processEficasUnknownEvent")
+ return getattr(self,functionName)(eficasWrapper, eficasEvent)
+
+ def _processEficasCloseEvent(self, eficasWrapper, eficasEvent):
+ print "This is the process of EficasCloseEvent"
+ print "Remove datassim case in study if empty..."
+ pass
+
+ def _processEficasSaveEvent(self, eficasWrapper, eficasEvent):
+ callbackId = eficasEvent.callbackId
+ if callbackId is None:
+ raise DevelException("the callback data should not be None. Can't guess what are the study and case")
+ [targetSalomeStudyId,targetSalomeStudyItem] = callbackId
+ if ( targetSalomeStudyId is None ) or ( targetSalomeStudyItem is None ):
+ raise DevelException("the parameters targetSalomeStudyId and targetSalomeStudyItem should not be None")
+
+ file_name = eficasWrapper.getCurrentFileName()
+ datassimStudyEditor.updateItem(targetSalomeStudyId, targetSalomeStudyItem, file_name)
+ #studyCase = omaStudyEditor.getOmaCaseFromItem(targetSalomeStudyId, targetSalomeStudyItem)
+ #studyCase = eficasWrapper.getData(studyCase)
+ #logger.debug("jdc="+str(studyCase.userdata.getJdc()))
+
+ def _processEficasUnknownEvent(self, eficasWrapper, eficasEvent):
+ print "Unknown Eficas Event"
--- /dev/null
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
+#
+# Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+# CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+# ---
+# Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+# ---
+#
+
+__all__ = [
+ "moduleID",
+ "objectID",
+ "unknownID",
+ "componentName",
+ "modulePixmap",
+ "verbose",
+ "getORB",
+ "getNS",
+ "getLCC",
+ "getStudyManager",
+ "getEngine",
+ "getEngineIOR",
+ "findOrCreateComponent",
+ "getObjectID",
+ ]
+
+from omniORB import CORBA
+from SALOME_NamingServicePy import SALOME_NamingServicePy_i
+from LifeCycleCORBA import LifeCycleCORBA
+import SALOMEDS
+import SALOMEDS_Attributes_idl
+
+#import OMA_ORB
+
+###
+# Get OMA module's ID
+###
+def moduleID():
+ MODULE_ID = 1100
+ return MODULE_ID
+
+###
+# Get OMA object's ID
+###
+def objectID():
+ OBJECT_ID = 1110
+ return OBJECT_ID
+
+###
+# Get unknown ID
+###
+def unknownID():
+ FOREIGN_ID = -1
+ return FOREIGN_ID
+
+def componentName():
+ """
+ This provide the name of the module component to be associated to the study.
+ """
+ # Note that this name should be (i) the name used for the class implementing
+ # the component CORBA interface and (ii) the name used to declare the component
+ # in the catalog of the module.
+ return "DATASSIM"
+
+# _MEM_ we use here the tr() translation methode to manage constant parameters
+# in the application. We could have specified instead constant values directly
+# in the code below. It's a matter of convenience.
+from PyQt4.QtCore import QObject
+QObjectTR=QObject()
+
+def componentUserName():
+ return "DATASSIM"
+
+def modulePixmap():
+ """
+ Get the reference pixmap for this module.
+ """
+ return "DATASSIM_small.png"
+
+__verbose__ = None
+def verbose():
+ global __verbose__
+ if __verbose__ is None:
+ try:
+ __verbose__ = int( os.getenv( 'SALOME_VERBOSE', 0 ) )
+ except:
+ __verbose__ = 0
+ pass
+ pass
+ return __verbose__
+
+###
+# Get ORB reference
+###
+__orb__ = None
+def getORB():
+ global __orb__
+ if __orb__ is None:
+ __orb__ = CORBA.ORB_init( [''], CORBA.ORB_ID )
+ pass
+ return __orb__
+
+###
+# Get naming service instance
+###
+__naming_service__ = None
+def getNS():
+ global __naming_service__
+ if __naming_service__ is None:
+ __naming_service__ = SALOME_NamingServicePy_i( getORB() )
+ pass
+ return __naming_service__
+
+##
+# Get life cycle CORBA instance
+##
+__lcc__ = None
+def getLCC():
+ global __lcc__
+ if __lcc__ is None:
+ __lcc__ = LifeCycleCORBA( getORB() )
+ pass
+ return __lcc__
+
+##
+# Get study manager
+###
+__study_manager__ = None
+def getStudyManager():
+ global __study_manager__
+ if __study_manager__ is None:
+ obj = getNS().Resolve( '/myStudyManager' )
+ __study_manager__ = obj._narrow( SALOMEDS.StudyManager )
+ pass
+ return __study_manager__
+
+###
+# Get OMA engine
+###
+__engine__ = None
+def getEngine():
+ global __engine__
+ if __engine__ is None:
+ __engine__ = getLCC().FindOrLoadComponent( "FactoryServer", componentName() )
+ pass
+ return __engine__
+
+###
+# Get OMA engine IOR
+###
+def getEngineIOR():
+ IOR = ""
+ if getORB() and getEngine():
+ IOR = getORB().object_to_string( getEngine() )
+ pass
+ return IOR
+
+###
+# Find or create OMA component object in a study
+###
+def findOrCreateComponent( study ):
+ father = study.FindComponent( componentName() )
+ if father is None:
+ builder = study.NewBuilder()
+ father = builder.NewComponent( componentName() )
+ attr = builder.FindOrCreateAttribute( father, "AttributeName" )
+ attr.SetValue( componentName() )
+ attr = builder.FindOrCreateAttribute( father, "AttributePixMap" )
+ attr.SetPixMap( modulePixmap() )
+ attr = builder.FindOrCreateAttribute( father, "AttributeLocalID" )
+ attr.SetValue( moduleID() )
+ try:
+ builder.DefineComponentInstance( father, getEngine() )
+ pass
+ except:
+ pass
+ pass
+ return father
+
+###
+# Get object's ID
+###
+def getObjectID( study, entry ):
+ ID = unknownID()
+ if study and entry:
+ sobj = study.FindObjectID( entry )
+ if sobj is not None:
+ test, anAttr = sobj.FindAttribute( "AttributeLocalID" )
+ if test: ID = anAttr._narrow( SALOMEDS.AttributeLocalID ).Value()
+ pass
+ pass
+ return
+
--- /dev/null
+# -*- coding: iso-8859-1 -*-
+# Copyright (C) 2010 EDF R&D
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+__author__="aribes/gboulant"
+
+from enumerate import Enumerate
+import studyedit
+import datassimModuleHelper
+
+#
+# ==============================================================================
+# Constant parameters and identifiers
+# ==============================================================================
+#
+DATASSIM_ITEM_TYPES = Enumerate([
+ "DATASSIM_CASE",
+])
+
+#
+# ==============================================================================
+# Function dedicated to the data management in the salome study
+# ==============================================================================
+#
+# For developpers, note that the data structures used here are:
+# - the SALOME study whose API is defined by SALOMEDS::Study
+# - an item in a study whose API is defined by SALOMEDS:SObject
+# - a study component, whose API is defined by SALOMEDS::SComponent
+# a SComponent is a reference in a study toward a SALOME component
+#
+
+def addInStudy(salomeStudyId, datassimCase):
+ """
+ This function adds in the specified SALOME study a study entry that corresponds
+ to the specified datassim case. This study case is put in a folder under
+ the DATASSIM component and is identified by the case name.
+ """
+
+ studyEditor = studyedit.getStudyEditor(salomeStudyId)
+
+ datassimRootEntry = studyEditor.findOrCreateComponent(
+ engineName = datassimModuleHelper.componentName(),
+ componentName = datassimModuleHelper.componentUserName())
+
+ itemName = datassimCase
+ itemValue = ""
+ itemType = DATASSIM_ITEM_TYPES.DATASSIM_CASE
+
+ salomeStudyItem = studyEditor.createItem(
+ datassimRootEntry, itemName,
+ comment = itemValue,
+ typeId = itemType)
+ # _MEM_ Note that we use the comment attribute to store the serialize
+ # description of the data.
+
+ return salomeStudyItem
+
+def updateItem(salomeStudyId, salomeStudyItem, datassimCase):
+
+ studyEditor = studyedit.getStudyEditor(salomeStudyId)
+
+ itemName = datassimCase
+ itemValue = ""
+
+ studyEditor.setItem(salomeStudyItem,
+ name = itemName,
+ comment = itemValue)
+
+def removeItem(salomeStudyId, item):
+ """
+ Remove the item from the specified study.
+ """
+ if not isValidDatassimCaseItem(salomeStudyId, item):
+ return False
+ studyEditor = studyedit.getStudyEditor(salomeStudyId)
+ return studyEditor.removeItem(item,True)
+
+
+def isValidDatassimCaseItem(salomeStudyId,item):
+ """
+ Return true if the specified item corresponds to a valid datassimCase
+ """
+ if item is None:
+ return False
+
+ studyEditor = studyedit.getStudyEditor(salomeStudyId)
+ itemType = studyEditor.getTypeId(item)
+ if itemType != DATASSIM_ITEM_TYPES.DATASSIM_CASE:
+ return False
+
+ return True
+
+
+def getDatassimCaseFromItem(salomeStudyId, item):
+ """
+ Get the datassim case from the selected item.
+ Note that the study must be specify to retrieve the attributes value from
+ the item reference. The attribute values are stored in the study object.
+ """
+ if not isValidDatassimCaseItem(salomeStudyId, item):
+ return None
+
+ itemName = item.GetName()
+ itemValue = item.GetComment()
+ return itemName
+
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2007-2009 EDF R&D
+#
+# This file is part of PAL_SRC.
+#
+# PAL_SRC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# PAL_SRC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with PAL_SRC; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+"""
+This module provides a new class :class:`StudyEditor` to complement
+:class:`Study` and :class:`StudyBuilder` classes.
+"""
+
+import re
+import salome
+
+_editors = {}
+_DEFAULT_CONTAINER = "FactoryServer"
+
+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()
+ if salome.hasDesktop():
+ return salome.sg.getActiveStudyId()
+ else:
+ return salome.myStudyId
+
+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]
+
+
+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.
+ The preferred way to get a StudyEditor object is through the method
+ :meth:`getStudyEditor` which allows to reuse existing instances.
+
+ .. attribute:: studyId
+
+ This instance attribute contains the ID of the edited study. This
+ attribute should not be modified.
+
+ .. 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
+ be modified.
+
+ .. attribute:: builder
+
+ This instance attribute contains the underlying :class:`StudyBuilder`
+ object. It can be used to edit the study but the attribute itself
+ should not be modified.
+
+ """
+ def __init__(self, studyId = None):
+ 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()
+
+ def findOrCreateComponent(self, engineName, componentName = None,
+ icon = None, loadEngine = True,
+ containerName = _DEFAULT_CONTAINER):
+ """
+ Find a component corresponding to the engine named `engineName` in the
+ study, or create it if none is found. Then eventually load the
+ corresponding engine and the CORBA objects of this component.
+
+ :type engineName: string
+ :param engineName: name of the engine corresponding to the component.
+
+ :type componentName: string
+ :param componentName: name of the new component if created. If
+ :const:`None`, use `engineName` instead.
+
+ :type icon: string
+ :param icon: icon for the new component (attribute "AttributePixMap").
+
+ :type loadEngine: boolean
+ :param loadEngine: If :const:`True`, find or load the corresponding
+ engine and associate it with the component.
+
+ :type containerName: string
+ :param containerName: name of the container in which the component
+ should be loaded.
+
+ :return: the SComponent found or created.
+
+ """
+ sComponent = self.study.FindComponent(engineName)
+ if sComponent is None:
+ sComponent = self.builder.NewComponent(engineName)
+ if componentName is None:
+ componentName = engineName
+ self.builder.SetName(sComponent, componentName)
+
+ if icon is not None:
+ self.setIcon(sComponent, icon)
+
+ if loadEngine:
+ self.loadComponentEngine(sComponent, containerName)
+
+ return sComponent
+
+ def loadComponentEngine(self, sComponent,
+ containerName = _DEFAULT_CONTAINER):
+ """
+ Load the engine corresponding to `sComponent` in the container
+ `containerName`, associate the engine with the component and load the
+ CORBA objects of this component in the study.
+ """
+ engine = salome.lcc.FindOrLoadComponent(containerName,
+ sComponent.GetComment())
+ self.builder.LoadWith(sComponent, engine)
+
+ def getOrLoadObject(self, item):
+ """
+ Get the CORBA object associated with the SObject `item`, eventually by
+ first loading it with the corresponding engine.
+ """
+ object = item.GetObject()
+ if object is None: # the engine has not been loaded yet
+ sComponent = item.GetFatherComponent()
+ self.loadComponentEngine(sComponent)
+ object = item.GetObject()
+ return object
+
+ def findOrCreateItem(self, fatherItem, name, fileType = None,
+ fileName = None, comment = None, icon = None,
+ IOR = None, typeId = None):
+ """
+ Find an object under `fatherItem` in the study with the given
+ attributes. Return the first one found if at least one exists,
+ otherwise create a new one with the given attributes and return it.
+
+ See :meth:`setItem` for the description of the parameters.
+ """
+ sObject = self.findItem(fatherItem, name, fileType, fileName, comment,
+ icon, IOR, typeId)
+ if sObject is None:
+ sObject = self.createItem(fatherItem, name, fileType, fileName,
+ comment, icon, IOR, typeId)
+ return sObject
+
+ def findItem(self, fatherItem, name = None, fileType = None,
+ fileName = None, comment = None, icon = None, IOR = None,
+ typeId = None):
+ """
+ Find an item with given attributes under `fatherItem` in the study. If
+ none is found, return :const:`None`. If several items correspond to
+ the parameters, only the first one is returned. The search is made
+ only on given parameters (i.e. not :const:`None`). To look explicitly
+ for an empty attribute, use an empty string in the corresponding
+ parameter.
+
+ See :meth:`setItem` for the description of the parameters.
+ """
+ foundItem = None;
+ childIterator = self.study.NewChildIterator(fatherItem)
+ while childIterator.More() and foundItem is None:
+ childItem = childIterator.Value()
+ if childItem and \
+ (name is None or childItem.GetName() == 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 \
+ (icon is None or \
+ self.getIcon(childItem) == icon) and \
+ (IOR is None or childItem.GetIOR() == IOR and \
+ (typeId is None or \
+ self.getTypeId(childItem) == typeId)):
+ foundItem = childItem
+ childIterator.Next()
+ return foundItem
+
+ 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)
+
+ aChildIterator = self.study.NewChildIterator(fatherItem)
+ aMaxId = -1
+ aLength = len(name)
+ aDelim = "_"
+ anIdRE = re.compile("^" + aDelim + "[0-9]+")
+ aNameRE = re.compile("^" + name)
+ while aChildIterator.More():
+ aSObj = aChildIterator.Value()
+ aChildIterator.Next()
+ aName = aSObj.GetName()
+ if re.match(aNameRE,aName):
+ aTmp = aName[aLength:]
+ if re.match(anIdRE,aTmp):
+ import string
+ anId = string.atol(aTmp[1:])
+ if aMaxId < anId:
+ aMaxId = anId
+ pass
+ pass
+ elif aMaxId < 0:
+ aMaxId = 0
+ 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
+
+ def setItem(self, item, name = None, fileType = None, fileName = None,
+ comment = None, icon = None, IOR = None, typeId = None):
+ """
+ Modify the attributes of an item in the study. Unspecified attributes
+ (i.e. those set to :const:`None`) are left unchanged.
+
+ :type item: SObject
+ :param item: item to modify.
+
+ :type name: string
+ :param name: item name (attribute 'AttributeName').
+
+ :type fileType: string
+ :param fileType: item file type (attribute 'AttributeFileType').
+
+ :type fileName: string
+ :param fileName: item file name (attribute
+ 'AttributeExternalFileDef').
+
+ :type comment: string
+ :param comment: item comment (attribute 'AttributeComment'). Note that
+ this attribute will appear in the 'Value' column in
+ the object browser.
+
+ :type icon: string
+ :param icon: item icon name (attribute 'AttributePixMap').
+
+ :type IOR: string
+ :param IOR: IOR of a CORBA object associated with the item
+ (attribute 'AttributeIOR').
+
+ :type typeId: integer
+ :param typeId: item type (attribute 'AttributeLocalID').
+ """
+ print "setItem (ID=%s): name=%s, fileType=%s, fileName=%s, 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))
+ 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))
+ if icon is not None:
+ self.setIcon(item, icon)
+ if IOR is not None:
+ self.builder.SetIOR(item, str(IOR))
+ if typeId is not None:
+ self.setTypeId(item, typeId)
+
+ def removeItem(self, item, withChildren = False ):
+ """
+ Remove the given item from the study (the item still is in
+ the study after the removal)
+ @param item: the browser object to be removed
+ @param withChildren: remove children if True
+ """
+ ok = False
+ try:
+ if withChildren:
+ self.builder.RemoveObjectWithChildren(item)
+ else:
+ self.builder.RemoveObject(item)
+ ok = True
+ except:
+ ok = False
+
+ return ok
+
+ def setItemAtTag(self, fatherItem, tag, name = None, fileType = None,
+ fileName = None, comment = None, icon = None, IOR = None,
+ typeId = None):
+ """
+ Find an item tagged `tag` under `fatherItem` in the study tree or
+ create it if there is none, then set its attributes.
+
+ :type fatherItem: SObject
+ :param fatherItem: item under which the tagged item will be looked for
+ and eventually created.
+
+ :type tag: integer
+ :param tag: tag of the item to look for.
+
+ :return: the SObject at `tag` if found or created successfully, or
+ :const:`None` if an error happened.
+
+ See :meth:`setItem` for the description of the other parameters.
+ """
+ found, sObj = fatherItem.FindSubObject(tag)
+ if not found:
+ sObj = self.builder.NewObjectToTag(fatherItem, tag)
+ self.setItem(sObj, name, fileType, fileName, comment, icon,
+ IOR, typeId)
+ return sObj
+
+ def getAttributeValue(self, sObject, attributeName, default = None):
+ """
+ Return the value of the attribute named `attributeName` on the object
+ `sObject`, or `default` if the attribute doesn't exist.
+ """
+ value = default
+ found, attr = self.builder.FindAttribute(sObject, attributeName)
+ if found:
+ value = attr.Value()
+ return value
+
+ def setAttributeValue(self, sObject, attributeName, attributeValue):
+ """
+ Set the value of the attribute named `attributeName` on the object
+ `sObject` to the value `attributeValue`.
+ """
+ attr = self.builder.FindOrCreateAttribute(sObject, attributeName)
+ attr.SetValue(attributeValue)
+
+ def getTypeId(self, sObject):
+ """
+ Return the value of the attribute "AttributeLocalID" of the object
+ `sObject`, or :const:`None` if it is not set.
+ """
+ return self.getAttributeValue(sObject, "AttributeLocalID")
+
+ def setTypeId(self, sObject, value):
+ """
+ Set the attribute "AttributeLocalID" of the object `sObject` to the
+ value `value`.
+ """
+ self.setAttributeValue(sObject, "AttributeLocalID", value)
+
+ def getFileType(self, sObject):
+ """
+ Return the value of the attribute "AttributeFileType" of the object
+ `sObject`, or an empty string if it is not set.
+ """
+ return self.getAttributeValue(sObject, "AttributeFileType", "")
+
+ def setFileType(self, sObject, value):
+ """
+ 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))
+
+ def getFileName(self, sObject):
+ """
+ Return the value of the attribute "AttributeExternalFileDef" of the
+ object `sObject`, or an empty string if it is not set.
+ """
+ return self.getAttributeValue(sObject, "AttributeExternalFileDef", "")
+
+ def setFileName(self, sObject, value):
+ """
+ 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))
+
+ def getIcon(self, sObject):
+ """
+ Return the value of the attribute "AttributePixMap" of the object
+ `sObject`, or an empty string if it is not set.
+ """
+ value = ""
+ found, attr = self.builder.FindAttribute(sObject, "AttributePixMap")
+ if found and attr.HasPixMap():
+ value = attr.GetPixMap()
+ return value
+
+ def setIcon(self, sObject, value):
+ """
+ Set the attribute "AttributePixMap" of the object `sObject` to the
+ value `value`.
+ """
+ attr = self.builder.FindOrCreateAttribute(sObject, "AttributePixMap")
+ # Explicit cast is necessary for unicode to string conversion
+ attr.SetPixMap(str(value))