From 9957128d724a1ec25a96f9c7c7a11a79a6d631bb Mon Sep 17 00:00:00 2001 From: boulant Date: Mon, 13 Feb 2012 10:08:07 +0000 Subject: [PATCH] IMP: pluginpreview --- doc/salome/gui/input/using_pluginsmanager.doc | 43 +++- src/SalomeApp/pluginsdemo/Makefile.am | 12 +- src/SalomeApp/pluginsdemo/myhelper.py | 41 ---- src/SalomeApp/pluginsdemo/salome_plugins.py | 107 +++++---- .../pluginsdemo/{tube.py => tubebuilder.py} | 0 src/SalomeApp/pluginsdemo/tubedialog.py | 124 ++++------- .../pluginsdemo/tubedialogWithApply.py | 30 --- src/SalomeApp/pluginsdemo/tubedialog_ui.py | 87 ++++++++ src/SalomeApp/pluginsdemo/xalome.py | 208 ++++++++++++++++++ 9 files changed, 445 insertions(+), 207 deletions(-) delete mode 100644 src/SalomeApp/pluginsdemo/myhelper.py rename src/SalomeApp/pluginsdemo/{tube.py => tubebuilder.py} (100%) delete mode 100644 src/SalomeApp/pluginsdemo/tubedialogWithApply.py create mode 100644 src/SalomeApp/pluginsdemo/tubedialog_ui.py create mode 100644 src/SalomeApp/pluginsdemo/xalome.py diff --git a/doc/salome/gui/input/using_pluginsmanager.doc b/doc/salome/gui/input/using_pluginsmanager.doc index 4ac23796c..d6f8234ff 100644 --- a/doc/salome/gui/input/using_pluginsmanager.doc +++ b/doc/salome/gui/input/using_pluginsmanager.doc @@ -5,6 +5,7 @@ -# \ref S1_SALOMEPLUGINS -# \ref S2_SALOMEPLUGINS -# \ref S3_SALOMEPLUGINS +-# \ref S4_SALOMEPLUGINS \section S1_SALOMEPLUGINS Objectives @@ -29,7 +30,7 @@ In this example, the end user has to write: -# the python script that creates the mesh from the parameters, using the GEOM and SMESH python interface, as in a clasic use case. -# the dialog box in PyQt to input the parameters --# file salome_plugins.py that declares the plugins +-# the file salome_plugins.py that declares the plugins This page explains only the last point. @@ -64,23 +65,24 @@ proxy to your code that you can manage in a python package installed in the standard SALOME python directories. In this code, the variable "context" is automatically transmitted by -the pluginmanager when you request the plugin with at least the following -attributes: +the pluginmanager when you request the plugin. This context provides +you with at at least the following attributes: \code activeStudy = context.study salomegui = context.sg \endcode -Once terminated, this script salome_plugin.py has to be moved to a +Once written, this script salome_plugin.py has to be moved to a specific place on your filesystem where SALOME is programmed to search -for plugins. The possible directories are: +for plugins. The possible directories are (in search order): --# The directory <*_ROOT_DIR>/share/salome/plugins, when this plugin - is developped in the framework of a SALOME module (<*_ROOT_DIR> - is the root installation directory of the module). +-# The directory <*_ROOT_DIR>/share/salome/plugins/, when + this plugin is developped in the framework of a SALOME module + (<*_ROOT_DIR> is the root installation directory of the module, and + is the name of the module in low letters). -# The directory ~/.config/salome/Plugins for personnal end user - plugins + plugins. -# Any path in the shell variable SALOME_PLUGIN_PATH (each path must be separated by a comma ":" for unix and ";" for windows). This variable should be set and exported before running the SALOME application. @@ -141,4 +143,27 @@ salome_pluginsmanager.AddFunction('O,Vx,Vy,Vz', Move this script in the directory ~/.config/salome/Plugins, run SALOME and enjoy your new function. +\section S4_SALOMEPLUGINS Other examples + +The GUI module provides you with some basic demo examples, located in +the directory src/SalomeApp/pluginsdemo of the source space, and +installed in the directory $GUI_ROOT_DIR/share/salome/plugins/gui. + +\note These examples are automatically installed when you install the GUI +but are not activated. To activate the plugins, edit the file +$GUI_ROOT_DIR/share/salome/plugins/gui/salome_plugins.py and turn the +variable DEMO_IS_ACTIVATED to True. + +The demo examples are: +-# \b trihedron: create a trihedron and display it with fit on the size +-# \b tube_shapewithgui: create a geom object from parameters given by a + dialog box. +-# \b tube_meshwithgui: create a mesh object from parameters given by a + dialog box. This illustrates that a plugin can work with more than + one SALOME module. +-# \b tube_shapewithguiAndPreview: same than tube_shapewithgui but with + an additionnal preview function (button apply in the dialog box). +-# \b runSalomeShellSession: run a SALOME prepared shell session in a + xterm. + */ diff --git a/src/SalomeApp/pluginsdemo/Makefile.am b/src/SalomeApp/pluginsdemo/Makefile.am index d602c6a7e..ed5f93763 100644 --- a/src/SalomeApp/pluginsdemo/Makefile.am +++ b/src/SalomeApp/pluginsdemo/Makefile.am @@ -32,9 +32,9 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am # pluginsdir =$(salomepluginsdir)/demo plugins_PYTHON = \ - salome_plugins.py \ - trihedron.py \ - tubedialog.py \ - tubedialogWithApply.py \ - tube.py \ - myhelper.py + salome_plugins.py \ + trihedron.py \ + tubedialog_ui.py \ + tubedialog.py \ + tubebuilder.py \ + xalome.py diff --git a/src/SalomeApp/pluginsdemo/myhelper.py b/src/SalomeApp/pluginsdemo/myhelper.py deleted file mode 100644 index 70c94b96f..000000000 --- a/src/SalomeApp/pluginsdemo/myhelper.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: iso-8859-1 -*- - -import salome -from salome.geom import geomtools - -def addToStudy(study,shape,name): - ''' - Helper function to add an object in the study. It returns the - associated entry so that this study could be manipulated using - study object functions. - ''' - studyId = study._get_StudyId() - geompy = geomtools.getGeompy(studyId) - entry = geompy.addToStudy( shape, "Tube" ) - return entry - -# Available in SALOME 6.5 only -def displayShape_version65(shapeStudyEntry): - gst = geomtools.GeomStudyTools() - gst.displayShapeByEntry(shapeStudyEntry) - -def eraseShape_version65(shapeStudyEntry): - gst = geomtools.GeomStudyTools() - gst.eraseShapeByEntry(shapeStudyEntry) - -ModeShading = 1 -DisplayMode=ModeShading -def displayShape(shapeStudyEntry): - """This displays the shape specified by its entry in the study""" - geomgui = salome.ImportComponentGUI("GEOM") - geomgui.createAndDisplayFitAllGO(shapeStudyEntry) - geomgui.setDisplayMode(shapeStudyEntry, DisplayMode) - -def eraseShape(shapeStudyEntry): - """ - This erases from the viewers the shape specified by its entry - in the study. - """ - geomgui = salome.ImportComponentGUI("GEOM") - eraseFromAllWindows=True - geomgui.eraseGO(shapeStudyEntry,eraseFromAllWindows) diff --git a/src/SalomeApp/pluginsdemo/salome_plugins.py b/src/SalomeApp/pluginsdemo/salome_plugins.py index b9de4eb76..2a2581627 100755 --- a/src/SalomeApp/pluginsdemo/salome_plugins.py +++ b/src/SalomeApp/pluginsdemo/salome_plugins.py @@ -1,7 +1,7 @@ # -*- coding: iso-8859-1 -*- import salome_pluginsmanager -DEMO_IS_ACTIVATED=False +DEMO_IS_ACTIVATED=True # ------------------------------------------------------------------------- # Example 1: creation of basic objects. @@ -71,18 +71,20 @@ if DEMO_IS_ACTIVATED: # The plugin function (tube_shapewithgui) delegates some action to # dedicated imported modules (tube.py and tubedialog.py). # -import tube -import myhelper +import tubebuilder +import xalome # A single dialog box is defined and recycled for every call. The # fields are initialized with default values given by the tube factory # tube.py. import tubedialog dialog = tubedialog.TubeDialog() -dialog.setData(tube.DEFAULT_RADIUS, tube.DEFAULT_LENGTH, tube.DEFAULT_WIDTH) +dialog.setData(tubebuilder.DEFAULT_RADIUS, + tubebuilder.DEFAULT_LENGTH, + tubebuilder.DEFAULT_WIDTH) def tube_shapewithgui(context): - global tube, myhelper, dialog + global tubebuilder, xalome, dialog activeStudy = context.study # Get the parameter values from a gui dialog box. If the dialog is @@ -91,9 +93,9 @@ def tube_shapewithgui(context): dialog.exec_() if dialog.wasOk(): radius, length, width = dialog.getData() - shape = tube.createGeometry(activeStudy, radius, length, width) - entry = myhelper.addToStudy(activeStudy, shape, "Tube" ) - myhelper.displayShape(entry) + shape = tubebuilder.createGeometry(activeStudy, radius, length, width) + entry = xalome.addToStudy(activeStudy, shape, "Tube" ) + xalome.displayShape(entry) if DEMO_IS_ACTIVATED: salome_pluginsmanager.AddFunction('Tube shape from parameters', @@ -104,7 +106,7 @@ if DEMO_IS_ACTIVATED: # ------------------------------------------------------------------------- # Example 2 bis: creation of a mesh with parameters that can be read from a GUI. # The plugin function (tube_meshwithgui) delegates some action to -# dedicated imported modules (tube.py and tubedialog.py). +# dedicated imported modules (tubebuilder.py and tubedialog.py). # def tube_meshwithgui(context): global tube, dialog @@ -116,7 +118,7 @@ def tube_meshwithgui(context): dialog.exec_() if dialog.wasOk(): radius, length, width = dialog.getData() - mesh = tube.createModel(activeStudy, radius, length, width) + mesh = tubebuilder.createModel(activeStudy, radius, length, width) if DEMO_IS_ACTIVATED: salome_pluginsmanager.AddFunction('Tube mesh from parameters', @@ -130,74 +132,89 @@ if DEMO_IS_ACTIVATED: # view because the dialog box is a not modal so that we can have # interaction with the complete SALOME application. This modal # situation requires to connect button click signal on global -# functions named the "callback" functions. +# functions as a "callback" mechanism. +# +# TODO: +# - coloring the preview in pink +# - store the tmp study objects in a "preview" folder # -import tubedialogWithApply -dialogWithApply = tubedialogWithApply.TubeDialogWithApply() -dialogWithApply.setData(tube.DEFAULT_RADIUS, tube.DEFAULT_LENGTH, tube.DEFAULT_WIDTH) +dialogWithApply = tubedialog.TubeDialogOnTopWithApply() +dialogWithApply.setData(tubebuilder.DEFAULT_RADIUS, + tubebuilder.DEFAULT_LENGTH, + tubebuilder.DEFAULT_WIDTH) activeStudy = None previewShapeEntry = None +DEFAULT_FOLDER_NAME="TubeList" +DEFAULT_SHAPE_NAME="tube" +PREVIEW_SHAPE_NAME="preview" + def acceptCallback(): - """Action to do when click on Ok""" - global tube, dialogWithApply, activeStudy, previewShapeEntry, deletePreviewShape + """Action to be done when click on Ok""" + global tubebuilder, xalome + global dialogWithApply, activeStudy + global previewShapeEntry, deletePreviewShape + global DEFAULT_FOLDER_NAME,DEFAULT_SHAPE_NAME + dialogWithApply.accept() if previewShapeEntry is not None: deletePreviewShape() radius, length, width = dialogWithApply.getData() - shape = tube.createGeometry(activeStudy, radius, length, width) - entry = myhelper.addToStudy(activeStudy, shape, "Tube" ) - myhelper.displayShape(entry) + shape = tubebuilder.createGeometry(activeStudy, radius, length, width) + entry = xalome.addToStudy(activeStudy, shape, DEFAULT_SHAPE_NAME, DEFAULT_FOLDER_NAME) + xalome.displayShape(entry) - def rejectCallback(): - """Action to do when click on Cancel""" - global tube, dialogWithApply, activeStudy, previewShapeEntry, deletePreviewShape + """Action to be done when click on Cancel""" + global dialogWithApply, previewShapeEntry, deletePreviewShape + dialogWithApply.reject() if previewShapeEntry is not None: deletePreviewShape() +import SALOMEDS +PREVIEW_COLOR=SALOMEDS.Color(1,0.6,1) # pink + def applyCallback(): - """Action to do when click on Apply""" - global tube, dialogWithApply, activeStudy, previewShapeEntry, deletePreviewShape + """Action to be done when click on Apply""" + global tubebuilder, xalome + global dialogWithApply, activeStudy + global previewShapeEntry, deletePreviewShape + global PREVIEW_COLOR, DEFAULT_SHAPE_NAME, DEFAULT_FOLDER_NAME, PREVIEW_SHAPE_NAME + # We first have to destroy the currently displayed preview shape. if previewShapeEntry is not None: deletePreviewShape() # Then we can create the new shape with the new parameter values radius, length, width = dialogWithApply.getData() - shape = tube.createGeometry(activeStudy, radius, length, width) - previewShapeEntry = myhelper.addToStudy(activeStudy, shape, "Tube" ) - myhelper.displayShape(previewShapeEntry) + shape = tubebuilder.createGeometry(activeStudy, radius, length, width) + # We apply a specific color on the shape for the preview state + shape.SetColor(PREVIEW_COLOR) + previewShapeEntry = xalome.addToStudy(activeStudy, shape, PREVIEW_SHAPE_NAME, DEFAULT_FOLDER_NAME ) + xalome.displayShape(previewShapeEntry) def deletePreviewShape(): - global activeStudy, previewShapeEntry - - from salome.kernel.studyedit import getStudyEditor, getStudyIdFromStudy - from salome.kernel.services import IDToSObject, IDToObject - - # WARN: please be aware that to delete a geom object, you have - # three operations to perform: - # 1. erase the shape from the viewer - # 2. delete the entry in the study - # 3. destroy the geom object - myhelper.eraseShape(previewShapeEntry) - item = IDToSObject(previewShapeEntry) - geomObj = IDToObject(previewShapeEntry) - ste = getStudyEditor(getStudyIdFromStudy(activeStudy)) - ste.removeItem(item,True) - geomObj.Destroy() + """This delete the shape currently being displayed as a preview""" + global activeStudy, previewShapeEntry, xsalome + xalome.deleteShape(activeStudy,previewShapeEntry) previewShapeEntry = None - + +# Connection of callback functions to the dialog butoon click signals dialogWithApply.handleAcceptWith(acceptCallback) dialogWithApply.handleRejectWith(rejectCallback) dialogWithApply.handleApplyWith(applyCallback) def tube_shapewithguiAndPreview(context): - global tube, dialogWithApply, activeStudy + """ + This plugin open a dialog in an asynchronous mode. Then it + required callback functions to be associated to the button + signals. + """ + global dialogWithApply, activeStudy activeStudy = context.study dialogWithApply.open() diff --git a/src/SalomeApp/pluginsdemo/tube.py b/src/SalomeApp/pluginsdemo/tubebuilder.py similarity index 100% rename from src/SalomeApp/pluginsdemo/tube.py rename to src/SalomeApp/pluginsdemo/tubebuilder.py diff --git a/src/SalomeApp/pluginsdemo/tubedialog.py b/src/SalomeApp/pluginsdemo/tubedialog.py index 42b0ee4dd..f914eb422 100644 --- a/src/SalomeApp/pluginsdemo/tubedialog.py +++ b/src/SalomeApp/pluginsdemo/tubedialog.py @@ -1,78 +1,33 @@ -# -*- coding: iso-8859-1 -*- import sys from PyQt4 import QtGui from PyQt4 import QtCore +from tubedialog_ui import TubeDialog_UI -class TubeDialog(QtGui.QDialog): - def __init__(self, parent=None): - QtGui.QDialog.__init__(self, parent) - self.setupUi() +class TubeDialog(TubeDialog_UI): def setupUi(self): - self.setObjectName("Dialog") - self.resize(400, 300) - self.hboxlayout = QtGui.QHBoxLayout(self) - self.hboxlayout.setMargin(9) - self.hboxlayout.setSpacing(6) - self.hboxlayout.setObjectName("hboxlayout") - self.vboxlayout = QtGui.QVBoxLayout() - self.vboxlayout.setMargin(0) - self.vboxlayout.setSpacing(6) - self.vboxlayout.setObjectName("vboxlayout") - self.hboxlayout1 = QtGui.QHBoxLayout() - self.hboxlayout1.setMargin(0) - self.hboxlayout1.setSpacing(6) - self.hboxlayout1.setObjectName("hboxlayout1") - self.vboxlayout1 = QtGui.QVBoxLayout() - self.vboxlayout1.setMargin(0) - self.vboxlayout1.setSpacing(6) - self.vboxlayout1.setObjectName("vboxlayout1") - self.lblRadius = QtGui.QLabel(self) - self.lblRadius.setObjectName("lblRadius") - self.vboxlayout1.addWidget(self.lblRadius) - self.lblLength = QtGui.QLabel(self) - self.lblLength.setObjectName("lblLength") - self.vboxlayout1.addWidget(self.lblLength) - self.lblWidth = QtGui.QLabel(self) - self.lblWidth.setObjectName("lblWidth") - self.vboxlayout1.addWidget(self.lblWidth) - self.hboxlayout1.addLayout(self.vboxlayout1) - self.vboxlayout2 = QtGui.QVBoxLayout() - self.vboxlayout2.setMargin(0) - self.vboxlayout2.setSpacing(6) - self.vboxlayout2.setObjectName("vboxlayout2") - self.txtRadius = QtGui.QLineEdit(self) - self.txtRadius.setObjectName("txtRadius") - self.vboxlayout2.addWidget(self.txtRadius) - self.txtLength = QtGui.QLineEdit(self) - self.txtLength.setObjectName("txtLength") - self.vboxlayout2.addWidget(self.txtLength) - self.txtWidth = QtGui.QLineEdit(self) - self.txtWidth.setObjectName("txtWidth") - self.vboxlayout2.addWidget(self.txtWidth) - self.hboxlayout1.addLayout(self.vboxlayout2) - self.vboxlayout.addLayout(self.hboxlayout1) - spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) - self.vboxlayout.addItem(spacerItem) - self.buttonBox = QtGui.QDialogButtonBox(self) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.NoButton|QtGui.QDialogButtonBox.Ok) - self.buttonBox.setObjectName("buttonBox") - self.vboxlayout.addWidget(self.buttonBox) - self.hboxlayout.addLayout(self.vboxlayout) - - self.setWindowTitle("Tube construction") - self.lblRadius.setText("Rayon") - self.lblLength.setText("Longueur") - self.lblWidth.setText("Epaisseur") - - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject) + TubeDialog_UI.setupUi(self) + self.handleAcceptWith(self.accept) + self.handleRejectWith(self.reject) + + def handleAcceptWith(self,callbackFunction): + """This defines the function to be connected to the signal 'accepted()' (click on Ok)""" + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), callbackFunction) + + def handleRejectWith(self,callbackFunction): + """This defines the function to be connected to the signal 'rejected()' (click on Cancel)""" + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), callbackFunction) + + def handleApplyWith(self,callbackFunction): + """This defines the function to be connected to the signal 'apply()' (click on Apply)""" + button = self.buttonBox.button(QtGui.QDialogButtonBox.Apply) + QtCore.QObject.connect(button, QtCore.SIGNAL("clicked()"), callbackFunction); def accept(self): '''Callback function when dialog is accepted (click Ok)''' self._wasOk = True + # We should test here the validity of values QtGui.QDialog.accept(self) def reject(self): @@ -98,11 +53,32 @@ class TubeDialog(QtGui.QDialog): return radius, length, width - -def TEST_getData(): - # This use case illustrates the MVC pattern on this simple dialog example. - a = QtGui.QApplication(sys.argv) - + +class TubeDialogOnTopWithApply(TubeDialog): + def setupUi(self): + """ + This setupUi adds a button 'Apply' to execute a processing + tasks (ex: preview), and set a flag that keeps the dialog on + top of all windows. + """ + TubeDialog.setupUi(self) + # Add a button "Apply" + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel| + QtGui.QDialogButtonBox.Apply| + QtGui.QDialogButtonBox.Ok) + + # Keep the dialog on top of the windows + self.setWindowFlags(self.windowFlags() | + QtCore.Qt.WindowStaysOnTopHint) + + +# +# ====================================================================== +# Unit test +# ====================================================================== +# +def TEST_getData_synchrone(): + """This use case illustrates the MVC pattern on this simple dialog example""" tubedialog = TubeDialog() tubedialog.setData(10,50,3) tubedialog.exec_() @@ -110,16 +86,12 @@ def TEST_getData(): radius, length, width = tubedialog.getData() print radius, length, width - sys.exit(0) def main( args ): a = QtGui.QApplication(sys.argv) - - tubedialog = TubeDialog() - tubedialog.setData(10,50,3) - sys.exit(tubedialog.exec_()) + TEST_getData_synchrone() + sys.exit(0) if __name__=="__main__": - #main(sys.argv) - TEST_getData() + main(sys.argv) diff --git a/src/SalomeApp/pluginsdemo/tubedialogWithApply.py b/src/SalomeApp/pluginsdemo/tubedialogWithApply.py deleted file mode 100644 index d74549696..000000000 --- a/src/SalomeApp/pluginsdemo/tubedialogWithApply.py +++ /dev/null @@ -1,30 +0,0 @@ -import sys -from PyQt4 import QtGui -from PyQt4 import QtCore - - -from tubedialog import TubeDialog -class TubeDialogWithApply(TubeDialog): - def setupUi(self): - """ - This setupUi adds a button Apply to execute tasks as preview - """ - TubeDialog.setupUi(self) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel| - QtGui.QDialogButtonBox.Apply| - QtGui.QDialogButtonBox.Ok) - - self.setWindowFlags(self.windowFlags() | - QtCore.Qt.WindowStaysOnTopHint) - - - def handleAcceptWith(self,callbackFunction): - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), callbackFunction) - - def handleRejectWith(self,callbackFunction): - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), callbackFunction) - - def handleApplyWith(self,callbackFunction): - button = self.buttonBox.button(QtGui.QDialogButtonBox.Apply) - QtCore.QObject.connect(button, QtCore.SIGNAL("clicked()"), callbackFunction); - diff --git a/src/SalomeApp/pluginsdemo/tubedialog_ui.py b/src/SalomeApp/pluginsdemo/tubedialog_ui.py new file mode 100644 index 000000000..277fd0a76 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/tubedialog_ui.py @@ -0,0 +1,87 @@ +# -*- coding: iso-8859-1 -*- +import sys +from PyQt4 import QtGui +from PyQt4 import QtCore + + +class TubeDialog_UI(QtGui.QDialog): + """ + This class defines the design of a Qt dialog box dedicated to the + salome plugin examples. It presents a UI form that contains + parameters for the spatial dimensions of geometrical object. + """ + def __init__(self, parent=None): + QtGui.QDialog.__init__(self, parent) + self.setupUi() + + def setupUi(self): + self.setObjectName("Dialog") + self.resize(400, 300) + self.hboxlayout = QtGui.QHBoxLayout(self) + self.hboxlayout.setMargin(9) + self.hboxlayout.setSpacing(6) + self.hboxlayout.setObjectName("hboxlayout") + self.vboxlayout = QtGui.QVBoxLayout() + self.vboxlayout.setMargin(0) + self.vboxlayout.setSpacing(6) + self.vboxlayout.setObjectName("vboxlayout") + self.hboxlayout1 = QtGui.QHBoxLayout() + self.hboxlayout1.setMargin(0) + self.hboxlayout1.setSpacing(6) + self.hboxlayout1.setObjectName("hboxlayout1") + self.vboxlayout1 = QtGui.QVBoxLayout() + self.vboxlayout1.setMargin(0) + self.vboxlayout1.setSpacing(6) + self.vboxlayout1.setObjectName("vboxlayout1") + self.lblRadius = QtGui.QLabel(self) + self.lblRadius.setObjectName("lblRadius") + self.vboxlayout1.addWidget(self.lblRadius) + self.lblLength = QtGui.QLabel(self) + self.lblLength.setObjectName("lblLength") + self.vboxlayout1.addWidget(self.lblLength) + self.lblWidth = QtGui.QLabel(self) + self.lblWidth.setObjectName("lblWidth") + self.vboxlayout1.addWidget(self.lblWidth) + self.hboxlayout1.addLayout(self.vboxlayout1) + self.vboxlayout2 = QtGui.QVBoxLayout() + self.vboxlayout2.setMargin(0) + self.vboxlayout2.setSpacing(6) + self.vboxlayout2.setObjectName("vboxlayout2") + self.txtRadius = QtGui.QLineEdit(self) + self.txtRadius.setObjectName("txtRadius") + self.vboxlayout2.addWidget(self.txtRadius) + self.txtLength = QtGui.QLineEdit(self) + self.txtLength.setObjectName("txtLength") + self.vboxlayout2.addWidget(self.txtLength) + self.txtWidth = QtGui.QLineEdit(self) + self.txtWidth.setObjectName("txtWidth") + self.vboxlayout2.addWidget(self.txtWidth) + self.hboxlayout1.addLayout(self.vboxlayout2) + self.vboxlayout.addLayout(self.hboxlayout1) + spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + self.vboxlayout.addItem(spacerItem) + self.buttonBox = QtGui.QDialogButtonBox(self) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.NoButton|QtGui.QDialogButtonBox.Ok) + self.buttonBox.setObjectName("buttonBox") + self.vboxlayout.addWidget(self.buttonBox) + self.hboxlayout.addLayout(self.vboxlayout) + + self.setWindowTitle("Tube construction") + self.lblRadius.setText("Rayon") + self.lblLength.setText("Longueur") + self.lblWidth.setText("Epaisseur") + +# +# ====================================================================== +# Unit test +# ====================================================================== +# +def main( args ): + a = QtGui.QApplication(sys.argv) + tubedialog = TubeDialog_UI() + sys.exit(tubedialog.exec_()) + +if __name__=="__main__": + main(sys.argv) + diff --git a/src/SalomeApp/pluginsdemo/xalome.py b/src/SalomeApp/pluginsdemo/xalome.py new file mode 100644 index 000000000..e628c0447 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/xalome.py @@ -0,0 +1,208 @@ +# -*- coding: iso-8859-1 -*- +# +# XALOME means "eXtension for sALOME. This module contains specific +# helper functions that extends salome for the needs of the salome +# plugin examples, or hide some complex technical parts of SALOME to +# ease the global understanding of the examples. +# +# (gboulant - 09/02/2012) +# +import salome +from salome.kernel.studyedit import getStudyEditor +from salome.kernel.services import IDToSObject, IDToObject +from salome.geom import geomtools + +# ====================================================================== +# Helper functions to add/remove a geometrical shape in/from the study +# ====================================================================== + +def addToStudy(study,shape,shapeName,folderName=None): + """ + Add a GEOM shape in the study. It returns the associated entry + that corresponds to the identifier of the entry in the study. This + entry can be used to retrieve an object in the study. A folderName + can be specified. In this case, a folder with this name is first + created in the Geometry part of the study, and the shape study + object is stored in this folder of the study. + """ + studyId = study._get_StudyId() + geompy = geomtools.getGeompy(studyId) + + if folderName is None: + # Insert the shape in the study by the standard way + entry = geompy.addToStudy( shape, shapeName ) + else: + # A folder name has been specified to embed this shape. Find + # or create a folder with this name in the Geometry study, and + # then store the shape in this folder. + studyEditor = getStudyEditor(studyId) + geomStudyFolder = studyEditor.findOrCreateComponent("GEOM") + shapeStudyFolder = studyEditor.findOrCreateItem(geomStudyFolder,folderName) + + shapeIor = salome.orb.object_to_string(shape) + geomgui = salome.ImportComponentGUI("GEOM") + shapeIcon = geomgui.getShapeTypeIcon(shapeIor) + + shapeStudyObject = studyEditor.createItem(shapeStudyFolder, + name=shapeName, + IOR=shapeIor, + icon=shapeIcon) + entry = shapeStudyObject.GetID() + + return entry + +def removeFromStudy(study,shapeStudyEntry): + """ + This removes the specified entry from the study. Note that this + operation does not destroy the underlying GEOM object, neither + erase the drawing in the viewer. + The underlying GEOM object is returned (so that it can be destroyed) + """ + studyId = study._get_StudyId() + shape = IDToObject(shapeStudyEntry) + studyObject = IDToSObject(shapeStudyEntry) + studyEditor = getStudyEditor(studyId) + studyEditor.removeItem(studyObject,True) + return shape + + +# ====================================================================== +# Helper functions to display/erase a shape in/from the viewer. The +# shape must be previously put in the study and the study entry must +# be known. +# ====================================================================== + +ModeShading = 1 +DisplayMode=ModeShading +PreviewColor=[236,163,255] +def displayShape(shapeStudyEntry, color=None): + """This displays the shape specified by its entry in the study""" + geomgui = salome.ImportComponentGUI("GEOM") + geomgui.createAndDisplayFitAllGO(shapeStudyEntry) + geomgui.setDisplayMode(shapeStudyEntry, DisplayMode) + if color is not None: + geomgui.setColor(shapeStudyEntry, color[0], color[1], color[2]) + +def eraseShape(shapeStudyEntry): + """ + This erases from the viewers the shape specified by its study + entry. + """ + geomgui = salome.ImportComponentGUI("GEOM") + eraseFromAllWindows=True + geomgui.eraseGO(shapeStudyEntry,eraseFromAllWindows) + +# Available in SALOME 6.5 only +def displayShape_version65(shapeStudyEntry): + gst = geomtools.GeomStudyTools() + gst.displayShapeByEntry(shapeStudyEntry) + +def eraseShape_version65(shapeStudyEntry): + gst = geomtools.GeomStudyTools() + gst.eraseShapeByEntry(shapeStudyEntry) + + +# ====================================================================== +# Helper functions for a complete suppression of a shape from the +# SALOME session. +# ====================================================================== +def deleteShape(study,shapeStudyEntry): + """ + This completly deletes a geom shape. + + WARNING: please be aware that to delete a geom object, you have + three operations to perform: + + 1. erase the shape from the viewers + 2. remove the entry from the study + 3. destroy the underlying geom object + """ + eraseShape(shapeStudyEntry) + shape = removeFromStudy(study, shapeStudyEntry) + shape.Destroy() + + +# +# ====================================================================== +# Unit tests +# ====================================================================== +# +# To experiment this unit test, just execute this script in +# SALOME. The script is self-consistent. + +def TEST_createAndDeleteShape(): + """ + This test is a simple use case that illustrates how to create a + GEOM shape in a SALOME session (create the GEOM object, put in in + the study, and display the shape in a viewer) and delete a shape + from a SALOME session (erase the shape from the viewer, delete the + entry from the study, and finally destroy the underlying GEOM + object). + """ + import salome + salome.salome_init() + study = salome.myStudy + studyId = salome.myStudyId + + from salome.geom import geomtools + geompy = geomtools.getGeompy(studyId) + + # -------------------------------------------------- + # Create a first shape (GEOM object) + radius = 5 + length = 100 + cylinder = geompy.MakeCylinderRH(radius, length) + + # Register the shape in the study, at the root of the GEOM + # folder. A name must be specified. The register operation + # (addToStudy) returns an identifier of the entry in the study. + cylinderName = "cyl.r%s.l%s"%(radius,length) + cylinderStudyEntry = addToStudy(study, cylinder, cylinderName) + + # Display the registered shape in a viewer + displayShape(cylinderStudyEntry) + + # -------------------------------------------------- + # A second shape + radius = 10 + sphere = geompy.MakeSphereR(radius) + sphereName = "sph.r%s"%radius + sphereStudyEntry = addToStudy(study, sphere, sphereName) + displayShape(sphereStudyEntry) + + # -------------------------------------------------- + # This new shape is stored in the study, but in a specific + # sub-folder, and is displayed in the viewer with a specific + # color. + length = 20 + box = geompy.MakeBoxDXDYDZ(length,length,length) + boxName = "box.l%s"%length + folderName = "boxset" + boxStudyEntry = addToStudy(study, box, boxName, folderName) + displayShape(boxStudyEntry,PreviewColor) + + # -------------------------------------------------- + # In this example, we illustrate how to erase a shape (the sphere) + # from the viewer. After this operation, the sphere is no longer + # displayed but still exists in the study. You can then redisplay + # it using the context menu of the SALOME object browser. + eraseShape(sphereStudyEntry) + + # -------------------------------------------------- + # In this last example, we completly delete an object from the + # SALOME session (erase from viewer, remove from study and finnaly + # destroy the object). This is done by a simple call to + # deleteShape(). + deleteShape(study,cylinderStudyEntry) + + # -------------------------------------------------- + # At the end of the executioon of this test, you should have in + # the SALOME session: + # - the box, in a dedicated folder of the study, and displayed in the viewer + # - the sphere, in the standard place of the study, and not displayed + + # If you comment the deleteShape line, you should see the cylinder + # in the study and displayed in the viewer. + +if __name__=="__main__": + TEST_createAndDeleteShape() -- 2.39.2