From 6f30a39cf0e334b55338328e63c320413f332dba Mon Sep 17 00:00:00 2001 From: vsr Date: Thu, 9 Aug 2012 06:41:59 +0000 Subject: [PATCH] Merge from V6_main_20120808 08Aug12 --- doc/salome/tui/input/index.doc | 12 + src/GUI_PY/Makefile.am | 55 + src/GUI_PY/SelectVarsDialog.ui | 347 ++ src/GUI_PY/__init__.py | 21 + src/GUI_PY/genericdialog.py | 129 + src/GUI_PY/genericdialog.ui | 89 + src/GUI_PY/helper.py | 150 + src/GUI_PY/mytestdialog.py | 152 + src/GUI_PY/mytestdialog.ui | 69 + src/GUI_PY/selectvars.py | 153 + src/GuiHelpers/Makefile.am | 82 + src/GuiHelpers/QtHelper.hxx | 65 + src/GuiHelpers/SALOME_AppStudyEditor.cxx | 106 + src/GuiHelpers/SALOME_AppStudyEditor.hxx | 47 + src/GuiHelpers/SALOME_GuiServices.cxx | 134 + src/GuiHelpers/SALOME_GuiServices.hxx | 84 + src/GuiHelpers/StandardApp_Module.cxx | 338 ++ src/GuiHelpers/StandardApp_Module.hxx | 145 + src/LightApp/images/en.png | Bin 0 -> 599 bytes src/LightApp/images/fr.png | Bin 0 -> 545 bytes src/OpenGLUtils/Makefile.am | 39 + src/OpenGLUtils/OpenGLUtils.h | 37 + src/OpenGLUtils/OpenGLUtils_FrameBuffer.cxx | 202 ++ src/OpenGLUtils/OpenGLUtils_FrameBuffer.h | 52 + src/Qtx/resources/Qtx_msg_fr.ts | 336 ++ .../SALOME_PYQT_GUILight/Makefile.am | 103 + .../SALOME_PYQT_DataModelLight.cxx | 203 ++ .../SALOME_PYQT_DataModelLight.h | 67 + .../SALOME_PYQT_DataObjectLight.cxx | 177 + .../SALOME_PYQT_DataObjectLight.h | 69 + .../SALOME_PYQT_GUILight.h | 49 + .../SALOME_PYQT_GUILight.sip | 26 + .../SALOME_PYQT_ModuleLight.cxx | 3128 +++++++++++++++++ .../SALOME_PYQT_ModuleLight.h | 222 ++ .../SALOME_PYQT_PyInterp.cxx | 120 + .../SALOME_PYQT_PyInterp.h | 45 + src/SalomeApp/pluginsdemo/Makefile.am | 41 + src/SalomeApp/pluginsdemo/minmax.ui | 148 + src/SalomeApp/pluginsdemo/minmax_dialog.py | 73 + src/SalomeApp/pluginsdemo/minmax_plugin.py | 184 + src/SalomeApp/pluginsdemo/salome_plugins.py | 281 ++ src/SalomeApp/pluginsdemo/smesh_plugins.py | 33 + src/SalomeApp/pluginsdemo/trihedron.py | 41 + src/SalomeApp/pluginsdemo/tubebuilder.py | 143 + src/SalomeApp/pluginsdemo/tubedialog.py | 117 + src/SalomeApp/pluginsdemo/tubedialog_ui.py | 107 + src/SalomeApp/pluginsdemo/xalome.py | 229 ++ src/TreeData/DataModel.cxx | 57 + src/TreeData/DataModel.hxx | 64 + src/TreeData/DataObject.cxx | 73 + src/TreeData/DataObject.hxx | 68 + src/TreeData/DataProcessor.cxx | 86 + src/TreeData/DataProcessor.hxx | 68 + src/TreeData/DockWidgets.cxx | 106 + src/TreeData/DockWidgets.hxx | 51 + src/TreeData/Makefile.am | 107 + src/TreeData/Test/Makefile.am | 99 + src/TreeData/Test/MyDataModel.cxx | 67 + src/TreeData/Test/MyDataModel.hxx | 54 + src/TreeData/Test/data.txt | 15 + src/TreeData/Test/guitester.cxx | 221 ++ src/TreeData/Test/mainwindow.cxx | 188 + src/TreeData/Test/mainwindow.hxx | 54 + src/TreeData/Test/mainwindow.ui | 140 + src/TreeData/Test/tester.cxx | 79 + src/TreeData/Test/testhelper.cxx | 93 + src/TreeData/Test/testhelper.hxx | 33 + src/TreeData/TreeData.hxx | 36 + src/TreeData/TreeGuiManager.cxx | 153 + src/TreeData/TreeGuiManager.hxx | 64 + src/TreeData/TreeItem.cxx | 242 ++ src/TreeData/TreeItem.hxx | 82 + src/TreeData/TreeModel.cxx | 210 ++ src/TreeData/TreeModel.hxx | 105 + src/TreeData/TreeObserver.cxx | 54 + src/TreeData/TreeObserver.hxx | 44 + src/TreeData/TreeView.cxx | 144 + src/TreeData/TreeView.hxx | 62 + src/VTKViewer/textures/texture1.dat | 284 ++ src/VTKViewer/textures/texture2.dat | 284 ++ src/VTKViewer/textures/texture3.dat | 284 ++ src/VTKViewer/textures/texture4.dat | 284 ++ src/VTKViewer/textures/texture5.dat | 284 ++ src/VTKViewer/textures/texture6.dat | 284 ++ src/VTKViewer/textures/texture7.dat | 284 ++ src/VTKViewer/textures/texture8.dat | 284 ++ src/VTKViewer/textures/texture9.dat | 284 ++ src/ViewerTools/Makefile.am | 56 + src/ViewerTools/ViewerTools.h | 41 + .../ViewerTools_CubeAxesDlgBase.cxx | 322 ++ src/ViewerTools/ViewerTools_CubeAxesDlgBase.h | 119 + src/ViewerTools/ViewerTools_DialogBase.cxx | 79 + src/ViewerTools/ViewerTools_DialogBase.h | 54 + .../ViewerTools_FontWidgetBase.cxx | 128 + src/ViewerTools/ViewerTools_FontWidgetBase.h | 71 + .../resources/ViewerTools_msg_en.ts | 74 + .../resources/ViewerTools_msg_fr.ts | 74 + tools/Makefile.am | 23 + tools/dlgfactory/GenericDialog.cxx | 29 + tools/dlgfactory/GenericDialog.hxx | 27 + tools/dlgfactory/GenericDialog.ui | 89 + tools/dlgfactory/Makefile.am | 105 + tools/dlgfactory/README.txt | 12 + tools/dlgfactory/__GDIALOG__.cxx | 6 + tools/dlgfactory/__GDIALOG__.hxx | 20 + tools/dlgfactory/__GDIALOG__.ui | 99 + tools/dlgfactory/__QDIALOG__.cxx | 20 + tools/dlgfactory/__QDIALOG__.hxx | 23 + tools/dlgfactory/__QDIALOG__.ui | 67 + tools/dlgfactory/dlgfactory.py | 124 + tools/dlgfactory/dlgfactory.sh | 155 + tools/dlgfactory/gtester.cxx | 38 + tools/dlgfactory/qtester.cxx | 38 + tools/vtkEDFOverloads/Makefile.am | 40 + tools/vtkEDFOverloads/vtkEDFCutter.cxx | 526 +++ tools/vtkEDFOverloads/vtkEDFCutter.h | 62 + tools/vtkEDFOverloads/vtkEDFFactory.cxx | 47 + tools/vtkEDFOverloads/vtkEDFFactory.h | 43 + .../vtkEDFOverloads/vtkEDFOverloadsDefines.h | 41 + 119 files changed, 16577 insertions(+) create mode 100644 doc/salome/tui/input/index.doc create mode 100644 src/GUI_PY/Makefile.am create mode 100644 src/GUI_PY/SelectVarsDialog.ui create mode 100644 src/GUI_PY/__init__.py create mode 100644 src/GUI_PY/genericdialog.py create mode 100644 src/GUI_PY/genericdialog.ui create mode 100644 src/GUI_PY/helper.py create mode 100644 src/GUI_PY/mytestdialog.py create mode 100644 src/GUI_PY/mytestdialog.ui create mode 100644 src/GUI_PY/selectvars.py create mode 100644 src/GuiHelpers/Makefile.am create mode 100644 src/GuiHelpers/QtHelper.hxx create mode 100644 src/GuiHelpers/SALOME_AppStudyEditor.cxx create mode 100644 src/GuiHelpers/SALOME_AppStudyEditor.hxx create mode 100644 src/GuiHelpers/SALOME_GuiServices.cxx create mode 100644 src/GuiHelpers/SALOME_GuiServices.hxx create mode 100644 src/GuiHelpers/StandardApp_Module.cxx create mode 100644 src/GuiHelpers/StandardApp_Module.hxx create mode 100644 src/LightApp/images/en.png create mode 100644 src/LightApp/images/fr.png create mode 100755 src/OpenGLUtils/Makefile.am create mode 100755 src/OpenGLUtils/OpenGLUtils.h create mode 100755 src/OpenGLUtils/OpenGLUtils_FrameBuffer.cxx create mode 100755 src/OpenGLUtils/OpenGLUtils_FrameBuffer.h create mode 100644 src/Qtx/resources/Qtx_msg_fr.ts create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/Makefile.am create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.cxx create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.h create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.cxx create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.h create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.h create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.sip create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx create mode 100644 src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h create mode 100644 src/SalomeApp/pluginsdemo/Makefile.am create mode 100644 src/SalomeApp/pluginsdemo/minmax.ui create mode 100644 src/SalomeApp/pluginsdemo/minmax_dialog.py create mode 100644 src/SalomeApp/pluginsdemo/minmax_plugin.py create mode 100755 src/SalomeApp/pluginsdemo/salome_plugins.py create mode 100644 src/SalomeApp/pluginsdemo/smesh_plugins.py create mode 100644 src/SalomeApp/pluginsdemo/trihedron.py create mode 100644 src/SalomeApp/pluginsdemo/tubebuilder.py create mode 100644 src/SalomeApp/pluginsdemo/tubedialog.py create mode 100644 src/SalomeApp/pluginsdemo/tubedialog_ui.py create mode 100644 src/SalomeApp/pluginsdemo/xalome.py create mode 100644 src/TreeData/DataModel.cxx create mode 100644 src/TreeData/DataModel.hxx create mode 100644 src/TreeData/DataObject.cxx create mode 100644 src/TreeData/DataObject.hxx create mode 100644 src/TreeData/DataProcessor.cxx create mode 100644 src/TreeData/DataProcessor.hxx create mode 100644 src/TreeData/DockWidgets.cxx create mode 100644 src/TreeData/DockWidgets.hxx create mode 100644 src/TreeData/Makefile.am create mode 100644 src/TreeData/Test/Makefile.am create mode 100644 src/TreeData/Test/MyDataModel.cxx create mode 100644 src/TreeData/Test/MyDataModel.hxx create mode 100755 src/TreeData/Test/data.txt create mode 100644 src/TreeData/Test/guitester.cxx create mode 100644 src/TreeData/Test/mainwindow.cxx create mode 100644 src/TreeData/Test/mainwindow.hxx create mode 100644 src/TreeData/Test/mainwindow.ui create mode 100644 src/TreeData/Test/tester.cxx create mode 100644 src/TreeData/Test/testhelper.cxx create mode 100644 src/TreeData/Test/testhelper.hxx create mode 100755 src/TreeData/TreeData.hxx create mode 100644 src/TreeData/TreeGuiManager.cxx create mode 100644 src/TreeData/TreeGuiManager.hxx create mode 100644 src/TreeData/TreeItem.cxx create mode 100644 src/TreeData/TreeItem.hxx create mode 100644 src/TreeData/TreeModel.cxx create mode 100644 src/TreeData/TreeModel.hxx create mode 100644 src/TreeData/TreeObserver.cxx create mode 100644 src/TreeData/TreeObserver.hxx create mode 100644 src/TreeData/TreeView.cxx create mode 100644 src/TreeData/TreeView.hxx create mode 100644 src/VTKViewer/textures/texture1.dat create mode 100644 src/VTKViewer/textures/texture2.dat create mode 100644 src/VTKViewer/textures/texture3.dat create mode 100644 src/VTKViewer/textures/texture4.dat create mode 100644 src/VTKViewer/textures/texture5.dat create mode 100644 src/VTKViewer/textures/texture6.dat create mode 100644 src/VTKViewer/textures/texture7.dat create mode 100644 src/VTKViewer/textures/texture8.dat create mode 100644 src/VTKViewer/textures/texture9.dat create mode 100755 src/ViewerTools/Makefile.am create mode 100644 src/ViewerTools/ViewerTools.h create mode 100644 src/ViewerTools/ViewerTools_CubeAxesDlgBase.cxx create mode 100644 src/ViewerTools/ViewerTools_CubeAxesDlgBase.h create mode 100644 src/ViewerTools/ViewerTools_DialogBase.cxx create mode 100644 src/ViewerTools/ViewerTools_DialogBase.h create mode 100644 src/ViewerTools/ViewerTools_FontWidgetBase.cxx create mode 100644 src/ViewerTools/ViewerTools_FontWidgetBase.h create mode 100644 src/ViewerTools/resources/ViewerTools_msg_en.ts create mode 100755 src/ViewerTools/resources/ViewerTools_msg_fr.ts create mode 100644 tools/Makefile.am create mode 100644 tools/dlgfactory/GenericDialog.cxx create mode 100644 tools/dlgfactory/GenericDialog.hxx create mode 100644 tools/dlgfactory/GenericDialog.ui create mode 100644 tools/dlgfactory/Makefile.am create mode 100644 tools/dlgfactory/README.txt create mode 100644 tools/dlgfactory/__GDIALOG__.cxx create mode 100644 tools/dlgfactory/__GDIALOG__.hxx create mode 100644 tools/dlgfactory/__GDIALOG__.ui create mode 100644 tools/dlgfactory/__QDIALOG__.cxx create mode 100644 tools/dlgfactory/__QDIALOG__.hxx create mode 100644 tools/dlgfactory/__QDIALOG__.ui create mode 100755 tools/dlgfactory/dlgfactory.py create mode 100755 tools/dlgfactory/dlgfactory.sh create mode 100644 tools/dlgfactory/gtester.cxx create mode 100644 tools/dlgfactory/qtester.cxx create mode 100755 tools/vtkEDFOverloads/Makefile.am create mode 100755 tools/vtkEDFOverloads/vtkEDFCutter.cxx create mode 100755 tools/vtkEDFOverloads/vtkEDFCutter.h create mode 100755 tools/vtkEDFOverloads/vtkEDFFactory.cxx create mode 100755 tools/vtkEDFOverloads/vtkEDFFactory.h create mode 100755 tools/vtkEDFOverloads/vtkEDFOverloadsDefines.h diff --git a/doc/salome/tui/input/index.doc b/doc/salome/tui/input/index.doc new file mode 100644 index 000000000..678dda879 --- /dev/null +++ b/doc/salome/tui/input/index.doc @@ -0,0 +1,12 @@ +/*! \mainpage + +\image html guiscreen.png + +To browse the \b SALOME GUI module Developer Documentation, follow the links below or use navigation menu at the top of the page: + + +*/ \ No newline at end of file diff --git a/src/GUI_PY/Makefile.am b/src/GUI_PY/Makefile.am new file mode 100644 index 000000000..782e15a70 --- /dev/null +++ b/src/GUI_PY/Makefile.am @@ -0,0 +1,55 @@ +# Copyright (C) 2007-2012 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 +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +mypkgpythondir = $(salomepythondir)/salome/gui + +# Python modules to be installed +mypkgpython_PYTHON = \ + __init__.py \ + selectvars.py \ + genericdialog.py \ + mytestdialog.py \ + helper.py + +PYUIC_FILES = \ + SelectVarsDialog_ui.py \ + genericdialog_ui.py \ + mytestdialog_ui.py + +nodist_mypkgpython_PYTHON = $(PYUIC_FILES) +CLEANFILES = $(PYUIC_FILES) + +EXTRA_DIST += \ + SelectVarsDialog.ui \ + genericdialog.ui \ + mytestdialog.ui + +# This rule indicates that some python files are generated from ui +# files using the PYUIC utility. The convention is to create a file +# name _ui.py when the ui file name is .ui. When +# implementing the dialog, you generally create a third file named +# .py that uses the UI_ classe defined in the +# generated file _ui.py. +%_ui.py:%.ui + $(PYUIC) -x $< -o $@ diff --git a/src/GUI_PY/SelectVarsDialog.ui b/src/GUI_PY/SelectVarsDialog.ui new file mode 100644 index 000000000..3dd933421 --- /dev/null +++ b/src/GUI_PY/SelectVarsDialog.ui @@ -0,0 +1,347 @@ + + + SelectVarsDialog + + + + 0 + 0 + 611 + 743 + + + + Select Variables of Interest + + + + + + + + Potential Variables List + + + Qt::AlignCenter + + + + + + + Selected Variables List + + + Qt::AlignCenter + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Import... + + + + + + + Export... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + All Input Variables + + + Qt::AlignCenter + + + + + + + Selected Input Variables + + + Qt::AlignCenter + + + + + + + QAbstractItemView::MultiSelection + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Add + + + + + + + Remove + + + + + + + New... + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QAbstractItemView::MultiSelection + + + + + + + All Output Variables + + + Qt::AlignCenter + + + + + + + Selected Output Variables + + + Qt::AlignCenter + + + + + + + QAbstractItemView::MultiSelection + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Add + + + + + + + Remove + + + + + + + New... + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + QAbstractItemView::MultiSelection + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + + + + + Select + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + OK + + + + + + + Cancel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + diff --git a/src/GUI_PY/__init__.py b/src/GUI_PY/__init__.py new file mode 100644 index 000000000..24ceaf589 --- /dev/null +++ b/src/GUI_PY/__init__.py @@ -0,0 +1,21 @@ +# Copyright (C) 2007-2012 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 +# diff --git a/src/GUI_PY/genericdialog.py b/src/GUI_PY/genericdialog.py new file mode 100644 index 000000000..6d13c9227 --- /dev/null +++ b/src/GUI_PY/genericdialog.py @@ -0,0 +1,129 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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__="gboulant" +__date__ ="$31 mars 2010 17:09:53$" + +from PyQt4.QtGui import QDialog, QMessageBox + +from genericdialog_ui import Ui_GenericDialog + +class GenericDialog(QDialog): + """ + This is an abstract generic dialog box for implementing default and + generic behaviour of dialog windows. + Note that this class can be instantiated but can't be used because the + OK behaviour is a default one indicating that the checkData function should + be implemented in a derived class. The general interface that should be + implemented in derived class is the MVC pattern: + + - setData(): + to initiate the values of the dialog windows from a given data model. + + - boolean checkData(): + to verify that the data are valid and notify user if not. + + - getData(): + to get the valid data model from values read in the dialog window. + """ + + __wasOk = False + checkDataMessage = "" + + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + QDialog.__init__(self,parent) + # Set up the user interface from Designer. + self.__ui = Ui_GenericDialog() + self.__ui.setupUi(self) + + def getPanel(self): + ''' + This returns the central panel where to draw the custom dialog + widgets. + ''' + return self.__ui.myCenterPanel + + def getButtonBox(self): + return self.__ui.buttonBox + + def accept(self): + """ + Slot function connected to the button OK + """ + if not self.checkData(): + QMessageBox.warning( self, "Alerte", self.checkDataMessage) + return + self.__wasOk = True + self.hide() + + def displayAndWait(self): + """ + This function can be used to display the dialog in the case + where the dialog is modal and does not need interactivity with + parent windows and other part of the application. When called, + the dialog is raised visible and keep waiting until the button + OK or the button CANCEL is pressed. Then the flow can go on + (see an example of implementation in the tests functions at + the end of this file). + In the general case, in particular if you need interaction + with the graphical framework (clic on widgets embedded in + other dialogs), you should used instead the show() command + (for a non modal dialog) or the open() command (for a window + modal dialog, i.e. a dialog that can not interact with its + direct parent but can interact with the other parts). + """ + self.__wasOk = False + self.exec_() + + def wasOk(self): + """ + Return True if the button OK was pressed to close the dialog windows. + """ + return self.__wasOk + + def checkData(self): + """ + This function should be implemented in a derived class. It should return + True in the case where the data are estimated to be valid data. + """ + self.checkDataMessage = "The checkData() function is not implemented yet" + return True + +# +# ============================================================================== +# Basic use cases and unit test functions +# ============================================================================== +# +def TEST_GenericDialog(): + import sys + from PyQt4.QtGui import QApplication + from PyQt4.QtCore import QObject, SIGNAL, SLOT + app = QApplication(sys.argv) + QObject.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) + + dlg=GenericDialog() + dlg.displayAndWait() + if dlg.wasOk(): + print "OK has been pressed" + else: + print "Cancel has been pressed" + +if __name__ == "__main__": + TEST_GenericDialog() diff --git a/src/GUI_PY/genericdialog.ui b/src/GUI_PY/genericdialog.ui new file mode 100644 index 000000000..3b151e58a --- /dev/null +++ b/src/GUI_PY/genericdialog.ui @@ -0,0 +1,89 @@ + + GenericDialog + + + + 0 + 0 + 498 + 352 + + + + Dialog + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + GenericDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + GenericDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/GUI_PY/helper.py b/src/GUI_PY/helper.py new file mode 100644 index 000000000..f294c0b94 --- /dev/null +++ b/src/GUI_PY/helper.py @@ -0,0 +1,150 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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: Guillaume Boulant (EDF/R&D) + +# ================================================================== +# This file provides helper functions to drive some gui features of a +# SALOME Application (the selection in the object browser for now, +# further development coming soon). Note that some of these helper +# functions are specialized for a GEOM or SMESH context (see the +# guihelper.py modules comming with the packages salome.geom and +# salome.smesh. +# ================================================================== + +# +# ================================================================== +# Definition of usefull objects and functions to deal with the SALOME +# technical context. +# ================================================================== +# + +from salome.kernel import services + +# +# Get SALOME PyQt interface to manipulate the GUI context +# (Get the active study for example. Note that the active study is a +# GUI concept only: it is the study that is currently active in the +# desktop) +# +import SalomePyQt +sgPyQt=SalomePyQt.SalomePyQt() + +# +# Get SALOME Swig interface to manipulate the GUI widget +# +import libSALOME_Swig +SalomeGUI = libSALOME_Swig.SALOMEGUI_Swig() + +# +# ================================================================== +# General helper function for GUI programming actions +# ================================================================== +# +# Get the active study +# +def getActiveStudy(): + """ + This returns a study object that corresponds to the active + study. The active study is a GUI concept: it's the study currently + active on the desktop. + """ + studyId = sgPyQt.getStudyId() + study = services.getStudyManager().GetStudyByID( studyId ) + return study + +# +# ================================================================== +# Functions to manipulate the objects in the browser (generic) +# ================================================================== +# +def getSObjectSelected(): + ''' + Returns the sobject and the entry of the item currently selected + in the objects browser. Returns "None, None" if no item is + selected. If several objects are selected, it returns the first + one of the list. + ''' + sobj = None + entry = None + study = getActiveStudy() + if SalomeGUI.SelectedCount() == 1: + # We only considere the first element of the list. If you need + # something else, create another function in your own context. + entry = SalomeGUI.getSelected( 0 ) + if entry != '': + sobj = study.FindObjectID( entry ) + return sobj, entry + +def showSObjectSelected(): + ''' + This function print the attributes of the selected object. + (this function is only for test purpose) + ''' + sobj, entry = getSObjectSelected() + if ( sobj ): + test, attr = sobj.FindAttribute( "AttributeName" ) + if test: + message = "My name is '%s'" % attr.Value() + print message + pass + +def deleteSObjectSelected(): + ''' + This function deletes the selected object. + ''' + sobj, entry = getSObjectSelected() + if ( sobj ): + study = getActiveStudy() + builder = study.NewBuilder() + builder.RemoveObject( sobj ) + SalomeGUI.updateObjBrowser(True) + pass + +# +# ================================================================== +# Use cases and demo functions +# ================================================================== +# + +# CAUTION: Before running this test functions, you first have to +# create (or import) an object and select this object in the objects +# browser. + +# +# Definitions: +# - the SObject is an item in the active study (Study Object). +# - the entry is the identifier of an item. +# - the object (geom object or smesh object) is a CORBA servant +# embedded in the SALOME component container and with a reference in +# the SALOME study, so that it can be retrieved. +# + +def TEST_getSObjectSelected(): + mySObject, myEntry = getSObjectSelected() + myName = mySObject.GetName() + print "The name of the selected object is %s"%myName + +def TEST_showSObjectSelected(): + showSObjectSelected() + +if __name__ == "__main__": + TEST_getSObjectSelected() + TEST_showSObjectSelected() diff --git a/src/GUI_PY/mytestdialog.py b/src/GUI_PY/mytestdialog.py new file mode 100644 index 000000000..82898c5ed --- /dev/null +++ b/src/GUI_PY/mytestdialog.py @@ -0,0 +1,152 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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__="gboulant" +__date__ ="$31 mars 2010 17:09:53$" + +from mytestdialog_ui import Ui_MyTestDialog +from genericdialog import GenericDialog + +class MyTestDialog(GenericDialog): + """ + This class is to illustrate the usage of the GenericDialog to implement + the dialog windows of the application with a common design template provided + by the generic class GenericDialog. + """ + def __init__(self, parent=None, name="MyTestDialog"): + GenericDialog.__init__(self, parent, name) + # Set up the user interface from Designer. + self.ui = Ui_MyTestDialog() + # BE CAREFULL HERE, the ui form is NOT put in the global dialog (already + # containing some generic widgets) but in the center panel created in the + # GenericDialog as a void container for the form. The MyTestDialog form + # is supposed here to create only the widgets to be placed in the center + # panel + self.ui.setupUi(self.getPanel()) + + # + # We implement here the interface of the MVC pattern + # + def setData(self, name): + """ + This function implements the mapping from the data model to the widgets + """ + self.ui.txtName.setText(name) + + def checkData(self): + """ + This function implements the control to be done on the values contained + in the widgets when trying to validate the dialog window (click OK first + trigs this function). + """ + if ( self.ui.txtName.text().trimmed() == "" ): + self.checkDataMessage = "The name can't be void" + return False + return True + + def getData(self): + """ + This function implements the mapping from the widgets to the data model + """ + name = str(self.ui.txtName.text().trimmed().toUtf8()) + # _MEM_: note here that (i) the utf8 format is used and (ii) we must not + # forget to convert to a standard python string (instead of a QString). + return name + + +from PyQt4.QtCore import SIGNAL +class MyTestDialogWithSignals(MyTestDialog): + """ + This class is to illustrate the usage of the GenericDialog in the + case where the dialog windows is not modal. In such a case, the + controller must be warn of close events using Qt signals. + """ + def __init__(self, parent=None, name="MyTestDialogWithSignals"): + MyTestDialog.__init__(self, parent, name) + + def accept(self): + """ + This function is the slot connected to the the OK button + (click event of the OK button). + """ + # The dialog is raised in a non modal mode (for example, to + # get interactivity with the parents windows. Then we have to + # emit a signal to warn the parent observer that the dialog + # has been validated so that it can process the event + MyTestDialog.accept(self) + if self.wasOk(): + self.emit(SIGNAL('inputValidated()')) + + + +# +# ============================================================================== +# Basic use case +# ============================================================================== +# + +def TEST_MyTestDialog_modal(): + import sys + from PyQt4.QtCore import QObject, SIGNAL, SLOT + from PyQt4.QtGui import QApplication + app = QApplication(sys.argv) + QObject.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) + + dlg=MyTestDialog() + dlg.setData("A default name") + dlg.displayAndWait() + if dlg.wasOk(): + name = dlg.getData() + print "The name has been modified to",name + + +class DialogListener: + def onProcessEvent(self): + print "onProcessEvent(): OK has been pressed" + import sys + sys.exit(0) + + +def TEST_MyTestDialog_non_modal(): + import sys + from PyQt4.QtCore import QObject, SIGNAL, SLOT + from PyQt4.QtGui import QApplication + app = QApplication(sys.argv) + QObject.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()")) + + dlg=MyTestDialogWithSignals() + # This dialog window will emit a inputValidated() signal when the + # OK button is pressed and the data are validated. Then, we + # connect this signal to a local slot so that the event can be + # processed. + dlgListener = DialogListener() + app.connect(dlg, SIGNAL('inputValidated()'), dlgListener.onProcessEvent) + # This connect instruction means that the signal inputValidated() + # emited by the dlg Qt object will raise a call to the slot + # dlgListener.onProcessEvent + + dlg.setData("A default name") + dlg.show() + + app.exec_() + +if __name__ == "__main__": + #TEST_MyTestDialog_modal() + TEST_MyTestDialog_non_modal() diff --git a/src/GUI_PY/mytestdialog.ui b/src/GUI_PY/mytestdialog.ui new file mode 100644 index 000000000..ca89393fb --- /dev/null +++ b/src/GUI_PY/mytestdialog.ui @@ -0,0 +1,69 @@ + + MyTestDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + TextLabel + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + diff --git a/src/GUI_PY/selectvars.py b/src/GUI_PY/selectvars.py new file mode 100644 index 000000000..40456c65e --- /dev/null +++ b/src/GUI_PY/selectvars.py @@ -0,0 +1,153 @@ +# Copyright (C) 2007-2012 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 +# + +import os +from PyQt4 import QtGui, QtCore +from PyQt4.QtCore import Qt + +import salome +from salome.kernel.studyedit import getStudyEditor +from salome.kernel.parametric import study_exchange_vars + +# ---------------------------------- # +# Dialog box for variables selection # +# ---------------------------------- # + +from SelectVarsDialog_ui import Ui_SelectVarsDialog + +class MySelectVarsDialog(Ui_SelectVarsDialog, QtGui.QDialog): + + def __init__(self, parent = None, modal = 0): + QtGui.QDialog.__init__(self, parent) + Ui_SelectVarsDialog.__init__(self) + self.setupUi(self) + self.connect(self.cancelButton, QtCore.SIGNAL("clicked()"), self.close) + self.connect(self.OKButton, QtCore.SIGNAL("clicked()"), self.accept) + self.connect(self.selectButton, QtCore.SIGNAL("clicked()"), self.initPotentialVariablesFromSelection) + self.connect(self.addInputVarButton, QtCore.SIGNAL("clicked()"), self.addSelectedInputVar) + self.connect(self.removeInputVarButton, QtCore.SIGNAL("clicked()"), self.removeSelectedInputVar) + self.connect(self.newInputVarButton, QtCore.SIGNAL("clicked()"), self.newInputVar) + self.connect(self.addOutputVarButton, QtCore.SIGNAL("clicked()"), self.addSelectedOutputVar) + self.connect(self.removeOutputVarButton, QtCore.SIGNAL("clicked()"), self.removeSelectedOutputVar) + self.connect(self.newOutputVarButton, QtCore.SIGNAL("clicked()"), self.newOutputVar) + self.connect(self.loadVarsButton, QtCore.SIGNAL("clicked()"), self.loadVars) + self.connect(self.saveVarsButton, QtCore.SIGNAL("clicked()"), self.saveVars) + self.refEntry = None + + def setExchangeVariables(self, exchangeVariables): + if exchangeVariables.refEntry is not None: + self._initPotentialVariables(exchangeVariables.refEntry) + self.selectedInputVarListWidget.addItems([x.name for x in exchangeVariables.inputVarList]) + self.selectedOutputVarListWidget.addItems([x.name for x in exchangeVariables.outputVarList]) + + def initPotentialVariablesFromSelection(self): + entries = salome.sg.getAllSelected() + if len(entries) != 1 : + QtGui.QMessageBox.warning(self, self.tr("Error"), + self.tr("One item must be selected in the object browser")) + return + selectedEntry = entries[0] + self._initPotentialVariables(selectedEntry) + + def _initPotentialVariables(self, entry): + sobj = getStudyEditor().study.FindObjectID(entry) + if sobj is None: + QtGui.QMessageBox.warning(self, self.tr("Error"), + self.tr('No item at entry %s' % entry)) + return + exchangeVariables = study_exchange_vars.getExchangeVariablesFromSObject(sobj) + if exchangeVariables is None: + QtGui.QMessageBox.warning(self, self.tr("Error"), + self.tr('Item at entry %s is not a valid ' + '"Variable List" object' % entry)) + return + self.refEntry = entry + self.varListObjLineEdit.setText(sobj.GetName()) + self.allInputVarListWidget.clear() + self.allOutputVarListWidget.clear() + self.allInputVarListWidget.addItems([x.name for x in exchangeVariables.inputVarList]) + self.allOutputVarListWidget.addItems([x.name for x in exchangeVariables.outputVarList]) + + def addSelectedInputVar(self): + for item in self.allInputVarListWidget.selectedItems(): + self.selectedInputVarListWidget.addItem(QtGui.QListWidgetItem(item)) + + def removeSelectedInputVar(self): + for item in self.selectedInputVarListWidget.selectedItems(): + self.selectedInputVarListWidget.takeItem(self.selectedInputVarListWidget.row(item)) + + def newInputVar(self): + newItem = QtGui.QListWidgetItem("TO EDIT!") + newItem.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEditable|Qt.ItemIsUserCheckable|Qt.ItemIsEnabled) + self.selectedInputVarListWidget.addItem(newItem); + + def addSelectedOutputVar(self): + for item in self.allOutputVarListWidget.selectedItems(): + self.selectedOutputVarListWidget.addItem(QtGui.QListWidgetItem(item)) + + def removeSelectedOutputVar(self): + for item in self.selectedOutputVarListWidget.selectedItems(): + self.selectedOutputVarListWidget.takeItem(self.selectedOutputVarListWidget.row(item)) + + def newOutputVar(self): + newItem = QtGui.QListWidgetItem("TO EDIT!") + newItem.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEditable|Qt.ItemIsUserCheckable|Qt.ItemIsEnabled) + self.selectedOutputVarListWidget.addItem(newItem); + + def getSelectedExchangeVariables(self): + inputVarList = [] + outputVarList = [] + for row in range(self.selectedInputVarListWidget.count()): + name = str(self.selectedInputVarListWidget.item(row).text()) + inputVarList.append(study_exchange_vars.Variable(name)) + for row in range(self.selectedOutputVarListWidget.count()): + name = str(self.selectedOutputVarListWidget.item(row).text()) + outputVarList.append(study_exchange_vars.Variable(name)) + return study_exchange_vars.ExchangeVariables(inputVarList, outputVarList, self.refEntry) + + def loadVars(self): + filename = QtGui.QFileDialog.getOpenFileName(self, self.tr("Import variables from file"), + os.getenv("HOME"), + self.tr("XML Files (*.xml)")) + if not filename: + return + try: + filename = str(filename) + exchange_variables = study_exchange_vars.loadExchangeVariablesFromXmlFile(filename) + self.setExchangeVariables(exchange_variables) + except Exception, e: + QtGui.QMessageBox.critical(self, self.tr("Error"), + self.tr("Cannot load file %s:\n%s" % (filename, e))) + + def saveVars(self): + default = os.path.join(os.getenv("HOME"), "vars.xml") + filename = QtGui.QFileDialog.getSaveFileName(self, self.tr("Export variables to file"), + default, self.tr("XML Files (*.xml)")) + if not filename: + return + try: + filename = str(filename) + exchange_variables = self.getSelectedExchangeVariables() + exchange_variables.saveToXmlFile(filename) + except Exception, e: + QtGui.QMessageBox.critical(self, self.tr("Error"), + self.tr("Cannot save file %s:\n%s" % (filename, e))) diff --git a/src/GuiHelpers/Makefile.am b/src/GuiHelpers/Makefile.am new file mode 100644 index 000000000..dc45c3c80 --- /dev/null +++ b/src/GuiHelpers/Makefile.am @@ -0,0 +1,82 @@ +# Copyright (C) 2011-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF/R&D) +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# header files +salomeinclude_HEADERS = \ + QtHelper.hxx \ + SALOME_GuiServices.hxx \ + SALOME_AppStudyEditor.hxx \ + StandardApp_Module.hxx + +# Libraries targets +lib_LTLIBRARIES = libSalomeGuiHelpers.la + +dist_libSalomeGuiHelpers_la_SOURCES = \ + SALOME_GuiServices.cxx \ + SALOME_AppStudyEditor.cxx \ + StandardApp_Module.cxx + + +QT_CXXFLAGS=@QT_INCLUDES@ @QT_MT_INCLUDES@ +CAS_CXXFLAGS=@CAS_CPPFLAGS@ @CAS_CXXFLAGS@ +BOOST_CPPFLAGS=@BOOST_CPPFLAGS@ +BOOST_LIBS=@BOOST_LIBS@ +CORBA_CXXFLAGS=@OMNIORB_CXXFLAGS@ @OMNIORB_INCLUDES@ +CORBA_LIBS=@OMNIORB_LIBS@ + +libSalomeGuiHelpers_la_CPPFLAGS = \ + $(QT_CXXFLAGS) \ + $(CAS_CXXFLAGS) \ + $(BOOST_CPPFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(KERNEL_CXXFLAGS) \ + -I$(srcdir)/../SalomeApp \ + -I$(srcdir)/../LightApp \ + -I$(srcdir)/../SUIT \ + -I$(srcdir)/../Qtx \ + -I$(srcdir)/../CAM \ + -I$(srcdir)/../STD \ + -I$(srcdir)/../OBJECT + + +libSalomeGuiHelpers_la_LDFLAGS = \ + ../SalomeApp/libSalomeApp.la \ + $(KERNEL_LDFLAGS) -lSalomeKernelHelpers \ + $(CORBA_LIBS) + +# +# ======================================================= +# Specific definitions for Qt MOC files +# + +# moc-files generation +%_moc.cxx: %.hxx + $(MOC) $< -o $@ + +# MOC pre-processing +MOC_FILES_HXX = \ + StandardApp_Module_moc.cxx + +nodist_libSalomeGuiHelpers_la_SOURCES = $(MOC_FILES_HXX) + +EXTRA_DIST+=$(MOC_FILES_HXX:%_moc.cxx=%.hxx) diff --git a/src/GuiHelpers/QtHelper.hxx b/src/GuiHelpers/QtHelper.hxx new file mode 100644 index 000000000..de40c7a10 --- /dev/null +++ b/src/GuiHelpers/QtHelper.hxx @@ -0,0 +1,65 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +#ifndef _QT_HELPER_HXX_ +#define _QT_HELPER_HXX_ + +// +// ============================================================= +// Macro and template functions for type conversions. +// ============================================================= +// +#include "Basics_Utils.hxx" // To get ToString macro +#include + +// This can be used to convert QString into char *. +#define QCHARSTAR(qstring) qstring.toLatin1().data() +// This converts a string into a QString +#define S2QS(string) QString(string.c_str()) +// This converts a QString into a string +#define QS2S(qstring) ToString(QCHARSTAR(qstring)) +#define QSTRING(any) S2QS(ToString(any)) + +// +// ============================================================= +// General helper macros for manipulating widgets values +// ============================================================= +// +#define GETTEXT(widget) ToString(QCHARSTAR(widget->text().trimmed())) +#define SETTEXT(widget,str) widget->setText(str.c_str()) + +// +// ============================================================= +// Qt Logger macros +// ============================================================= +// + +// We can use the macros defined by SALOMELocalTrace/utilities.h +// as proposed in the file KERNEL_helper.hxx. But we can use instead +// the Qt debug function: +#include +#define QDEBUG qWarning() +//#define QDEBUG qDebug() +#define QLOG(data) QDEBUG << "[XSALOME] " << data +#ifdef LOG +#undef LOG +#endif +#define LOG QLOG + +#endif // __QT_HELPER_H_ diff --git a/src/GuiHelpers/SALOME_AppStudyEditor.cxx b/src/GuiHelpers/SALOME_AppStudyEditor.cxx new file mode 100644 index 000000000..f2e9bb4a8 --- /dev/null +++ b/src/GuiHelpers/SALOME_AppStudyEditor.cxx @@ -0,0 +1,106 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#include "SALOME_AppStudyEditor.hxx" + +#include +#include +#include +#include + +SALOME_AppStudyEditor::SALOME_AppStudyEditor(SalomeApp_Application * salomeApp) + : SALOME_StudyEditor() +{ + _salomeApp = salomeApp; + updateActiveStudy(); +} + +/** + * This updates the editor with the current active study. If the + * active study id is identical to the study id currently associated + * to this object, then no update is performed. + */ +int SALOME_AppStudyEditor::updateActiveStudy() { + int activeStudyId = SALOME_AppStudyEditor::getActiveStudyId(_salomeApp); + if ( activeStudyId != this->getStudyId() ) { + this->setStudyById(activeStudyId); + } + return activeStudyId; +} + +// GUI context only +int SALOME_AppStudyEditor::getActiveStudyId(SalomeApp_Application * salomeApp) { + SalomeApp_Study* appStudy = dynamic_cast (salomeApp->activeStudy()); + _PTR(Study) aCStudy = appStudy->studyDS(); + int studyId = aCStudy->StudyId(); + return studyId; +} + +SALOMEDS::SObject_ptr SALOME_AppStudyEditor::IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject) { + if (!iobject.IsNull()) { + if (iobject->hasEntry()) { + SALOMEDS::SObject_var sobject = _study->FindObjectID(iobject->getEntry()); + return sobject._retn(); + } + } + return SALOMEDS::SObject::_nil(); +} + +/** + * This function creates a list of all the "study objects" (SObject) + * that map with the selection in the object browser (the "interactive + * objects", IObjects). Please note that the objects belongs to the + * active study. + */ +SALOME_StudyEditor::SObjectList * SALOME_AppStudyEditor::getSelectedObjects() { + + // _GBO_: please note that the use of this function can be + // underoptimal in the case where the number of selected objects is + // high, because we create a vector list of SObjects while the list + // of IObject can be processed directly. In the case where a high + // number of objects is selected (~1000), it's certainly better to + // use directly the SALOME_ListIO and iterators on it. + + LightApp_SelectionMgr* aSelectionMgr = _salomeApp->selectionMgr(); + SALOME_ListIO selectedIObjects; + aSelectionMgr->selectedObjects(selectedIObjects); + /* + * This returns a list containing the selected objects of the objects + * browser. Please note that the objects of the browser ARE NOT the + * objects of the study. What is returned by this function is a list + * of "interactive objects" (IObject) which are objects of the + * graphical context. Each of this IObject is characterized by an + * entry string that corresponds to the entry string of an associated + * "study object" (SObject) in the active study. The mapping can be + * done using the function IObjectToSObject. + */ + + SObjectList * listOfSObject = new SObjectList(); + SALOME_ListIteratorOfListIO It (selectedIObjects); + for (; It.More(); It.Next()) { + SALOMEDS::SObject_ptr sobject = this->IObjectToSObject(It.Value()); + if (!sobject->_is_nil()) { + listOfSObject->push_back(sobject); + } + } + + return listOfSObject; +} diff --git a/src/GuiHelpers/SALOME_AppStudyEditor.hxx b/src/GuiHelpers/SALOME_AppStudyEditor.hxx new file mode 100644 index 000000000..5eb0c0eee --- /dev/null +++ b/src/GuiHelpers/SALOME_AppStudyEditor.hxx @@ -0,0 +1,47 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#ifndef __APP_STUDY_EDITOR_HXX__ +#define __APP_STUDY_EDITOR_HXX__ + +#include +#include CORBA_CLIENT_HEADER(SALOMEDS) +#include +#include + +#include "SALOME_StudyEditor.hxx" + +class SALOME_AppStudyEditor: public SALOME_StudyEditor { +public: + SALOME_AppStudyEditor(SalomeApp_Application * salomeApp); + int updateActiveStudy(); + + SALOMEDS::SObject_ptr IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject); + SALOME_StudyEditor::SObjectList * getSelectedObjects(); + + static int getActiveStudyId(SalomeApp_Application * salomeApp); + +private: + SalomeApp_Application * _salomeApp; + +}; + +#endif // __APP_STUDY_EDITOR_HXX__ diff --git a/src/GuiHelpers/SALOME_GuiServices.cxx b/src/GuiHelpers/SALOME_GuiServices.cxx new file mode 100644 index 000000000..fcb5b988a --- /dev/null +++ b/src/GuiHelpers/SALOME_GuiServices.cxx @@ -0,0 +1,134 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#include "SALOME_GuiServices.hxx" +#include + +namespace GUI { + /*! + * Get the SALOME application, i.e. the main GUI framework of + * SALOME. This function returns a pointer to the singleton instance + * of the SalomeApp_Application. + * + * The SALOME application can be used to get reference to + * the SALOME KERNEL services such that the naming service, the + * lifeCycleCORBA, ... Theses services can be retrieved using static + * functions (not required to get the singleton instance): + * + * SALOME_NamingService *aNamingService = SalomeApp_Application::namingService(); + * + * Please note that this usage can be done only from within the + * SALOME session server process, i.e. the process that embed the + * SALOME application. + */ + SalomeApp_Application * getSalomeApplication() { + static SalomeApp_Application * app; + if ( app == NULL ) { + app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() ); + } + return app; + } + + /*! + * Get the selection manager of the SALOME application. The + * selection manager can be used to get the selected items in the + * objects browser that is a GUI display of the active study. + * The function returns a pointer to the selectionMgr attribute of + * the SalomeApp_Application singleton instance. + */ + LightApp_SelectionMgr * getSelectionManager() { + SalomeApp_Application* anApp = GUI::getSalomeApplication(); + if ( anApp == NULL ) return NULL; + return dynamic_cast( anApp->selectionMgr() ); + } + + + SUIT_ResourceMgr * getResourcesManager() { + return SUIT_Session::session()->resourceMgr(); + } + // Note that the resource manager can be also retrieved from the + // SALOME application using the resourceMgr() method: + // + + /** + * This returns the current active study id if an active study is + * defined in the SALOME session, returns -1 otherwise. Note that + * the active study doesn't make sense outside of the GUI SALOME + * process, i.e. the SALOME_SessionServer embedding the + * SalomeApp_Application. + */ + int getActiveStudyId() { + SALOME::Session_var aSession = KERNEL::getSalomeSession(); + if ( CORBA::is_nil(aSession) ) { + INFOS("ERR: can't request for active study because the session is NULL"); + return -1; + } + return aSession->GetActiveStudyId(); + } + + /** + * This returns the current active study if an active study is + * defined in the SALOME session, returns null otherwise. + */ + SALOMEDS::Study_ptr getActiveStudy() { + return KERNEL::getStudyById(getActiveStudyId()); + } + + + // __GBO__ Question: what is the difference between a + // SALOMEDS::Study and a SalomeApp_Study? + SalomeApp_Study* getSalomeAppActiveStudy() { + SUIT_Application* app = getSalomeApplication(); + if( app ) + return dynamic_cast( app->activeStudy() ); + else + return NULL; + } + + + SALOMEDS::SObject_ptr IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject) { + if (!iobject.IsNull()) { + if (iobject->hasEntry()) { + SalomeApp_Study* appStudy = getSalomeAppActiveStudy(); + if ( appStudy != NULL ) { + // + // IMPORTANT NOTE: + // + // Note that the SalomeApp_Study give acces to shared + // pointer (i.e. _PTR()) that points to proxy + // objects (i.e. SALOMEDSClien_) that embeds + // the CORBA servants (i.e. SALOMEDS::_ptr). + // Then to retrieve the corba servant, a method is to + // retrieve the SALOMEDS::Study servant first and the to + // request this servant to get the SObject given its entry. + // + _PTR(Study) studyClient = appStudy->studyDS(); + SALOMEDS::Study_var study = KERNEL::getStudyManager()->GetStudyByID(studyClient->StudyId()); + SALOMEDS::SObject_ptr sobject = study->FindObjectID(iobject->getEntry()); + return sobject; + } + } + } + return SALOMEDS::SObject::_nil(); + } + +} + diff --git a/src/GuiHelpers/SALOME_GuiServices.hxx b/src/GuiHelpers/SALOME_GuiServices.hxx new file mode 100644 index 000000000..990596c8e --- /dev/null +++ b/src/GuiHelpers/SALOME_GuiServices.hxx @@ -0,0 +1,84 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#ifndef __GUI_SERVICES_H__ +#define __GUI_SERVICES_H__ + +#include +#include +#include +#include + +#include "SALOMEconfig.h" +#include CORBA_SERVER_HEADER(SALOMEDS) +#include +#include + +namespace GUI { + + // SALOME GUI main services + SalomeApp_Application * getSalomeApplication(); + LightApp_SelectionMgr * getSelectionManager(); + SUIT_ResourceMgr * getResourcesManager(); + + // Helper functions to deal with the study in a GUI context. + // + // First of all, in a GUI context, there is one of the opened + // studies that is considered as active. Please note that the active + // study is a GUI concept and it can be obtained only in the + // SALOME_SessionServer process, i.e. the process that embeds the + // SalomeApp_Application. The concept of active study doesn't make + // sense outside of the GUI context. + // + // The active study is associated with an GUI Objects Browser that + // displays a graphical representation of the study. The items that + // can be selected in the Objects Browser are name Interactive + // Objects (instance of class SALOME_InteractiveObject). To work + // with data, we have to retrieve from this Interactive Object (IO) + // the underlying Study Object (instance of class SALOMEDS::SObject) + // and from this last the data object that can be anything (that + // depends of the SALOME module technical choices). In general, on + // of the attribute of a SObject is a CORBA servant that handles the + // data to work with + SALOMEDS::Study_ptr getActiveStudy(); + int getActiveStudyId(); + + // Another way to get the active study (to be converted in + // SALOMEDS::Study): + SalomeApp_Study * getSalomeAppActiveStudy(); + + SALOMEDS::SObject_ptr IObjectToSObject(const Handle(SALOME_InteractiveObject)& iobject); + + template typename TInterface::_var_type + IObjectToInterface(const Handle(SALOME_InteractiveObject)& iobject) { + SALOMEDS::SObject_ptr sobject = IObjectToSObject(iobject); + return KERNEL::SObjectToInterface(sobject); + } + // _MEM_: note that template functions have to be declared AND + // implemented in the header because they are not compiled in this + // library but in every client library that includes this header + // file. The effective compilation depends on the particular class + // used for TInterface. + + +} + +#endif // GUI_SERVICES diff --git a/src/GuiHelpers/StandardApp_Module.cxx b/src/GuiHelpers/StandardApp_Module.cxx new file mode 100644 index 000000000..6ace49427 --- /dev/null +++ b/src/GuiHelpers/StandardApp_Module.cxx @@ -0,0 +1,338 @@ +// Copyright (C) 2011-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 : Guillaume Boulant (EDF) + +#include "StandardApp_Module.hxx" + +#include +#include +#include +#include +#include "QtxPopupMgr.h" + +#include CORBA_CLIENT_HEADER(SALOMEDS) +#include CORBA_CLIENT_HEADER(SALOMEDS_Attributes) + +// QT Includes +#include +#include + +#include +#include "QtHelper.hxx" + +// Constructor +StandardApp_Module::StandardApp_Module() : + SalomeApp_Module( "" ), + LightApp_Module( "" ) +{ + // Note that it's no use to specify here the moduleName because it's + // automatically determined by the name of the GUI library + // (lib.so) just before initialize step. If you want + // nevertheless to setup the module name you should specified this + // name in the initialize function below using the CAM_module + // function setModuleName(QString&). You are warn then that the + // loading of resource files may be incorect and should be manually + // managed. In conclusion, if you don't need a special + // configuration, please conform to the standard convention: if + // is the name of the module as declared in the GUI + // configuration file (SalomeApp.xml), then you just have to provide + // a library whose name is lib.so and which contains a + // factory "extern C" function 'CAM_Module* createModule()' +} + +int StandardApp_Module::ACTIONID_DEFAULT_INIT_VALUE = 910; +int StandardApp_Module::ACTIONID_UNDEFINED = -1; + +// Module's initialization +void StandardApp_Module::initialize( CAM_Application* app ) +{ + // + // ---------------------------------------------------------------- + // Standard initialization + // ---------------------------------------------------------------- + // + SalomeApp_Module::initialize( app ); + _resourceMgr = app->resourceMgr(); + // Please note that the moduleName() function is inherited from + // CAM_module classe, and that its value is determined automatically + // from the name specified in the SalomeApp.xml associated to this + // module and which corresponds to the name of the GUI library + // (lib.so). For XSALOME, see + // share/salome/resources/xsalome/SalomeApp.xml in the install + // directory. + _defaultMenuId = this->createMenu( QCHARSTAR(moduleName()), -1, -1, 30 ); + _defaultToolbarId = this->createTool ( QCHARSTAR(moduleName()) ); + _actionId_internalCount = StandardApp_Module::ACTIONID_DEFAULT_INIT_VALUE; + + // + // ---------------------------------------------------------------- + // The following initializes the GUI widget and associated actions + // ---------------------------------------------------------------- + // These functions may be redefined in specialized version of this class + this->createModuleWidgets(); + this->createModuleActions(); +} + +QIcon StandardApp_Module::createIcon(const QString& iconName) { + // The icon file is supposed to be available througth the resource + // manager, i.e. in the folder containing the XSALOME resources (see + // specification in the module file SalomeApp.xml). + QPixmap aPixmap = _resourceMgr->loadPixmap( QCHARSTAR(moduleName()), iconName ); + return QIcon( aPixmap ); +} + +int StandardApp_Module::newActionId() { + _actionId_internalCount++; + return _actionId_internalCount; +} + +/*! + * This function creates an action and connects it to a button in the + * toolbar and to an item in the menu associated to this module. This + * function applies a common and standard procedure with a maximum of + * default values. If no identifier is specified, then a static + * internal counter is used to associate an identifier to the created + * action. In any case, the action identifier is returned. + * + * Note that the action (object of type QAction) can be retrieved + * using the method "QAction * action(int identifier)" of the super + * class. + */ +int StandardApp_Module::createStandardAction(const QString& label, + QObject * slotobject, + const char* slotmember, + const QString& iconName, + const QString& tooltip, + const int identifier) +{ + + // If the tooltip is not defined, we choose instead the label text. + QString effToolTip(tooltip); + if ( effToolTip.isEmpty() ) + effToolTip = label; + + QIcon actionIcon = this->createIcon(iconName); + + // If the identifier is not specified, then we use an internal + // counter. + int effIdentifier = identifier; + if ( effIdentifier == StandardApp_Module::ACTIONID_UNDEFINED ) { + effIdentifier=newActionId(); + } + + // Creating the action + QAction * action= this->createAction( effIdentifier, label, actionIcon, + label, effToolTip, 0, getApp()->desktop(), + false, slotobject, slotmember); + + return effIdentifier; +} + +/** + * Integrate the action in the default toolbar + */ +void StandardApp_Module::addActionInToolbar(int actionId) { + this->createTool( actionId, _defaultToolbarId ); +} + +/** + * Integrate the action in the default menu + */ +void StandardApp_Module::addActionInMenubar(int actionId) { + this->createMenu( actionId, _defaultMenuId, 10 ); +} + +/** + * Add the specified action as an item in the popup menu, with the + * specified visible rule. The default is "visible for object browser". + */ +void StandardApp_Module::addActionInPopupMenu(int actionId,const QString& rule) { + // _GBO_ for a fine customization of the rule (for example with a + // test on the type of the selected object), see the LIGTH module: + // implement "LightApp_Selection* createSelection() const;" + int parentId = -1; + QtxPopupMgr* mgr = this->popupMgr(); + mgr->insert ( this->action( actionId ), parentId, 0 ); + mgr->setRule( this->action( actionId ), rule, QtxPopupMgr::VisibleRule ); +} + +/*! + * This function can be used to create additionnal widget for this + * module GUI (e.g. docked widget). It can be redefined in a + * specialized version of this class. + */ +void StandardApp_Module::createModuleWidgets() { + // Nothing to do in this default gui +} + +/*! + * This function can be used to defined the list of actions for this + * module GUI. It can be redefined in a specialized version of this + * class. + * Depending on wether you use the method "createStandardAction" or + * not, the actions will be automatically plugged in the toolbar and + * the menu associated to the module. + */ +void StandardApp_Module::createModuleActions() { + int actionId = this->createStandardAction("Test", this, SLOT(OnTest()), + "f1.png", "Run the default test function"); + this->addActionInToolbar(actionId); +} + +// Get compatible dockable windows. +void StandardApp_Module::windows( QMap& theMap ) const +{ + theMap.clear(); + theMap.insert( SalomeApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea ); + theMap.insert( SalomeApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea ); +} + +// Module's engine IOR +QString StandardApp_Module::engineIOR() const +{ + CORBA::String_var anIOR = getApp()->orb()->object_to_string(getEngine()); + return QString( anIOR.in() ); +} + +/*! + * This specifies the filename for the icon to be used for the study + * component associated to the module. Note that this icon could be + * different than the module icon which is defined by the + * SalomeApp.xml file dedicated to this module (see the shared + * resources folder dedicated to the module) and which is used for the + * toolbar of the SALOME application. + */ +QString StandardApp_Module::studyIconName() +{ + // By default, we return the module icone name + return iconName(); // inherited from CAM_Module +} + +/*! + * This can be used to switch the layout of main application + * dockwidgets to one of the predefined configuration (see enum + * DockLayoutType). When a layout is set, the previous layout is + * memorized and can be restored using the unsetDockLayout function (1 + * step undo). It is typically to be used in the functions + * activateModule to setup the layout and deactivateModule to unset + * the layout, i.e. restore to the previous state. + */ +void StandardApp_Module::setDockLayout(DockLayoutType layoutType) { + SUIT_Desktop* desk = getApp()->desktop(); + _areaAtBottomLeftCorner = desk->corner(Qt::BottomLeftCorner); + _areaAtBottomRightCorner = desk->corner(Qt::BottomRightCorner); + + if ( layoutType == DOCKLAYOUT_LEFT_VLARGE ) { + desk->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); + desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + } else { + desk->setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea); + desk->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + } +} + +/*! + * This function restores the layout state that was previously in + * place before the last setDockLayout call. + */ +void StandardApp_Module::unsetDockLayout() { + SUIT_Desktop* desk = getApp()->desktop(); + desk->setCorner(Qt::BottomLeftCorner, _areaAtBottomLeftCorner); + desk->setCorner(Qt::BottomRightCorner, _areaAtBottomRightCorner); +} + +// Module's activation +bool StandardApp_Module::activateModule( SUIT_Study* theStudy ) +{ + bool bOk = SalomeApp_Module::activateModule( theStudy ); + + setMenuShown( true ); + setToolShown( true ); + + if ( this->createStudyComponentAtActivation() ) { + this->createStudyComponent(theStudy); + } + + return bOk; +} + +/*! + * This function should be implemented in a specialized class and must + * return true if you want to automatically create a study component + * for this module at activation step (when you first load the module + * for a given study). The default function return true. + */ +bool StandardApp_Module::createStudyComponentAtActivation() { + return true; +} + +/*! + * This creates a root entry in the active study for this module, i.e + * a SComponent with the name of the module and the icon specified for + * the module. This component is associated to the engine (return by + * getEngine()) if the engine is a SALOMEDS::Driver. + */ +void StandardApp_Module::createStudyComponent(SUIT_Study* theStudy) { + + SALOME_NamingService *aNamingService = SalomeApp_Application::namingService(); + CORBA::Object_var aSMObject = aNamingService->Resolve("/myStudyManager"); + SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow(aSMObject); + SALOMEDS::Study_var aDSStudy = aStudyManager->GetStudyByID(theStudy->id()); + + SALOMEDS::SComponent_var aFather = aDSStudy->FindComponent(QCHARSTAR(moduleName())); + if (aFather->_is_nil()) + { + SALOMEDS::StudyBuilder_var aStudyBuilder = aDSStudy->NewBuilder(); + aFather = aStudyBuilder->NewComponent(QCHARSTAR(moduleName())); + SALOMEDS::GenericAttribute_var anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributeName"); + SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr); + aName->SetValue(QCHARSTAR(moduleName())); + aName->Destroy(); + anAttr = aStudyBuilder->FindOrCreateAttribute(aFather, "AttributePixMap"); + SALOMEDS::AttributePixMap_var aPixMap = SALOMEDS::AttributePixMap::_narrow(anAttr); + aPixMap->SetPixMap(QCHARSTAR(studyIconName())); + + // WARN: The engine should be associated to the SComponent IF + // AND ONLY IF it is a SALOMEDS::Driver. Otherwise, there is no + // need to do that, and it could even lead to exception + // raising (eh, you work on SALOME isn't it?) + SALOMEDS::Driver_var driver = SALOMEDS::Driver::_narrow(this->getEngine()); + if ( ! driver->_is_nil() ) { + STDLOG("Associate the SComponent to the engine"); + aStudyBuilder->DefineComponentInstance(aFather, this->getEngine()); + } + } + +} + +// Module's deactivation +bool StandardApp_Module::deactivateModule( SUIT_Study* theStudy ) +{ + setMenuShown( false ); + setToolShown( false ); + + return SalomeApp_Module::deactivateModule( theStudy ); +} + +void StandardApp_Module::OnTest() +{ + // Just for test + STDLOG("OnTest: engine IOR = "< +#include + +#include +#include CORBA_SERVER_HEADER(SALOME_Component) + +#include + +/*! + * This class is provided as the base class for the standard gui part + * of a SALOME module. To define a gui part, you just have to + * implement the virtual functions: + * - getEngine() to specify the engine component associated to this module + * - createModuleActions(...) to specify the action functions + * - createModuleWidgets(...) to specify special additionnal widgets + * + * The gui part of a SALOME module is an extension of the SALOME + * client Application for this module. Technically speaking, it + * consists in a plugin that provides a derived class of CAM_Module + * (provided by the GUI module). + * + * A standard gui is the standard design for most of SALOME module + * (object browser on the left, viewer on the rigth, python console on + * the bottom, and toolbox in the toolbar with standard definition of + * the tool function). This standard design suggests also to specify + * the engine associated to the module by implementing the virtual + * pure function getEngine(). The engine of a module is the SALOME + * component that is associated to the study component for this + * module, and generally which is responsible for the persistency + * functions or data management for the module. + * + * See a use case example in the test module Xsalome provided by the + * test package (tst/module/gui/Xsalome.hxx and + * tst/module/gui/factory.cxx in the XSALOME library). + */ +class StandardApp_Module: public SalomeApp_Module +{ + Q_OBJECT + +public: + + // ================================================================ + // This part defines the standard interface of the SalomeApp_Module + // ================================================================ + + StandardApp_Module(); + void initialize( CAM_Application* ); + QString engineIOR() const; + virtual void windows( QMap& theMap ) const; + +public slots: + bool deactivateModule( SUIT_Study* ); + bool activateModule( SUIT_Study* ); + + // ================================================================ + // This part defines the specific interface of this class + // ================================================================ + +public: + /* Creates an action with standard default values */ + int createStandardAction(const QString& label, + QObject * slotobject, + const char* slotmember, + const QString& iconName=QString(), + const QString& tooltip=QString(), + const int identifier=ACTIONID_UNDEFINED); + + void addActionInToolbar(int actionId); + void addActionInMenubar(int actionId); + void addActionInPopupMenu(int actionId,const QString& rule="client='ObjectBrowser'"); + +protected: + /* Implement this to create additionnal widget (e.g. docked widget) */ + virtual void createModuleWidgets(); + /* Implement this to define the actions for this gui */ + virtual void createModuleActions(); + + /* Use this to create a root entry in the study for this module */ + void createStudyComponent(SUIT_Study*); + /* Implement this to say if study component entry should be created + at activation step */ + virtual bool createStudyComponentAtActivation(); + + /* The engine is the SALOME component associated to the study */ + virtual Engines::EngineComponent_ptr getEngine() const = 0; + // Note that the function getEngine() is virtual pure and must be + // implemented in the specific inherited classes. Note also that the + // const flag is required because getEngine is used by functions + // with const flags (see for ex: engineIOR()). + virtual QString studyIconName(); + + QIcon createIcon(const QString& iconName); + int newActionId(); + + enum DockLayoutType { + DOCKLAYOUT_BOTTOM_HLARGE, // Bottom is Horizontal Large + DOCKLAYOUT_LEFT_VLARGE, // Left is Vertical Large + }; + virtual void setDockLayout(DockLayoutType layoutType); + virtual void unsetDockLayout(); + + SUIT_ResourceMgr* _resourceMgr; + int _defaultMenuId; + int _defaultToolbarId; + + static int ACTIONID_DEFAULT_INIT_VALUE; + static int ACTIONID_UNDEFINED; + +private: + int _actionId_internalCount; + Qt::DockWidgetArea _areaAtBottomLeftCorner; + Qt::DockWidgetArea _areaAtBottomRightCorner; + + // ========================================================= + // This part defines slots for test purposes + // ========================================================= + +protected slots: + void OnTest(); +}; + +#endif diff --git a/src/LightApp/images/en.png b/src/LightApp/images/en.png new file mode 100644 index 0000000000000000000000000000000000000000..ff701e19f6d2c0658fb23b1d94124cba4ce60851 GIT binary patch literal 599 zcmV-d0;v6oP)U(k2*|8J(R-+sudaynhucHbwAMTnor{mwqO^w7JHzaBsT z{O^B8RYf5+LvDs&KmRKVd78=o{`1#HTiEo_OolaGleS)G+IQ#sUI`b*pv<`1zCJ=H0jd{{2S>p`ri%{LsXJ%FbMS z$#S`6f|?OG!^Jxczkf6Q`UNF{l0Sd`ad7zm>({^EzyAS6{{CgrkluOb3l1A>ZU2~A zK+FZ=zkmP!`TOVhpFbzBzFaPmD2$N3;+$pK?>zdet`f0002ovPDHLkV1gy;I?Vt8 literal 0 HcmV?d00001 diff --git a/src/LightApp/images/fr.png b/src/LightApp/images/fr.png new file mode 100644 index 0000000000000000000000000000000000000000..8332c4ec23c853944c29b02d7b32a88033f48a71 GIT binary patch literal 545 zcmV++0^a?JP)lgG%);U`26kn-@hOg zU%!6+4+cOs(0HIde9xZz`}Onxub&LUB0x(30+2WcIRJn#2ut|?gWYu1Cf+!-K%B8# zdf?1WA}#uZ8oj7u>$I1i0Al&`=O0k%-@icgAIJnM0xA6maSq6BK-ECw|NZ*S`0Lj% z1_pot6puj;05Ax`F!=umqj7^frO?t|3^&I1kxUq9yECc+jQpY84SWH_0#pxl$?v~F z@*hy-KN0|X07U)z`4{NpU%#2aHUI<=%a31wK(7Du52Oc(|3O^?R1IN+RRjI-n*kVB z3=9AP#PZ|EACPLGJ%9cJNh|>9B%spYzZw7h1%?tp0I_@ndg9MNE>313@6R75NcceF zkr51-#U+7;F#`Sf7i0rK0I_`g_NQ&Z + +#include + +#ifndef WNT +# ifndef GLX_GLXEXT_LEGACY +# define GLX_GLXEXT_LEGACY +# endif +# include +# include +#else +# include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#ifndef GL_FRAMEBUFFER_EXT +#define GL_FRAMEBUFFER_EXT 0x8D40 +#endif + +#ifndef GL_RENDERBUFFER_EXT +#define GL_RENDERBUFFER_EXT 0x8D41 +#endif + +#ifndef GL_COLOR_ATTACHMENT0_EXT +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#endif + +#ifndef GL_DEPTH_ATTACHMENT_EXT +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#endif + +#ifndef GL_FRAMEBUFFER_COMPLETE_EXT +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#endif + +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers); +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer); +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target); +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers); + +static PFNGLGENFRAMEBUFFERSEXTPROC vglGenFramebuffersEXT = NULL; +static PFNGLBINDFRAMEBUFFEREXTPROC vglBindFramebufferEXT = NULL; +static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC vglFramebufferTexture2DEXT = NULL; +static PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC vglCheckFramebufferStatusEXT = NULL; +static PFNGLDELETEFRAMEBUFFERSEXTPROC vglDeleteFramebuffersEXT = NULL; +static PFNGLGENRENDERBUFFERSEXTPROC vglGenRenderbuffersEXT = NULL; +static PFNGLBINDRENDERBUFFEREXTPROC vglBindRenderbufferEXT = NULL; +static PFNGLRENDERBUFFERSTORAGEEXTPROC vglRenderbufferStorageEXT = NULL; +static PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC vglFramebufferRenderbufferEXT = NULL; +static PFNGLDELETERENDERBUFFERSEXTPROC vglDeleteRenderbuffersEXT = NULL; + +#ifndef WNT +#define GL_GetProcAddress( x ) glXGetProcAddressARB( (const GLubyte*)x ) +#else +#define GL_GetProcAddress( x ) wglGetProcAddress( (const LPCSTR)x ) +#endif + +bool InitializeEXT() +{ + vglGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)GL_GetProcAddress( "glGenFramebuffersEXT" ); + vglBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)GL_GetProcAddress( "glBindFramebufferEXT" ); + vglFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)GL_GetProcAddress( "glFramebufferTexture2DEXT" ); + vglCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)GL_GetProcAddress( "glCheckFramebufferStatusEXT" ); + vglDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)GL_GetProcAddress( "glDeleteFramebuffersEXT" ); + vglGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)GL_GetProcAddress( "glGenRenderbuffersEXT" ); + vglBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)GL_GetProcAddress( "glBindRenderbufferEXT" ); + vglRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)GL_GetProcAddress( "glRenderbufferStorageEXT" ); + vglFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)GL_GetProcAddress( "glFramebufferRenderbufferEXT" ); + vglDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)GL_GetProcAddress( "glDeleteRenderbuffersEXT" ); + + bool ok = vglGenFramebuffersEXT && vglBindFramebufferEXT && vglFramebufferTexture2DEXT && + vglCheckFramebufferStatusEXT && vglDeleteFramebuffersEXT && vglGenRenderbuffersEXT && + vglBindRenderbufferEXT && vglRenderbufferStorageEXT && vglFramebufferRenderbufferEXT && + vglDeleteRenderbuffersEXT; + + return ok; +} + +static bool IsEXTInitialized = InitializeEXT(); + +OpenGLUtils_FrameBuffer::OpenGLUtils_FrameBuffer() + : textureId( 0 ), + fboId( 0 ), + rboId( 0 ) +{ +} + +OpenGLUtils_FrameBuffer::~OpenGLUtils_FrameBuffer() +{ + release(); +} + +bool OpenGLUtils_FrameBuffer::init( const GLsizei& xSize, const GLsizei& ySize ) +{ + char* ext = (char*)glGetString( GL_EXTENSIONS ); + if( !IsEXTInitialized || + strstr( ext, "GL_EXT_framebuffer_object" ) == NULL ) + { + MESSAGE( "Initializing OpenGL FrameBuffer extension failed" ); + return false; + } + + // create a texture object + glEnable( GL_TEXTURE_2D ); + glGenTextures( 1, &textureId ); + glBindTexture( GL_TEXTURE_2D, textureId ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, xSize, ySize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); + glBindTexture( GL_TEXTURE_2D, 0 ); + + // create a renderbuffer object to store depth info + vglGenRenderbuffersEXT( 1, &rboId ); + vglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, rboId ); + vglRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, xSize, ySize ); + vglBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 ); + + // create a framebuffer object + vglGenFramebuffersEXT( 1, &fboId ); + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboId ); + + // attach the texture to FBO color attachment point + vglFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0 ); + + // attach the renderbuffer to depth attachment point + vglFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId ); + + // check FBO status + GLenum status = vglCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); + + // Unbind FBO + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); + + return status == GL_FRAMEBUFFER_COMPLETE_EXT; +} + +void OpenGLUtils_FrameBuffer::release() +{ + if( !IsEXTInitialized ) + return; + + glDeleteTextures( 1, &textureId ); + textureId = 0; + + vglDeleteFramebuffersEXT( 1, &fboId ); + fboId = 0; + + vglDeleteRenderbuffersEXT( 1, &rboId ); + rboId = 0; +} + +void OpenGLUtils_FrameBuffer::bind() +{ + if( !IsEXTInitialized ) + return; + + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fboId ); +} + +void OpenGLUtils_FrameBuffer::unbind() +{ + if( !IsEXTInitialized ) + return; + + vglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); +} diff --git a/src/OpenGLUtils/OpenGLUtils_FrameBuffer.h b/src/OpenGLUtils/OpenGLUtils_FrameBuffer.h new file mode 100755 index 000000000..daaf5ddb5 --- /dev/null +++ b/src/OpenGLUtils/OpenGLUtils_FrameBuffer.h @@ -0,0 +1,52 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +// File : OpenGLUtils_FrameBuffer.h +// Module : SALOME +// +#ifndef OPENGLUTILS_FRAMEBUFFER_H +#define OPENGLUTILS_FRAMEBUFFER_H + +#include "OpenGLUtils.h" + +#ifdef WIN32 +#include +#endif + +#include + +class OPENGLUTILS_EXPORT OpenGLUtils_FrameBuffer +{ +public: + OpenGLUtils_FrameBuffer(); + ~OpenGLUtils_FrameBuffer(); + + bool init( const GLsizei&, const GLsizei& ); + void release(); + + void bind(); + void unbind(); + +private: + GLuint textureId; + GLuint fboId; + GLuint rboId; +}; + +#endif diff --git a/src/Qtx/resources/Qtx_msg_fr.ts b/src/Qtx/resources/Qtx_msg_fr.ts new file mode 100644 index 000000000..c98d41bee --- /dev/null +++ b/src/Qtx/resources/Qtx_msg_fr.ts @@ -0,0 +1,336 @@ + + + + + QtxTreeView + + Enable sorting + Autoriser le tri + + + + QtxWorkspaceAction + + Arranges the windows as overlapping tiles + Ranger les fenêtres en les superposant + + + Cascade + Cascade + + + Arranges the windows as nonoverlapping tiles + Ranger les fenêtres sans les superposer + + + Tile + Mosaïque + + + Arranges the windows as nonoverlapping horizontal tiles + Ranger les fenêtres en mosaïque horizontale + + + Tile horizontally + Mosaïque horizontale + + + Arranges the windows as nonoverlapping vertical tiles + Ranger les fenêtres en mosaïque verticale + + + Tile vertically + Mosaïque verticale + + + + QtxMainWindow + + Menu bar + Barre de menu + + + Status bar + Barre de statut + + + + QtxPathDialog + + Open file + Ouvrir le fichier + + + Save file + Sauvegarder le fichier + + + File name + Nom du fichier + + + File name not specified + Le nom du fichier n'est pas indiqué + + + File \"%1\" does not exist + Le fichier \"%1\" n'existe pas + + + File \"%1\" already exist. Do you want to overwrite it? + Le fichier \"%1\" existe déjà. Voulez-vous l'écraser ? + + + Directory \"%1\" does not exist + Le répertoire \"%1\" n'existe pas + + + Directory \"%1\" can't be created because file with the same name exist + Il est impossible de créer le répertoire \"%1\" parce qu'un fichier avec ce nom existe déjà + + + Directory \"%1\" not empty. Do you want to remove all files in this directory? + Le répertoire \"%1\" n'est pas vide. Voulez-vous supprimer tous les fichiers dans ce répertoire? + + + File dialog + Fenêtre de dialogue de fichiers + + + All files (*.*) + Tous les fichiers (*.*) + + + + QtxFontEdit + + B + Bold + G + + + I + Italic + I + + + U + Underline + S + + + S + Strikethrough + R + + + + QtxPathListEdit + + Warning + Avertissement + + + Path \"%1\" doesn't exist. Add it to list anyway? + Le chemin \"%1\" n'existe pas. Faut-il l'ajouter dans la liste? + + + Error + Erreur + + + Location \"%1\" doesn't point to file + L'emplacement \"%1\" ne pointe sur aucun fichier + + + Location \"%1\" doesn't point to directory + L'emplacement \"%1\" ne pointe sur aucun répertoire + + + Path \"%1\" already exist in the list + Le chemin \"%1\" existe déjà dans la liste + + + + QtxMRUAction + + Most Recently Used + Récemment utilisés + + + Clear + Effacer + + + <Empty> + <Vide> + + + + QtxDialog + + &OK + &OK + + + &Cancel + &Annuler + + + C&lose + &Fermer + + + &Help + &Aide + + + &Apply + A&ppliquer + + + &Yes + &Oui + + + &No + &Non + + + + QtxSearchTool + + Case sensitive + Sensible à la casse + + + Regular expression + Expression régulière + + + Wrap search + Continuer la recherche + + + + QtxSplash + + Error + Erreur + + + &OK + &OK + + + + QtxWorkstack + + Split vertically + Diviser verticalement + + + Split horizontally + Diviser horisontalement + + + Close + Fermer + + + Rename + Renommer + + + Enter new name: + Indiquer un nouveau nom: + + + + QtxWorkstackAction + + Split the active window on two vertical parts + Diviser la fenêtre actuelle en deux parties verticales + + + Split vertically + Diviser verticalement + + + Split the active window on two horizontal parts + Diviser la fenêtre actuelle en deux parties horizontales + + + Split horizontally + Diviser horizontalement + + + + QtxColorButton + + Auto + Auto + + + Other colors... + Autres couleurs... + + + + QtxColorScale + + Color scale + Echelle de couleurs + + + + QtxBackgroundTool + + Browse... + Parcourir... + + + Not implemented yet + Pas encore disponible + + + Center + Centre + + + Tile + Mosaïque + + + Stretch + Etiré + + + Images Files (*.bmp *.png *.jpg *.jpeg *.gif *.tiff) + Fichiers images (*.bmp *.png *.jpg *.jpeg *.gif *.tiff) + + + Image + Image + + + Single Color + Couleur unique + + + Custom + Personnalisé + + + Select Picture + Choisir l'image + + + + QtxBackgroundDialog + + Change background + Modifier l'arrière plan + + + diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/Makefile.am b/src/SALOME_PYQT/SALOME_PYQT_GUILight/Makefile.am new file mode 100644 index 000000000..525818cac --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/Makefile.am @@ -0,0 +1,103 @@ +# Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 +# + +# File : Makefile.am +# Author : Roman NIKOLAEV Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) +# +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# Library target +lib_LTLIBRARIES = libSalomePyQtGUILight.la + + +# extra source files (generated by sip) +SIP_SRC = sipAPISalomePyQtGUILight.h \ + sipSalomePyQtGUILightcmodule.cc + +# Sip definition file +SIP_FILES = SALOME_PYQT_GUILight.sip + +# extra dist files +EXTRA_DIST += $(SIP_FILES) + + +# extra clean files +CLEANFILES = $(SIP_SRC) + +# moc files (generated my moc) +MOC_FILES = \ + SALOME_PYQT_ModuleLight_moc.cxx \ + SALOME_PYQT_DataModelLight_moc.cxx + + +# exported header files +salomeinclude_HEADERS = \ + SALOME_PYQT_GUILight.h \ + SALOME_PYQT_ModuleLight.h \ + SALOME_PYQT_DataObjectLight.h \ + SALOME_PYQT_DataModelLight.h \ + SALOME_PYQT_PyInterp.h + +# library sources +dist_libSalomePyQtGUILight_la_SOURCES = \ + SALOME_PYQT_ModuleLight.cxx \ + SALOME_PYQT_DataObjectLight.cxx \ + SALOME_PYQT_DataModelLight.cxx \ + SALOME_PYQT_PyInterp.cxx + +nodist_libSalomePyQtGUILight_la_SOURCES = $(MOC_FILES) $(SIP_SRC) + + +libSalomePyQtGUILight_la_CPPFLAGS = $(QT_INCLUDES) $(SIP_INCLUDES) $(PYTHON_INCLUDES) \ + $(CAS_CPPFLAGS) $(VTK_INCLUDES) $(OGL_INCLUDES) $(BOOST_CPPFLAGS) \ + -DHAVE_CONFIG_H @KERNEL_CXXFLAGS@ -DCALL_OLD_METHODS \ + -I. -I$(srcdir)/../../PyInterp -I$(srcdir)/../../PyConsole \ + -I$(srcdir)/../../SUIT -I$(srcdir)/../../Qtx -I$(srcdir)/../../LightApp \ + -I$(srcdir)/../../Plot2d -I$(srcdir)/../../OCCViewer \ + -I$(srcdir)/../../CAM -I$(srcdir)/../../STD \ + -I$(srcdir)/../../SUITApp \ + -I$(srcdir)/../../CAM -I$(srcdir)/../../STD + +if GUI_ENABLE_CORBA +libSalomePyQtGUILight_la_CPPFLAGS += -I$(srcdir)/../../SalomeApp \ + @CORBA_CXXFLAGS@ @CORBA_INCLUDES@ +endif + + +if !GUI_ENABLE_CORBA + libSalomePyQtGUILight_la_CPPFLAGS += -DGUI_DISABLE_CORBA +endif + +# linkage flags +libSalomePyQtGUILight_la_LIBADD = $(PYTHON_LIBS) $(SIP_LIBS) $(PYQT_LIBS) $(VTK_LIBS) \ + $(OGL_LIBS) ../../PyInterp/libPyInterp.la ../../LightApp/libLightApp.la + +if GUI_ENABLE_CORBA + libSalomePyQtGUILight_la_LIBADD +=../../SalomeApp/libSalomeApp.la $(KERNEL_LDFLAGS) -lSalomeContainer +endif + + + +# Custom build step: generate C++ wrapping according to $(SIP_FILES) +$(SIP_SRC): $(SIP_FILES) + $(SIP) $(PYQT_SIPFLAGS) $< + +# extra dependency (SALOME_PYQT_Module.cxx depends on header files generated by sip) +$(dist_libSalomePyQtGUILight_la_SOURCES): $(SIP_SRC) + diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.cxx new file mode 100644 index 000000000..70222af53 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.cxx @@ -0,0 +1,203 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) +// Date : 22/06/2007 +// +#include "PyInterp_Interp.h" // // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! + +#include "SALOME_PYQT_DataModelLight.h" +#include "SALOME_PYQT_DataObjectLight.h" +#include "SALOME_PYQT_ModuleLight.h" +#include + +#include +#include +#include +#include + + +//================================================================================= +// function : SALOME_PYQT_DataModelLight() +// purpose : constructor +//================================================================================= +SALOME_PYQT_DataModelLight::SALOME_PYQT_DataModelLight(CAM_Module * theModule) + : LightApp_DataModel( theModule ), + myFileName( "" ), + myStudyURL( "" ), + myModified( false ) +{ + +} + +//================================================================================= +// function : ~SALOME_PYQT_DataModelLight() +// purpose : destructor +//================================================================================= +SALOME_PYQT_DataModelLight::~SALOME_PYQT_DataModelLight() +{ +} + +//================================================================================= +// function : open() +// purpose : Open data model operation +//================================================================================= +bool SALOME_PYQT_DataModelLight::open( const QString& theURL, CAM_Study* study, QStringList theListOfFiles) +{ + MESSAGE("SALOME_PYQT_DataModelLight::open()"); + LightApp_Study* aDoc = dynamic_cast( study ); + SALOME_PYQT_ModuleLight* aModule = dynamic_cast(module()); + if ( !aDoc || !aModule) + return false; + + LightApp_DataModel::open( theURL, aDoc, theListOfFiles ); + + setModified( false ); + + return aModule->open(theListOfFiles); + +} + +//================================================================================= +// function : save() +// purpose : Save data model operation +//================================================================================= +bool SALOME_PYQT_DataModelLight::save( QStringList& theListOfFiles) +{ + MESSAGE("SALOME_PYQT_DataModelLight::save()"); + bool isMultiFile = false; // temporary solution + + LightApp_DataModel::save(theListOfFiles); + LightApp_Study* study = dynamic_cast( module()->application()->activeStudy() ); + SALOME_PYQT_ModuleLight* aModule = dynamic_cast(module()); + + if(!aModule || !study) + return false; + + + std::string aTmpDir = study->GetTmpDir(myStudyURL.toLatin1().constData(), isMultiFile ); + + theListOfFiles.append(QString(aTmpDir.c_str())); + int listSize = theListOfFiles.size(); + aModule->save(theListOfFiles); + + setModified( false ); + + //Return true if in the List of files was added item(s) + //else return false + return theListOfFiles.size() > listSize; +} + +//================================================================================= +// function : saveAs() +// purpose : SaveAs data model operation +//================================================================================= +bool SALOME_PYQT_DataModelLight::saveAs ( const QString& theURL, CAM_Study* theStudy, QStringList& theListOfFiles) +{ + myStudyURL = theURL; + return save(theListOfFiles); +} + + + +bool SALOME_PYQT_DataModelLight::create( CAM_Study* study ) +{ + return true; +} + +//================================================================================= +// function : dumpPython() +// purpose : Re-defined from LigthApp_DataModel in order to participate +// in dump study process +//================================================================================= +bool SALOME_PYQT_DataModelLight::dumpPython( const QString& theURL, + CAM_Study* theStudy, + bool isMultiFile, + QStringList& theListOfFiles ) +{ + MESSAGE("SALOME_PYQT_DataModelLight::dumpPython()"); + + LightApp_DataModel::dumpPython( theURL, theStudy, isMultiFile, theListOfFiles ); + + LightApp_Study* study = dynamic_cast( theStudy ); + SALOME_PYQT_ModuleLight* aModule = dynamic_cast(module()); + + if(!aModule || !study) + return false; + + std::string aTmpDir = study->GetTmpDir( theURL.toLatin1().constData(), isMultiFile ); + + theListOfFiles.append( QString( aTmpDir.c_str() ) ); + int oldSize = theListOfFiles.size(); + + aModule->dumpPython( theListOfFiles ); + + //Return true if some items have been added, else return false + return theListOfFiles.size() > oldSize; +} + +//================================================================================= +// function : isModified() +// purpose : returns this model's modification status that can be controlled +// with help of setModified() calls by the underlying Python module +//================================================================================= +bool SALOME_PYQT_DataModelLight::isModified() const +{ + return myModified; +} + +//================================================================================= +// function : setModified() +// purpose : sets the model's modification status, should be used by +// the underlying Python module when its data changes. +//================================================================================= +void SALOME_PYQT_DataModelLight::setModified( bool flag ) +{ + myModified = flag; +} + +//================================================================================= +// function : close() +// purpose : Close data model operation +//================================================================================= +bool SALOME_PYQT_DataModelLight::close() +{ + LightApp_DataModel::close(); + return true; +} + + +void SALOME_PYQT_DataModelLight::update ( LightApp_DataObject* theObj, LightApp_Study* theStudy ) +{ + // Nothing to do here: we always keep the data tree in the up-to-date state + // The only goal of this method is to hide default behavior from LightApp_DataModel + return; +} + +CAM_DataObject* SALOME_PYQT_DataModelLight::getRoot() +{ + LightApp_Study* study = dynamic_cast( module()->application()->activeStudy() ); + CAM_ModuleObject *aModelRoot = dynamic_cast(root()); + if(study && aModelRoot == NULL) { + aModelRoot = createModuleObject( study->root() ); + aModelRoot->setDataModel( this ); + setRoot(aModelRoot); + } + return aModelRoot; +} diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.h new file mode 100644 index 000000000..35ca6d19f --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataModelLight.h @@ -0,0 +1,67 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) +// Date : 22/06/2007 +// +#ifndef SALOME_PYQT_DATAMODELLIGHT_H +#define SALOME_PYQT_DATAMODELLIGHT_H + +#include "SALOME_PYQT_GUILight.h" +#include + +#include +#include "SALOME_PYQT_DataObjectLight.h" + +class SALOME_PYQT_RootObjectLight; + + + +class SALOME_PYQT_LIGHT_EXPORT SALOME_PYQT_DataModelLight : public LightApp_DataModel +{ + Q_OBJECT + +public: + SALOME_PYQT_DataModelLight( CAM_Module* theModule ); + virtual ~SALOME_PYQT_DataModelLight(); + + virtual bool open ( const QString&, CAM_Study*, QStringList ); + virtual bool save ( QStringList& ); + virtual bool saveAs ( const QString&, CAM_Study*, QStringList& ); + virtual bool close (); + virtual bool create ( CAM_Study* ); + virtual bool dumpPython( const QString&, + CAM_Study*, + bool, + QStringList& ); + + virtual bool isModified () const; + void setModified( bool ); + + virtual void update ( LightApp_DataObject* = 0, LightApp_Study* = 0 ); + + CAM_DataObject* getRoot(); + + private: + QString myFileName; + QString myStudyURL; + bool myModified; +}; + +#endif // SALOME_PYQT_DATAMODELLIGHT_H diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.cxx new file mode 100644 index 000000000..11ba2f851 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.cxx @@ -0,0 +1,177 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) +// Date : 22/06/2007 +// +#include "SALOME_PYQT_DataObjectLight.h" +#include +#include +#include +#include + + +#include +#include + + +/*! + * Class: SALOME_PYQT_DataObjectLight + * Description: LIGHT PYTHON module's data object + */ + +static int _ID = 0; + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight() +// purpose : constructor +//================================================================================= +SALOME_PYQT_DataObjectLight::SALOME_PYQT_DataObjectLight ( SUIT_DataObject* parent ) + : CAM_DataObject(parent), + LightApp_DataObject( parent ) + +{ + _ID++; + myEntry = QString("PYLIGHT_OBJ_%1").arg(_ID); +} + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight() +// purpose : destructor +//================================================================================= +SALOME_PYQT_DataObjectLight::~SALOME_PYQT_DataObjectLight() +{ + +} + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight::entry() +// purpose : return entry of object +//================================================================================= +QString SALOME_PYQT_DataObjectLight::entry() const +{ + return myEntry; +} + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight::refEntry() +// purpose : return entry of the data object referenced by this one (if any) +//================================================================================= +QString SALOME_PYQT_DataObjectLight::refEntry() const +{ + return myRefEntry; +} + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight::setRefEntry() +// purpose : sets entry of the data object referenced by this one +//================================================================================= +void SALOME_PYQT_DataObjectLight::setRefEntry( const QString& refEntry ) +{ + myRefEntry = refEntry; +} + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight::name() +// purpose : return name of object +//================================================================================= +QString SALOME_PYQT_DataObjectLight::name() const +{ + return myName; +} + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight::icon() +// purpose : return icon of object +//================================================================================= +QPixmap SALOME_PYQT_DataObjectLight::icon(const int index) const +{ + if(index == NameId) + return myIcon; + else + return LightApp_DataObject::icon( index ); +} + + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight::toolTip() +// purpose : return toolTip of object +//================================================================================= +QString SALOME_PYQT_DataObjectLight::toolTip(const int index) const +{ + return myToolTip; +} + +//================================================================================= +// function : SALOME_PYQT_DataObjectLight::toolTip() +// purpose : return toolTip of object +//================================================================================= +QColor SALOME_PYQT_DataObjectLight::color( const ColorRole role, const int id ) const +{ + QColor c; + + switch ( role ) + { + case Text: + case Foreground: + if ( !isReference() ) + c = myColor; + break; + + default: + break; + } + + // Issue 21379: LightApp_DataObject::color() defines colors for valid references + if ( !c.isValid() ) + c = LightApp_DataObject::color( role, id ); + + return c; +} + +bool SALOME_PYQT_DataObjectLight::setName(const QString& name) +{ + myName = name; + return true; +} + +void SALOME_PYQT_DataObjectLight::setIcon(const QString& iconname) +{ + if(!iconname.isEmpty()) { + LightApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if(anApp) { + QString modulename = anApp->activeModule()->name(); + if(!modulename.isEmpty()) + { + myIcon = SUIT_Session::session()->resourceMgr()->loadPixmap(modulename, + QObject::tr(iconname.toLatin1())); + } + } + } +} + +void SALOME_PYQT_DataObjectLight::setToolTip(const QString& tooltip) +{ + myToolTip = tooltip; +} + +void SALOME_PYQT_DataObjectLight::setColor(const QColor& color) +{ + myColor = color; +} diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.h new file mode 100644 index 000000000..b76e2d8c5 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_DataObjectLight.h @@ -0,0 +1,69 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) +// Date : 22/06/2007 +// +#ifndef SALOME_PYQT_DATAOBJECTLIGHT_H +#define SALOME_PYQT_DATAOBJECTLIGHT_H + + +#include "SALOME_PYQT_GUILight.h" +#include +#include + +#include + +/*! + * SALOME_PYQT_DataObjectLight - PYTHON LIGHT module's data object class + */ +class SALOME_PYQT_LIGHT_EXPORT SALOME_PYQT_DataObjectLight : public virtual LightApp_DataObject +{ + + public: + SALOME_PYQT_DataObjectLight( SUIT_DataObject* = 0 ); + + virtual ~SALOME_PYQT_DataObjectLight(); + + virtual QString entry() const; + + virtual QString refEntry() const; + void setRefEntry( const QString& refEntry ); + + virtual QString name() const; + virtual QPixmap icon(const int = NameId) const; + virtual QString toolTip(const int = NameId) const; + + bool setName(const QString& name); + void setIcon(const QString& icon); + void setToolTip(const QString& tooltip); + + virtual QColor color( const ColorRole, const int = NameId ) const; + void setColor(const QColor& color); + + private: + QString myEntry; + QString myRefEntry; + QString myName; + QString myToolTip; + QPixmap myIcon; + QColor myColor; +}; + +#endif // SALOME_PYQT_DATAOBJECTLIGHT_H diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.h new file mode 100644 index 000000000..19d5f2d96 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.h @@ -0,0 +1,49 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +// File : SALOME_PYQT_GUI.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// +#if !defined ( SALOME_PYQT_GUILIGHT_H ) +#define SALOME_PYQT_GUIILIGHT_H + +// ======================================================== +// set dllexport type for Win platform +#ifdef WNT + +#if defined SALOME_PYQT_LIGHT_EXPORTS || defined SalomePyQtGUILight_EXPORTS +#define SALOME_PYQT_LIGHT_EXPORT __declspec(dllexport) +#else +#define SALOME_PYQT_LIGHT_EXPORT __declspec(dllimport) +#endif + +#else // WNT + +#define SALOME_PYQT_LIGHT_EXPORT + +#endif // WNT + +// ======================================================== +// avoid warning messages +#ifdef WNT +#pragma warning (disable : 4786) +#pragma warning (disable : 4251) +#endif + +#endif // SALOME_PYQT_GUIILIGHT_H diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.sip b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.sip new file mode 100644 index 000000000..51264cbf4 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_GUILight.sip @@ -0,0 +1,26 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// +// File : SALOME_PYQT_GUI.sip +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// + +%Module SalomePyQtGUILight + +%Import QtGuimod.sip +%Import QtXmlmod.sip diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx new file mode 100644 index 000000000..b9a6aa3d2 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.cxx @@ -0,0 +1,3128 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +// File : SALOME_PYQT_Module.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// +#include "SALOME_PYQT_PyInterp.h" +#include +#include +#include +#include +#include + +#include "SALOME_PYQT_ModuleLight.h" +#include "SALOME_PYQT_DataModelLight.h" + +#ifndef GUI_DISABLE_CORBA +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sipAPISalomePyQtGUILight.h" + +#include +#if SIP_VERSION < 0x040700 +#include "sipQtGuiQWidget.h" +#include "sipQtGuiQMenu.h" +#endif + +#include + +/*! + \brief Default name of the module, replaced at the moment + of module creation. + \internal +*/ +const char* DEFAULT_NAME = "SALOME_PYQT_ModuleLight"; + +/*! + \brief Default menu group number. + \internal +*/ +const int DEFAULT_GROUP = 40; + +/*! + \var IsCallOldMethods + \brief Allow calling obsolete callback methods. + \internal + + If the macro CALL_OLD_METHODS is not defined, the invoking + of obsolete Python module's methods like setSetting(), definePopup(), + etc. is blocked. + + CALL_OLD_METHODS macro can be defined for example by adding + -DCALL_OLD_METHODS compilation option to the Makefile. +*/ +#ifdef CALL_OLD_METHODS +const bool IsCallOldMethods = true; +#else +const bool IsCallOldMethods = false; +#endif + +/* Py_ssize_t for old Pythons */ +/* This code is as recommended by: */ +/* http://www.python.org/dev/peps/pep-0353/#conversion-guidelines */ +#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) +typedef int Py_ssize_t; +# define PY_SSIZE_T_MAX INT_MAX +# define PY_SSIZE_T_MIN INT_MIN +#endif + +// +// NB: Python requests. +// General rule for Python requests created by SALOME_PYQT_Module: +// all requests should be executed SYNCHRONOUSLY within the main GUI thread. +// However, it is obligatory that ANY Python call is wrapped with a request object, +// so that ALL Python API calls are serialized with PyInterp_Dispatcher. +// + +/*! + \class SALOME_PYQT_Module::XmlHandler + \brief XML resource files parser. + \internal + + This class is used to provide backward compatibility with + existing Python modules in which obsolete menu definition system + (via XML files) is used. +*/ + +class SALOME_PYQT_ModuleLight::XmlHandler +{ +public: + XmlHandler( SALOME_PYQT_ModuleLight* module, const QString& fileName ); + void createActions(); + void createPopup ( QMenu* menu, + const QString& context, + const QString& parent, + const QString& object ); + void activateMenus( bool ); + +protected: + void createToolBar ( QDomNode& parentNode ); + void createMenu ( QDomNode& parentNode, + const int parentMenuId = -1, + QMenu* parentPopup = 0 ); + + void insertPopupItems( QDomNode& parentNode, + QMenu* menu ); + +private: + SALOME_PYQT_ModuleLight* myModule; + QDomDocument myDoc; + QList myMenuItems; +}; + +// +// NB: Library initialization +// Since the SalomePyQtGUILight library is not imported in Python it's initialization function +// should be called manually (and only once) in order to initialize global sip data +// and to get C API from sip : sipBuildResult for example +// + +#define INIT_FUNCTION initSalomePyQtGUILight +#if defined(SIP_STATIC_MODULE) +extern "C" void INIT_FUNCTION(); +#else +PyMODINIT_FUNC INIT_FUNCTION(); +#endif + +/*! + \fn CAM_Module* createModule() + \brief Module factory function. + \internal + + Creates an instance of SALOME_PYQT_Module object by request + of an application when the module is loaded and initialized. + + \return new module object +*/ + +extern "C" { + SALOME_PYQT_LIGHT_EXPORT CAM_Module* createModule() { + + static bool alreadyInitialized = false; + if ( !alreadyInitialized ) { + // call only once (see comment above) ! + static PyThreadState *gtstate = 0; +#ifndef GUI_DISABLE_CORBA + if(SUIT_PYTHON::initialized) + gtstate = SUIT_PYTHON::_gtstate; + else + gtstate = KERNEL_PYTHON::_gtstate; +#else + gtstate = SUIT_PYTHON::_gtstate; +#endif + PyEval_RestoreThread( gtstate ); + INIT_FUNCTION(); + PyEval_ReleaseThread( gtstate ); + alreadyInitialized = !alreadyInitialized; + } + return new SALOME_PYQT_ModuleLight(); + } +} + +/*! + \class FuncMsg + \brief Function call in/out tracer. + \internal +*/ + +class FuncMsg +{ +public: + FuncMsg( const QString& funcName ) + { + myName = funcName; + MESSAGE( myName.toLatin1().constData() << " [ begin ]" ); + } + ~FuncMsg() + { + MESSAGE( myName.toLatin1().constData() << " [ end ]" ); + } + void message( const QString& msg ) + { + MESSAGE( myName.toLatin1().constData() << " : " << msg.toLatin1().constData() ); + } +private: + QString myName; +}; + +/*! + \class SALOME_PYQT_ModuleLight + \brief This class implements module API for all the Python-based + SALOME modules. +*/ + +// +// Static variables definition +// +SALOME_PYQT_ModuleLight::InterpMap SALOME_PYQT_ModuleLight::myInterpMap; +SALOME_PYQT_ModuleLight* SALOME_PYQT_ModuleLight::myInitModule = 0; + +/*! + \brief Get the module being initialized. + + This is a little trick :) needed to provide an access from Python + (SalomePyQt) to the module being currently activated. The problem + that during the process of module initialization (initialize() + function) it is not yet available via application->activeModule() + call. + + This method returns valid pointer only if called in scope of + initialize() function. + + \return the module being currently initialized +*/ +SALOME_PYQT_ModuleLight* SALOME_PYQT_ModuleLight::getInitModule() +{ + return myInitModule; +} + +/*! + \brief Constructor +*/ +SALOME_PYQT_ModuleLight::SALOME_PYQT_ModuleLight() +: LightApp_Module( DEFAULT_NAME ), + myInterp( 0 ), + myModule( 0 ), + myXmlHandler ( 0 ), + myLastActivateStatus( true ) +{ +} + +/*! + \brief Destructor +*/ +SALOME_PYQT_ModuleLight::~SALOME_PYQT_ModuleLight() +{ + if ( myXmlHandler ) + delete myXmlHandler; + if ( myInterp && myModule ) { + PyLockWrapper aLock = myInterp->GetLockWrapper(); + Py_XDECREF(myModule); + } +} + +/*! + \brief Initialization of the module. + + This method can be used for creation of the menus, toolbars and + other such staff. + + There are two ways to do this: + - for obsolete modules this method first tries to read + _.xml resource file which contains a menu, + toolbars and popup menus description; + - new modules can create menus by direct calling of the + corresponding methods of SalomePyQt Python API in the Python + module's initialize() method which is called from here. + + NOTE: SALOME supports two modes of modules loading: + - immediate (all the modules are created and initialized + immediately when the application object is created; + - postponed modules loading (used currently); in this mode + the module is loaded only be request. + If postponed modules loading is not used, the active + study might be not yet defined at this stage, so initialize() + method should not perform any study-based initialization. + + \param app parent application object +*/ +void SALOME_PYQT_ModuleLight::initialize( CAM_Application* app ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::initialize()" ); + + // call base implementation + LightApp_Module::initialize( app ); + + // try to get XML resource file name + SUIT_ResourceMgr* aResMgr = getApp()->resourceMgr(); + if ( !myXmlHandler && aResMgr ) { + // get current language + QString aLang = aResMgr->stringValue( "language", "language", QString() ); + if ( aLang.isEmpty() ) + aLang = "en"; + // define resource file name + QString aFileName = name() + "_" + aLang + ".xml"; + aFileName = aResMgr->path( "resources", name(), aFileName ); + // create XML handler instance + if ( !aFileName.isEmpty() && QFile::exists( aFileName ) ) + myXmlHandler = new SALOME_PYQT_ModuleLight::XmlHandler( this, aFileName ); + // create menus & toolbars from XML file if required + if ( myXmlHandler ) + myXmlHandler->createActions(); + } + + // perform internal initialization and call module's initialize() funtion + // InitializeReq: request class for internal init() operation + class InitializeReq : public PyInterp_Request + { + public: + InitializeReq( CAM_Application* _app, + SALOME_PYQT_ModuleLight* _obj ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myApp( _app ), + myObj( _obj ) {} + + protected: + virtual void execute() + { + myObj->init( myApp ); + } + + private: + CAM_Application* myApp; + SALOME_PYQT_ModuleLight* myObj; + }; + + // post request + PyInterp_Dispatcher::Get()->Exec( new InitializeReq( app, this ) ); +} + +/*! + \brief Activation of the module. + + This function is usually used in order to show the module's + specific menus and toolbars, update actions state and perform + other such actions required when the module is activated. + + Note, that returning \c false in this function prevents the + module activation. + + \param theStudy parent study + \return \c true if activation is successful and \c false otherwise +*/ +bool SALOME_PYQT_ModuleLight::activateModule( SUIT_Study* theStudy ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::activateModule()" ); + + // call base implementation + bool res = LightApp_Module::activateModule( theStudy ); + + if ( !res ) + return res; + + // internal activation + return activateModuleInternal( theStudy ); +} + +/*! + \brief Perform internal activation of the module. + + The only goal of this function is to extract common functionality + for LightApp_Module and SalomeApp_module classes requried by the + specific architecture aspects of "light" / "full" SALOME modes. + + \sa activateModule() +*/ +bool SALOME_PYQT_ModuleLight::activateModuleInternal( SUIT_Study* theStudy ) +{ + // reset the activation status to the default value + myLastActivateStatus = true; + + // perform internal activation + // ActivateReq: request class for internal activate() operation + class ActivateReq : public PyInterp_Request + { + public: + ActivateReq( SUIT_Study* _study, + SALOME_PYQT_ModuleLight* _obj ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myStudy ( _study ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->activate( myStudy ); + } + + private: + SUIT_Study* myStudy; + SALOME_PYQT_ModuleLight* myObj; + }; + + // post request + PyInterp_Dispatcher::Get()->Exec( new ActivateReq( theStudy, this ) ); + + // check activation status (set by activate()) + if ( !lastActivationStatus() ) + return false; + + // activate menus, toolbars, etc + if ( myXmlHandler ) myXmlHandler->activateMenus( true ); + setMenuShown( true ); + setToolShown( true ); + + // connect preferences changing signal + connect( getApp(), SIGNAL( preferenceChanged( const QString&, const QString&, const QString& ) ), + this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) ); + + // perform custom activation actions + // CustomizeReq: request class for internal customize() operation + class CustomizeReq : public PyInterp_Request + { + public: + CustomizeReq( SUIT_Study* _study, + SALOME_PYQT_ModuleLight* _obj ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myStudy ( _study ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->customize( myStudy ); + } + + private: + SUIT_Study* myStudy; + SALOME_PYQT_ModuleLight* myObj; + }; + + // post request + PyInterp_Dispatcher::Get()->Exec( new CustomizeReq( theStudy, this ) ); + + return true; +} + +/*! + \brief Deactivation of the module. + + This function is usually used in order to hide the module's + specific menus and toolbars and perform other such actions + required when the module is deactivated. + + \param theStudy parent study + \return \c true if deactivation is successful and \c false otherwise +*/ +bool SALOME_PYQT_ModuleLight::deactivateModule( SUIT_Study* theStudy ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::deactivateModule()" ); + + // disconnect preferences changing signal + disconnect( getApp(), SIGNAL( preferenceChanged( const QString&, const QString&, const QString& ) ), + this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) ); + + // perform internal deactivation + // DeactivateReq: request class for internal deactivate() operation + class DeactivateReq : public PyInterp_LockRequest + { + public: + DeactivateReq( PyInterp_Interp* _py_interp, + SUIT_Study* _study, + SALOME_PYQT_ModuleLight* _obj ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myStudy ( _study ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->deactivate( myStudy ); + } + + private: + SUIT_Study* myStudy; + SALOME_PYQT_ModuleLight* myObj; + }; + + // post request + PyInterp_Dispatcher::Get()->Exec( new DeactivateReq( myInterp, theStudy, this ) ); + + // deactivate menus, toolbars, etc + if ( myXmlHandler ) myXmlHandler->activateMenus( false ); + setMenuShown( false ); + setToolShown( false ); + + // call base implementation + return LightApp_Module::deactivateModule( theStudy ); +} + +/*! + \brief Get last activation status. + \return status of last module activation operation + \sa activateModule() +*/ +bool SALOME_PYQT_ModuleLight::lastActivationStatus() const +{ + return myLastActivateStatus; +} + +/*! + \breif Process application preferences changing. + + Called when any application setting is changed. + + \param module preference module + \param section preference resource file section + \param setting preference resource name +*/ +void SALOME_PYQT_ModuleLight::preferenceChanged( const QString& module, + const QString& section, + const QString& setting ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::preferenceChanged()" ); + + // perform synchronous request to Python event dispatcher + class Event : public PyInterp_LockRequest + { + public: + Event( PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + const QString& _section, + const QString& _setting ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj ( _obj ), + mySection( _section ), + mySetting( _setting ) {} + + protected: + virtual void execute() + { + myObj->prefChanged( mySection, mySetting ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + QString mySection, mySetting; + }; + + if ( module != moduleName() ) { + // module's own preferences are processed by preferencesChanged() method + // ... + // post the request only if dispatcher is not busy! + // execute request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new Event( myInterp, this, section, setting ) ); + } +} + +/*! + \brief Process study activation. + + Called when study desktop is activated. Used for notifying the Python + module about changing of the active study. +*/ +void SALOME_PYQT_ModuleLight::studyActivated() +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::studyActivated()" ); + + // StudyChangedReq: request class for internal studyChanged() operation + class StudyChangedReq : public PyInterp_Request + { + public: + StudyChangedReq( SUIT_Study* _study, + SALOME_PYQT_ModuleLight* _obj ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myStudy ( _study ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->studyChanged( myStudy ); + } + + private: + SUIT_Study* myStudy; + SALOME_PYQT_ModuleLight* myObj; + }; + + // post request + PyInterp_Dispatcher::Get()->Exec( new StudyChangedReq( application()->activeStudy(), this ) ); +} + +/*! + \brief Process GUI action (from main menu, toolbar or + context popup menu action). +*/ +void SALOME_PYQT_ModuleLight::onGUIEvent() +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::onGUIEvent()" ); + + // get sender action + QAction* action = qobject_cast( sender() ); + if ( !action ) + return; + + // get action ID + int id = actionId( action ); + fmsg.message( QString( "action id = %1" ).arg( id ) ); + + // perform synchronous request to Python event dispatcher + class GUIEvent : public PyInterp_LockRequest + { + public: + GUIEvent( PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + int _id ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myId ( _id ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->guiEvent( myId ); + } + + private: + int myId; + SALOME_PYQT_ModuleLight* myObj; + }; + + // post request + PyInterp_Dispatcher::Get()->Exec( new GUIEvent( myInterp, this, id ) ); +} + +/*! + \brief Process context popup menu request. + + Called when user activates popup menu in some window + (view, object browser, etc). + + \param theContext popup menu context (e.g. "ObjectBrowser") + \param thePopupMenu popup menu + \param title popup menu title (not used) +*/ +void SALOME_PYQT_ModuleLight::contextMenuPopup( const QString& theContext, + QMenu* thePopupMenu, + QString& /*title*/ ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::contextMenuPopup()" ); + fmsg.message( QString( "context: %1" ).arg( theContext ) ); + + // perform synchronous request to Python event dispatcher + class PopupMenuEvent : public PyInterp_LockRequest + { + public: + PopupMenuEvent( PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + const QString& _context, + QMenu* _popup ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myContext( _context ), + myPopup ( _popup ), + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->contextMenu( myContext, myPopup ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + QString myContext; + QMenu* myPopup; + }; + + // post request only if dispatcher is not busy! + // execute request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new PopupMenuEvent( myInterp, this, theContext, thePopupMenu ) ); +} + +/*! + \brief Export preferences for the Python module. + + Called only once when the first instance of the module is created. +*/ +void SALOME_PYQT_ModuleLight::createPreferences() +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::createPreferences()" ); + + // perform synchronous request to Python event dispatcher + class Event : public PyInterp_LockRequest + { + public: + Event( PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj ( _obj ) {} + + protected: + virtual void execute() + { + myObj->initPreferences(); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + }; + + // post request only if dispatcher is not busy! + // execute request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new Event( myInterp, this ) ); +} + +/*! + \brief Define the dockable windows associated with the module. + + To fill the list of windows the correspondind Python module's windows() + method is called from SALOME_PYQT_ModuleLight::init() method. + + By default, ObjectBrowser, PythonConsole and LogWindow windows are + associated to the module. + + Allowed dockable windows: + - LightApp_Application::WT_ObjectBrowser : object browser + - LightApp_Application::WT_PyConsole : python console + - LightApp_Application::WT_LogWindow : log messages output window + + Dock area is defined by Qt::DockWidgetArea enumeration: + - Qt::TopDockWidgetArea : top dock area + - Qt::BottomDockWidgetArea : bottom dock area + - Qt::LeftDockWidgetArea : left dock area + - Qt::RightDockWidgetArea : right dock area + + \param mappa map of dockable windows: { : } +*/ +void SALOME_PYQT_ModuleLight::windows( QMap& mappa ) const +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::windows()" ); + + mappa = myWindowsMap; +} + +/*! + \brief Define the compatible view windows associated with the module. + + The associated view windows are opened automatically when the module + is activated. + + To fill the list of views the correspondind Python module's views() + method is called from SALOME_PYQT_ModuleLight::init() method. + By default, the list is empty. + + \param listik list of view windows types +*/ +void SALOME_PYQT_ModuleLight::viewManagers( QStringList& lst ) const +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::viewManagers()" ); + + lst = myViewMgrList; +} + +/*! + \brief Process module's preferences changing. + + Called when the module's preferences are changed. + + \param section setting section + \param setting setting name +*/ +void SALOME_PYQT_ModuleLight::preferencesChanged( const QString& section, const QString& setting ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::preferencesChanged()" ); + + // perform synchronous request to Python event dispatcher + class Event : public PyInterp_LockRequest + { + public: + Event( PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + const QString& _section, + const QString& _setting ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj ( _obj ), + mySection( _section ), + mySetting( _setting ) {} + + protected: + virtual void execute() + { + myObj->prefChanged( mySection, mySetting ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + QString mySection, mySetting; + }; + + // post request only if dispatcher is not busy! + // execut request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new Event( myInterp, this, section, setting ) ); +} + +/*! + \brief Internal module initialization: + + Performs the following actions: + - initialize or get the Python interpreter (one per study) + - import the Python module + - pass the workspace widget to the Python module + - call Python module's initialize() method + - call Python module's windows() method + - call Python module's views() method + + \param app parent application object +*/ +void SALOME_PYQT_ModuleLight::init( CAM_Application* app ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::init()" ); + + // reset interpreter to NULL + myInterp = NULL; + + // get study Id + LightApp_Application* anApp = dynamic_cast( app ); + if ( !anApp ) + return; + LightApp_Study* aStudy = dynamic_cast( app->activeStudy() ); + if ( !aStudy ) + return; + int aStudyId = aStudy ? aStudy->id() : 0; + + // initialize Python subinterpreter (on per study) and put it in variable + initInterp( aStudyId ); + if ( !myInterp ) + return; // Error + + // import Python GUI module + importModule(); + if ( !myModule ) + return; // Error + + // this module is being activated now! + myInitModule = this; + + // then call Python module's initialize() method + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + // ... (the Python module is already imported) + // ... finally call Python module's initialize() method + if ( PyObject_HasAttrString( myModule, (char*)"initialize" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"initialize", (char*)"" ) ); + if ( !res ) { + PyErr_Print(); + } + } + + // get required dockable windows list from the Python module + // by calling windows() method + // ... first put default values + myWindowsMap.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea ); + myWindowsMap.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea ); + myWindowsMap.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea ); + + if ( PyObject_HasAttrString( myModule , (char*)"windows" ) ) { + PyObjWrapper res1( PyObject_CallMethod( myModule, (char*)"windows", (char*)"" ) ); + if ( !res1 ) { + PyErr_Print(); + } + else { + myWindowsMap.clear(); + if ( PyDict_Check( res1 ) ) { + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + while ( PyDict_Next( res1, &pos, &key, &value ) ) { + // parse the return value + // it should be a map: {integer:integer} + int aKey, aValue; + if( key && PyInt_Check( key ) && value && PyInt_Check( value ) ) { + aKey = PyInt_AsLong( key ); + aValue = PyInt_AsLong( value ); + myWindowsMap[ aKey ] = aValue; + } + } + } + } + } + + // get compatible view windows types from the Python module + // by calling views() method + if ( PyObject_HasAttrString( myModule , (char*)"views" ) ) { + PyObjWrapper res2( PyObject_CallMethod( myModule, (char*)"views", (char*)"" ) ); + if ( !res2 ) { + PyErr_Print(); + } + else { + // parse the return value + // result can be one string... + if ( PyString_Check( res2 ) ) { + myViewMgrList.append( PyString_AsString( res2 ) ); + } + // ... or list of strings + else if ( PyList_Check( res2 ) ) { + int size = PyList_Size( res2 ); + for ( int i = 0; i < size; i++ ) { + PyObject* value = PyList_GetItem( res2, i ); + if( value && PyString_Check( value ) ) { + myViewMgrList.append( PyString_AsString( value ) ); + } + } + } + } + } + // module is already activated! + myInitModule = 0; +} + +/*! + \brief Internal activation: + + Performs the following actions: + - initialize or get the Python interpreter (one per study) + - import the Python GUI module + - call Python module's activate() method + + \param theStudy parent study object +*/ +void SALOME_PYQT_ModuleLight::activate( SUIT_Study* theStudy ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::activate()" ); + + // get study Id + LightApp_Study* aStudy = dynamic_cast( theStudy ); + int aStudyId = aStudy ? aStudy->id() : 0; + + // initialize Python subinterpreter (on per study) and put it in variable + initInterp( aStudyId ); + if ( !myInterp ) { + myLastActivateStatus = false; + return; // Error + } + + // import Python GUI module + importModule(); + if ( !myModule ) { + myLastActivateStatus = false; + return; // Error + } + + // get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + + // call Python module's activate() method (for the new modules) + if ( PyObject_HasAttrString( myModule , (char*)"activate" ) ) { + PyObject* res1 = PyObject_CallMethod( myModule, (char*)"activate", (char*)"" ); + if ( !res1 || !PyBool_Check( res1 ) ) { + PyErr_Print(); + // always true for old modules (no return value) + myLastActivateStatus = true; + } + else { + // detect return status + myLastActivateStatus = PyObject_IsTrue( res1 ); + } + } + + // Connect the SUIT_Desktop signal windowActivated() to this->onActiveViewChanged() + SUIT_Desktop* aDesk = theStudy->application()->desktop(); + if ( aDesk ) + { + connect( aDesk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ), + this, SLOT( onActiveViewChanged( SUIT_ViewWindow* ) ) ); + // If a active window exists send activeViewChanged + // If a getActiveView() in SalomePyQt available we no longer need this + SUIT_ViewWindow* aView = aDesk->activeWindow(); + if ( aView ) + activeViewChanged( aView ); + + // get all view currently opened in the study and connect their signals to + // the corresponding slots of the class. + QList wndList = aDesk->windows(); + SUIT_ViewWindow* wnd; + foreach ( wnd, wndList ) + connectView( wnd ); + } +} + +/*! + \brief Additional customization after module is activated: + + Performs the following actions: + - get the Python interpreter (one per study) + - import the Python GUI module + - call Python module's setSettings() method (obsolete function, + used for compatibility with old code) + + \param theStudy parent study object +*/ +void SALOME_PYQT_ModuleLight::customize( SUIT_Study* theStudy ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::customize()" ); + + // get study Id + LightApp_Study* aStudy = dynamic_cast( theStudy ); + int aStudyId = aStudy ? aStudy->id() : 0; + + // initialize Python subinterpreter (on per study) and put it in variable + initInterp( aStudyId ); + if ( !myInterp ) + return; // Error + + // import Python GUI module + importModule(); + if ( !myModule ) + return; // Error + + if ( IsCallOldMethods ) { + // call Python module's setWorkspace() method + setWorkSpace(); + } + + // get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + + if ( IsCallOldMethods ) { + // call Python module's setSettings() method (obsolete) + if ( PyObject_HasAttrString( myModule , (char*)"setSettings" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"setSettings", (char*)"" ) ); + if( !res ) { + PyErr_Print(); + } + } + } +} + +/*! + \brief Internal deactivation: + + Performs the following actions: + - call Python module's deactivate() method + + \param theStudy parent study object +*/ +void SALOME_PYQT_ModuleLight::deactivate( SUIT_Study* theStudy ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::deactivate()" ); + + // check if the subinterpreter is initialized and Python module is imported + if ( !myInterp || !myModule ) { + // Error! Python subinterpreter should be initialized and module should be imported first! + return; + } + // then call Python module's deactivate() method + if ( PyObject_HasAttrString( myModule , (char*)"deactivate" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"deactivate", (char*)"" ) ); + if( !res ) { + PyErr_Print(); + } + } + + // Disconnect the SUIT_Desktop signal windowActivated() + SUIT_Desktop* aDesk = theStudy->application()->desktop(); + if ( aDesk ) + { + disconnect( aDesk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ), + this, SLOT( onActiveViewChanged( SUIT_ViewWindow* ) ) ); + } +} + +/*! + \brief Perform internal actions when active study is changed. + + Called when active the study is actived (user brings its + desktop to top): + - initialize or get the Python interpreter (one per study) + - import the Python GUI module + - call Python module's activeStudyChanged() method + + \param theStudy study being activated +*/ +void SALOME_PYQT_ModuleLight::studyChanged( SUIT_Study* theStudy ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::studyChanged()" ); + + // get study Id + LightApp_Study* aStudy = dynamic_cast( theStudy ); + int aStudyId = aStudy ? aStudy->id() : 0; + + // initialize Python subinterpreter (on per study) and put it in variable + initInterp( aStudyId ); + if ( !myInterp ) + return; // Error + + // import Python GUI module + importModule(); + if ( !myModule ) + return; // Error + + if ( IsCallOldMethods ) { + // call Python module's setWorkspace() method + setWorkSpace(); + } + + // get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + + // call Python module's activeStudyChanged() method + if ( PyObject_HasAttrString( myModule, (char*)"activeStudyChanged" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"activeStudyChanged", (char*)"i", aStudyId ) ); + if( !res ) { + PyErr_Print(); + } + } +} + +/*! + \brief Process (internally) context popup menu request. + + Performs the following actions: + - calls Python module's definePopup(...) method (obsolete function, + used for compatibility with old code) to define the popup menu context + - parses XML resourses file (if exists) and fills the popup menu with the items) + - calls Python module's customPopup(...) method (obsolete function, + used for compatibility with old code) to allow module to customize the popup menu + - for new modules calls createPopupMenu() function to allow the + modules to build the popup menu by using insertItem(...) Qt functions. + + \param theContext popup menu context + \param thePopupMenu popup menu +*/ +void SALOME_PYQT_ModuleLight::contextMenu( const QString& theContext, QMenu* thePopupMenu ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::contextMenu()" ); + + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule ) + return; + + QString aContext( "" ), aObject( "" ), aParent( theContext ); + + if ( IsCallOldMethods && PyObject_HasAttrString( myModule, (char*)"definePopup" ) ) { + // call definePopup() Python module's function + // this is obsolete function, used only for compatibility reasons + PyObjWrapper res( PyObject_CallMethod( myModule, + (char*)"definePopup", + (char*)"sss", + theContext.toLatin1().constData(), + aObject.toLatin1().constData(), + aParent.toLatin1().constData() ) ); + if( !res ) { + PyErr_Print(); + } + else { + // parse return value + char *co, *ob, *pa; + if( PyArg_ParseTuple( res, "sss", &co, &ob, &pa ) ) { + aContext = co; + aObject = ob; + aParent = pa; + } + } + } // if ( IsCallOldMethods ... ) + + // first try to create menu via XML parser: + // we create popup menus without help of QtxPopupMgr + if ( myXmlHandler ) + myXmlHandler->createPopup( thePopupMenu, aContext, aParent, aObject ); + +#if SIP_VERSION < 0x040800 + PyObjWrapper sipPopup( sipBuildResult( 0, "M", thePopupMenu, sipClass_QMenu) ); +#else + PyObjWrapper sipPopup( sipBuildResult( 0, "D", thePopupMenu, sipType_QMenu, NULL) ); +#endif + + // then call Python module's createPopupMenu() method (for new modules) + if ( PyObject_HasAttrString( myModule, (char*)"createPopupMenu" ) ) { + PyObjWrapper res1( PyObject_CallMethod( myModule, + (char*)"createPopupMenu", + (char*)"Os", + sipPopup.get(), + theContext.toLatin1().constData() ) ); + if( !res1 ) { + PyErr_Print(); + } + } + + if ( IsCallOldMethods && PyObject_HasAttrString( myModule, (char*)"customPopup" ) ) { + // call customPopup() Python module's function + // this is obsolete function, used only for compatibility reasons + PyObjWrapper res2( PyObject_CallMethod( myModule, + (char*)"customPopup", + (char*)"Osss", + sipPopup.get(), + aContext.toLatin1().constData(), + aObject.toLatin1().constData(), + aParent.toLatin1().constData() ) ); + if( !res2 ) { + PyErr_Print(); + } + } +} + +/*! + \brief Internal GUI event handling. + + Performs the following actions: + - calls Python module's OnGUIEvent() method + + \param theId GUI action ID +*/ +void SALOME_PYQT_ModuleLight::guiEvent( const int theId ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::guiEvent()" ); + + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule ) + return; + + if ( PyObject_HasAttrString( myModule, (char*)"OnGUIEvent" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"OnGUIEvent", (char*)"i", theId ) ); + if( !res ) { + PyErr_Print(); + } + } +} + +/*! + \brief Initialize (internally) preferences for the module. + + Performs the following actions: + - calls Python module's createPreferences() method +*/ +void SALOME_PYQT_ModuleLight::initPreferences() +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::initPreferences()" ); + + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule ) + return; + + // temporary set myInitModule because createPreferences() method + // might be called during the module intialization process + myInitModule = this; + + if ( PyObject_HasAttrString( myModule, (char*)"createPreferences" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"createPreferences", (char*)"" ) ); + if( !res ) { + PyErr_Print(); + } + } + + myInitModule = 0; +} + +/*! + \brief Initialize python subinterpreter (one per study). + \param theStudyId study ID +*/ +void SALOME_PYQT_ModuleLight::initInterp( int theStudyId ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::initInterp()" ); + + // check study Id + if ( !theStudyId ) { + // Error! Study Id must not be 0! + myInterp = NULL; + return; + } + // try to find the subinterpreter + if( myInterpMap.contains( theStudyId ) ) { + // found! + myInterp = myInterpMap[ theStudyId ]; + return; + } + + myInterp = new SALOME_PYQT_PyInterp(); + if(!myInterp) + return; + + myInterp->initialize(); + myInterpMap[ theStudyId ] = myInterp; + +#ifndef GUI_DISABLE_CORBA + if(!SUIT_PYTHON::initialized) { + // import 'salome' module and call 'salome_init' method; + // do it only once on interpreter creation + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + // ... then import a module + PyObjWrapper aMod = PyImport_ImportModule( "salome" ); + if( !aMod ) { + // Error! + PyErr_Print(); + return; + } + // ... then call a method + int embedded = 1; + PyObjWrapper aRes( PyObject_CallMethod( aMod, (char*)"salome_init", (char*)"ii", theStudyId, embedded ) ); + if( !aRes ) { + // Error! + PyErr_Print(); + return; + } + } +#endif +} + +/*! + \brief Import Python GUI module and remember the reference to the module. + + Attention! initInterp() should be called first!!! +*/ +void SALOME_PYQT_ModuleLight::importModule() +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::importModule()" ); + + // check if the subinterpreter is initialized + if ( !myInterp ) { + // Error! Python subinterpreter should be initialized first! + myModule = 0; + return; + } + // import Python GUI module and puts it in attribute + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + // ... then import a module + QString aMod = name() + "GUI"; + try { + myModule = PyImport_ImportModule( aMod.toLatin1().data() ); + } + catch (...) { + } + if( !myModule ) { + // Error! + PyErr_Print(); + return; + } +} + +/*! + \brief Set study workspace to the Python module. + + Calls setWorkSpace() method of the Pythohn module with + PyQt QWidget object to use with interpreter. + + Attention! initInterp() and importModule() should be called first!!! +*/ +void SALOME_PYQT_ModuleLight::setWorkSpace() +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::setWorkSpace()" ); + + // check if the subinterpreter is initialized and Python module is imported + if ( !myInterp || !myModule ) { + // Error! Python subinterpreter should be initialized and module should be imported first! + return; + } + + // call setWorkspace() method + // ... first get python lock + PyLockWrapper aLock = myInterp->GetLockWrapper(); + + // ... then try to import SalomePyQt module. If it's not possible don't go on. + PyObjWrapper aQtModule( PyImport_ImportModule( "SalomePyQt" ) ); + if( !aQtModule ) { + // Error! + PyErr_Print(); + return; + } + + if ( IsCallOldMethods ) { + // ... then get workspace object + QWidget* aWorkspace = 0; + if ( getApp()->desktop()->inherits( "STD_MDIDesktop" ) ) { + STD_MDIDesktop* aDesktop = dynamic_cast( getApp()->desktop() ); + if ( aDesktop ) + aWorkspace = aDesktop->workspace(); + } + else if ( getApp()->desktop()->inherits( "STD_TabDesktop" ) ) { + STD_TabDesktop* aDesktop = dynamic_cast( getApp()->desktop() ); + if ( aDesktop ) + aWorkspace = aDesktop->workstack(); + } +#if SIP_VERSION < 0x040800 + PyObjWrapper pyws( sipBuildResult( 0, "M", aWorkspace, sipClass_QWidget) ); +#else + PyObjWrapper pyws( sipBuildResult( 0, "D", aWorkspace, sipType_QWidget , NULL) ); +#endif + // ... and finally call Python module's setWorkspace() method (obsolete) + if ( PyObject_HasAttrString( myModule, (char*)"setWorkSpace" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"setWorkSpace", (char*)"O", pyws.get() ) ); + if( !res ) { + PyErr_Print(); + } + } + } +} + +/*! + \brief Preference changing callback function (internal). + + Performs the following actions: + - call Python module's preferenceChanged() method + + \param section setting section name + \param setting setting name +*/ +void SALOME_PYQT_ModuleLight::prefChanged( const QString& section, const QString& setting ) +{ + FuncMsg fmsg( "SALOME_PYQT_ModuleLight::prefChanged()" ); + + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule ) + return; + + if ( PyObject_HasAttrString( myModule, (char*)"preferenceChanged" ) ) { + PyObjWrapper res( PyObject_CallMethod( myModule, + (char*)"preferenceChanged", + (char*)"ss", + section.toLatin1().constData(), + setting.toLatin1().constData() ) ); + if( !res ) { + PyErr_Print(); + } + } +} + +/*! + \brief Get default menu group identifier + \return menu group ID (40 by default) +*/ +int SALOME_PYQT_ModuleLight::defaultMenuGroup() +{ + return DEFAULT_GROUP; +} + +// +// The next methods call the parent implementation. +// This is done to open protected methods from CAM_Module class. +// + +/*! + \brief Create toolbar with specified \a name. + \param name toolbar name + \return toolbar ID or -1 if toolbar creation is failed +*/ +int SALOME_PYQT_ModuleLight::createTool( const QString& name ) +{ + return LightApp_Module::createTool( name ); +} + +/*! + \brief Insert action with specified \a id to the toolbar. + \param id action ID + \param tBar toolbar ID + \param idx required index in the toolbar + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createTool( const int id, const int tBar, const int idx ) +{ + return LightApp_Module::createTool( id, tBar, idx ); +} + +/*! + \brief Insert action with specified \a id to the toolbar. + \param id action ID + \param tBar toolbar name + \param idx required index in the toolbar + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createTool( const int id, const QString& tBar, const int idx ) +{ + return LightApp_Module::createTool( id, tBar, idx ); +} + +/*! + \brief Insert action to the toolbar. + \param a action + \param tBar toolbar ID + \param id required action ID + \param idx required index in the toolbar + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createTool( QAction* a, const int tBar, const int id, const int idx ) +{ + return LightApp_Module::createTool( a, tBar, id, idx ); +} + +/*! + \brief Insert action to the toolbar. + \param a action + \param tBar toolbar name + \param id required action ID + \param idx required index in the toolbar + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createTool( QAction* a, const QString& tBar, const int id, const int idx ) +{ + return LightApp_Module::createTool( a, tBar, id, idx ); +} + +/*! + \brief Create main menu. + \param subMenu menu name + \param menu parent menu ID + \param id required menu ID + \param group menu group ID + \param idx required index in the menu + \return menu ID or -1 if menu could not be added +*/ +int SALOME_PYQT_ModuleLight::createMenu( const QString& subMenu, const int menu, const int id, const int group, const int idx ) +{ + return LightApp_Module::createMenu( subMenu, menu, id, group, idx ); +} + +/*! + \brief Create main menu. + \param subMenu menu name + \param menu parent menu name (list of menu names separated by "|") + \param id required menu ID + \param group menu group ID + \param idx required index in the menu + \return menu ID or -1 if menu could not be added +*/ +int SALOME_PYQT_ModuleLight::createMenu( const QString& subMenu, const QString& menu, const int id, const int group, const int idx ) +{ + return LightApp_Module::createMenu( subMenu, menu, id, group, idx ); +} + +/*! + \brief Insert action to the main menu. + \param id action ID + \param menu parent menu ID + \param group menu group ID + \param idx required index in the menu + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createMenu( const int id, const int menu, const int group, const int idx ) +{ + return LightApp_Module::createMenu( id, menu, group, idx ); +} + +/*! + \brief Insert action to the main menu. + \param id action ID + \param menu parent menu name (list of menu names separated by "|") + \param group menu group ID + \param idx required index in the menu + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createMenu( const int id, const QString& menu, const int group, const int idx ) +{ + return LightApp_Module::createMenu( id, menu, group, idx ); +} + +/*! + \brief Insert action to the main menu. + \param a action + \param menu parent menu ID + \param group menu group ID + \param idx required index in the menu + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createMenu( QAction* a, const int menu, const int id, const int group, const int idx ) +{ + return LightApp_Module::createMenu( a, menu, id, group, idx ); +} + +/*! + \brief Insert action to the main menu. + \param a action + \param menu parent menu name (list of menu names separated by "|") + \param group menu group ID + \param idx required index in the menu + \return action ID or -1 if action could not be added +*/ +int SALOME_PYQT_ModuleLight::createMenu( QAction* a, const QString& menu, const int id, const int group, const int idx ) +{ + return LightApp_Module::createMenu( a, menu, id, group, idx ); +} + +/*! + \brief Create separator action which can be used in the menu or toolbar. + \return new separator action +*/ +QAction* SALOME_PYQT_ModuleLight::separator() +{ + return LightApp_Module::separator(); +} + +/*! + \brief Get action by specified \a id. + \return action or 0 if it is not found +*/ +QAction* SALOME_PYQT_ModuleLight::action( const int id ) const +{ + QAction* a = LightApp_Module::action( id ); + if ( !a ) { + // try menu + QMenu* m = menuMgr()->findMenu( id ); + if ( m ) a = m->menuAction(); + } + return a; +} + +/*! + \brief Get action identifier. + \return action ID or -1 if action is not registered +*/ +int SALOME_PYQT_ModuleLight::actionId( const QAction* a ) const +{ + return LightApp_Module::actionId( a ); +} + +/*! + \brief Create new action. + + If the action with specified identifier already registered + it is not created, but its attributes are only modified. + + \param id action ID + \param text tooltip text + \param icon icon + \param menu menu text + \param tip status tip + \param key keyboard shortcut + \param toggle \c true for checkable action + \return created action +*/ +QAction* SALOME_PYQT_ModuleLight::createAction( const int id, const QString& text, const QString& icon, + const QString& menu, const QString& tip, const int key, + const bool toggle, QObject* parent ) +{ + QIcon anIcon = loadIcon( icon ); + QAction* a = action( id ); + if ( a ) { + if ( a->toolTip().isEmpty() && !text.isEmpty() ) a->setToolTip( text ); + if ( a->text().isEmpty() && !menu.isEmpty() ) a->setText( menu ); + if ( a->icon().isNull() && !anIcon.isNull() ) a->setIcon( anIcon ); + if ( a->statusTip().isEmpty() && !tip.isEmpty() ) a->setStatusTip( tip ); + if ( a->shortcut().isEmpty() && key ) a->setShortcut( key ); + if ( a->isCheckable() != toggle ) a->setCheckable( toggle ); + disconnect( a, SIGNAL( triggered( bool ) ), this, SLOT( onGUIEvent() ) ); + connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onGUIEvent() ) ); + } + else { + a = LightApp_Module::createAction( id, + text, + anIcon, + menu, + tip, + key, + parent ? parent : this, + toggle, + this, + SLOT( onGUIEvent() ) ); + } + return a; +} + +/*! + \brief Create new action group. + + If the action with specified identifier already registered + it is not created, but its attributes are only modified. + + \param id action ID + \param text tooltip text + \param icon icon + \param menu menu text + \param tip status tip + \param key keyboard shortcut + \param toggle \c true for checkable action + \return created action +*/ +QtxActionGroup* SALOME_PYQT_ModuleLight::createActionGroup(const int id, const bool exclusive) +{ + QtxActionGroup* a = qobject_cast( action( id ) ); + if ( !a ) { + a = new QtxActionGroup( this ); + LightApp_Module::registerAction( id, a ); + } + a->setExclusive( exclusive ); + return a; +} + +/*! + \brief Load icon from resource file. + \param fileName icon file name + \return icon (null icon if loading failed) +*/ +QIcon SALOME_PYQT_ModuleLight::loadIcon( const QString& fileName ) +{ + QIcon anIcon; + if ( !fileName.isEmpty() ) { + QPixmap pixmap = getApp()->resourceMgr()->loadPixmap( name(), tr( fileName.toLatin1() ) ); + if ( !pixmap.isNull() ) + anIcon = QIcon( pixmap ); + } + return anIcon; +} + +/*! + \brief Add global application preference (for example, + application specific section). + \param label preference name + \return preference ID +*/ +int SALOME_PYQT_ModuleLight::addGlobalPreference( const QString& label ) +{ + LightApp_Preferences* pref = preferences(); + if ( !pref ) + return -1; + + return pref->addPreference( label, -1 ); +} + +/*! + \brief Add preference. + \param label preference name + \return preference ID +*/ +int SALOME_PYQT_ModuleLight::addPreference( const QString& label ) +{ + return LightApp_Module::addPreference( label ); +} + +/*! + \brief Add preference. + \param label preference name + \param pId parent preference ID + \param type preference type + \param section resource file section name + \param param resource file setting name + \return preference ID +*/ +int SALOME_PYQT_ModuleLight::addPreference( const QString& label, + const int pId, const int type, + const QString& section, + const QString& param ) +{ + return LightApp_Module::addPreference( label, pId, type, section, param ); +} + +/*! + \brief Get the preference property. + \param id preference ID + \param prop property name + \return property value (invalid QVariant() if property is not found) +*/ +QVariant SALOME_PYQT_ModuleLight::preferenceProperty( const int id, + const QString& prop ) const +{ + QVariant v = LightApp_Module::preferenceProperty( id, prop ); + return v; +} + +/*! + \brief Set the preference property. + \param id preference ID + \param prop property name + \param var property value +*/ +void SALOME_PYQT_ModuleLight::setPreferenceProperty( const int id, + const QString& prop, + const QVariant& var ) +{ + LightApp_Module::setPreferenceProperty( id, prop, var ); +} + + +/*! + \brief Signal handler windowActivated(SUIT_ViewWindow*) of SUIT_Desktop + \param pview view being activated +*/ +void SALOME_PYQT_ModuleLight::onActiveViewChanged( SUIT_ViewWindow* pview ) +{ + class ActiveViewChange : public PyInterp_LockRequest + { + public: + ActiveViewChange( PyInterp_Interp* _py_interp, SALOME_PYQT_ModuleLight* _obj, const SUIT_ViewWindow* _pview ) + : PyInterp_LockRequest( _py_interp, 0, true ), + myObj(_obj),myView(_pview) {} + + protected: + virtual void execute() + { + myObj->activeViewChanged( myView ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + const SUIT_ViewWindow * myView; + }; + + PyInterp_Dispatcher::Get()->Exec( new ActiveViewChange( myInterp, this, pview ) ); +} + +/*! + \brief Processes the view changing, calls Python module's activeViewChanged() method + \param pview view being activated +*/ +void SALOME_PYQT_ModuleLight::activeViewChanged( const SUIT_ViewWindow* pview ) +{ + if ( !myInterp || !myModule ) + return; + + // Do not use SUIT_ViewWindow::closing() signal here. View manager reacts on + // this signal and deletes view. So our slot does not works if it is connected + // on this signal. SUIT_ViewManager::deleteView(SUIT_ViewWindow*) is used here + + connectView( pview ); + + if ( PyObject_HasAttrString( myModule, (char*)"activeViewChanged" ) ) + { + if ( !pview ) + return; + + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"activeViewChanged", (char*)"i" , pview->getId() ) ); + if( !res ) + PyErr_Print(); + } +} + +/*! + \brief Signal handler cloneView() of OCCViewer_ViewWindow + \param pview view being cloned +*/ +void SALOME_PYQT_ModuleLight::onViewCloned( SUIT_ViewWindow* pview ) +{ + class ViewClone : public PyInterp_LockRequest + { + public: + ViewClone( PyInterp_Interp* _py_interp, SALOME_PYQT_ModuleLight* _obj, const SUIT_ViewWindow* _pview ) + : PyInterp_LockRequest( _py_interp, 0, true ), + myObj(_obj), myView(_pview) {} + + protected: + virtual void execute() + { + myObj->viewCloned( myView ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + const SUIT_ViewWindow* myView; + }; + + PyInterp_Dispatcher::Get()->Exec( new ViewClone( myInterp, this, pview ) ); +} + +/*! + \brief Processes the view cloning, calls Python module's activeViewCloned() method + \param pview view being cloned +*/ +void SALOME_PYQT_ModuleLight::viewCloned( const SUIT_ViewWindow* pview ) +{ + if ( !myInterp || !myModule || !pview ) + return; + + if ( PyObject_HasAttrString( myModule, (char*)"viewCloned" ) ) + { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"viewCloned", (char*)"i", pview->getId() ) ); + if( !res ) + PyErr_Print(); + } +} + +/*! + \brief Signal handler tryClose(SUIT_ViewWindow*) of a view + \param pview view being closed +*/ +void SALOME_PYQT_ModuleLight::onViewTryClose( SUIT_ViewWindow* pview ) +{ + class ViewTryClose : public PyInterp_LockRequest + { + public: + ViewTryClose( PyInterp_Interp* _py_interp, SALOME_PYQT_ModuleLight* _obj, const SUIT_ViewWindow* _pview ) + : PyInterp_LockRequest( _py_interp, 0, true ), + myObj(_obj),myView(_pview) {} + + protected: + virtual void execute() + { + myObj->viewTryClose( myView ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + const SUIT_ViewWindow * myView; + }; + + PyInterp_Dispatcher::Get()->Exec( new ViewTryClose( myInterp, this, pview ) ); +} + +/*! + \brief Processes the view closing attempt, calls Python module's viewTryClose() method + \param pview view user tries to close +*/ +void SALOME_PYQT_ModuleLight::viewTryClose( const SUIT_ViewWindow* pview ) +{ + if ( !myInterp || !myModule ) + return; + + if ( PyObject_HasAttrString( myModule, (char*)"viewTryClose" ) ) + { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"viewTryClose", (char*)"i", pview->getId() ) ); + if ( !res ) + { + PyErr_Print(); + } + } +} + +/*! + \brief Signal handler closing(SUIT_ViewWindow*) of a view + \param pview view being closed +*/ +void SALOME_PYQT_ModuleLight::onViewClosed( SUIT_ViewWindow* pview ) +{ + class ViewClose : public PyInterp_LockRequest + { + public: + ViewClose( PyInterp_Interp* _py_interp, SALOME_PYQT_ModuleLight* _obj, const SUIT_ViewWindow* _pview ) + : PyInterp_LockRequest( _py_interp, 0, true ), + myObj(_obj),myView(_pview) {} + + protected: + virtual void execute() + { + myObj->viewClosed( myView ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + const SUIT_ViewWindow * myView; + }; + + PyInterp_Dispatcher::Get()->Exec( new ViewClose( myInterp, this, pview ) ); +} + +/*! + \brief Processes the view closing, calls Python module's viewClosed() method + \param pview view being closed +*/ +void SALOME_PYQT_ModuleLight::viewClosed( const SUIT_ViewWindow* pview ) +{ + if ( !myInterp || !myModule ) + return; + + if ( PyObject_HasAttrString( myModule, (char*)"viewClosed" ) ) + { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"viewClosed", (char*)"i", pview->getId() ) ); + if ( !res ) + { + PyErr_Print(); + } + } +} + +/*! + \brief Connects or disconnects signals about activating and cloning view on the module slots + \param pview view which is connected/disconnected +*/ +void SALOME_PYQT_ModuleLight::connectView( const SUIT_ViewWindow* pview ) +{ + SUIT_ViewManager* viewMgr = pview->getViewManager(); + SUIT_ViewModel* viewModel = viewMgr ? viewMgr->getViewModel() : 0; + + if ( viewMgr ) + { + disconnect( viewMgr, SIGNAL( tryCloseView( SUIT_ViewWindow* ) ), + this, SLOT( onViewTryClose( SUIT_ViewWindow* ) ) ); + disconnect( viewMgr, SIGNAL( deleteView( SUIT_ViewWindow* ) ), + this, SLOT( onViewClosed( SUIT_ViewWindow* ) ) ); + + connect( viewMgr, SIGNAL( tryCloseView( SUIT_ViewWindow* ) ), + this, SLOT( onViewTryClose( SUIT_ViewWindow* ) ) ); + connect( viewMgr, SIGNAL( deleteView( SUIT_ViewWindow* ) ), + this, SLOT( onViewClosed( SUIT_ViewWindow* ) ) ); + } + + // Connect cloneView() signal of an OCC View + if ( pview->inherits( "OCCViewer_ViewWindow" ) ) + { + disconnect( pview, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), + this, SLOT( onViewCloned( SUIT_ViewWindow* ) ) ); + connect( pview, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), + this, SLOT( onViewCloned( SUIT_ViewWindow* ) ) ); + } + // Connect cloneView() signal of Plot2d View manager + else if ( viewModel && viewModel->inherits( "Plot2d_Viewer" ) ) + { + disconnect( viewModel, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), + this, SLOT( onViewCloned( SUIT_ViewWindow* ) ) ); + connect( viewModel, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), + this, SLOT( onViewCloned( SUIT_ViewWindow* ) ) ); + } +} + +/*! + \brief Get tag name for the DOM element. + \param element DOM element + \return empty string if the element does not have tag name + \internal +*/ +static QString tagName( const QDomElement& element ) +{ + return element.tagName().trimmed(); +} + +/*! + \brief Get DOM element's attribute by its name. + \param element DOM element + \param attName attribute name + \return empty string if the element does not have such attribute + \internal +*/ +static QString attribute( const QDomElement& element, const QString& attName ) +{ + return element.attribute( attName ).trimmed(); +} + +/*! + \brief Inspect specified string for the boolean value. + + This function returns \c true if string represents boolean value: + - "true", "yes" or "1" for \c true + - "false", "no" or "0" for \c false + Second parameter allows to specify what boolean value is expected: + - 1: \c true + - 0: \c false + - other value is not taken into account (return represented value) + + \param value inspected string + \param check expected boolean value + \return boolean value represented by the string (\a check is not 1 or 0) + or \c true if value correspond to the specified \a check +*/ +static bool checkBool( const QString& value, const int check = -1 ) +{ + QString v = value.toLower(); + if ( ( v == "true" || v == "yes" || v == "1" ) && ( check != 0 ) ) + return true; + if ( ( v == "false" || v == "no" || v == "0" ) && ( check == 0 ) ) + return true; + return false; +} + +/*! + \brief Inspect specified string for the integer value. + + This function returns returns -1 if item is empty or represents + an invalid number. + \param value inspected string + \param def default value + \param shift shift value (it is added to the integer value to produce shifted result) +*/ +static int checkInt( const QString& value, const int def = -1, const int shift = -1 ) +{ + bool bOk; + int val = value.toInt( &bOk ); + if ( !bOk ) val = def; + if ( shift > 0 && bOk && val < 0 ) + val += shift; + return val; +} + +/*! + \brief Constructor + \internal + \param module parent module pointer + \param fileName XML file path +*/ +SALOME_PYQT_ModuleLight::XmlHandler::XmlHandler( SALOME_PYQT_ModuleLight* module, + const QString& fileName ) +: myModule( module ) +{ + if ( fileName.isEmpty() ) + return; + QFile aFile( fileName ); + if ( !aFile.open( QIODevice::ReadOnly ) ) + return; + myDoc.setContent( &aFile ); + aFile.close(); +} + +/*! + \brief Parse XML file and create actions. + \internal + + Called by SALOME_PYQT_ModuleLight::activate() in order to create actions + (menus, toolbars). +*/ +void SALOME_PYQT_ModuleLight::XmlHandler::createActions() +{ + // get document element + QDomElement aDocElem = myDoc.documentElement(); + + // create main menu actions + QDomNodeList aMenuList = aDocElem.elementsByTagName( "menu-item" ); + for ( int i = 0; i < aMenuList.count(); i++ ) { + QDomNode n = aMenuList.item( i ); + createMenu( n ); + } + + // create toolbars actions + QDomNodeList aToolsList = aDocElem.elementsByTagName( "toolbar" ); + for ( int i = 0; i < aToolsList.count(); i++ ) { + QDomNode n = aToolsList.item( i ); + createToolBar( n ); + } +} + +/*! + \brief Create popup menu. + \internal + \param menu popup menu + \param context popup menu context + \param context popup menu parent object name + \param context popup menu object name +*/ +void SALOME_PYQT_ModuleLight::XmlHandler::createPopup( QMenu* menu, + const QString& context, + const QString& parent, + const QString& object ) +{ + // get document element + QDomElement aDocElem = myDoc.documentElement(); + + // get popup menus actions + QDomNodeList aPopupList = aDocElem.elementsByTagName( "popupmenu" ); + for ( int i = 0; i < aPopupList.count(); i++ ) { + QDomNode n = aPopupList.item( i ); + if ( !n.isNull() && n.isElement() ) { + QDomElement e = n.toElement(); + // QString lab = attribute( e, "label-id" ); // not used // + QString ctx = attribute( e, "context-id" ); + QString prt = attribute( e, "parent-id" ); + QString obj = attribute( e, "object-id" ); + if ( ctx == context && prt == parent && obj == object ) { + insertPopupItems( n, menu ); + break; + } + } + } +} + +/*! + \brief Activate menus + \internal + \param enable if \c true menus are activated, otherwise menus are deactivated +*/ +void SALOME_PYQT_ModuleLight::XmlHandler::activateMenus( bool enable ) +{ + if ( !myModule ) + return; + + QtxActionMenuMgr* mgr = myModule->menuMgr(); + int id; + foreach( id, myMenuItems ) mgr->setEmptyEnabled( id, enable ); +} + +/*! + \brief Create main menu item and insert actions to it. + \internal + \param parentNode XML node with menu description + \param parentMenuId parent menu ID (-1 for top-level menu) + \param parentPopup parent popup menu (0 for top-level menu) +*/ +void SALOME_PYQT_ModuleLight::XmlHandler::createMenu( QDomNode& parentNode, + const int parentMenuId, + QMenu* parentPopup ) +{ + if ( !myModule || parentNode.isNull() ) + return; + + QDomElement parentElement = parentNode.toElement(); + if ( !parentElement.isNull() ) { + QString plabel = attribute( parentElement, "label-id" ); + int pid = checkInt( attribute( parentElement, "item-id" ) ); + int ppos = checkInt( attribute( parentElement, "pos-id" ) ); + int group = checkInt( attribute( parentElement, "group-id" ), + myModule->defaultMenuGroup() ); + if ( !plabel.isEmpty() ) { + QMenu* popup = 0; + int menuId = -1; + // create menu + menuId = myModule->createMenu( plabel, // label + parentMenuId, // parent menu ID, -1 for top-level menu + pid, // ID + group, // group ID + ppos ); // position + myMenuItems.append( menuId ); + QDomNode node = parentNode.firstChild(); + while ( !node.isNull() ) { + if ( node.isElement() ) { + QDomElement elem = node.toElement(); + QString aTagName = tagName( elem ); + if ( aTagName == "popup-item" ) { + int id = checkInt( attribute( elem, "item-id" ) ); + int pos = checkInt( attribute( elem, "pos-id" ) ); + int group = checkInt( attribute( elem, "group-id" ), + myModule->defaultMenuGroup() ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + QString tooltip = attribute( elem, "tooltip-id" ); + QString accel = attribute( elem, "accel-id" ); + bool toggle = checkBool( attribute( elem, "toggle-id" ) ); + + // -1 action ID is not allowed : it means that attribute is missed in the XML file! + // also check if the action with given ID is already created + if ( id != -1 ) { + // create menu action + QAction* action = myModule->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + toggle ); // toogled action + myModule->createMenu( action, // action + menuId, // parent menu ID + id, // ID (same as for createAction()) + group, // group ID + pos ); // position + } + } + else if ( aTagName == "submenu" ) { + // create sub-menu + createMenu( node, menuId, popup ); + } + else if ( aTagName == "separator" ) { + // create menu separator + int id = checkInt( attribute( elem, "item-id" ) ); // separator can have ID + int pos = checkInt( attribute( elem, "pos-id" ) ); + int group = checkInt( attribute( elem, "group-id" ), + myModule->defaultMenuGroup() ); + QAction* action = myModule->separator(); + myModule->createMenu( action, // separator action + menuId, // parent menu ID + id, // ID + group, // group ID + pos ); // position + } + } + node = node.nextSibling(); + } + } + } +} + +/*! + \brief Create a toolbar and insert actions to it. + \param parentNode XML node with toolbar description +*/ +void SALOME_PYQT_ModuleLight::XmlHandler::createToolBar( QDomNode& parentNode ) +{ + if ( !myModule || parentNode.isNull() ) + return; + + QDomElement parentElement = parentNode.toElement(); + if ( !parentElement.isNull() ) { + QString aLabel = attribute( parentElement, "label-id" ); + if ( !aLabel.isEmpty() ) { + // create toolbar + int tbId = myModule->createTool( aLabel ); + QDomNode node = parentNode.firstChild(); + while ( !node.isNull() ) { + if ( node.isElement() ) { + QDomElement elem = node.toElement(); + QString aTagName = tagName( elem ); + if ( aTagName == "toolbutton-item" ) { + int id = checkInt( attribute( elem, "item-id" ) ); + int pos = checkInt( attribute( elem, "pos-id" ) ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + QString tooltip = attribute( elem, "tooltip-id" ); + QString accel = attribute( elem, "accel-id" ); + bool toggle = checkBool( attribute( elem, "toggle-id" ) ); + + // -1 action ID is not allowed : it means that attribute is missed in the XML file! + // also check if the action with given ID is already created + if ( id != -1 ) { + // create toolbar action + QAction* action = myModule->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + toggle ); // toogled action + myModule->createTool( action, tbId, -1, pos ); + } + } + else if ( aTagName == "separatorTB" || aTagName == "separator" ) { + // create toolbar separator + int pos = checkInt( attribute( elem, "pos-id" ) ); + QAction* action = myModule->separator(); + myModule->createTool( action, tbId, -1, pos ); + } + } + node = node.nextSibling(); + } + } + } +} + +/*! + \brief Fill popup menu with the items. + \param parentNode XML node with popup menu description + \param menu popup menu +*/ +void SALOME_PYQT_ModuleLight::XmlHandler::insertPopupItems( QDomNode& parentNode, QMenu* menu ) +{ + if ( !myModule && parentNode.isNull() ) + return; + + // we create popup menus without help of QtxPopupMgr + QDomNode node = parentNode.firstChild(); + while ( !node.isNull() ) { + if ( node.isElement() ) { + QDomElement elem = node.toElement(); + QString aTagName = tagName( elem ); + QList actions = menu->actions(); + if ( aTagName == "popup-item" ) { + // insert a command item + int id = checkInt( attribute( elem, "item-id" ) ); + int pos = checkInt( attribute( elem, "pos-id" ) ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + QString tooltip = attribute( elem, "tooltip-id" ); + QString accel = attribute( elem, "accel-id" ); + bool toggle = checkBool( attribute( elem, "toggle-id" ) ); + + // -1 action ID is not allowed : it means that attribute is missed in the XML file! + // also check if the action with given ID is already created + if ( id != -1 ) { + QAction* action = myModule->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + toggle ); // toogled action + QAction* before = ( pos >= 0 && pos < actions.count() ) ? actions[ pos ] : 0; + menu->insertAction( before, action ); + } + } + else if ( aTagName == "submenu" ) { + // create sub-menu + ////int id = checkInt( attribute( elem, "item-id" ) ); // not used // + int pos = checkInt( attribute( elem, "pos-id" ) ); + QString label = attribute( elem, "label-id" ); + QString icon = attribute( elem, "icon-id" ); + + QIcon anIcon; + if ( !icon.isEmpty() ) { + QPixmap pixmap = myModule->getApp()->resourceMgr()->loadPixmap( myModule->name(), icon ); + if ( !pixmap.isNull() ) + anIcon = QIcon( pixmap ); + } + + QMenu* newPopup = menu->addMenu( anIcon, label ); + QAction* before = ( pos >= 0 && pos < actions.count() ) ? actions[ pos ] : 0; + menu->insertMenu( before, newPopup ); + insertPopupItems( node, newPopup ); + } + else if ( aTagName == "separator" ) { + // create menu separator + int pos = checkInt( attribute( elem, "pos-id" ) ); + QAction* action = myModule->separator(); + QAction* before = ( pos >= 0 && pos < actions.count() ) ? actions[ pos ] : 0; + menu->insertAction( before, action ); + } + } + node = node.nextSibling(); + } +} + +/* + * Save study request. + * Called when user save study. + */ +void SALOME_PYQT_ModuleLight::save(QStringList& theListOfFiles) +{ + MESSAGE("SALOME_PYQT_ModuleLight::save()") + // perform synchronous request to Python event dispatcher + class SaveEvent: public PyInterp_LockRequest + { + public: + SaveEvent(PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + QStringList& _files_list) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj( _obj ) , + myFilesList(_files_list) {} + protected: + virtual void execute() + { + myObj->saveEvent(myFilesList); + } + private: + SALOME_PYQT_ModuleLight* myObj; + QStringList& myFilesList; + }; + + // Posting the request only if dispatcher is not busy! + // Executing the request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new SaveEvent( myInterp, this, theListOfFiles ) ); +} + +void SALOME_PYQT_ModuleLight::saveEvent(QStringList& theListOfFiles) +{ + MESSAGE("SALOME_PYQT_ModuleLight::saveEvent()"); + QStringList::Iterator it = theListOfFiles.begin(); + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule || (it == theListOfFiles.end())) + return; + + if ( PyObject_HasAttrString(myModule, (char*)"saveFiles") ) { + // temporary set myInitModule because saveEvent() method + // might be called by the framework when this module is inactive, + // but still it should be possible to access this module's data + // from Python + myInitModule = this; + + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"saveFiles", + (char*)"s", (*it).toLatin1().constData())); + + myInitModule = 0; + + if( !res ) { + PyErr_Print(); + } + else{ + // parse the return value + // result can be one string... + if ( PyString_Check( res ) ) { + QString astr = PyString_AsString( res ); + //SCRUTE(astr); + theListOfFiles.append(astr); + } + //also result can be a list... + else if ( PyList_Check( res ) ) { + int size = PyList_Size( res ); + for ( int i = 0; i < size; i++ ) { + PyObject* value = PyList_GetItem( res, i ); + if( value && PyString_Check( value ) ) { + theListOfFiles.append( PyString_AsString( value ) ); + } + } + } + } + } +} + +/* + * Python dump request. + * Called when user activates dump study operation. + */ +void SALOME_PYQT_ModuleLight::dumpPython(QStringList& theListOfFiles) +{ + MESSAGE("SALOME_PYQT_ModuleLight::dumpPython()") + // perform synchronous request to Python event dispatcher + class DumpEvent: public PyInterp_LockRequest + { + public: + DumpEvent(PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + QStringList& _files_list) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj( _obj ) , + myFilesList(_files_list) {} + protected: + virtual void execute() + { + myObj->dumpEvent(myFilesList); + } + private: + SALOME_PYQT_ModuleLight* myObj; + QStringList& myFilesList; + }; + + // Posting the request only if dispatcher is not busy! + // Executing the request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new DumpEvent( myInterp, this, theListOfFiles ) ); +} + +void SALOME_PYQT_ModuleLight::dumpEvent(QStringList& theListOfFiles) +{ + MESSAGE("SALOME_PYQT_ModuleLight::dumpEvent()"); + QStringList::Iterator it = theListOfFiles.begin(); + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule || (it == theListOfFiles.end())) + return; + + if ( PyObject_HasAttrString(myModule, (char*)"dumpStudy") ) { + // temporary set myInitModule because dumpEvent() method + // might be called by the framework when this module is inactive, + // but still it should be possible to access this module's data + // from Python + myInitModule = this; + + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"dumpStudy", + (char*)"s", (*it).toLatin1().constData())); + + myInitModule = 0; + + if( !res ) { + PyErr_Print(); + } + else{ + // parse the return value + // result can be one string... + if ( PyString_Check( res ) ) { + QString astr = PyString_AsString( res ); + //SCRUTE(astr); + theListOfFiles.append(astr); + } + //also result can be a list... + else if ( PyList_Check( res ) ) { + int size = PyList_Size( res ); + for ( int i = 0; i < size; i++ ) { + PyObject* value = PyList_GetItem( res, i ); + if( value && PyString_Check( value ) ) { + theListOfFiles.append( PyString_AsString( value ) ); + } + } + } + } + } +} + +/* + * Open study request. + * Called when user open study. + */ +bool SALOME_PYQT_ModuleLight::open(QStringList theListOfFiles) +{ + MESSAGE("SALOME_PYQT_ModuleLight::open()"); + // perform synchronous request to Python event dispatcher + bool opened = false; + class OpenEvent: public PyInterp_LockRequest + { + public: + OpenEvent(PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + QStringList _files_list, + bool& _opened) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj( _obj ) , + myFilesList(_files_list), + myOpened(_opened) {} + protected: + virtual void execute() + { + myObj->openEvent(myFilesList,myOpened); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + QStringList myFilesList; + bool& myOpened; + }; + + // Posting the request only if dispatcher is not busy! + // Executing the request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new OpenEvent( myInterp, this, theListOfFiles, opened) ); + return opened; +} + + +void SALOME_PYQT_ModuleLight::openEvent(QStringList theListOfFiles, bool &opened) +{ + MESSAGE("SALOME_PYQT_ModuleLight::openEvent()"); + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule || theListOfFiles.isEmpty()) + return; + QStringList* theList = new QStringList(theListOfFiles); + +#if SIP_VERSION < 0x040800 + PyObjWrapper sipList( sipBuildResult( 0, "M", theList, sipClass_QStringList) ); +#else + PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) ); +#endif + if ( PyObject_HasAttrString(myModule , (char*)"openFiles") ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"openFiles", + (char*)"O", sipList.get())); + if( !res || !PyBool_Check( res )) { + PyErr_Print(); + opened = false; + } + else{ + opened = PyObject_IsTrue( res ); + + } + } +} + +/* + * Create new empty Data Object and return its entry + */ +QString SALOME_PYQT_ModuleLight::createObject(const QString& parent) +{ + SALOME_PYQT_DataObjectLight* obj=0; + if(!parent.isEmpty()) + { + SALOME_PYQT_DataObjectLight* parentObj = findObject(parent); + if(parentObj) + { + obj = new SALOME_PYQT_DataObjectLight(parentObj); + } + } + else + { + SALOME_PYQT_DataModelLight* dm = + dynamic_cast( dataModel()); + if(dm) + { + obj = new SALOME_PYQT_DataObjectLight(dm->getRoot()); + } + } + if (obj) + return obj->entry(); + else + return QString::null; +} + +/* + * Create new Data Object with name, icon and tooltip + * and return its entry + */ +QString SALOME_PYQT_ModuleLight::createObject(const QString& aname, + const QString& iconname, + const QString& tooltip, + const QString& parent) +{ + QString entry = createObject(parent); + SALOME_PYQT_DataObjectLight* obj = findObject(entry); + + if(obj) + { + obj->setName(aname); + obj->setToolTip(tooltip); + obj->setIcon(iconname); + return obj->entry(); + } + else + return QString::null; +} + +/* + * Find object by entry + */ +SALOME_PYQT_DataObjectLight* SALOME_PYQT_ModuleLight::findObject(const QString& entry) +{ + SALOME_PYQT_DataObjectLight* obj = 0; + SALOME_PYQT_DataModelLight* dm = + dynamic_cast( dataModel()); + if(!entry.isEmpty() && dm ){ + for ( SUIT_DataObjectIterator it( dm->getRoot(), SUIT_DataObjectIterator::DepthLeft ); it.current(); ++it ) { + SALOME_PYQT_DataObjectLight* curentobj = + dynamic_cast( it.current() ); + + if(curentobj && curentobj->entry() == entry) { + obj = curentobj; + return obj; + } + } + } + return obj; +} + +/* + * Set Name for object + */ +void SALOME_PYQT_ModuleLight::setName(const QString& obj, const QString& name) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + dataObj->setName(name); + } +} + +/* + * Set Icon for object + */ +void SALOME_PYQT_ModuleLight::setIcon(const QString& obj, const QString& iconname) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + dataObj->setIcon(iconname); + } +} + +/* + * Return Name of object + */ +QString SALOME_PYQT_ModuleLight::getName(const QString& obj) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + return dataObj->name(); + } + return QString::null; +} + +/* + * Return Tool Tip of object + */ +QString SALOME_PYQT_ModuleLight::getToolTip(const QString& obj) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + return dataObj->toolTip(); + } + return QString::null; +} + + +/* + * Set Tool Tip for object + */ +void SALOME_PYQT_ModuleLight::setToolTip(const QString& obj, const QString& tooltip) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + dataObj->setToolTip(tooltip); + } +} + +/* + * Return color of object + */ +QColor SALOME_PYQT_ModuleLight::getColor(const QString& obj) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject( obj ); + if( dataObj ) { + return dataObj->color( SUIT_DataObject::Foreground ); + } + return QColor(); +} + +/* + * Set color for object + */ +void SALOME_PYQT_ModuleLight::setColor(const QString& obj, const QColor& color) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject( obj ); + if( dataObj ) { + dataObj->setColor( color ); + } +} + +/* + * Return entry of the referenced object (if any) + */ +QString SALOME_PYQT_ModuleLight::getReference(const QString& obj) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + return dataObj->refEntry(); + } + return QString::null; +} + + +/* + * Set entry of the referenced object + */ +void SALOME_PYQT_ModuleLight::setReference(const QString& obj, const QString& refEntry) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + dataObj->setRefEntry(refEntry); + } +} + +/* + * Remove object by entry + */ +void SALOME_PYQT_ModuleLight::removeObject(const QString& obj) +{ + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) { + dataObj->parent()->removeChild(dataObj); + } +} + + +/* + * Remove chields from object + */ +void SALOME_PYQT_ModuleLight::removeChild(const QString& obj) +{ + MESSAGE("SALOME_PYQT_ModuleLight::removeChild()"); + DataObjectList lst; + if(!obj.isEmpty()) + { + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) + { + dataObj->children(lst); + QListIterator it( lst ); + while( it.hasNext() ) + { + SALOME_PYQT_DataObjectLight* sobj = dynamic_cast( it.next() ); + dataObj->removeChild(sobj); + } + } + } + else + { + SALOME_PYQT_DataModelLight* dm = + dynamic_cast( dataModel()); + if(dm) + { + dm->getRoot()->children(lst); + QListIterator it( lst ); + while(it.hasNext() ) + { + SALOME_PYQT_DataObjectLight* sobj = dynamic_cast( it.next() ); + dm->getRoot()->removeChild(sobj); + } + } + } +} + +QStringList SALOME_PYQT_ModuleLight::getChildren(const QString& obj, const bool rec) +{ + DataObjectList lst; + QStringList entryList; + if(!obj.isEmpty()) + { + SALOME_PYQT_DataObjectLight* dataObj = findObject(obj); + if(dataObj) + { + dataObj->children(lst,rec); + QListIterator it( lst ); + while(it.hasNext()) + { + SALOME_PYQT_DataObjectLight* sobj = dynamic_cast( it.next() ); + entryList.append(sobj->entry()); + } + } + } + else + { + SALOME_PYQT_DataModelLight* dm = + dynamic_cast( dataModel()); + if(dm) + { + dm->getRoot()->children(lst); + QListIterator it( lst ); + while( it.hasNext() ) + { + SALOME_PYQT_DataObjectLight* sobj = dynamic_cast( it.next() ); + entryList.append(sobj->entry()); + } + } + } + return entryList; +} + +/*! + * Create new instance of data model and return it. + */ +CAM_DataModel* SALOME_PYQT_ModuleLight::createDataModel() +{ + MESSAGE( "SALOME_PYQT_ModuleLight::createDataModel()" ); + return new SALOME_PYQT_DataModelLight(this); +} + +/*! + * Returns the Python module object currently loaded. + */ +PyObject* SALOME_PYQT_ModuleLight::getPythonModule() +{ + return myModule; +} + +bool SALOME_PYQT_ModuleLight::isDraggable( const SUIT_DataObject* what ) const +{ + MESSAGE("SALOME_PYQT_ModuleLight::isDraggable()"); + // perform synchronous request to Python event dispatcher + bool draggable = false; + class IsDraggableEvent: public PyInterp_LockRequest + { + public: + IsDraggableEvent(PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + LightApp_DataObject* _data_object, + bool& _is_draggable ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj( _obj ) , + myDataObject( _data_object ), + myIsDraggable( _is_draggable ) {} + protected: + virtual void execute() + { + myIsDraggable = myObj->isDraggableEvent( myDataObject ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + LightApp_DataObject* myDataObject; + bool& myIsDraggable; + }; + + const LightApp_DataObject* data_object = dynamic_cast( what ); + + // Posting the request only if dispatcher is not busy! + // Executing the request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new IsDraggableEvent( myInterp, + const_cast( this ), + const_cast( data_object ), + draggable ) ); + return draggable; +} + +bool SALOME_PYQT_ModuleLight::isDraggableEvent( LightApp_DataObject* what ) +{ + MESSAGE("SALOME_PYQT_ModuleLight::isDraggableEvent()"); + + bool draggable = false; + + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule || !what ) + return draggable; + + if ( PyObject_HasAttrString(myModule , (char*)"isDraggable") ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"isDraggable", + (char*)"s", what->entry().toLatin1().constData() ) ); + if( !res || !PyBool_Check( res )) { + PyErr_Print(); + draggable = false; + } + else{ + draggable = PyObject_IsTrue( res ); + } + } + + return draggable; +} + +bool SALOME_PYQT_ModuleLight::isDropAccepted( const SUIT_DataObject* where ) const +{ + MESSAGE("SALOME_PYQT_ModuleLight::isDropAccepted()"); + // perform synchronous request to Python event dispatcher + bool dropAccepted = false; + class IsDropAcceptedEvent: public PyInterp_LockRequest + { + public: + IsDropAcceptedEvent(PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + LightApp_DataObject* _data_object, + bool& _is_drop_accepted ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj( _obj ) , + myDataObject( _data_object ), + myIsDropAccepted( _is_drop_accepted ) {} + protected: + virtual void execute() + { + myIsDropAccepted = myObj->isDropAcceptedEvent( myDataObject ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + LightApp_DataObject* myDataObject; + bool& myIsDropAccepted; + }; + + const LightApp_DataObject* data_object = dynamic_cast( where ); + + // Posting the request only if dispatcher is not busy! + // Executing the request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new IsDropAcceptedEvent( myInterp, + const_cast( this ), + const_cast( data_object ), + dropAccepted ) ); + return dropAccepted; +} + +bool SALOME_PYQT_ModuleLight::isDropAcceptedEvent( LightApp_DataObject* where ) +{ + MESSAGE("SALOME_PYQT_ModuleLight::isDropAcceptedEvent()"); + + bool dropAccepted = false; + + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule || !where ) + return dropAccepted; + + if ( PyObject_HasAttrString(myModule , (char*)"isDropAccepted") ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"isDropAccepted", + (char*)"s", where->entry().toLatin1().constData() ) ); + if( !res || !PyBool_Check( res )) { + PyErr_Print(); + dropAccepted = false; + } + else{ + dropAccepted = PyObject_IsTrue( res ); + } + } + + return dropAccepted; +} + +void SALOME_PYQT_ModuleLight::dropObjects( const DataObjectList& what, SUIT_DataObject* where, + const int row, Qt::DropAction action ) +{ + MESSAGE("SALOME_PYQT_ModuleLight::dropObjects()"); + // perform synchronous request to Python event dispatcher + class DropObjectsEvent: public PyInterp_LockRequest + { + public: + DropObjectsEvent(PyInterp_Interp* _py_interp, + SALOME_PYQT_ModuleLight* _obj, + const DataObjectList& _what, + SUIT_DataObject* _where, + const int _row, + Qt::DropAction _action ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myObj( _obj ) , + myWhat( _what ), + myWhere( _where ), + myRow ( _row ), + myAction ( _action ){} + protected: + virtual void execute() + { + myObj->dropObjectsEvent( myWhat, myWhere, myRow, myAction ); + } + + private: + SALOME_PYQT_ModuleLight* myObj; + DataObjectList myWhat; + SUIT_DataObject* myWhere; + int myRow; + Qt::DropAction myAction; + }; + + // Posting the request only if dispatcher is not busy! + // Executing the request synchronously + if ( !PyInterp_Dispatcher::Get()->IsBusy() ) + PyInterp_Dispatcher::Get()->Exec( new DropObjectsEvent( myInterp, this, what, where, row, action ) ); +} + +void SALOME_PYQT_ModuleLight::dropObjectsEvent( const DataObjectList& what, SUIT_DataObject* where, + const int row, Qt::DropAction action ) +{ + MESSAGE("SALOME_PYQT_ModuleLight::dropObjectsEvent()"); + // Python interpreter should be initialized and Python module should be + // import first + if ( !myInterp || !myModule || what.isEmpty() || !where ) + return; + + QStringList* theList = new QStringList(); + + LightApp_DataObject* whereObject = dynamic_cast( where ); + if ( !whereObject ) return; + + for ( int i = 0; i < what.count(); i++ ) { + LightApp_DataObject* dataObject = dynamic_cast( what[i] ); + if ( dataObject ) theList->append( dataObject->entry() ); + } + +#if SIP_VERSION < 0x040800 + PyObjWrapper sipList( sipBuildResult( 0, "M", theList, sipClass_QStringList) ); +#else + PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL) ); +#endif + if ( PyObject_HasAttrString(myModule, (char*)"dropObjects") ) { + PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"dropObjects", (char*)"Osii", + sipList.get(), + whereObject->entry().toLatin1().constData(), + row, action ) ); + + if( !res ) { + PyErr_Print(); + } + } +} diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h new file mode 100644 index 000000000..c2c92eac3 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_ModuleLight.h @@ -0,0 +1,222 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +// File : SALOME_PYQT_Module.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) +// +#ifndef SALOME_PYQT_MODULELIGHT_H +#define SALOME_PYQT_MODULELIGHT_H + +#include "PyInterp_Interp.h" // // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! +#include "SALOME_PYQT_GUILight.h" +#include "LightApp_Module.h" +#include "SALOME_PYQT_DataObjectLight.h" +#include + +#include +#include +#include +#include +#include + +class SALOME_PYQT_RootObjectLight; +class SALOME_PYQT_PyInterp; +class SUIT_ViewWindow; +class QAction; +class QtxActionGroup; +class QMenu; + + +class SALOME_PYQT_LIGHT_EXPORT SALOME_PYQT_ModuleLight: virtual public LightApp_Module +{ + Q_OBJECT; + +private: + class XmlHandler; + + //! study to Python subinterpreter map + typedef QMap InterpMap; + static SALOME_PYQT_ModuleLight* myInitModule; //!< Python GUI being initialized (not zero only during the initialization) + + XmlHandler* myXmlHandler; //!< XML resource file parser + QMap myWindowsMap; //!< windows map + QStringList myViewMgrList;//!< compatible view managers list + bool myLastActivateStatus; //!< latest module activation status + +protected: + PyObject* myModule; //!< Python GUI module + PyInterp_Interp* myInterp; //!< current Python subinterpreter + static InterpMap myInterpMap; //!< study to Python subinterpreter map + +public: + SALOME_PYQT_ModuleLight(); + ~SALOME_PYQT_ModuleLight(); + +public: + static SALOME_PYQT_ModuleLight* getInitModule(); + + void initialize( CAM_Application* ); + void windows( QMap& ) const; + void viewManagers( QStringList& ) const; + void contextMenuPopup( const QString&, QMenu*, QString& ); + void createPreferences(); + void studyActivated(); + void preferencesChanged( const QString&, const QString& ); + + static int defaultMenuGroup(); + + int createTool( const QString& ); + int createTool( const int, const int, const int = -1 ); + int createTool( const int, const QString&, const int = -1 ); + int createTool( QAction*, const int, + const int = -1, const int = -1 ); + int createTool( QAction*, const QString&, + const int = -1, const int = -1 ); + + int createMenu( const QString&, const int, + const int = -1, const int = -1, const int = -1 ); + int createMenu( const QString&, const QString&, + const int = -1, const int = -1, const int = -1 ); + int createMenu( const int, const int, + const int = -1, const int = -1 ); + int createMenu( const int, const QString&, + const int = -1, const int = -1 ); + int createMenu( QAction*, const int, + const int = -1, const int = -1, const int = -1 ); + int createMenu( QAction*, const QString&, + const int = -1, const int = -1, const int = -1 ); + + QAction* separator(); + + QAction* action( const int ) const; + int actionId( const QAction* ) const; + QAction* createAction( const int, const QString&, const QString&, + const QString&, const QString&, const int, + const bool = false, QObject* = 0 ); + QtxActionGroup* createActionGroup( const int, const bool ); + + + QIcon loadIcon( const QString& fileName ); + + int addGlobalPreference( const QString& ); + int addPreference( const QString& ); + int addPreference( const QString&, const int, const int = LightApp_Preferences::Auto, + const QString& = QString(), + const QString& = QString() ); + QVariant preferenceProperty( const int, const QString& ) const; + void setPreferenceProperty( const int, const QString&, + const QVariant& ); + + void save(QStringList& theListOfFiles); + bool open(QStringList theListOfFiles); + void dumpPython(QStringList& theListOfFiles); + + /*create new SALOME_PYQT_DataObjectLight and return its entry*/ + QString createObject(const QString& parent); + QString createObject(const QString& name, + const QString& iconname, + const QString& tooltip, + const QString& parent); + /*Sets Name, Icon and Tool Tip for object*/ + void setName(const QString& obj,const QString& iconname); + void setIcon(const QString& obj,const QString& name); + void setToolTip(const QString& obj, const QString& tooltip); + + /*Gets Name and Tool Tip for object*/ + QString getName(const QString& obj); + QString getToolTip(const QString& obj); + + void setColor(const QString& obj, const QColor& color); + QColor getColor(const QString& obj); + + void setReference( const QString& obj, + const QString& refEntry ); + QString getReference( const QString& obj ); + + /*remove object*/ + void removeObject(const QString& obj); + /*remove child*/ + void removeChild(const QString& obj); + /*return list of child objets*/ + QStringList getChildren(const QString& obj, const bool rec); + + /*Access to the underlying Python module object */ + PyObject* getPythonModule(); + + /*Drag and drop support*/ + virtual bool isDraggable( const SUIT_DataObject* ) const; + virtual bool isDropAccepted( const SUIT_DataObject* ) const; + virtual void dropObjects( const DataObjectList&, SUIT_DataObject*, + const int, Qt::DropAction ); + +public slots: + virtual bool activateModule( SUIT_Study* ); + virtual bool deactivateModule( SUIT_Study* ); + void preferenceChanged( const QString&, + const QString&, + const QString& ); + void onGUIEvent(); + + void onActiveViewChanged( SUIT_ViewWindow* ); + void onViewTryClose( SUIT_ViewWindow* ); + void onViewClosed( SUIT_ViewWindow* ); + void onViewCloned( SUIT_ViewWindow* ); + +protected: + /* create data model */ + virtual CAM_DataModel* createDataModel(); + virtual bool activateModuleInternal( SUIT_Study* ); + +private: + void init( CAM_Application* ); + void activate( SUIT_Study* ); + void deactivate( SUIT_Study* ); + bool lastActivationStatus() const; + void customize( SUIT_Study* ); + void studyChanged( SUIT_Study* ); + void contextMenu( const QString&, QMenu* ); + void guiEvent( const int ); + void initPreferences(); + void prefChanged( const QString&, const QString& ); + + virtual void initInterp ( int ); + void importModule(); + void setWorkSpace(); + + void activeViewChanged( const SUIT_ViewWindow* ); + void viewTryClose( const SUIT_ViewWindow* ); + void viewClosed( const SUIT_ViewWindow* ); + void viewCloned( const SUIT_ViewWindow* ); + void connectView( const SUIT_ViewWindow* ); + + void saveEvent(QStringList& theListOfFiles); + void dumpEvent(QStringList& theListOfFiles); + void openEvent(QStringList theListOfFiles, bool& opened); + + bool isDraggableEvent( LightApp_DataObject* ); + bool isDropAcceptedEvent( LightApp_DataObject* ); + void dropObjectsEvent( const DataObjectList&, SUIT_DataObject*, + const int, Qt::DropAction ); + + SALOME_PYQT_DataObjectLight* findObject(const QString& entry); + + friend class XmlHandler; +}; + +#endif // SALOME_PYQT_MODULELIGHT_H diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx new file mode 100644 index 000000000..fc4142496 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.cxx @@ -0,0 +1,120 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 "SALOME_PYQT_PyInterp.h" // this include must be first !! + +#include +#include +#include + +#ifndef GUI_DISABLE_CORBA +#include +#endif + + + + +/*! + * constructor : the main SALOME Python interpreter is used for PyQt GUI. + * calls initialize method defined in base class, which calls virtual methods + * initstate & initcontext redefined here + */ +SALOME_PYQT_PyInterp::SALOME_PYQT_PyInterp(): PyInterp_Interp() +{ +} + +SALOME_PYQT_PyInterp::~SALOME_PYQT_PyInterp() +{ +} + +void SALOME_PYQT_PyInterp::initPython() +{ + /* + * Do nothing + * The initialization has been done in main + */ + MESSAGE("SALOME_PYQT_PyInterp::initPython"); +#ifndef GUI_DISABLE_CORBA + if(SUIT_PYTHON::initialized) { + ASSERT(SUIT_PYTHON::_gtstate); // initialisation in main + SCRUTE(SUIT_PYTHON::_gtstate); + _tstate = SUIT_PYTHON::_gtstate; + } + else { + ASSERT(KERNEL_PYTHON::_gtstate); // initialisation in main + SCRUTE(KERNEL_PYTHON::_gtstate); + _tstate = KERNEL_PYTHON::_gtstate; + } +#else + SCRUTE(SUIT_PYTHON::_gtstate); + _tstate = SUIT_PYTHON::_gtstate; +#endif +} + +bool SALOME_PYQT_PyInterp::initState() +{ + /* + * The GIL is assumed to not be held on the call + * The GIL is acquired in initState and will be held on initState exit + * It is the caller responsability to release the lock on exit if needed + */ + PyEval_AcquireThread(_tstate); + SCRUTE(_tstate); + PyEval_ReleaseThread(_tstate); + return true; +} + + +bool SALOME_PYQT_PyInterp::initContext() +{ + /* + * The GIL is assumed to be held + * It is the caller responsability to acquire the GIL before calling initContext + * It will still be held on initContext exit + */ + _g = PyDict_New(); // create interpreter dictionnary context + PyObject *bimod = PyImport_ImportModule("__builtin__"); + PyDict_SetItemString(_g, "__builtins__", bimod); + Py_DECREF(bimod); + return true; +} + +int SALOME_PYQT_PyInterp::run(const char *command) +{ + MESSAGE("compile"); + PyObject *code = Py_CompileString((char *)command,"PyGUI",Py_file_input); + if(!code){ + // Une erreur s est produite en general SyntaxError + PyErr_Print(); + return -1; + } + //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0 + // PyObject *r = PyEval_EvalCode(code,_g,_g); + //#else + PyObject *r = PyEval_EvalCode((PyCodeObject *)code,_g,_g); + //#endif + Py_DECREF(code); + if(!r){ + // Une erreur s est produite a l execution + PyErr_Print(); + return -1 ; + } + Py_DECREF(r); + return 0; +} diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h new file mode 100644 index 000000000..d894ab644 --- /dev/null +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyInterp.h @@ -0,0 +1,45 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +// File : SALOME_PYQT_Module.h +// Author : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) +// Date : 13/04/2009 +// +#ifndef SALOME_PYQT_PYINTERP_H +#define SALOME_PYQT_PYINTERP_H + +#include "SALOME_PYQT_GUILight.h" + +#include "PyInterp_Interp.h" // this include must be first !!! + +class SALOME_PYQT_LIGHT_EXPORT SALOME_PYQT_PyInterp : public PyInterp_Interp +{ + public: + SALOME_PYQT_PyInterp(); + ~SALOME_PYQT_PyInterp(); + + int run(const char *command); + + protected: + virtual void initPython(); + virtual bool initState(); + virtual bool initContext(); +}; + +#endif // SALOME_PYQT_PYINTERP_H diff --git a/src/SalomeApp/pluginsdemo/Makefile.am b/src/SalomeApp/pluginsdemo/Makefile.am new file mode 100644 index 000000000..f949438e4 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/Makefile.am @@ -0,0 +1,41 @@ +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# +# Note that the plugins files should be installed in the directory +# (ROOT_DIR/share/salome/plugins) or one of this +# sub-directories (the search of plugins by the plugin manager is +# recurcive from this folder, in each SALOME module, i.e. each +# variable *_ROOT_DIR). +# +pluginsdir =$(salomepluginsdir)/demo +plugins_PYTHON = \ + salome_plugins.py \ + smesh_plugins.py \ + trihedron.py \ + tubedialog_ui.py \ + tubedialog.py \ + tubebuilder.py \ + xalome.py \ + minmax_dialog.py \ + minmax_plugin.py diff --git a/src/SalomeApp/pluginsdemo/minmax.ui b/src/SalomeApp/pluginsdemo/minmax.ui new file mode 100644 index 000000000..3c9eafd98 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/minmax.ui @@ -0,0 +1,148 @@ + + + Dialog + + + + 0 + 0 + 178 + 156 + + + + Get min and max value of control + + + true + + + + + + Mesh + + + + + + + true + + + + + + + Control + + + + + + + + + + Min + + + + + + + true + + + + + + + Max + + + + + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close|QDialogButtonBox::Help + + + + + + + mesh + control + minvalue + maxvalue + buttonBox + + + + + buttonBox + rejected() + Dialog + OnCancel() + + + 253 + 371 + + + 262 + 101 + + + + + buttonBox + helpRequested() + Dialog + helpMessage() + + + 131 + 373 + + + 131 + 64 + + + + + control + activated(QString) + Dialog + compute_minmax() + + + 250 + 137 + + + 131 + 81 + + + + + + compute_minmax() + helpMessage() + OnCancel() + OnOk() + + diff --git a/src/SalomeApp/pluginsdemo/minmax_dialog.py b/src/SalomeApp/pluginsdemo/minmax_dialog.py new file mode 100644 index 000000000..c7d310e9f --- /dev/null +++ b/src/SalomeApp/pluginsdemo/minmax_dialog.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'minmax.ui' +# +# Created: Thu Mar 1 15:23:57 2012 +# by: PyQt4 UI code generator 4.8.1 +# +# WARNING! All changes made in this file will be lost! + +from PyQt4 import QtCore, QtGui + +try: + _fromUtf8 = QtCore.QString.fromUtf8 +except AttributeError: + _fromUtf8 = lambda s: s + +class Ui_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName(_fromUtf8("Dialog")) + Dialog.resize(178, 156) + Dialog.setSizeGripEnabled(True) + self.gridLayout = QtGui.QGridLayout(Dialog) + self.gridLayout.setObjectName(_fromUtf8("gridLayout")) + self.label_2 = QtGui.QLabel(Dialog) + self.label_2.setObjectName(_fromUtf8("label_2")) + self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) + self.mesh = QtGui.QLineEdit(Dialog) + self.mesh.setReadOnly(True) + self.mesh.setObjectName(_fromUtf8("mesh")) + self.gridLayout.addWidget(self.mesh, 0, 1, 1, 2) + self.label_3 = QtGui.QLabel(Dialog) + self.label_3.setObjectName(_fromUtf8("label_3")) + self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1) + self.control = QtGui.QComboBox(Dialog) + self.control.setObjectName(_fromUtf8("control")) + self.gridLayout.addWidget(self.control, 1, 1, 1, 2) + self.label = QtGui.QLabel(Dialog) + self.label.setObjectName(_fromUtf8("label")) + self.gridLayout.addWidget(self.label, 2, 0, 1, 1) + self.minvalue = QtGui.QLineEdit(Dialog) + self.minvalue.setReadOnly(True) + self.minvalue.setObjectName(_fromUtf8("minvalue")) + self.gridLayout.addWidget(self.minvalue, 2, 1, 1, 2) + self.label_4 = QtGui.QLabel(Dialog) + self.label_4.setObjectName(_fromUtf8("label_4")) + self.gridLayout.addWidget(self.label_4, 3, 0, 1, 1) + self.maxvalue = QtGui.QLineEdit(Dialog) + self.maxvalue.setReadOnly(True) + self.maxvalue.setObjectName(_fromUtf8("maxvalue")) + self.gridLayout.addWidget(self.maxvalue, 3, 1, 1, 2) + self.buttonBox = QtGui.QDialogButtonBox(Dialog) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Help) + self.buttonBox.setObjectName(_fromUtf8("buttonBox")) + self.gridLayout.addWidget(self.buttonBox, 4, 0, 1, 3) + + self.retranslateUi(Dialog) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), Dialog.OnCancel) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("helpRequested()")), Dialog.helpMessage) + QtCore.QObject.connect(self.control, QtCore.SIGNAL(_fromUtf8("activated(QString)")), Dialog.compute_minmax) + QtCore.QMetaObject.connectSlotsByName(Dialog) + Dialog.setTabOrder(self.mesh, self.control) + Dialog.setTabOrder(self.control, self.minvalue) + Dialog.setTabOrder(self.minvalue, self.maxvalue) + Dialog.setTabOrder(self.maxvalue, self.buttonBox) + + def retranslateUi(self, Dialog): + Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Get min and max value of control", None, QtGui.QApplication.UnicodeUTF8)) + self.label_2.setText(QtGui.QApplication.translate("Dialog", "Mesh", None, QtGui.QApplication.UnicodeUTF8)) + self.label_3.setText(QtGui.QApplication.translate("Dialog", "Control", None, QtGui.QApplication.UnicodeUTF8)) + self.label.setText(QtGui.QApplication.translate("Dialog", "Min", None, QtGui.QApplication.UnicodeUTF8)) + self.label_4.setText(QtGui.QApplication.translate("Dialog", "Max", None, QtGui.QApplication.UnicodeUTF8)) + diff --git a/src/SalomeApp/pluginsdemo/minmax_plugin.py b/src/SalomeApp/pluginsdemo/minmax_plugin.py new file mode 100644 index 000000000..c743e5279 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/minmax_plugin.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) + +def minmax(context): + # get context study, studyId, salomeGui + study = context.study + studyId = context.studyId + sg = context.sg + + from PyQt4.QtGui import QDialog + from PyQt4.QtGui import QMessageBox + from PyQt4.QtCore import Qt + from PyQt4.QtCore import SIGNAL + + from minmax_dialog import Ui_Dialog + + import salome + import smesh + + controls_dict = { + "Aspect Ratio 3D" : smesh.FT_AspectRatio3D, + "Volume" : smesh.FT_Volume3D, + "Element Diameter 3D" : smesh.FT_MaxElementLength3D, + "Length 2D" : smesh.FT_Length2D, + "MultiConnection 2D" : smesh.FT_MultiConnection2D, + "Area" : smesh.FT_Area, + "Taper" : smesh.FT_Taper, + "Aspect Ratio" : smesh.FT_AspectRatio, + "Minimum Angle" : smesh.FT_MinimumAngle, + "Warping" : smesh.FT_Warping, + "Skew" : smesh.FT_Skew, + "Element Diameter 2D" : smesh.FT_MaxElementLength2D, + "Length" : smesh.FT_Length, + "MultiConnection" : smesh.FT_MultiConnection, + } + + controls_3d = [ + "Aspect Ratio 3D", + "Volume", + "Element Diameter 3D", + ] + controls_2d = [ + "Length 2D", + "MultiConnection 2D", + "Area", + "Taper", + "Aspect Ratio", + "Minimum Angle", + "Warping", + "Skew", + "Element Diameter 2D" + ] + controls_1d = [ + "Length", + "MultiConnection", + ] + + class MinmaxDialog(QDialog): + def __init__(self): + QDialog.__init__(self, None, Qt.Tool) + # Set up the user interface from Designer. + self.ui = Ui_Dialog() + self.ui.setupUi(self) + self.show() + + self.clearLineEdit() + + # Connect up the selectionChanged() event of the object browser. + self.connect(sg.getObjectBrowser(), SIGNAL("selectionChanged()"), self.select) + + self.mm = None + self.ui.control.setFocus() + self.select() + + pass + + def OnCancel(self): + self.disconnect(sg.getObjectBrowser(), SIGNAL("selectionChanged()"), self.select) + self.reject() + pass + + def clearLineEdit(self): + self.ui.mesh.setText("Select a Mesh") + self.ui.mesh.setStyleSheet("QLineEdit { color: grey }") + self.ui.minvalue.setText("") + self.ui.maxvalue.setText("") + + def select(self): + self.disconnect(sg.getObjectBrowser(), SIGNAL("selectionChanged()"), self.select) + self.ui.control.clear() + self.ui.minvalue.setText("") + self.ui.maxvalue.setText("") + objId = salome.sg.getSelected(0) + if objId: + mm = study.FindObjectID(objId).GetObject() + mesh = None + try: + mesh = mm.GetMEDMesh() + except: + #print "No mesh selected" + self.clearLineEdit() + mesh = None + pass + if mesh: + self.ui.mesh.setStyleSheet("") + self.ui.mesh.setText(mesh.getName()) + #print "Mesh selected: ", mesh.getName() + self.mm = mm + e = self.mm.NbEdges() + f = self.mm.NbFaces() + v = self.mm.NbVolumes() + #print "NbEdges: ",e + #print "NbFaces: ",f + #print "NbVolumes: ",v + controls = [] + if e: + controls += controls_1d + pass + if f: + controls += controls_2d + pass + if v: + controls += controls_3d + pass + self.ui.control.addItems(controls) + self.compute_minmax() + self.connect(sg.getObjectBrowser(), SIGNAL("selectionChanged()"), self.select) + pass + + def helpMessage(self): + QMessageBox.about(None, "About Min/Max value of control", + """ + Displays the min/max value of a control + --------------------------------- + +This plugin displays the min and max value of a control +on a mesh. +Inputs: + - The mesh to analyse + - The control to compute + """) + pass + + def compute_minmax(self): + if self.mm: + control = self.ui.control.currentText() + #print "Compute control: ",control + fun = smesh.GetFunctor(controls_dict[str(control)]) + fun.SetMesh(self.mm.GetMesh()) + hist = fun.GetHistogram(1) + maxVal = hist[0].max + minVal = hist[0].min + #print "Max value for %s: %f"%(control, maxVal) + #print "Min value for %s: %f"%(control, minVal) + self.ui.maxvalue.setText("%f"%(maxVal)) + self.ui.minvalue.setText("%f"%(minVal)) + else: + print "Pas de maillage" + pass + pass + pass + + window = MinmaxDialog() + window.exec_() + pass + diff --git a/src/SalomeApp/pluginsdemo/salome_plugins.py b/src/SalomeApp/pluginsdemo/salome_plugins.py new file mode 100755 index 000000000..edb361b5f --- /dev/null +++ b/src/SalomeApp/pluginsdemo/salome_plugins.py @@ -0,0 +1,281 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) + +import salome_pluginsmanager + +DEMO_IS_ACTIVATED = False + +if DEMO_IS_ACTIVATED: + # Check that GEOM and SMESH modules are present + try: + import geompy, smesh + except: + DEMO_IS_ACTIVATED = False + +if DEMO_IS_ACTIVATED: + # ------------------------------------------------------------------------- + # Example 1: creation of basic objects. + # The plugin function is implemented here and declared in the pluginsmanager. + # + import salome + + def trihedron(context): + import geompy + + # Intialize the geompy factory with the active study + activeStudy = context.study + geompy.init_geom(activeStudy) + + # Create the objects + Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) + Vy = geompy.MakeVectorDXDYDZ(0, 10, 0) + Vz = geompy.MakeVectorDXDYDZ(0, 0, 10) + origin = geompy.MakeVertex(0, 0, 0) + + # Register the objects in the active study + geompy.addToStudy( Vx, "Vx" ) + geompy.addToStudy( Vy, "Vy" ) + geompy.addToStudy( Vz, "Vz" ) + geompy.addToStudy( origin, "origin" ) + + + salome_pluginsmanager.AddFunction('DEMO/O,Vx,Vy,Vz', + 'Creates the trihedron', + trihedron) + + + # ------------------------------------------------------------------------- + # Example 1 bis: creation of basic objects and automatic display + def trihedron_withdisplay(context): + import geompy + + # Intialize the geompy factory with the active study + activeStudy = context.study + geompy.init_geom(activeStudy) + + # Create the objects + Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) + Vy = geompy.MakeVectorDXDYDZ(0, 10, 0) + Vz = geompy.MakeVectorDXDYDZ(0, 0, 10) + origin = geompy.MakeVertex(0, 0, 0) + + # Register the objects in the active study + entries=[] + entries.append(geompy.addToStudy( Vx, "Vx" )) + entries.append(geompy.addToStudy( Vy, "Vy" )) + entries.append(geompy.addToStudy( Vz, "Vz" )) + entries.append(geompy.addToStudy( origin, "origin" )) + + # This part is to automatically display the objects in the active viewer. + gcomp = salome.ImportComponentGUI("GEOM") + for entry in entries: + gcomp.createAndDisplayFitAllGO(entry) + + + salome_pluginsmanager.AddFunction('DEMO/O,Vx,Vy,Vz (2)', + 'Creates Basic GEOM objects', + trihedron_withdisplay) + + # ------------------------------------------------------------------------- + # Example 2: creation of a shape with parameters that can be read from a GUI. + # The plugin function (tube_shapewithgui) delegates some action to + # dedicated imported modules (tube.py and tubedialog.py). + # + + 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(tubebuilder.DEFAULT_RADIUS, + tubebuilder.DEFAULT_LENGTH, + tubebuilder.DEFAULT_WIDTH) + + def tube_shapewithgui(context): + global tubebuilder, xalome, dialog + activeStudy = context.study + + # Get the parameter values from a gui dialog box. If the dialog is + # closed using the Ok button, then the data are requested from the + # gui and used to create the shape of the tube. + dialog.exec_() + if dialog.wasOk(): + radius, length, width = dialog.getData() + shape = tubebuilder.createGeometry(activeStudy, radius, length, width) + entry = xalome.addToStudy(activeStudy, shape, "Tube" ) + xalome.displayShape(entry) + + + salome_pluginsmanager.AddFunction('DEMO/Tube shape from parameters', + 'Creates a tube object from specified parameters', + tube_shapewithgui) + + + # ------------------------------------------------------------------------- + # 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 (tubebuilder.py and tubedialog.py). + # + def tube_meshwithgui(context): + global tube, dialog + activeStudy = context.study + + # Get the parameter values from a gui dialog box. If the dialog is + # closed using the Ok button, then the data are requested from the + # gui and used to create the shape of the tube. + dialog.exec_() + if dialog.wasOk(): + radius, length, width = dialog.getData() + mesh = tubebuilder.createModel(activeStudy, radius, length, width) + + + salome_pluginsmanager.AddFunction('DEMO/Tube mesh from parameters', + 'Creates a tube object from specified parameters', + tube_meshwithgui) + + + # ------------------------------------------------------------------------- + # Example 2 ter: creation of a geom object with a preview function in + # the dialog box. This use case is more complex from the gui point of + # 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 as a "callback" mechanism. + # + # TODO: + # - coloring the preview in pink + # - store the tmp study objects in a "preview" folder + # + 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 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 = tubebuilder.createGeometry(activeStudy, radius, length, width) + entry = xalome.addToStudy(activeStudy, shape, DEFAULT_SHAPE_NAME, DEFAULT_FOLDER_NAME) + xalome.displayShape(entry) + + def rejectCallback(): + """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 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 = 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(): + """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): + """ + 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() + + + salome_pluginsmanager.AddFunction('DEMO/Tube geometry from parameters with preview', + 'Creates a tube object from specified parameters', + tube_shapewithguiAndPreview) + + + +# ------------------------------------------------------------------------- +# Example 3: run a shell session in a xterm to get a SALOME python console +def runSalomeShellSession(context): + import os,subprocess + import salome_version + version = salome_version.getVersion(full=True) + kernel_appli_dir = os.environ['KERNEL_ROOT_DIR'] + command = "" + if os.path.exists("/usr/bin/xterm"): + command = 'xterm -T "SALOME %s - Shell session" -e %s/runSession &'%(version,kernel_appli_dir) + elif os.path.exists("/usr/bin/gnome-terminal"): + command = 'gnome-terminal -t "SALOME %s - Shell session" -e %s/runSession &'%(version,kernel_appli_dir) + else: + print "Neither xterm nor gnome-terminal is installed." + + if command is not "": + try: + subprocess.check_call(command, shell = True) + except Exception, e: + print "Error: ",e + + +salome_pluginsmanager.AddFunction('SALOME shell session', + 'Execute a SALOME shell session in an external xterm', + runSalomeShellSession) diff --git a/src/SalomeApp/pluginsdemo/smesh_plugins.py b/src/SalomeApp/pluginsdemo/smesh_plugins.py new file mode 100644 index 000000000..77269a599 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/smesh_plugins.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +#!/usr/bin/env python +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) + +import salome_pluginsmanager + +DEMO_IS_ACTIVATED = True + +from minmax_plugin import * + +# register the function in the plugin manager +if DEMO_IS_ACTIVATED: + salome_pluginsmanager.AddFunction('Get min or max value of control', + 'Get min or max value of control', + minmax) diff --git a/src/SalomeApp/pluginsdemo/trihedron.py b/src/SalomeApp/pluginsdemo/trihedron.py new file mode 100644 index 000000000..8a82c9b52 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/trihedron.py @@ -0,0 +1,41 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) +# Example 1: creation of basic objects (O, Vx, Vy, Vz) +# + +# Intialize the geompy factory with the active study +import geompy +import salome +geompy.init_geom(salome.myStudy) + +# Create the objects +Vx = geompy.MakeVectorDXDYDZ(10, 0, 0) +Vy = geompy.MakeVectorDXDYDZ(0, 10, 0) +Vz = geompy.MakeVectorDXDYDZ(0, 0, 10) +origin = geompy.MakeVertex(0, 0, 0) + +# Register the objects in the active study +geompy.addToStudy( Vx, "Vx" ) +geompy.addToStudy( Vy, "Vy" ) +geompy.addToStudy( Vz, "Vz" ) +geompy.addToStudy( origin, "origin" ) + + diff --git a/src/SalomeApp/pluginsdemo/tubebuilder.py b/src/SalomeApp/pluginsdemo/tubebuilder.py new file mode 100644 index 000000000..5aedfe676 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/tubebuilder.py @@ -0,0 +1,143 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) + +import salome + +DEFAULT_RADIUS = 100 +DEFAULT_LENGTH = 300 +DEFAULT_WIDTH = 20 + +from salome.geom import geomtools + +def createGeometry(study, radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH, width=DEFAULT_WIDTH): + ''' + This function creates the geometry on the specified study and with + given parameters. + ''' + print "TUBE: creating the geometry ..." + studyId = study._get_StudyId() + geompy = geomtools.getGeompy(studyId) + + radius_ext = radius + radius_int = radius_ext - width + + CylinderExt = geompy.MakeCylinderRH(radius_ext, length) + CylinderInt = geompy.MakeCylinderRH(radius_int, length) + Tube = geompy.MakeCut(CylinderExt, CylinderInt) + return Tube + +def createGeometryWithPartition(study, radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH, width=DEFAULT_WIDTH): + ''' + This function create the geometrical shape with a partition so + that the hexaedric algorithm could be used for meshing. + ''' + shape = createGeometry(study,radius,length,width) + + # We have to create a partition so that we can use an hexaedric + # meshing algorithm. + studyId = study._get_StudyId() + geompy = geomtools.getGeompy(studyId) + + print "TUBE: creating a partition ..." + toolPlane = geompy.MakeFaceHW(2.1*length,2.1*radius,3) + partition = geompy.MakePartition([shape], [toolPlane], [], [], geompy.ShapeType["SOLID"], 0, [], 0) + entry = geompy.addToStudy( partition, "TubeWithPartition" ) + return partition + +def createMesh(study, shape): + '''This function creates the mesh of the specified shape on the specified study''' + print "TUBE: creating the mesh ..." + import smesh + + smesh.SetCurrentStudy(study) + mesh = smesh.Mesh(shape) + Regular_1D = mesh.Segment() + Nb_Segments = Regular_1D.NumberOfSegments(10) + Nb_Segments.SetDistrType( 0 ) + Quadrangle_2D = mesh.Quadrangle() + Hexa_3D = mesh.Hexahedron() + + isDone = mesh.Compute() + + if salome.sg.hasDesktop(): + smesh.SetName(mesh.GetMesh(), 'TubeMesh') + smesh.SetName(Regular_1D.GetAlgorithm(), 'Regular_1D') + smesh.SetName(Nb_Segments, 'Nb. Segments_1') + smesh.SetName(Quadrangle_2D.GetAlgorithm(), 'Quadrangle_2D') + smesh.SetName(Hexa_3D.GetAlgorithm(), 'Hexa_3D') + salome.sg.updateObjBrowser(0) + + return mesh + + +def createModel(study, radius=DEFAULT_RADIUS, length=DEFAULT_LENGTH,width=DEFAULT_WIDTH): + ''' + This function create the geomtrical shape AND the associated mesh. + ''' + # We first create a shape with a partition so that the hexaedric + # algorithm could be used. + shape = createGeometryWithPartition(study,radius,length,width) + + # Then the mesh can be defined and computed + mesh = createMesh(study,shape) + +def exportModel(mesh, filename): + ''' + This exports the mesh to the specified filename in the med format + ''' + print "TUBE: exporting mesh to file %s ..."%filename + import SMESH + mesh.ExportMED(filename, 0, SMESH.MED_V2_2, 1 ) + + +# +# =================================================================== +# Use cases and test functions +# =================================================================== +# +def TEST_createGeometry(): + salome.salome_init() + theStudy=salome.myStudy + createGeometry(theStudy) + +def TEST_createMesh(): + salome.salome_init() + theStudy=salome.myStudy + shape = createGeometryWithPartition(theStudy) + mesh = createMesh(theStudy, shape) + +def TEST_createModel(): + salome.salome_init() + theStudy=salome.myStudy + createModel(theStudy) + +def TEST_exportModel(): + salome.salome_init() + theStudy=salome.myStudy + shape = createGeometryWithPartition(theStudy) + mesh = createMesh(theStudy, shape) + exportModel(mesh,"tubemesh.med") + +if __name__ == "__main__": + #TEST_createGeometry() + #TEST_createMesh() + TEST_createModel() + #TEST_exportModel() diff --git a/src/SalomeApp/pluginsdemo/tubedialog.py b/src/SalomeApp/pluginsdemo/tubedialog.py new file mode 100644 index 000000000..09d3d8f40 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/tubedialog.py @@ -0,0 +1,117 @@ +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) + +import sys +from PyQt4 import QtGui +from PyQt4 import QtCore + +from tubedialog_ui import TubeDialog_UI + + +class TubeDialog(TubeDialog_UI): + def setupUi(self): + 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): + '''Callback function when dialog is rejected (click Cancel)''' + self._wasOk = False + QtGui.QDialog.reject(self) + + def wasOk(self): + return self._wasOk + + def setData(self, radius, length, width): + self.txtRadius.setText(str(radius)) + self.txtLength.setText(str(length)) + self.txtWidth.setText(str(width)) + + def getData(self): + try: + radius=eval(str(self.txtRadius.text())) + length=eval(str(self.txtLength.text())) + width=eval(str(self.txtWidth.text())) + except: + print "pb a la saisie" + + return radius, length, width + + +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_() + if tubedialog.wasOk(): + radius, length, width = tubedialog.getData() + print radius, length, width + + +def main( args ): + a = QtGui.QApplication(sys.argv) + TEST_getData_synchrone() + sys.exit(0) + +if __name__=="__main__": + main(sys.argv) + diff --git a/src/SalomeApp/pluginsdemo/tubedialog_ui.py b/src/SalomeApp/pluginsdemo/tubedialog_ui.py new file mode 100644 index 000000000..de6ec8bf7 --- /dev/null +++ b/src/SalomeApp/pluginsdemo/tubedialog_ui.py @@ -0,0 +1,107 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) + +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..724afa40c --- /dev/null +++ b/src/SalomeApp/pluginsdemo/xalome.py @@ -0,0 +1,229 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) + +# +# 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) + if shape is not None: + 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() diff --git a/src/TreeData/DataModel.cxx b/src/TreeData/DataModel.cxx new file mode 100644 index 000000000..c08d07fa5 --- /dev/null +++ b/src/TreeData/DataModel.cxx @@ -0,0 +1,57 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#include "DataModel.hxx" + +DataModel::DataModel() { + +} + +DataModel::~DataModel() { + _mapDataObjects.clear(); +} + +bool DataModel::addDataObject(DataObject * dataObject) { + _mapDataObjects[dataObject->getNameId()] = dataObject; + return true; +} +bool DataModel::removeDataObject(string nameId) { + _mapDataObjects.erase(nameId); + return true; +} +bool DataModel::removeDataObject(DataObject * dataObject) { + if ( dataObject == NULL ) return false; + return removeDataObject(dataObject->getNameId()); +} + +DataObject * DataModel::getDataObject(string id) { + return _mapDataObjects[id]; +} + + + +map::iterator DataModel::begin() { + return _mapDataObjects.begin(); +} + +map::iterator DataModel::end() { + return _mapDataObjects.end(); +} diff --git a/src/TreeData/DataModel.hxx b/src/TreeData/DataModel.hxx new file mode 100644 index 000000000..c30a1e35e --- /dev/null +++ b/src/TreeData/DataModel.hxx @@ -0,0 +1,64 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + + +#ifndef DATAMODEL_H +#define DATAMODEL_H + +#include "TreeData.hxx" + +#include +#include "DataObject.hxx" + +class TREEDATA_EXPORT DataModel { + +public: + DataModel(); + ~DataModel(); + + /*! + * This function can be used to create a specific instance of + * DataObject. Note that this function is a pure virtual method and + * then no default behavior is done. In particular, the newly + * created object is not automatically added to the data model. This + * behavior should be implemented in a dedicated version of this + * class. + */ + virtual DataObject * newDataObject() = 0; + + /*! Function to add data object to the model */ + bool addDataObject(DataObject * dataObject); + /*! Functions to remove data object from the model */ + bool removeDataObject(string nameId); + bool removeDataObject(DataObject * dataObject); + /*! Function to retrieve a data object in the model */ + DataObject * getDataObject(string nameId); + + map::iterator begin(); + map::iterator end(); + +private: + map _mapDataObjects; + + +}; + +#endif // DATAMODEL_H diff --git a/src/TreeData/DataObject.cxx b/src/TreeData/DataObject.cxx new file mode 100644 index 000000000..d8be9ead3 --- /dev/null +++ b/src/TreeData/DataObject.cxx @@ -0,0 +1,73 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#include "DataObject.hxx" +#include + +// Static assignement +int DataObject::_lastId=0; +const string DataObject::_BASENAME = string("object_"); +const string DataObject::pathsep = string("/"); + +DataObject::DataObject() { + _nameId = _BASENAME+ToString(_lastId); + _lastId++; + // The default label is set to the nameId, but it can be modified + // using setLabel whereas the nameId can't be modified. + _label = _nameId; +} + +DataObject::~DataObject() { + _properties.clear(); +} + +void DataObject::setLabel(string label) { + _label = label; +} +string DataObject::getLabel() { + return _label; +} + +string DataObject::getPathName() { + string pathName; + pathName = this->getPath() + pathsep + this->getLabel(); + return pathName; +} + + +string DataObject::getNameId() { + return _nameId; +} + +void DataObject::setProperty(string key, string value) { + _properties[key] = value; +} +string DataObject::getProperty(string key) { + return _properties[key]; +} + +string DataObject::toString() { + string serialize="\n"; + serialize+="nameId = "+getNameId()+"\n"; + serialize+="label = "+getLabel()+"\n"; + serialize+="path = "+getPath(); + return serialize; +} diff --git a/src/TreeData/DataObject.hxx b/src/TreeData/DataObject.hxx new file mode 100644 index 000000000..089b36fdc --- /dev/null +++ b/src/TreeData/DataObject.hxx @@ -0,0 +1,68 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#ifndef DATAOBJECT_H +#define DATAOBJECT_H + +#include "TreeData.hxx" + +#include +#include +using namespace std; + +class TREEDATA_EXPORT DataObject { + +public: + DataObject(); + ~DataObject(); + + void setLabel(string label); + string getLabel(); + void setProperty(string key, string value); + string getProperty(string key); + + /*! + * This function specifies the localization of the object in the + * hierarchical organization that can be defined by the DataModel it + * belongs to. + */ + virtual string getPath() = 0; + string getPathName(); + string getNameId(); + + static const string pathsep; + + /*! This function can be used for debug */ + string toString(); + +private: + /*! The name this object can be displayed with */ + string _label; + /*! The identifier of this object. An identifier is invariant all the session long */ + string _nameId; + /*! The dictionnary of properties that characterize this object */ + map _properties; + + static int _lastId; + static const string _BASENAME; +}; + +#endif // DATAOBJECT_H diff --git a/src/TreeData/DataProcessor.cxx b/src/TreeData/DataProcessor.cxx new file mode 100644 index 000000000..ac52d5eab --- /dev/null +++ b/src/TreeData/DataProcessor.cxx @@ -0,0 +1,86 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + + +#include "DataProcessor.hxx" +#include +#include "QtHelper.hxx" + +DataProcessor::DataProcessor(DataModel * dataModel) { + _dataModel = dataModel; +} + +/*! + * This function retrieves in the data model all the DataObject + * associated to the item nameIds contained in the specified list. The + * input list is what the TreeView sends via the notification signal. + */ +DataObjectVector * DataProcessor::extract(QStringList itemNameIdList) { + if ( _dataModel == NULL ) { + STDLOG("No data model associated to this processor"); + return NULL; + } + + DataObjectVector * dataObjectList = new DataObjectVector(); + + // We can request the dataModel to obtain the dataObject associated + // to each of the item (iteNameId is a TreeView id, Qt stuff only). + QStringList::const_iterator it; + for (it = itemNameIdList.constBegin(); it != itemNameIdList.constEnd(); ++it) { + QString itemNameId = *it; + DataObject * dataObject = _dataModel->getDataObject(QS2S(itemNameId)); + + if ( dataObject != NULL ) { + dataObjectList->push_back(dataObject); + } else { + LOG("No data object associated to the item "<preprocess(itemNameIdList); + + // We can request the dataModel to obtain the dataObject associated + // to each of the item (iteNameId is a TreeView id, Qt stuff only). + QStringList::const_iterator it; + for (it = itemNameIdList.constBegin(); it != itemNameIdList.constEnd(); ++it) { + QString itemNameId = *it; + DataObject * dataObject = _dataModel->getDataObject(QS2S(itemNameId)); + + if ( dataObject != NULL ) { + this->processDataObject(dataObject); + } else { + STDLOG("No data object associated to the item "<postprocess(itemNameIdList); +} + + diff --git a/src/TreeData/DataProcessor.hxx b/src/TreeData/DataProcessor.hxx new file mode 100644 index 000000000..4798598df --- /dev/null +++ b/src/TreeData/DataProcessor.hxx @@ -0,0 +1,68 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#ifndef _DATAPROCESSOR_H_ +#define _DATAPROCESSOR_H_ + +#include "TreeData.hxx" + +#include "DataModel.hxx" +#include "DataObject.hxx" +#include +#include + +#include +typedef std::vector DataObjectVector; + +// +// ================================================================= +// This class can be used to automize processing on data objects. +// The inputs of public functions are list of selected items in the +// tree view. The function automize the extraction of associated +// DataObject and can automize the processing of these object if the +// virtual function processDataObject is implemented. +// ================================================================= +// + +class TREEDATA_EXPORT DataProcessor { + +public: + DataProcessor(DataModel * dataModel); + + DataObjectVector * extract(QStringList itemNameIdList); + void process(QStringList itemNameIdList); + + +protected: + virtual void preprocess(QStringList itemNameIdList) { + // Implement something to be executed at the begining of the process function + }; + virtual void postprocess(QStringList itemNameIdList) { + // Implement something to be executed at the end of the process function + }; + // Implement what must be done with each DataObject during the process function + virtual void processDataObject(DataObject * dataObject) = 0; + +private: + DataModel * _dataModel; +}; + +#endif diff --git a/src/TreeData/DockWidgets.cxx b/src/TreeData/DockWidgets.cxx new file mode 100644 index 000000000..fcb4e1827 --- /dev/null +++ b/src/TreeData/DockWidgets.cxx @@ -0,0 +1,106 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#include "DockWidgets.hxx" + +// Qt includes +#include + +// SALOME includes +#include +#include +#include + +/*! + * This create a gui container to hold widgets dedicated to the XCAD + * data model. By default, the dock widgets are not visible. Use the + * show() method to control the visibility (usefull when activating + * and desactivating the module to show/hide the dock widgets). + * + * This class does not make any hypothesis on what will be embedded in + * the dock widgets (only that it is QTreeView). The QTreeView is + * defined elsewhere and is generaly rendering a tree model containing + * tree items. + */ +DockWidgets::DockWidgets(SalomeApp_Application* salomeApp, + bool tabify, + const char * title) { + _salomeApp = salomeApp; + + QMainWindow *parent = _salomeApp->desktop(); + _dwDataPanel = new QDockWidget(parent); + _dwDataPanel->setVisible(false); + _dwDataPanel->setWindowTitle(title); + parent->addDockWidget(Qt::LeftDockWidgetArea, _dwDataPanel); + // + // At this step, the _dwDataPanel is located side by side with the object + // browser (or one over the other). + // + // It is possible to tabify the different dock widgets in one single + // tabbed widget. See the above example: + this->tabify(tabify); +} + +void DockWidgets::tabify(bool tabify) { + if ( tabify ) { + // We first get the object browser tree view, and then the + // associated DockWidget. Note that the tree view is a SALOME + // specific extention of the originate QTreeView and called + // QtxTreeView. + SUIT_DataBrowser* objectBrowser = _salomeApp->objectBrowser(); + QtxTreeView* treeView = objectBrowser->treeView(); + QWidget* pw = treeView->parentWidget(); + QDockWidget* dwObjectBrowser = 0; + while ( pw && !dwObjectBrowser ) { + dwObjectBrowser = ::qobject_cast( pw ); + pw = pw->parentWidget(); + }; + QMainWindow *parent = _salomeApp->desktop(); + parent->tabifyDockWidget(_dwDataPanel, dwObjectBrowser); + parent->setTabOrder(_dwDataPanel, dwObjectBrowser); + parent->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + } + else { + // TO BE IMPLEMENTED + } +} + +/*! + * This function controls the visibility of the dock widgets. + */ +void DockWidgets::show(bool isVisible) { + _dwDataPanel->setVisible(isVisible); +} + +/*! + * This function initializes the central part of the dock widget with + * a tree view that can hold a hierarchical data model. + */ +void DockWidgets::setDataView(QTreeView * dataView) { + _tvDataView = dataView; + _tvDataView->setParent(_dwDataPanel); + _tvDataView->setMinimumHeight(200); + _dwDataPanel->setWidget(_tvDataView); +} + +void DockWidgets::setPropertiesView(QTreeView * propertiesView) { + // Not implemented yet +} diff --git a/src/TreeData/DockWidgets.hxx b/src/TreeData/DockWidgets.hxx new file mode 100644 index 000000000..2c5847d13 --- /dev/null +++ b/src/TreeData/DockWidgets.hxx @@ -0,0 +1,51 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#ifndef _DOCKWIDGETS_H_ +#define _DOCKWIDGETS_H_ + +#include "TreeData.hxx" + +// Qt includes +#include +#include + +// SALOME includes +#include + +class TREEDATA_EXPORT DockWidgets { + public: + DockWidgets(SalomeApp_Application* salomeApp, + bool tabify=false, + const char * title="Data Model"); + + void tabify(bool tabify); + void show(bool isVisible); + void setDataView(QTreeView * dataView); + void setPropertiesView(QTreeView * propertyView); + + private: + SalomeApp_Application* _salomeApp; + QDockWidget * _dwDataPanel; + QTreeView * _tvDataView; +}; + +#endif // _DOCKWIDGETS_H_ diff --git a/src/TreeData/Makefile.am b/src/TreeData/Makefile.am new file mode 100644 index 000000000..99998ac29 --- /dev/null +++ b/src/TreeData/Makefile.am @@ -0,0 +1,107 @@ +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +SUBDIRS = . Test + +# moc-files generation +%_moc.cxx: %.hxx + $(MOC) $< -o $@ + +mostlyclean-local: + rm -f @builddir@/*_moc.cxx + rm -f @builddir@/*.qm + +# Libraries targets +lib_LTLIBRARIES = libSalomeTreeData.la + +# +# Generic source files +# +salomeinclude_HEADERS = \ + TreeData.hxx \ + DockWidgets.hxx \ + TreeModel.hxx \ + TreeItem.hxx \ + TreeView.hxx \ + TreeObserver.hxx \ + DataModel.hxx \ + DataObject.hxx \ + DataProcessor.hxx \ + TreeGuiManager.hxx + +dist_libSalomeTreeData_la_SOURCES = \ + DockWidgets.cxx \ + TreeModel.cxx \ + TreeItem.cxx \ + TreeView.cxx \ + TreeObserver.cxx \ + DataModel.cxx \ + DataObject.cxx \ + DataProcessor.cxx \ + TreeGuiManager.cxx + +# MOC pre-processing +MOC_FILES_HXX = \ + TreeModel_moc.cxx \ + TreeView_moc.cxx \ + TreeObserver_moc.cxx + +nodist_libSalomeTreeData_la_SOURCES = $(MOC_FILES_HXX) + +CORBA_CXXFLAGS=@OMNIORB_CXXFLAGS@ @OMNIORB_INCLUDES@ +CORBA_LIBS=@OMNIORB_LIBS@ + +QT_CXXFLAGS=@QT_INCLUDES@ @QT_MT_INCLUDES@ +CAS_CXXFLAGS=@CAS_CPPFLAGS@ @CAS_CXXFLAGS@ + +BOOST_CPPFLAGS=@BOOST_CPPFLAGS@ +BOOST_LIBS=@BOOST_LIBS@ + +libSalomeTreeData_la_CPPFLAGS = \ + $(QT_CXXFLAGS) \ + $(CAS_CXXFLAGS) \ + $(BOOST_CPPFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(KERNEL_CXXFLAGS) \ + -I$(srcdir)/../SalomeApp \ + -I$(srcdir)/../LightApp \ + -I$(srcdir)/../CAM \ + -I$(srcdir)/../STD \ + -I$(srcdir)/../ObjBrowser \ + -I$(srcdir)/../SUIT \ + -I$(srcdir)/../Qtx \ + -I$(srcdir)/../GuiHelpers + + + + +libSalomeTreeData_la_LDFLAGS = \ + $(CORBA_LIBS) $(QT_LIBS)\ + $(KERNEL_LDFLAGS) -lSalomeLifeCycleCORBA -lSalomeKernelHelpers \ + $(top_builddir)/src/SalomeApp/libSalomeApp.la \ + $(top_builddir)/src/LightApp/libLightApp.la \ + $(top_builddir)/src/SUIT/libsuit.la \ + $(top_builddir)/src/Qtx/libqtx.la \ + $(top_builddir)/src/CAM/libCAM.la \ + $(top_builddir)/src/STD/libstd.la \ + $(top_builddir)/src/ObjBrowser/libObjBrowser.la diff --git a/src/TreeData/Test/Makefile.am b/src/TreeData/Test/Makefile.am new file mode 100644 index 000000000..8d6141e76 --- /dev/null +++ b/src/TreeData/Test/Makefile.am @@ -0,0 +1,99 @@ +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF) +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# moc-files generation +%_moc.cxx: %.hxx + $(MOC) $< -o $@ + +mostlyclean-local: + rm -f @builddir@/*_moc.cxx + rm -f @builddir@/*.qm + rm -f @builddir@/*_moc.cxx @builddir@/ui_*.h + +# qt forms files generation (uic) +ui_%.h: %.ui + $(UIC) -o $@ $< + + +CORBA_CXXFLAGS=@OMNIORB_CXXFLAGS@ @OMNIORB_INCLUDES@ +CORBA_LIBS=@OMNIORB_LIBS@ +QT_CXXFLAGS=@QT_INCLUDES@ @QT_MT_INCLUDES@ + +TEST_CPPFLAGS = \ + $(QT_CXXFLAGS) \ + $(CORBA_CXXFLAGS) \ + $(KERNEL_CXXFLAGS) \ + -I$(top_srcdir)/src/GuiHelpers \ + -I$(top_srcdir)/src/TreeData \ + -I. + +TEST_LDFLAGS = \ + $(CORBA_LIBS) $(QT_LIBS) \ + $(top_builddir)/src/TreeData/libSalomeTreeData.la \ + $(top_builddir)/src/GuiHelpers/libSalomeGuiHelpers.la \ + $(KERNEL_LDFLAGS) -lSalomeLifeCycleCORBA -lSalomeKernelHelpers + +# Program targets +bin_PROGRAMS = TreeData_guitester TreeData_tester + +MOC_FILES_HXX = \ + mainwindow_moc.cxx + +UIC_FILES = \ + ui_mainwindow.h + +BUILT_SOURCES = $(UIC_FILES) + +nodist_TreeData_guitester_SOURCES = $(MOC_FILES_HXX) $(UIC_FILES) + +TreeData_guitester_SOURCES = \ + testhelper.hxx \ + testhelper.cxx \ + guitester.cxx \ + mainwindow.hxx \ + mainwindow.cxx \ + MyDataModel.hxx \ + MyDataModel.cxx + +TreeData_guitester_CPPFLAGS = \ + $(TEST_CPPFLAGS) + +TreeData_guitester_LDFLAGS = \ + $(TEST_LDFLAGS) + +TreeData_tester_SOURCES = \ + tester.cxx \ + MyDataModel.cxx + +TreeData_tester_CPPFLAGS = \ + $(TEST_CPPFLAGS) + +TreeData_tester_LDFLAGS = \ + $(TEST_LDFLAGS) + +# test data files +testdir = $(salomeresdir)/testdata +test_DATA = \ + data.txt + +EXTRA_DIST+=$(test_DATA) diff --git a/src/TreeData/Test/MyDataModel.cxx b/src/TreeData/Test/MyDataModel.cxx new file mode 100644 index 000000000..731c8fdc7 --- /dev/null +++ b/src/TreeData/Test/MyDataModel.cxx @@ -0,0 +1,67 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 "MyDataModel.hxx" + +// +// ================================================================= +// MyDataObject implementation +// ================================================================= +// + +const string MyDataObject::PROPERTY_KEY_TYPE = "type"; +const string MyDataObject::PROPERTY_KEY_CIRCUIT ="circuit"; +const string MyDataObject::PROPERTY_KEY_REPFONC ="rf"; + +MyDataObject::MyDataObject() : DataObject() { + this->setProperty(PROPERTY_KEY_TYPE, "Tuyauterie"); + this->setProperty(PROPERTY_KEY_CIRCUIT,"RRA"); + this->setProperty(PROPERTY_KEY_REPFONC,"RF_01"); +} + +/*! This function specified the localization of the object in the + * hierarchical organization + */ +string MyDataObject::getPath() { + // We choose here a convention for organizing the path for this + // class of object. + /* + string path = getProperty(PROPERTY_KEY_CIRCUIT) + pathsep + + getProperty(PROPERTY_KEY_REPFONC) + pathsep + + getProperty(PROPERTY_KEY_TYPE); + */ + string path = getProperty(PROPERTY_KEY_TYPE) + pathsep + + getProperty(PROPERTY_KEY_CIRCUIT) + pathsep + + getProperty(PROPERTY_KEY_REPFONC); + + return path; +} + +// +// ================================================================= +// MyDataModel implementation +// ================================================================= +// +MyDataModel::MyDataModel() : DataModel() { +} + +DataObject * MyDataModel::newDataObject() { + MyDataObject * dataObject = new MyDataObject(); + return dataObject; +} diff --git a/src/TreeData/Test/MyDataModel.hxx b/src/TreeData/Test/MyDataModel.hxx new file mode 100644 index 000000000..cf539559b --- /dev/null +++ b/src/TreeData/Test/MyDataModel.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +#ifndef _MYDATAMODEL_H_ +#define _MYDATAMODEL_H_ + +// +// ================================================================= +// Definition of an atom in the data model as an implementation of +// the virtual class DataObject +// ================================================================= +// + +#include "DataObject.hxx" +class MyDataObject: public DataObject { +public: + MyDataObject(); + virtual string getPath(); + static const string PROPERTY_KEY_TYPE; + static const string PROPERTY_KEY_CIRCUIT; + static const string PROPERTY_KEY_REPFONC; +}; + + +// +// ================================================================= +// Definition of the data model as an implementation of the virtual +// class DataModel. It implements the DataObject factory. +// ================================================================= +// +#include "DataModel.hxx" +class MyDataModel: public DataModel { +public: + MyDataModel(); + virtual DataObject * newDataObject(); +}; + +#endif // _MYDATAMODEL_H_ diff --git a/src/TreeData/Test/data.txt b/src/TreeData/Test/data.txt new file mode 100755 index 000000000..d28285b3b --- /dev/null +++ b/src/TreeData/Test/data.txt @@ -0,0 +1,15 @@ +Tuyauterie;RF1;T1 +Tuyauterie;RF1;T2 +Tuyauterie;RF1;T3 +Tuyauterie;RF2;T1 +Tuyauterie;RF3;T1 +Tuyauterie;RF3;T2 +Composansts;RF1;T1 +Composansts;RF1;T2 +Composansts;RF3;T2 +Genie Civil;RF1;T1 +Genie Civil;RF1;T2 +Genie Civil;RF1;T3 +Genie Civil;RF2;T1 +Genie Civil;RF3;T1 +Genie Civil;RF3;T2 diff --git a/src/TreeData/Test/guitester.cxx b/src/TreeData/Test/guitester.cxx new file mode 100644 index 000000000..c2e45d896 --- /dev/null +++ b/src/TreeData/Test/guitester.cxx @@ -0,0 +1,221 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +#include +#include +#include + +#include + +// +// ================================================================= +// Generic helper functions +// ================================================================= +// +/*! + * This functions displays a main window that embeds the specified + * widget. A dockwidget is used to create a context similar to as the + * SALOME target context. + */ +void showWidget(QWidget * widget) { + + QMainWindow * window = new QMainWindow(); + + // Prepare a gui framework for testing the widget. We use a + // dockwidget, just to be in a context similar to as the SALOME + // target context. + QDockWidget * dwDataPanel = new QDockWidget(window); + dwDataPanel->setVisible(true); + dwDataPanel->setWindowTitle("XCAD data model"); + window->addDockWidget(Qt::LeftDockWidgetArea, dwDataPanel); + + // Then plug the widget in the dock widget framework: + widget->setParent(dwDataPanel); + widget->setMinimumHeight(300); + dwDataPanel->setWidget(widget); + + window->show(); +} + +// +// ================================================================= +// Tests functions for TreeModel +// ================================================================= +// +#include "TreeModel.hxx" +#include "MyDataModel.hxx" +#include "testhelper.hxx" + + +/*! + * This function fills the specified tree with data that show + * different levels of path in the tree. + */ +void _TEST_treemodel_addData_01(TreeModel * dataTreeModel) { + // We can first add categories (for example to set categories + // properties) + QStringList path; + DataObject * folder; + + path << "folder_1"; + folder = TESTHELPER_dummyObject("folder_1.1"); + dataTreeModel->addData(folder, path); + folder = TESTHELPER_dummyObject("folder_1.2"); + dataTreeModel->addData(folder, path); + + path.clear(); + path << "folder_2"; + folder = TESTHELPER_dummyObject("folder_2.1"); + dataTreeModel->addData(folder, path); + + // Then we can add data + DataObject * data; + path.clear(); + path << "folder_1" << "folder_1.1"; + data = TESTHELPER_dummyObject("data_1.1.1"); + dataTreeModel->addData(data, path); + data = TESTHELPER_dummyObject("data_1.1.2"); + dataTreeModel->addData(data, path); + // You can notice that there is no conceptual difference between a + // folder and an item, as in the QTreeModel. + + // No limit to the depth + path.clear(); + path << "xcad" << "data1" << "x" << "y"; + data = TESTHELPER_dummyObject("z"); + dataTreeModel->addData(data,path); +} + +#define LOOPSIZE 15 +/*! + * This function fills the specified tree with a huge amount of data + */ +void _TEST_treemodel_addData_02(TreeModel * dataTreeModel) { + QStringList path; + DataObject * data; + + START_TIMING(treemodel); + for (int i=0; iaddData(data,path); + path.clear(); + } + } + } + END_TIMING(treemodel,1); +} + +void _TEST_treemodel_addData_03(TreeModel * dataTreeModel) { + MyDataObject * dataObject = new MyDataObject(); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_TYPE, "Tuyauterie"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_CIRCUIT, "RCP"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_REPFONC, "RF1"); + dataTreeModel->addData(dataObject); + + dataObject = new MyDataObject(); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_TYPE, "Tuyauterie"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_CIRCUIT, "RCP"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_REPFONC, "RF1"); + dataTreeModel->addData(dataObject); + + dataObject = new MyDataObject(); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_TYPE, "Tuyauterie"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_CIRCUIT, "RCP"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_REPFONC, "RF2"); + dataTreeModel->addData(dataObject); + + dataObject = new MyDataObject(); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_TYPE, "Tuyauterie"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_CIRCUIT, "RRA"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_REPFONC, "RF1"); + dataTreeModel->addData(dataObject); + + dataObject = new MyDataObject(); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_TYPE, "Génie civil"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_CIRCUIT, "RRA"); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_REPFONC, "RF1"); + dataTreeModel->addData(dataObject); +} + +/*! + * This test function shows how it's possible to load data from a file + * to populate the tree model. + */ +void _TEST_treemodel_loadDataFromFile(TreeModel * dataTreeModel, const QString &filename) { + TESTHELPER_loadDataFromFile(dataTreeModel, filename); +} + +/*! + * Main test function for the tree model demo. + */ +#include "TreeModel.hxx" +#include "TreeView.hxx" +void TEST_treemodel() { + + START_TIMING(treemodel); + + // We first prepare a data view embedding a tree model + TreeView * dataView = new TreeView(); + QStringList headers; + headers << QObject::tr("Name") << QObject::tr("Value"); + TreeModel * dataTreeModel = new TreeModel(headers); + dataView->setModel(dataTreeModel); + END_TIMING(treemodel,1); + + // Then we can fill the tree model with data. Can proceed with + // different ways (comment/uncomment which you want to test): + _TEST_treemodel_loadDataFromFile(dataTreeModel, TESTHELPER_testfilename(DATAFILENAME)); + //_TEST_treemodel_addData_01(dataTreeModel); + //_TEST_treemodel_addData_02(dataTreeModel); + //_TEST_treemodel_addData_03(dataTreeModel); + // Finally, show the widget in a main window + END_TIMING(treemodel,1); + + showWidget(dataView); + END_TIMING(treemodel,1); +} + +// +// ================================================================= +// Tests functions for TreeModel with interactive changes +// ================================================================= +// +#include "mainwindow.hxx" +void TEST_treemodel_interactif() { + MainWindow * window = new MainWindow(); + window->show(); +} + +// +// ================================================================= +// +int main(int argc, char * argv[ ]) +{ + QApplication app(argc, argv); + TEST_treemodel(); + //TST_treemodel_interactif(); + return app.exec(); +} diff --git a/src/TreeData/Test/mainwindow.cxx b/src/TreeData/Test/mainwindow.cxx new file mode 100644 index 000000000..bb310118a --- /dev/null +++ b/src/TreeData/Test/mainwindow.cxx @@ -0,0 +1,188 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 + +#include "mainwindow.hxx" +#include "TreeModel.hxx" + +#include +#include "testhelper.hxx" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + setupUi(this); + + QStringList headers; + headers << tr("Title") << tr("Description"); + + TreeModel *model = new TreeModel(headers); + TESTHELPER_loadDataFromFile(model, TESTHELPER_testfilename(DATAFILENAME)); + + view->setModel(model); + for (int column = 0; column < model->columnCount(); ++column) + view->resizeColumnToContents(column); + + connect(exitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + + connect(view->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection &, + const QItemSelection &)), + this, SLOT(updateActions())); + + connect(actionsMenu, SIGNAL(aboutToShow()), this, SLOT(updateActions())); + connect(insertRowAction, SIGNAL(triggered()), this, SLOT(insertRow())); + connect(insertColumnAction, SIGNAL(triggered()), this, SLOT(insertColumn())); + connect(removeRowAction, SIGNAL(triggered()), this, SLOT(removeRow())); + connect(removeColumnAction, SIGNAL(triggered()), this, SLOT(removeColumn())); + connect(insertChildAction, SIGNAL(triggered()), this, SLOT(insertChild())); + connect(newDataAction, SIGNAL(triggered()), this, SLOT(newData())); + + updateActions(); +} + +void MainWindow::newData() { + LOG("MainWindow::newData(): START"); + + bool ok; + QString text = QInputDialog::getText(this, tr("QInputDialog::getText()"), + tr("Data path:"), QLineEdit::Normal, + "folder/subfolder/item", &ok); + if (!ok || text.trimmed().isEmpty()) + return; + + QStringList path = text.trimmed().split("/"); + TreeModel *model = (TreeModel *)view->model(); + + QString label = path.last(); + path.removeLast(); + DataObject * data = TESTHELPER_dummyObject(label); + model->addData(data,path); + + LOG("MainWindow::newData(): END"); +} + +void MainWindow::insertChild() +{ + QModelIndex index = view->selectionModel()->currentIndex(); + QAbstractItemModel *model = view->model(); + + if (model->columnCount(index) == 0) { + if (!model->insertColumn(0, index)) + return; + } + + if (!model->insertRow(0, index)) + return; + + for (int column = 0; column < model->columnCount(index); ++column) { + QModelIndex child = model->index(0, column, index); + model->setData(child, QVariant("[No data]"), Qt::EditRole); + if (!model->headerData(column, Qt::Horizontal).isValid()) + model->setHeaderData(column, Qt::Horizontal, QVariant("[No header]"), + Qt::EditRole); + } + + view->selectionModel()->setCurrentIndex(model->index(0, 0, index), + QItemSelectionModel::ClearAndSelect); + updateActions(); +} + +bool MainWindow::insertColumn(const QModelIndex &parent) +{ + QAbstractItemModel *model = view->model(); + int column = view->selectionModel()->currentIndex().column(); + + // Insert a column in the parent item. + bool changed = model->insertColumn(column + 1, parent); + if (changed) + model->setHeaderData(column + 1, Qt::Horizontal, QVariant("[No header]"), + Qt::EditRole); + + updateActions(); + + return changed; +} + +void MainWindow::insertRow() +{ + QModelIndex index = view->selectionModel()->currentIndex(); + QAbstractItemModel *model = view->model(); + + if (!model->insertRow(index.row()+1, index.parent())) + return; + + updateActions(); + + for (int column = 0; column < model->columnCount(index.parent()); ++column) { + QModelIndex child = model->index(index.row()+1, column, index.parent()); + model->setData(child, QVariant("[No data]"), Qt::EditRole); + } +} + +bool MainWindow::removeColumn(const QModelIndex &parent) +{ + QAbstractItemModel *model = view->model(); + int column = view->selectionModel()->currentIndex().column(); + + // Insert columns in each child of the parent item. + bool changed = model->removeColumn(column, parent); + + if (!parent.isValid() && changed) + updateActions(); + + return changed; +} + +void MainWindow::removeRow() +{ + QModelIndex index = view->selectionModel()->currentIndex(); + QAbstractItemModel *model = view->model(); + if (model->removeRow(index.row(), index.parent())) + updateActions(); +} + +void MainWindow::updateActions() +{ + bool hasSelection = !view->selectionModel()->selection().isEmpty(); + removeRowAction->setEnabled(hasSelection); + removeColumnAction->setEnabled(hasSelection); + + bool hasCurrent = view->selectionModel()->currentIndex().isValid(); + insertRowAction->setEnabled(hasCurrent); + insertColumnAction->setEnabled(hasCurrent); + + if (hasCurrent) { + view->closePersistentEditor(view->selectionModel()->currentIndex()); + + int row = view->selectionModel()->currentIndex().row(); + int column = view->selectionModel()->currentIndex().column(); + if (view->selectionModel()->currentIndex().parent().isValid()) + statusBar()->showMessage(tr("Position: (%1,%2)").arg(row).arg(column)); + else + statusBar()->showMessage(tr("Position: (%1,%2) in top level").arg(row).arg(column)); + } +} + +void MainWindow::contextMenuEvent(QContextMenuEvent *event) { + QMenu menu(this); + menu.addAction(newDataAction); + menu.exec(event->globalPos()); +} diff --git a/src/TreeData/Test/mainwindow.hxx b/src/TreeData/Test/mainwindow.hxx new file mode 100644 index 000000000..5f973f340 --- /dev/null +++ b/src/TreeData/Test/mainwindow.hxx @@ -0,0 +1,54 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +#include "ui_mainwindow.h" + +class QAction; +class QTreeView; +class QWidget; + +class MainWindow : public QMainWindow, private Ui::MainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0); + +protected: + void contextMenuEvent(QContextMenuEvent *event); + +public slots: + void updateActions(); + +private slots: + void insertChild(); + bool insertColumn(const QModelIndex &parent = QModelIndex()); + void insertRow(); + bool removeColumn(const QModelIndex &parent = QModelIndex()); + void removeRow(); + void newData(); +}; + +#endif diff --git a/src/TreeData/Test/mainwindow.ui b/src/TreeData/Test/mainwindow.ui new file mode 100644 index 000000000..a7cfe6bdf --- /dev/null +++ b/src/TreeData/Test/mainwindow.ui @@ -0,0 +1,140 @@ + + MainWindow + + + + 0 + 0 + 573 + 468 + + + + Editable Tree Model + + + + + 0 + + + 0 + + + + + true + + + QAbstractItemView::SelectItems + + + QAbstractItemView::ScrollPerPixel + + + false + + + true + + + + + + + + + 0 + 0 + 573 + 29 + + + + + &Actions + + + + + + + + + + + + &File + + + + + + Data + + + + + + + + + + + E&xit + + + Ctrl+Q + + + + + Insert Row + + + Ctrl+I, R + + + + + Remove Row + + + Ctrl+R, R + + + + + Insert Column + + + Ctrl+I, C + + + + + Remove Column + + + Ctrl+R, C + + + + + Insert Child + + + Ctrl+N + + + + + new + + + + + + + + diff --git a/src/TreeData/Test/tester.cxx b/src/TreeData/Test/tester.cxx new file mode 100644 index 000000000..e26206df8 --- /dev/null +++ b/src/TreeData/Test/tester.cxx @@ -0,0 +1,79 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 "QtHelper.hxx" + +// +// ================================================================= +// Helper functions for DataObject and DataModel classes +// ================================================================= +// + +// ---- +// A DataObject can't be used as is but must be specialized to +// specify the behavior in the hierarchic model. +#include "MyDataModel.hxx" + +void TEST_DataObject() { + // In this test, the object id should increase at each instance + DataObject * dataObject; + for (int i=0; i<100; i++) { + dataObject = new MyDataObject(); + QLOG("object nameId = " << dataObject->getNameId().c_str()); + } + QLOG("path = " << dataObject->getPath().c_str()); + QLOG("pathname = " << dataObject->getPathName().c_str()); + + QLOG("serialize= " << dataObject->toString().c_str()); + +} + +void TEST_DataModel() { + MyDataModel * dataModel = new MyDataModel(); + + int refIter = 53; + string refNameId; + + DataObject * dataObject; + for (int i=0; i<100; i++) { + // We can either create the data object using its constructor or + // using the factory of the model (the prefered way): + // dataObject = new MyDataObject(); + dataObject = dataModel->newDataObject(); + dataObject->setLabel("myobject"+ToString(i)); + if ( i == refIter ) { + refNameId = dataObject->getNameId(); + } + dataModel->addDataObject(dataObject); + } + + dataObject = dataModel->getDataObject(refNameId); + QLOG("object nameId = " << dataObject->getNameId().c_str()); + QLOG("path = " << dataObject->getPath().c_str()); + QLOG("pathname = " << dataObject->getPathName().c_str()); +} + +// +// ================================================================= +// +int main(int argc, char * argv[ ]) +{ + TEST_DataObject(); + //TEST_DataModel(); +} diff --git a/src/TreeData/Test/testhelper.cxx b/src/TreeData/Test/testhelper.cxx new file mode 100644 index 000000000..c993c643a --- /dev/null +++ b/src/TreeData/Test/testhelper.cxx @@ -0,0 +1,93 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 "testhelper.hxx" + +#include +#include + +#include "QtHelper.hxx" +#include "MyDataModel.hxx" + +// Standard C include (for getenv) +#include + +QString TESTHELPER_testfilename(const char * basefilename) { + QString aFile; + char * GUI_ROOT_DIR = getenv("GUI_ROOT_DIR"); + QString * root; + if ( GUI_ROOT_DIR != NULL ) { + root = new QString(GUI_ROOT_DIR); + } + else { + root = new QString("/home/gboulant/development/projets/salome/devel/XSALOME/install"); + } + QString relativePathName = "/share/salome/resources/gui/testdata/"; + aFile.append(*root + relativePathName + basefilename); + + QLOG("The test file is : "<setLabel(QCHARSTAR(label)); + return dataObject; +} + + +#define SEP ";" +/*! + * This test function shows how it's possible to load data from a file + * to populate the tree model. + */ +void TESTHELPER_loadDataFromFile(TreeModel * dataTreeModel, const QString &filename) { + QFile file ( filename ); + file.open ( QIODevice::ReadOnly ); + + MyDataObject * dataObject; + while ( 1 ) { + QByteArray byteArray = file.readLine(); + + if ( byteArray.isEmpty() ) + break; + + QString data = (QString ( byteArray.mid(0, byteArray.size()-1))).trimmed(); + QStringList dataList = data.split ( SEP ); + // The data list is used here to set properties (and then the path + // of location in the tree model). + + dataObject = new MyDataObject(); + // The label is autogenerated, but we may specify here a custom + // one. We just fill the properties with data values read in the + // file. + dataObject->setProperty(MyDataObject::PROPERTY_KEY_TYPE, QCHARSTAR(dataList[0])); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_REPFONC, QCHARSTAR(dataList[1])); + dataObject->setProperty(MyDataObject::PROPERTY_KEY_CIRCUIT, QCHARSTAR(dataList[2])); + if ( ! dataTreeModel->addData(dataObject) ) { + QLOG("ERR: data not added"); + } + } + + file.close(); +} diff --git a/src/TreeData/Test/testhelper.hxx b/src/TreeData/Test/testhelper.hxx new file mode 100644 index 000000000..ca0680e71 --- /dev/null +++ b/src/TreeData/Test/testhelper.hxx @@ -0,0 +1,33 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +#ifndef _TESTHELPER_HXX_ +#define _TESTHELPER_HXX_ + +#include +#include "TreeModel.hxx" +#include "DataObject.hxx" + +#define DATAFILENAME "data.txt" + +QString TESTHELPER_testfilename(const char * basefilename); +DataObject * TESTHELPER_dummyObject(QString label); +void TESTHELPER_loadDataFromFile(TreeModel * dataTreeModel, const QString &filename); + +#endif // _TESTHELPER_HXX_ diff --git a/src/TreeData/TreeData.hxx b/src/TreeData/TreeData.hxx new file mode 100755 index 000000000..6d98c97f5 --- /dev/null +++ b/src/TreeData/TreeData.hxx @@ -0,0 +1,36 @@ +// Copyright (C) 2007-2012 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 +// + +#ifndef TREEDATA_HXX +#define TREEDATA_HXX + +#ifdef WIN32 +# if defined SALOMETREEDATA_EXPORTS || defined SalomeTreeData_EXPORTS +# define TREEDATA_EXPORT __declspec( dllexport ) +# else +# define TREEDATA_EXPORT __declspec( dllimport ) +# endif +#else +# define TREEDATA_EXPORT +#endif + +#endif //TREEDATA_HXX diff --git a/src/TreeData/TreeGuiManager.cxx b/src/TreeData/TreeGuiManager.cxx new file mode 100644 index 000000000..22594e1f5 --- /dev/null +++ b/src/TreeData/TreeGuiManager.cxx @@ -0,0 +1,153 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#include "TreeGuiManager.hxx" + +// SALOME includes +#include + +// XCAD includes +#include "TreeView.hxx" +#include "QtHelper.hxx" + +// TODO: +// IMP: The constructor should have a dockwidget as argument. +// The creation of the void dockwidget (without the data tree +// embedded) should be done previously by the StandardApp_Module. +// The constructor would fill the dockwidget with a data tree view + +/*! + * The construction of the gui manager setups a graphic framework that + * consists in a set of dock widgets implanted in the SALOME GUI and + * embedding a tree view rendering a data model (collection of data + * objects) in a hierarchic graphical organisation. + * + * The data model is a straith list of data objects while the view is + * a tree representation of this collection where folders corresponds + * to specific properties of the objects. + * + * This represention is for the needs of navigation in a huge amount + * of data and to ease the selection and processing of items. + */ +TreeGuiManager::TreeGuiManager(SalomeApp_Application * salomeApp, const char * title) + : TreeObserver() +{ + _salomeApp = salomeApp; + + bool tabify = false; + _dockWidgets = new DockWidgets(_salomeApp, tabify, title); + + // Create a TreeView to be associated to a TreeModel dedicated to + // the Xcad data: + _dataTreeView = new TreeView(); + QStringList headers; + headers << tr("Name") << tr("Value"); + _dataTreeModel = new TreeModel(headers); + _dataTreeView->setModel(_dataTreeModel); + + // Then plug the TreeView in the dock widget: + _dockWidgets->setDataView(_dataTreeView); + + // We specify here the dataview to be observed + this->observe(_dataTreeView); +} + +/*! + * This returns the SALOME application (SalomeApp_Application + * instance) associated to this TreeGuiManager. + */ +SalomeApp_Application * TreeGuiManager::getSalomeApplication() { + return _salomeApp; +} + + +/*! + * This function set a layout of the different dock widgets in one + * single tabbed widget. + */ +void TreeGuiManager::tabifyDockWidgets(bool tabify) { + _dockWidgets->tabify(tabify); +} + +/*! + * This function switch on/off the dock widgets managed by this + * gui manager. + */ +void TreeGuiManager::showDockWidgets(bool isVisible) { + _dockWidgets->show(isVisible); +} + +/*! + * This returns the data tree model defined in this + * TreeGuiManager. The data tree model is a tree representation of the + * data model associated to this TreeGuiManager. + */ +TreeModel * TreeGuiManager::getDataTreeModel() { + return _dataTreeModel; +} + +/*! + * This returns the data tree view defined in this + * TreeGuiManager. The data tree view can be request to customize the + * popup menu associated to the tree representation. + */ +TreeView * TreeGuiManager::getDataTreeView() { + return _dataTreeView; +} + + +/*! + * This function specifies the data model to be used by the + * TreeGuiManager. + */ +void TreeGuiManager::setDataModel(DataModel * dataModel) { + _dataModel = dataModel; +} + +DataModel * TreeGuiManager::getDataModel() { + return _dataModel; +} + +/*! + * This function processes the edit signals received from the + * TreeView. This is a default implementation that only prints the + * reception of the signal and some information about the dataObject + * associated to the item whose id is specified. In practice, the data + * model could be requested here to retrieve the data object to be + * edited from the nameId. + * TO BE IMPLEMENTED IN A DOMAIN SPECIFIC VERSION OF THIS CLASS + */ + +void TreeGuiManager::processItemList(QStringList itemNameIdList, + int actionId) +{ + // WARN: THIS IS A DEFAULT IMPLEMENTATION GIVEN FOR DEMONSTRATION + // OF WHAT TO DO WITH THE PARAMETERS + + QString itemNameId = itemNameIdList[0]; + LOG("TreeGuiManager: signal received : process item "<getDataObject(QS2S(itemNameId)); + if ( dataObject != NULL ) { + LOG("TreeGuiManager: dataObject = "<toString().c_str()); + } else { + LOG("TreeGuiManager: no data object associated to this item"); + } +} diff --git a/src/TreeData/TreeGuiManager.hxx b/src/TreeData/TreeGuiManager.hxx new file mode 100644 index 000000000..6d79fc8a9 --- /dev/null +++ b/src/TreeData/TreeGuiManager.hxx @@ -0,0 +1,64 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#ifndef _TREEGUIMANAGER_H_ +#define _TREEGUIMANAGER_H_ + +#include "TreeData.hxx" + +// SALOME includes +#include + +// TREEDATA includes +#include "DockWidgets.hxx" +#include "TreeModel.hxx" +#include "DataModel.hxx" +#include "TreeView.hxx" +#include "TreeObserver.hxx" + +class TREEDATA_EXPORT TreeGuiManager : public TreeObserver { + +public: + TreeGuiManager(SalomeApp_Application * salomeApp, const char * title="Data Model"); + void tabifyDockWidgets(bool tabify); + void showDockWidgets(bool isVisible); + SalomeApp_Application * getSalomeApplication(); + + TreeModel * getDataTreeModel(); + TreeView * getDataTreeView(); + + void setDataModel(DataModel * dataModel); + DataModel * getDataModel(); + +private: + SalomeApp_Application * _salomeApp; + + DockWidgets * _dockWidgets; + TreeView * _dataTreeView; + + TreeModel * _dataTreeModel; + DataModel * _dataModel; + +public slots: + virtual void processItemList(QStringList itemNameIdList, int actionId); +}; + +#endif /* _TREEGUIMANAGER_H_ */ diff --git a/src/TreeData/TreeItem.cxx b/src/TreeData/TreeItem.cxx new file mode 100644 index 000000000..26394f61f --- /dev/null +++ b/src/TreeData/TreeItem.cxx @@ -0,0 +1,242 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + + +#include +#include "TreeItem.hxx" + +TreeItem::TreeItem(const QString &nameId, + const QVector &columnValues, + TreeItem *parent) +{ + this->initialize(nameId, columnValues, parent); +} + +/*! + * This initializes the tree item. Called by the constructors. + */ +void TreeItem::initialize(const QString &nameId, + const QVector &columnValues, + TreeItem *parent) { + _itemNameId = nameId; + _itemData = columnValues; + _parentItem = parent; + + // An item is associated to the model of its parent. It can't be + //done automatically in the case where the item has no parent. Then + //the function associatedToModel has to be called explicitely from + //within the user code (for exemple at construction of the model, + //when creating the root item). + if ( parent != NULL ) { + this->associateToModel(parent->associatedModel()); + } +} + +TreeItem::~TreeItem() +{ + qDeleteAll(_childItems); + qDeleteAll(_childItemsMapById); + qDeleteAll(_childItemsMapByLabel); +} + +/*! + * This must be used to specified which model this item belongs to. It + * is required because the item sometimes requests its model for + * global informations about the data tree. In standard usage, this + * function is automatically set when the item is instantiated by + * requested the parent item. Then only the root item needs a manual + * setting. + */ +void TreeItem::associateToModel(TreeModel * model) { + _associatedModel = model; +} + +TreeModel * TreeItem::associatedModel() { + return _associatedModel; +} + +/*! + * This provide an identifier for this item + */ +QString TreeItem::nameId() { + return _itemNameId; +} + +/*! + * This creates an item from the specified dataObject and put it in + * the decendency of this item at the specified relativePath. The + * created item could not be a direct child of this item in the case + * where the relative path is not null. Note that no reference on the + * dataObject is kept in this instance. Only the identifier is used to + * set the item identifier, and the properties may be used to set the + * values of the item (stored in columns). + */ +void TreeItem::appendChild(DataObject * dataObject, + const QStringList &relativePath) { + // Definition of the nameId + QString nameId = QString(dataObject->getNameId().c_str()); + + // Definition of columns data values + QVector columnValues; + columnValues << QString(dataObject->getLabel().c_str()); + columnValues << "No value"; // We could use the dataObject properties + + // Append the item at the specified location with the specified values: + this->appendChild(nameId, columnValues, relativePath); +} + +void TreeItem::appendChild(const QString &nameId, + const QVector &columnValues, + const QStringList &relativePath) { + + if ( relativePath.isEmpty() ) { + // It is a direct child => just create and append to this. + TreeItem * child = new TreeItem(nameId, columnValues, this); + this->appendChild(child); + return; + } + + // The child is embedded in a sub-folder (to be created if doesn't + // exist). + // We first check if the sub-folder already exist: + TreeItem * folder = this->childByLabel(relativePath[0]); + if ( folder == NULL ) { + // The folder does not exist. It must be created before going any + // further. By convention we choose the folder name as + // identifier. + QString folderNameId = relativePath[0]; + QVector folderColumnValues; + folderColumnValues << relativePath[0] << "No value"; + folder = new TreeItem(folderNameId, folderColumnValues, this); + this->appendChild(folder); + } + + // We create the relative path of the next iteration (delete the + // first folder path). + QStringList nextRelativePath; + for (int i = 1; i < relativePath.size(); ++i) + nextRelativePath << relativePath[i]; + + folder->appendChild(nameId, columnValues, nextRelativePath); +} + +/*! + * This appends the specified child to this item. This item is the + * direct parent of the specified child. + */ +void TreeItem::appendChild(TreeItem *item) +{ + TreeModel * model = this->associatedModel(); + + int position = this->childCount(); + model->beginInsertRows(this->modelIndex(), position, position); + _childItems.append(item); + _childItemsMapById[item->nameId()] = item; + _childItemsMapByLabel[item->data(0).toString()] = item; + model->endInsertRows(); +} + +/*! + * The child() function returns the child that corresponds to the + * specified row number in the item's list of child items. + */ +TreeItem *TreeItem::child(int row) +{ + return _childItems.value(row); +} + +TreeItem *TreeItem::childById(const QString &nameId) +{ + QMap ::iterator it; + it = _childItemsMapById.find ( nameId ); + + if ( it != _childItemsMapById.end() ) { + return it.value(); + } + return NULL; +} + +TreeItem *TreeItem::childByLabel(const QString &label) +{ + QMap ::iterator it; + it = _childItemsMapByLabel.find ( label ); + + if ( it != _childItemsMapByLabel.end() ) { + return it.value(); + } + return NULL; +} + + + +int TreeItem::childCount() const +{ + return _childItems.count(); +} + +/*! + * The rowIndex() function reports the item's location within its + * parent's list of items. + */ +int TreeItem::rowIndex() const +{ + if (_parentItem) + return _parentItem->_childItems.indexOf(const_cast(this)); + + return 0; +} + +int TreeItem::columnCount() const +{ + return _itemData.count(); +} + +QVariant TreeItem::data(int column) const +{ + return _itemData.value(column); +} + +TreeItem *TreeItem::parent() +{ + return _parentItem; +} + +bool TreeItem::setData(int column, const QVariant &value) +{ + if (column < 0 || column >= _itemData.size()) + return false; + + _itemData[column] = value; + return true; +} + +QModelIndex TreeItem::modelIndex(int column) +{ + TreeModel * model = this->associatedModel(); + if (_parentItem && (_parentItem != model->getRootItem())) + return model->index(rowIndex(), + column, + _parentItem->modelIndex()); + else + return model->index(rowIndex(), + column, + QModelIndex()); +} diff --git a/src/TreeData/TreeItem.hxx b/src/TreeData/TreeItem.hxx new file mode 100644 index 000000000..c7f25a73c --- /dev/null +++ b/src/TreeData/TreeItem.hxx @@ -0,0 +1,82 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#ifndef TREEITEM_H +#define TREEITEM_H + +#include "TreeData.hxx" + +#include +#include +#include +#include + +#include "DataObject.hxx" +#include "TreeModel.hxx" + +class TREEDATA_EXPORT TreeItem +{ + public: + TreeItem(const QString &nameId, const QVector &columnValues, TreeItem *parent = 0); + ~TreeItem(); + + QString nameId(); + void associateToModel(TreeModel * model); + TreeModel * associatedModel(); + QModelIndex modelIndex(int column=0); + TreeItem *parent(); + + void appendChild(TreeItem * child); + void appendChild(DataObject * dataObject, + const QStringList &relativePath=QStringList()); + void appendChild(const QString &nameId, + const QVector &columnValues, + const QStringList &relativePath=QStringList()); + + + + TreeItem *child(int row); + TreeItem *childById(const QString &nameId); + TreeItem *childByLabel(const QString &label); + int childCount() const; + int columnCount() const; + int rowIndex() const; + QVariant data(int column) const; + bool setData(int column, const QVariant &value); + + + private: + void initialize(const QString &nameId, + const QVector &columnValues, + TreeItem *parent); + + QList _childItems; + QMap _childItemsMapById; + QMap _childItemsMapByLabel; + + QString _itemNameId; + QVector _itemData; + TreeItem * _parentItem; + TreeModel * _associatedModel; + +}; + +#endif diff --git a/src/TreeData/TreeModel.cxx b/src/TreeData/TreeModel.cxx new file mode 100644 index 000000000..1014e0517 --- /dev/null +++ b/src/TreeData/TreeModel.cxx @@ -0,0 +1,210 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + + +#include + +#include "TreeItem.hxx" +#include "TreeModel.hxx" + +TreeModel::TreeModel(const QStringList &headers, QObject *parent) + : QAbstractItemModel(parent) +{ + QVector rootData; + foreach (QString header, headers) + rootData << header; + + // _MEM_ We have to specify a string identifier for each item so + // that it could be easily retrieved by its parent. In the case of + // the root item, the value of the identifier doesn't matter => we + // choose an arbitrary value + //QString rootNameId = "rootItem"; + _rootItem = new TreeItem("rootItem", rootData); + _rootItem->associateToModel(this); +} + +TreeModel::~TreeModel() +{ + delete _rootItem; +} + +TreeItem * TreeModel::getRootItem() { + return _rootItem; +} + +// +// ================================================================= +// This part of the implementation is the standard interface required +// for providing an operational TreeModel. These methods are used by +// the TreeView for display purpose. We just have to implement how we +// want the items to be displayed in the view. +// ================================================================= +// +int TreeModel::columnCount(const QModelIndex & /* parent */) const +{ + return _rootItem->columnCount(); +} + +/*! + * This function is used by the tree model to inform the tree view of + * what data used for rendering of the item in the different possible + * role (edition, ...). + */ +QVariant TreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role != Qt::DisplayRole && role != Qt::EditRole) + return QVariant(); + + TreeItem *item = getItem(index); + + return item->data(index.column()); +} + +Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +/*! + * This retrieves the item asociated to the specified index. + */ +TreeItem *TreeModel::getItem(const QModelIndex &index) const +{ + // The item associated to an index can be retrieved using the + // internalPointer() function on the index object. + if (index.isValid()) { + TreeItem *item = static_cast(index.internalPointer()); + if (item) return item; + } + return _rootItem; +} + +QVariant TreeModel::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + return _rootItem->data(section); + + return QVariant(); +} + +/*! + * This retrieves the index of the item located at (row,column) place + * relative to the parent specified by its index. + */ +QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const +{ + if (parent.isValid() && parent.column() != 0) + return QModelIndex(); + + TreeItem *parentItem = getItem(parent); + + TreeItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); +} + +QModelIndex TreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + TreeItem *childItem = getItem(index); + TreeItem *parentItem = childItem->parent(); + + if (parentItem == _rootItem) + return QModelIndex(); + + return createIndex(parentItem->rowIndex(), 0, parentItem); +} + +int TreeModel::rowCount(const QModelIndex &parent) const +{ + TreeItem *parentItem = getItem(parent); + + return parentItem->childCount(); +} + +bool TreeModel::setData(const QModelIndex &index, const QVariant &value, + int role) +{ + if (role != Qt::EditRole) + return false; + + TreeItem *item = getItem(index); + bool result = item->setData(index.column(), value); + + if (result) + emit dataChanged(index, index); + + return result; +} + +bool TreeModel::setHeaderData(int section, Qt::Orientation orientation, + const QVariant &value, int role) +{ + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + bool result = _rootItem->setData(section, value); + + if (result) + emit headerDataChanged(orientation, section, section); + + return result; +} + + +// +// ================================================================= +// This part is a specific behavior to get a TreeModel that can +// organize itself the tree hierarchy using data provided in a +// filesystem-like format: +// +// data="a/b/c" ==> creation/filling of the hierarchy a->b->c +// The "folder" categories are unique whereas the leaves may exists +// in multiple instances. +// ================================================================= +// + +/* + * The addData functions run a recurcive filling of the tree model, starting + * form the rootItem and descending in the tree using the recurcive + * function TreeItem::addData. + */ + +bool TreeModel::addData(DataObject * dataObject) { + QStringList path = QString(dataObject->getPath().c_str()).split(DataObject::pathsep.c_str()); + return addData(dataObject, path); +} +bool TreeModel::addData(DataObject * dataObject, const QStringList &path) { + TreeItem * rootItem = this->getItem(); + rootItem->appendChild(dataObject, path); + return true; +} diff --git a/src/TreeData/TreeModel.hxx b/src/TreeData/TreeModel.hxx new file mode 100644 index 000000000..dce9771b3 --- /dev/null +++ b/src/TreeData/TreeModel.hxx @@ -0,0 +1,105 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + + +#ifndef TREEMODEL_H +#define TREEMODEL_H + +#include "TreeData.hxx" + +#include +#include +#include +#include + +#include "DataObject.hxx" + +class TreeItem; +class TreeView; + +class TREEDATA_EXPORT TreeModel : public QAbstractItemModel +{ + Q_OBJECT + + // IMPORTANT NOTE: + // In this implementation of QAbstractItemModel, a tree item is + // associated to the tree model it belongs to (it can request its + // model throw a pointer to this model). Then we declare the + // TreeItem as a friend class so that it can request the protected + // methods (for example beginInsertRows and endInsertRows, required + // to manage correctly the addition of an item in the model. An + // item can append a child to itself, so it needs to inform the + // model when it begins and when it ends). + friend class TreeItem; + friend class TreeView; + +public: + TreeModel(const QStringList &headers, QObject *parent = 0); + ~TreeModel(); + + // + // ================================================================= + // This part of the specification is the standard interface required + // for providing an operational TreeModel. These methods are used by + // the TreeView for display purpose. We just have to implement how + // we want the items to be displayed in the view. + // ================================================================= + // + // MEM: note that these methods are not intended to be used + // directly. That's the job of the viewer to know how to use + // them. We just have to give the implementation for customizing the + // appearance of the tree. The implementation generally requests the + // items'data to set the appearance features. + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + Qt::ItemFlags flags(const QModelIndex &index) const; + + // + // ================================================================= + // This part is a specific behavior to get a TreeModel that can + // organize itself the tree hierarchy using data provided in a + // filesystem-like format: + // + // data="a/b/c" ==> creation/filling of the hierarchy a->b->c + // The "folder" categories are unique whereas the leaves may exists + // in multiple instances. + // ================================================================= + // + bool addData(DataObject * dataObject); + bool addData(DataObject * dataObject, const QStringList &path); + + // TODO: We should implement the delete and the update fucntions + + // This part contains helper functions for general purposes + TreeItem * getRootItem(); + +private: + TreeItem *getItem(const QModelIndex &index = QModelIndex()) const; + TreeItem * _rootItem; +}; + +#endif // TREEMODEL_H diff --git a/src/TreeData/TreeObserver.cxx b/src/TreeData/TreeObserver.cxx new file mode 100644 index 000000000..8bf910362 --- /dev/null +++ b/src/TreeData/TreeObserver.cxx @@ -0,0 +1,54 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + +#include "TreeObserver.hxx" +#include "QtHelper.hxx" + +TreeObserver::TreeObserver() : QObject() { +} + +/*! + * This declares the TreeView to be observed by this tree events + * listener. + */ +void TreeObserver::observe(TreeView * treeView) { + // We just connect the signals emitted from the treeview to + // corresponding slots of this observer. + connect(treeView, SIGNAL(itemListToProcess(QStringList,int)), + this, SLOT(processItemList(QStringList,int))); +} + +/*! + * This slot should be implemented in a specialized version of + * TreeObserver to process the signal emitted from the TreeView. The + * parameters are: + * - itemNameIdList: the list of name identifiers of model objects + * associated to the selected qt items in the TreeView (ids for + * requesting directly the data model). + * - actionId: the identifier of the action selected in the popup menu + * that triggered this signal. + */ +void TreeObserver::processItemList(QStringList itemNameIdList, int actionId) { + LOG("TreeObserver::processItemList: signal received:\n"<< + "item list: "< +#include "TreeView.hxx" + +class TREEDATA_EXPORT TreeObserver : public QObject { + + Q_OBJECT + +public: + TreeObserver(); + void observe(TreeView * treeView); + +public slots: + /* These slots should be implemented in a specialized version of + the TreeObserver to process signals emitted from the TreeView */ + virtual void processItemList(QStringList itemNameIdList, int actionId); +}; + +#endif // _TREEOBSERVER_ diff --git a/src/TreeData/TreeView.cxx b/src/TreeData/TreeView.cxx new file mode 100644 index 000000000..bb82e5cf9 --- /dev/null +++ b/src/TreeData/TreeView.cxx @@ -0,0 +1,144 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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: Guillaume Boulant (EDF/R&D) + + +// include Qt +#include +#include +#include +#include + +// include Xcad +#include "TreeView.hxx" +#include "TreeModel.hxx" +#include "TreeItem.hxx" +#include "QtHelper.hxx" + +TreeView::TreeView(QWidget * parent) + : QTreeView(parent) +{ + // We authorize the multiple selection of items + this->setSelectionMode(QAbstractItemView::ExtendedSelection); + + _lastActionId = 0; + + // Default actions for tests + int displayActionId = addAction(QObject::tr("Afficher")); + int editActionId = addAction(QObject::tr("Editer")); +} + +TreeView::~TreeView() { +} + +/*! + * This function defines a menu item to add in the popup menu + * associated to this TreeView, and return an integer that corresponds + * to the unique identifier of this action (identifier used in the + * signal emitted to notify observers that an action has been + * selected). Then the caller of this function has to take care of + * this return id (i.e. has to store it in its internal tables) to be + * able to process the notifications from this TreeView. + */ +int TreeView::addAction(QString label) { + QAction * action = new QAction(this); + int actionId = _lastActionId; + action->setObjectName(_idToName(actionId)); + action->setText(label); + _listActions << action; + _lastActionId++; + + return actionId; +} + +/*! + * This function removes all actions previously defined for the popup + * menu of this TreeView. + */ +void TreeView::clearActions() { + _listActions.clear(); +} + +/*! + * You must use this function to create the name of an action object + * from its id. + */ +QString TreeView::_idToName(int actionId) { + return QString::number(actionId); +} +/*! + * You must use this function to create the id of an action object + * from its name (stored in objectName() attribute of the QAction). + */ +int TreeView::_nameToId(QString actionName) { + return actionName.toInt(); +} + +void TreeView::contextMenuEvent(QContextMenuEvent *event) { + if ( _listActions.size() == 0 ) { + // Just return there is no actions defined for this popup menu + return; + } + + // _TODO_ display the QMenu only if the selected item is acceptable + QMenu menu(this); + for (int i = 0; i < _listActions.size(); ++i) { + menu.addAction(_listActions.at(i)); + } + connect(&menu, SIGNAL(triggered(QAction*)), + this, SLOT(processMenuAction(QAction*))); + + menu.exec(event->globalPos()); +} + +/*! + * This SLOT is connected on the signal emited by the menu when an + * action is selected. + */ +void TreeView::processMenuAction(QAction * actionSelected) { + LOG("processMenuAction: START"); + + // We first check than at least on item is selected + QModelIndexList indexList = this->selectionModel()->selectedRows(0); + if ( indexList.isEmpty() ) { + LOG("No item selected"); + return; + } + + // Then we can gather the list of model item ids associated the + // selection. + TreeModel *model = (TreeModel *)this->model(); + QListIterator it(indexList); + QStringList nameIdList; + while (it.hasNext()) { + TreeItem * item = model->getItem(it.next()); + nameIdList << item->nameId(); + } + + // Finally, one can emit a signal to observers specifying the list of + // id and the type of action (i.e. the action identifier) + int actionId = _nameToId(actionSelected->objectName()); + LOG("TreeView::processMenuAction: signal emitted:\n"<< + "item list: "< +#include +#include +#include + +class TREEDATA_EXPORT TreeView : public QTreeView +{ + Q_OBJECT + +public: + TreeView(QWidget * parent = 0 ); + ~TreeView(); + int addAction(QString label); + void clearActions(); + +protected: + void contextMenuEvent(QContextMenuEvent *event); + +private: + int _lastActionId; + QList _listActions; + QString _idToName(int actionId); + int _nameToId(QString actionName); + + // --- + +private slots: + void processMenuAction(QAction * actionSelected); + +signals: + void itemListToProcess(QStringList itemNameIdList, int actionId); +}; + +#endif // TREEVIEW_H + diff --git a/src/VTKViewer/textures/texture1.dat b/src/VTKViewer/textures/texture1.dat new file mode 100644 index 000000000..eb5e52c94 --- /dev/null +++ b/src/VTKViewer/textures/texture1.dat @@ -0,0 +1,284 @@ +000000000 +000000000 +000000000 +000000000 +000010000 +000000000 +000000000 +000000000 +000000000 + +00000000000 +00000000000 +00000000000 +00000000000 +00000110000 +00000110000 +00000000000 +00000000000 +00000000000 +00000000000 +00000000000 + +0000000000000 +0000000000000 +0000000000000 +0000000000000 +0000000000000 +0000001100000 +0000001100000 +0000000000000 +0000000000000 +0000000000000 +0000000000000 +0000000000000 +0000000000000 + +000000000000000 +000000000000000 +000000000000000 +000000000000000 +000000000000000 +000000000000000 +000000011000000 +000000011000000 +000000000000000 +000000000000000 +000000000000000 +000000000000000 +000000000000000 +000000000000000 +000000000000000 + +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000001110000000 +00000001110000000 +00000001110000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 +00000000000000000 + +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000011110000000 +0000000011110000000 +0000000011110000000 +0000000011110000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 +0000000000000000000 + +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000111100000000 +000000000111100000000 +000000000111100000000 +000000000111100000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 +000000000000000000000 + +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000001111000000000 +00000000001111000000000 +00000000001111000000000 +00000000001111000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 +00000000000000000000000 + +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000111110000000000 +0000000000111110000000000 +0000000000111110000000000 +0000000000111110000000000 +0000000000111110000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 +0000000000000000000000000 + +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000001111110000000000 +000000000001111110000000000 +000000000001111110000000000 +000000000001111110000000000 +000000000001111110000000000 +000000000001111110000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 +000000000000000000000000000 + +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000011111100000000000 +00000000000011111100000000000 +00000000000011111100000000000 +00000000000011111100000000000 +00000000000011111100000000000 +00000000000011111100000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 +00000000000000000000000000000 + +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000111111000000000000 +0000000000000111111000000000000 +0000000000000111111000000000000 +0000000000000111111000000000000 +0000000000000111111000000000000 +0000000000000111111000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 +0000000000000000000000000000000 + +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000001111111000000000000 +00000000000001111111000000000000 +00000000000001111111000000000000 +00000000000001111111000000000000 +00000000000001111111000000000000 +00000000000001111111000000000000 +00000000000001111111000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 +00000000000000000000000000000000 diff --git a/src/VTKViewer/textures/texture2.dat b/src/VTKViewer/textures/texture2.dat new file mode 100644 index 000000000..431f780d4 --- /dev/null +++ b/src/VTKViewer/textures/texture2.dat @@ -0,0 +1,284 @@ +000010000 +000010000 +000010000 +000010000 +111111111 +000010000 +000010000 +000010000 +000010000 + +00000100000 +00000100000 +00000100000 +00000100000 +00000100000 +11111111111 +00000100000 +00000100000 +00000100000 +00000100000 +00000100000 + +0000001000000 +0000001000000 +0000001000000 +0000001000000 +0000001000000 +0000001000000 +1111111111111 +0000001000000 +0000001000000 +0000001000000 +0000001000000 +0000001000000 +0000001000000 + +000000010000000 +000000010000000 +000000010000000 +000000010000000 +000000010000000 +000000010000000 +000000010000000 +111111111111111 +000000010000000 +000000010000000 +000000010000000 +000000010000000 +000000010000000 +000000010000000 +000000010000000 + +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +11111111111111111 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 + +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +1111111111111111111 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 + +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +111111111111111111111 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 + +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +11111111111111111111111 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 + +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +1111111111111111111111111 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 + +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +111111111111111111111111111 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 + +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +11111111111111111111111111111 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 + +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +1111111111111111111111111111111 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 + +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +11111111111111111111111111111111 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 diff --git a/src/VTKViewer/textures/texture3.dat b/src/VTKViewer/textures/texture3.dat new file mode 100644 index 000000000..21683f19a --- /dev/null +++ b/src/VTKViewer/textures/texture3.dat @@ -0,0 +1,284 @@ +000010000 +000010000 +110010011 +001111100 +000010000 +001111100 +110010011 +000010000 +000010000 + +00000100000 +00000100000 +10000100001 +01100100110 +00011111000 +00000100000 +00011111000 +01100100110 +10000100001 +00000100000 +00000100000 + +0000001000000 +0000001000000 +0000001000000 +1100001000011 +0011001001100 +0000111110000 +0000001000000 +0000111110000 +0011001001100 +1100001000011 +0000001000000 +0000001000000 +0000001000000 + +000000010000000 +000000010000000 +000000010000000 +100000010000001 +011000010000110 +000110010011000 +000001111100000 +000000010000000 +000001111100000 +000110010011000 +011000010000110 +100000010000001 +000000010000000 +000000010000000 +000000010000000 + +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 +11000000100000011 +00110000100001100 +00001100100110000 +00000011111000000 +00000000100000000 +00000011111000000 +00001100100110000 +00110000100001100 +11000000100000011 +00000000100000000 +00000000100000000 +00000000100000000 +00000000100000000 + +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 +1000000001000000001 +0110000001000000110 +0001100001000011000 +0000011001001100000 +0000000111110000000 +0000000001000000000 +0000000111110000000 +0000011001001100000 +0001100001000011000 +0110000001000000110 +1000000001000000001 +0000000001000000000 +0000000001000000000 +0000000001000000000 +0000000001000000000 + +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +110000000010000000011 +001100000010000001100 +000011000010000110000 +000000110010011000000 +000000001111100000000 +000000000010000000000 +000000001111100000000 +000000110010011000000 +000011000010000110000 +001100000010000001100 +110000000010000000011 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 +000000000010000000000 + +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +10000000000100000000001 +01100000000100000000110 +00011000000100000011000 +00000110000100001100000 +00000001100100110000000 +00000000011111000000000 +00000000000100000000000 +00000000011111000000000 +00000001100100110000000 +00000110000100001100000 +00011000000100000011000 +01100000000100000000110 +10000000000100000000001 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 +00000000000100000000000 + +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +1100000000001000000000011 +0011000000001000000001100 +0000110000001000000110000 +0000001100001000011000000 +0000000011001001100000000 +0000000000111110000000000 +0000000000001000000000000 +0000000000111110000000000 +0000000011001001100000000 +0000001100001000011000000 +0000110000001000000110000 +0011000000001000000001100 +1100000000001000000000011 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 +0000000000001000000000000 + +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +100000000000010000000000001 +011000000000010000000000110 +000110000000010000000011000 +000001100000010000001100000 +000000011000010000110000000 +000000000110010011000000000 +000000000001111100000000000 +000000000000010000000000000 +000000000001111100000000000 +000000000110010011000000000 +000000011000010000110000000 +000001100000010000001100000 +000110000000010000000011000 +011000000000010000000000110 +100000000000010000000000001 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 +000000000000010000000000000 + +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +11000000000000100000000000011 +00110000000000100000000001100 +00001100000000100000000110000 +00000011000000100000011000000 +00000000110000100001100000000 +00000000001100100110000000000 +00000000000011111000000000000 +00000000000000100000000000000 +00000000000011111000000000000 +00000000001100100110000000000 +00000000110000100001100000000 +00000011000000100000011000000 +00001100000000100000000110000 +00110000000000100000000001100 +11000000000000100000000000011 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 +00000000000000100000000000000 + +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +1000000000000001000000000000001 +0110000000000001000000000000110 +0001100000000001000000000011000 +0000011000000001000000001100000 +0000000110000001000000110000000 +0000000001100001000011000000000 +0000000000011001001100000000000 +0000000000000111110000000000000 +0000000000000001000000000000000 +0000000000000111110000000000000 +0000000000011001001100000000000 +0000000001100001000011000000000 +0000000110000001000000110000000 +0000011000000001000000001100000 +0001100000000001000000000011000 +0110000000000001000000000000110 +1000000000000001000000000000001 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 +0000000000000001000000000000000 + +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +10000000000000010000000000000010 +01100000000000010000000000001100 +00011000000000010000000000110000 +00000110000000010000000011000000 +00000001100000010000001100000000 +00000000011000010000110000000000 +00000000000110010011000000000000 +00000000000001111100000000000000 +00000000000001111100000000000000 +00000000000110010011000000000000 +00000000011000010000110000000000 +00000001100000010000001100000000 +00000110000000010000000011000000 +00011000000000010000000000110000 +01100000000000010000000000001100 +10000000000000010000000000000010 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 +00000000000000010000000000000000 diff --git a/src/VTKViewer/textures/texture4.dat b/src/VTKViewer/textures/texture4.dat new file mode 100644 index 000000000..3d6964107 --- /dev/null +++ b/src/VTKViewer/textures/texture4.dat @@ -0,0 +1,284 @@ +000111000 +011000110 +010000010 +100000001 +100000001 +100000001 +010000010 +011000110 +000111000 + +00001110000 +00110001100 +01000000010 +01000000010 +10000000001 +10000000001 +10000000001 +01000000010 +01000000010 +00110001100 +00001110000 + +0000111110000 +0001000001000 +0010000000100 +0100000000010 +0100000000010 +1000000000001 +1000000000001 +1000000000001 +0100000000010 +0100000000010 +0010000000100 +0001000001000 +0000111110000 + +000001111100000 +000110000011000 +001000000000100 +010000000000010 +010000000000010 +100000000000001 +100000000000001 +100000000000001 +100000000000001 +100000000000001 +010000000000010 +010000000000010 +001000000000100 +000110000011000 +000001111100000 + +00000011111000000 +00001100000110000 +00010000000001000 +00100000000000100 +01000000000000010 +01000000000000010 +10000000000000001 +10000000000000001 +10000000000000001 +10000000000000001 +10000000000000001 +01000000000000010 +01000000000000010 +00100000000000100 +00010000000001000 +00001100000110000 +00000011111000000 + +0000000111110000000 +0000011000001100000 +0001100000000011000 +0010000000000000100 +0010000000000000100 +0100000000000000010 +0100000000000000010 +1000000000000000001 +1000000000000000001 +1000000000000000001 +1000000000000000001 +1000000000000000001 +0100000000000000010 +0100000000000000010 +0010000000000000100 +0010000000000000100 +0001100000000011000 +0000011000001100000 +0000000111110000000 + +000000001111100000000 +000000110000011000000 +000011000000000110000 +000100000000000001000 +001000000000000000100 +001000000000000000100 +010000000000000000010 +010000000000000000010 +100000000000000000001 +100000000000000000001 +100000000000000000001 +100000000000000000001 +100000000000000000001 +010000000000000000010 +010000000000000000010 +001000000000000000100 +001000000000000000100 +000100000000000001000 +000011000000000110000 +000000110000011000000 +000000001111100000000 + +00000000011111000000000 +00000011100000111000000 +00000100000000000100000 +00011000000000000011000 +00010000000000000001000 +00100000000000000000100 +01000000000000000000010 +01000000000000000000010 +01000000000000000000010 +10000000000000000000001 +10000000000000000000001 +10000000000000000000001 +10000000000000000000001 +10000000000000000000001 +01000000000000000000010 +01000000000000000000010 +01000000000000000000010 +00100000000000000000100 +00010000000000000001000 +00011000000000000011000 +00000100000000000100000 +00000011100000111000000 +00000000011111000000000 + +0000000000111110000000000 +0000000111000001110000000 +0000011000000000001100000 +0000100000000000000010000 +0001000000000000000001000 +0010000000000000000000100 +0010000000000000000000100 +0100000000000000000000010 +0100000000000000000000010 +0100000000000000000000010 +1000000000000000000000001 +1000000000000000000000001 +1000000000000000000000001 +1000000000000000000000001 +1000000000000000000000001 +0100000000000000000000010 +0100000000000000000000010 +0100000000000000000000010 +0010000000000000000000100 +0010000000000000000000100 +0001000000000000000001000 +0000100000000000000010000 +0000011000000000001100000 +0000000111000001110000000 +0000000000111110000000000 + +000000000001111100000000000 +000000001110000011100000000 +000000110000000000011000000 +000001000000000000000100000 +000010000000000000000010000 +000100000000000000000001000 +001000000000000000000000100 +001000000000000000000000100 +010000000000000000000000010 +010000000000000000000000010 +010000000000000000000000010 +100000000000000000000000001 +100000000000000000000000001 +100000000000000000000000001 +100000000000000000000000001 +100000000000000000000000001 +010000000000000000000000010 +010000000000000000000000010 +010000000000000000000000010 +001000000000000000000000100 +001000000000000000000000100 +000100000000000000000001000 +000010000000000000000010000 +000001000000000000000100000 +000000110000000000011000000 +000000001110000011100000000 +000000000001111100000000000 + +00000000000011111000000000000 +00000000011100000111100000000 +00000001100000000000010000000 +00000010000000000000001100000 +00001100000000000000000010000 +00001000000000000000000001000 +00010000000000000000000001000 +00100000000000000000000000100 +00100000000000000000000000010 +01000000000000000000000000010 +01000000000000000000000000010 +01000000000000000000000000010 +10000000000000000000000000001 +10000000000000000000000000001 +10000000000000000000000000001 +10000000000000000000000000001 +10000000000000000000000000001 +01000000000000000000000000010 +01000000000000000000000000010 +01000000000000000000000000010 +00100000000000000000000000010 +00100000000000000000000000100 +00010000000000000000000001000 +00001000000000000000000001000 +00001100000000000000000110000 +00000010000000000000001000000 +00000001100000000000110000000 +00000000011100000111000000000 +00000000000011111000000000000 + +0000000000000111110000000000000 +0000000001111000001111000000000 +0000000010000000000000100000000 +0000001100000000000000011000000 +0000010000000000000000000100000 +0000100000000000000000000010000 +0001000000000000000000000001000 +0001000000000000000000000001000 +0010000000000000000000000000100 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000000000000000000010 +1000000000000000000000000000001 +1000000000000000000000000000001 +1000000000000000000000000000001 +1000000000000000000000000000001 +1000000000000000000000000000001 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000000000000000000010 +0010000000000000000000000000100 +0001000000000000000000000001000 +0001000000000000000000000001000 +0000100000000000000000000010000 +0000010000000000000000000100000 +0000001100000000000000011000000 +0000000010000000000000100000000 +0000000001111000001111000000000 +0000000000000111110000000000000 + +00000000000001111110000000000000 +00000000001110000001110000000000 +00000000110000000000001100000000 +00000001000000000000000010000000 +00000110000000000000000001100000 +00001000000000000000000000010000 +00001000000000000000000000010000 +00010000000000000000000000001000 +00100000000000000000000000000100 +00100000000000000000000000000100 +01000000000000000000000000000010 +01000000000000000000000000000010 +01000000000000000000000000000010 +01000000000000000000000000000010 +10000000000000000000000000000001 +10000000000000000000000000000001 +10000000000000000000000000000001 +10000000000000000000000000000001 +01000000000000000000000000000010 +01000000000000000000000000000010 +01000000000000000000000000000010 +01000000000000000000000000000010 +00100000000000000000000000000100 +00100000000000000000000000000100 +00010000000000000000000000001000 +00001000000000000000000000010000 +00001000000000000000000000010000 +00000110000000000000000001100000 +00000001000000000000000010000000 +00000000110000000000001100000000 +00000000001110000001110000000000 +00000000000001111110000000000000 diff --git a/src/VTKViewer/textures/texture5.dat b/src/VTKViewer/textures/texture5.dat new file mode 100644 index 000000000..221e1e986 --- /dev/null +++ b/src/VTKViewer/textures/texture5.dat @@ -0,0 +1,284 @@ +100000001 +010000010 +001000100 +000101000 +000010000 +000101000 +001000100 +010000010 +100000001 + +10000000001 +01000000010 +00100000100 +00010001000 +00001010000 +00000100000 +00001010000 +00010001000 +00100000100 +01000000010 +10000000001 + +1000000000001 +0100000000010 +0010000000100 +0001000001000 +0000100010000 +0000010100000 +0000001000000 +0000010100000 +0000100010000 +0001000001000 +0010000000100 +0100000000010 +1000000000001 + +100000000000001 +010000000000010 +001000000000100 +000100000001000 +000010000010000 +000001000100000 +000000101000000 +000000010000000 +000000101000000 +000001000100000 +000010000010000 +000100000001000 +001000000000100 +010000000000010 +100000000000001 + +10000000000000001 +01000000000000010 +00100000000000100 +00010000000001000 +00001000000010000 +00000100000100000 +00000010001000000 +00000001010000000 +00000000100000000 +00000001010000000 +00000010001000000 +00000100000100000 +00001000000010000 +00010000000001000 +00100000000000100 +01000000000000010 +10000000000000001 + +1000000000000000001 +0100000000000000010 +0010000000000000100 +0001000000000001000 +0000100000000010000 +0000010000000100000 +0000001000001000000 +0000000100010000000 +0000000010100000000 +0000000001000000000 +0000000010100000000 +0000000100010000000 +0000001000001000000 +0000010000000100000 +0000100000000010000 +0001000000000001000 +0010000000000000100 +0100000000000000010 +1000000000000000001 + +100000000000000000001 +010000000000000000010 +001000000000000000100 +000100000000000001000 +000010000000000010000 +000001000000000100000 +000000100000001000000 +000000010000010000000 +000000001000100000000 +000000000101000000000 +000000000010000000000 +000000000101000000000 +000000001000100000000 +000000010000010000000 +000000100000001000000 +000001000000000100000 +000010000000000010000 +000100000000000001000 +001000000000000000100 +010000000000000000010 +100000000000000000001 + +10000000000000000000001 +01000000000000000000010 +00100000000000000000100 +00010000000000000001000 +00001000000000000010000 +00000100000000000100000 +00000010000000001000000 +00000001000000010000000 +00000000100000100000000 +00000000010001000000000 +00000000001010000000000 +00000000000100000000000 +00000000001010000000000 +00000000010001000000000 +00000000100000100000000 +00000001000000010000000 +00000010000000001000000 +00000100000000000100000 +00001000000000000010000 +00010000000000000001000 +00100000000000000000100 +01000000000000000000010 +10000000000000000000001 + +1000000000000000000000001 +0100000000000000000000010 +0010000000000000000000100 +0001000000000000000001000 +0000100000000000000010000 +0000010000000000000100000 +0000001000000000001000000 +0000000100000000010000000 +0000000010000000100000000 +0000000001000001000000000 +0000000000100010000000000 +0000000000010100000000000 +0000000000001000000000000 +0000000000010100000000000 +0000000000100010000000000 +0000000001000001000000000 +0000000010000000100000000 +0000000100000000010000000 +0000001000000000001000000 +0000010000000000000100000 +0000100000000000000010000 +0001000000000000000001000 +0010000000000000000000100 +0100000000000000000000010 +1000000000000000000000001 + +100000000000000000000000001 +010000000000000000000000010 +001000000000000000000000100 +000100000000000000000001000 +000010000000000000000010000 +000001000000000000000100000 +000000100000000000001000000 +000000010000000000010000000 +000000001000000000100000000 +000000000100000001000000000 +000000000010000010000000000 +000000000001000100000000000 +000000000000101000000000000 +000000000000010000000000000 +000000000000101000000000000 +000000000001000100000000000 +000000000010000010000000000 +000000000100000001000000000 +000000001000000000100000000 +000000010000000000010000000 +000000100000000000001000000 +000001000000000000000100000 +000010000000000000000010000 +000100000000000000000001000 +001000000000000000000000100 +010000000000000000000000010 +100000000000000000000000001 + +10000000000000000000000000001 +01000000000000000000000000010 +00100000000000000000000000100 +00010000000000000000000001000 +00001000000000000000000010000 +00000100000000000000000100000 +00000010000000000000001000000 +00000001000000000000010000000 +00000000100000000000100000000 +00000000010000000001000000000 +00000000001000000010000000000 +00000000000100000100000000000 +00000000000010001000000000000 +00000000000001010000000000000 +00000000000000100000000000000 +00000000000001010000000000000 +00000000000010001000000000000 +00000000000100000100000000000 +00000000001000000010000000000 +00000000010000000001000000000 +00000000100000000000100000000 +00000001000000000000010000000 +00000010000000000000001000000 +00000100000000000000000100000 +00001000000000000000000010000 +00010000000000000000000001000 +00100000000000000000000000100 +01000000000000000000000000010 +10000000000000000000000000001 + +1000000000000000000000000000001 +0100000000000000000000000000010 +0010000000000000000000000000100 +0001000000000000000000000001000 +0000100000000000000000000010000 +0000010000000000000000000100000 +0000001000000000000000001000000 +0000000100000000000000010000000 +0000000010000000000000100000000 +0000000001000000000001000000000 +0000000000100000000010000000000 +0000000000010000000100000000000 +0000000000001000001000000000000 +0000000000000100010000000000000 +0000000000000010100000000000000 +0000000000000001000000000000000 +0000000000000010100000000000000 +0000000000000100010000000000000 +0000000000001000001000000000000 +0000000000010000000100000000000 +0000000000100000000010000000000 +0000000001000000000001000000000 +0000000010000000000000100000000 +0000000100000000000000010000000 +0000001000000000000000001000000 +0000010000000000000000000100000 +0000100000000000000000000010000 +0001000000000000000000000001000 +0010000000000000000000000000100 +0100000000000000000000000000010 +1000000000000000000000000000001 + +10000000000000000000000000000001 +01000000000000000000000000000010 +00100000000000000000000000000100 +00010000000000000000000000001000 +00001000000000000000000000010000 +00000100000000000000000000100000 +00000010000000000000000001000000 +00000001000000000000000010000000 +00000000100000000000000100000000 +00000000010000000000001000000000 +00000000001000000000010000000000 +00000000000100000000100000000000 +00000000000010000001000000000000 +00000000000001000010000000000000 +00000000000000100100000000000000 +00000000000000011000000000000000 +00000000000000011000000000000000 +00000000000000100100000000000000 +00000000000001000010000000000000 +00000000000010000001000000000000 +00000000000100000000100000000000 +00000000001000000000010000000000 +00000000010000000000001000000000 +00000000100000000000000100000000 +00000001000000000000000010000000 +00000010000000000000000001000000 +00000100000000000000000000100000 +00001000000000000000000000010000 +00010000000000000000000000001000 +00100000000000000000000000000100 +01000000000000000000000000000010 +10000000000000000000000000000001 diff --git a/src/VTKViewer/textures/texture6.dat b/src/VTKViewer/textures/texture6.dat new file mode 100644 index 000000000..caf5163f9 --- /dev/null +++ b/src/VTKViewer/textures/texture6.dat @@ -0,0 +1,284 @@ +000111000 +011000110 +010000010 +100000001 +100010001 +100000001 +010000010 +011000110 +000111000 + +00001110000 +00110001100 +01000000010 +01000000010 +10000110001 +10000110001 +10000000001 +01000000010 +01000000010 +00110001100 +00001110000 + +0000111110000 +0001000001000 +0010000000100 +0100000000010 +0100000000010 +1000001100001 +1000001100001 +1000000000001 +0100000000010 +0100000000010 +0010000000100 +0001000001000 +0000111110000 + +000001111100000 +000110000011000 +001000000000100 +010000000000010 +010000000000010 +100000000000001 +100000011000001 +100000011000001 +100000000000001 +100000000000001 +010000000000010 +010000000000010 +001000000000100 +000110000011000 +000001111100000 + +00000011111000000 +00001100000110000 +00010000000001000 +00100000000000100 +01000000000000010 +01000000000000010 +10000000000000001 +10000001110000001 +10000001110000001 +10000001110000001 +10000000000000001 +01000000000000010 +01000000000000010 +00100000000000100 +00010000000001000 +00001100000110000 +00000011111000000 + +0000000111110000000 +0000011000001100000 +0001100000000011000 +0010000000000000100 +0010000000000000100 +0100000000000000010 +0100000000000000010 +1000000011110000001 +1000000011110000001 +1000000011110000001 +1000000011110000001 +1000000000000000001 +0100000000000000010 +0100000000000000010 +0010000000000000100 +0010000000000000100 +0001100000000011000 +0000011000001100000 +0000000111110000000 + +000000001111100000000 +000000110000011000000 +000011000000000110000 +000100000000000001000 +001000000000000000100 +001000000000000000100 +010000000000000000010 +010000000000000000010 +100000000111100000001 +100000000111100000001 +100000000111100000001 +100000000111100000001 +100000000000000000001 +010000000000000000010 +010000000000000000010 +001000000000000000100 +001000000000000000100 +000100000000000001000 +000011000000000110000 +000000110000011000000 +000000001111100000000 + +00000000011111000000000 +00000011100000111000000 +00000100000000000100000 +00011000000000000011000 +00010000000000000001000 +00100000000000000000100 +01000000000000000000010 +01000000000000000000010 +01000000000000000000010 +10000000001111000000001 +10000000001111000000001 +10000000001111000000001 +10000000001111000000001 +10000000000000000000001 +01000000000000000000010 +01000000000000000000010 +01000000000000000000010 +00100000000000000000100 +00010000000000000001000 +00011000000000000011000 +00000100000000000100000 +00000011100000111000000 +00000000011111000000000 + +0000000000111110000000000 +0000000111000001110000000 +0000011000000000001100000 +0000100000000000000010000 +0001000000000000000001000 +0010000000000000000000100 +0010000000000000000000100 +0100000000000000000000010 +0100000000000000000000010 +0100000000000000000000010 +1000000000111110000000001 +1000000000111110000000001 +1000000000111110000000001 +1000000000111110000000001 +1000000000111110000000001 +0100000000000000000000010 +0100000000000000000000010 +0100000000000000000000010 +0010000000000000000000100 +0010000000000000000000100 +0001000000000000000001000 +0000100000000000000010000 +0000011000000000001100000 +0000000111000001110000000 +0000000000111110000000000 + +000000000001111100000000000 +000000001110000011100000000 +000000110000000000011000000 +000001000000000000000100000 +000010000000000000000010000 +000100000000000000000001000 +001000000000000000000000100 +001000000000000000000000100 +010000000000000000000000010 +010000000000000000000000010 +010000000001111110000000010 +100000000001111110000000001 +100000000001111110000000001 +100000000001111110000000001 +100000000001111110000000001 +100000000001111110000000001 +010000000000000000000000010 +010000000000000000000000010 +010000000000000000000000010 +001000000000000000000000100 +001000000000000000000000100 +000100000000000000000001000 +000010000000000000000010000 +000001000000000000000100000 +000000110000000000011000000 +000000001110000011100000000 +000000000001111100000000000 + +00000000000011111000000000000 +00000000011100000111100000000 +00000001100000000000010000000 +00000010000000000000001100000 +00001100000000000000000010000 +00001000000000000000000001000 +00010000000000000000000001000 +00100000000000000000000000100 +00100000000000000000000000010 +01000000000000000000000000010 +01000000000000000000000000010 +01000000000011111100000000010 +10000000000011111100000000001 +10000000000011111100000000001 +10000000000011111100000000001 +10000000000011111100000000001 +10000000000011111100000000001 +01000000000000000000000000010 +01000000000000000000000000010 +01000000000000000000000000010 +00100000000000000000000000010 +00100000000000000000000000100 +00010000000000000000000001000 +00001000000000000000000001000 +00001100000000000000000110000 +00000010000000000000001000000 +00000001100000000000110000000 +00000000011100000111000000000 +00000000000011111000000000000 + +0000000000000111110000000000000 +0000000001111000001111000000000 +0000000010000000000000100000000 +0000001100000000000000011000000 +0000010000000000000000000100000 +0000100000000000000000000010000 +0001000000000000000000000001000 +0001000000000000000000000001000 +0010000000000000000000000000100 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000111111000000000010 +1000000000000111111000000000001 +1000000000000111111000000000001 +1000000000000111111000000000001 +1000000000000111111000000000001 +1000000000000111111000000000001 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000000000000000000010 +0100000000000000000000000000010 +0010000000000000000000000000100 +0001000000000000000000000001000 +0001000000000000000000000001000 +0000100000000000000000000010000 +0000010000000000000000000100000 +0000001100000000000000011000000 +0000000010000000000000100000000 +0000000001111000001111000000000 +0000000000000111110000000000000 + +00000000000001111110000000000000 +00000000001110000001110000000000 +00000000110000000000001100000000 +00000001000000000000000010000000 +00000110000000000000000001100000 +00001000000000000000000000010000 +00001000000000000000000000010000 +00010000000000000000000000001000 +00100000000000000000000000000100 +00100000000000000000000000000100 +01000000000000000000000000000010 +01000000000000000000000000000010 +01000000000001111111000000000010 +01000000000001111111000000000010 +10000000000001111111000000000001 +10000000000001111111000000000001 +10000000000001111111000000000001 +10000000000001111111000000000001 +01000000000001111111000000000010 +01000000000000000000000000000010 +01000000000000000000000000000010 +01000000000000000000000000000010 +00100000000000000000000000000100 +00100000000000000000000000000100 +00010000000000000000000000001000 +00001000000000000000000000010000 +00001000000000000000000000010000 +00000110000000000000000001100000 +00000001000000000000000010000000 +00000000110000000000001100000000 +00000000001110000001110000000000 +00000000000001111110000000000000 diff --git a/src/VTKViewer/textures/texture7.dat b/src/VTKViewer/textures/texture7.dat new file mode 100644 index 000000000..a75e7bb12 --- /dev/null +++ b/src/VTKViewer/textures/texture7.dat @@ -0,0 +1,284 @@ +000111000 +011010110 +010010010 +100010001 +111111111 +100010001 +010010010 +011010110 +000111000 + +00001110000 +00110101100 +01000100010 +01000100010 +10000100001 +11111111111 +10000100001 +01000100010 +01000100010 +00110101100 +00001110000 + +0000111110000 +0001001001000 +0010001000100 +0100001000010 +0100001000010 +1000001000001 +1111111111111 +1000001000001 +0100001000010 +0100001000010 +0010001000100 +0001001001000 +0000111110000 + +000001111100000 +000110010011000 +001000010000100 +010000010000010 +010000010000010 +100000010000001 +100000010000001 +111111111111111 +100000010000001 +100000010000001 +010000010000010 +010000010000010 +001000010000100 +000110010011000 +000001111100000 + +00000011111000000 +00001100100110000 +00010000100001000 +00100000100000100 +01000000100000010 +01000000100000010 +10000000100000001 +10000000100000001 +11111111111111111 +10000000100000001 +10000000100000001 +01000000100000010 +01000000100000010 +00100000100000100 +00010000100001000 +00001100100110000 +00000011111000000 + +0000000111110000000 +0000011001001100000 +0001100001000011000 +0010000001000000100 +0010000001000000100 +0100000001000000010 +0100000001000000010 +1000000001000000001 +1000000001000000001 +1111111111111111111 +1000000001000000001 +1000000001000000001 +0100000001000000010 +0100000001000000010 +0010000001000000100 +0010000001000000100 +0001100001000011000 +0000011001001100000 +0000000111110000000 + +000000001111100000000 +000000110010011000000 +000011000010000110000 +000100000010000001000 +001000000010000000100 +001000000010000000100 +010000000010000000010 +010000000010000000010 +100000000010000000001 +100000000010000000001 +111111111111111111111 +100000000010000000001 +100000000010000000001 +010000000010000000010 +010000000010000000010 +001000000010000000100 +001000000010000000100 +000100000010000001000 +000011000010000110000 +000000110010011000000 +000000001111100000000 + +00000000011111000000000 +00000011100100111000000 +00000100000100000100000 +00011000000100000011000 +00010000000100000001000 +00100000000100000000100 +01000000000100000000010 +01000000000100000000010 +01000000000100000000010 +10000000000100000000001 +10000000000100000000001 +11111111111111111111111 +10000000000100000000001 +10000000000100000000001 +01000000000100000000010 +01000000000100000000010 +01000000000100000000010 +00100000000100000000100 +00010000000100000001000 +00011000000100000011000 +00000100000100000100000 +00000011100100111000000 +00000000011111000000000 + +0000000000111110000000000 +0000000111001001110000000 +0000011000001000001100000 +0000100000001000000010000 +0001000000001000000001000 +0010000000001000000000100 +0010000000001000000000100 +0100000000001000000000010 +0100000000001000000000010 +0100000000001000000000010 +1000000000001000000000001 +1000000000001000000000001 +1111111111111111111111111 +1000000000001000000000001 +1000000000001000000000001 +0100000000001000000000010 +0100000000001000000000010 +0100000000001000000000010 +0010000000001000000000100 +0010000000001000000000100 +0001000000001000000001000 +0000100000001000000010000 +0000011000001000001100000 +0000000111001001110000000 +0000000000111110000000000 + +000000000001111100000000000 +000000001110010011100000000 +000000110000010000011000000 +000001000000010000000100000 +000010000000010000000010000 +000100000000010000000001000 +001000000000010000000000100 +001000000000010000000000100 +010000000000010000000000010 +010000000000010000000000010 +010000000000010000000000010 +100000000000010000000000001 +100000000000010000000000001 +111111111111111111111111111 +100000000000010000000000001 +100000000000010000000000001 +010000000000010000000000010 +010000000000010000000000010 +010000000000010000000000010 +001000000000010000000000100 +001000000000010000000000100 +000100000000010000000001000 +000010000000010000000010000 +000001000000010000000100000 +000000110000010000011000000 +000000001110010011100000000 +000000000001111100000000000 + +00000000000011111000000000000 +00000000011100100111100000000 +00000001100000100000010000000 +00000010000000100000001100000 +00001100000000100000000010000 +00001000000000100000000001000 +00010000000000100000000001000 +00100000000000100000000000100 +00100000000000100000000000010 +01000000000000100000000000010 +01000000000000100000000000010 +01000000000000100000000000010 +10000000000000100000000000001 +10000000000000100000000000001 +11111111111111111111111111111 +10000000000000100000000000001 +10000000000000100000000000001 +01000000000000100000000000010 +01000000000000100000000000010 +01000000000000100000000000010 +00100000000000100000000000010 +00100000000000100000000000100 +00010000000000100000000001000 +00001000000000100000000001000 +00001100000000100000000110000 +00000010000000100000001000000 +00000001100000100000110000000 +00000000011100100111000000000 +00000000000011111000000000000 + +0000000000000111110000000000000 +0000000001111001001111000000000 +0000000010000001000000100000000 +0000001100000001000000011000000 +0000010000000001000000000100000 +0000100000000001000000000010000 +0001000000000001000000000001000 +0001000000000001000000000001000 +0010000000000001000000000000100 +0100000000000001000000000000010 +0100000000000001000000000000010 +0100000000000001000000000000010 +0100000000000001000000000000010 +1000000000000001000000000000001 +1000000000000001000000000000001 +1111111111111111111111111111111 +1000000000000001000000000000001 +1000000000000001000000000000001 +0100000000000001000000000000010 +0100000000000001000000000000010 +0100000000000001000000000000010 +0100000000000001000000000000010 +0010000000000001000000000000100 +0001000000000001000000000001000 +0001000000000001000000000001000 +0000100000000001000000000010000 +0000010000000001000000000100000 +0000001100000001000000011000000 +0000000010000001000000100000000 +0000000001111001001111000000000 +0000000000000111110000000000000 + +00000000000001111110000000000000 +00000000001110010001110000000000 +00000000110000010000001100000000 +00000001000000010000000010000000 +00000110000000010000000001100000 +00001000000000010000000000010000 +00001000000000010000000000010000 +00010000000000010000000000001000 +00100000000000010000000000000100 +00100000000000010000000000000100 +01000000000000010000000000000010 +01000000000000010000000000000010 +01000000000000010000000000000010 +01000000000000010000000000000010 +10000000000000010000000000000001 +11111111111111111111111111111111 +10000000000000010000000000000001 +10000000000000010000000000000001 +01000000000000010000000000000010 +01000000000000010000000000000010 +01000000000000010000000000000010 +01000000000000010000000000000010 +00100000000000010000000000000100 +00100000000000010000000000000100 +00010000000000010000000000001000 +00001000000000010000000000010000 +00001000000000010000000000010000 +00000110000000010000000001100000 +00000001000000010000000010000000 +00000000110000010000001100000000 +00000000001110010001110000000000 +00000000000001111110000000000000 diff --git a/src/VTKViewer/textures/texture8.dat b/src/VTKViewer/textures/texture8.dat new file mode 100644 index 000000000..7ffdbf0f1 --- /dev/null +++ b/src/VTKViewer/textures/texture8.dat @@ -0,0 +1,284 @@ +000111000 +011010110 +110010011 +101111101 +100010001 +101111101 +110010011 +011010110 +000111000 + +00001110000 +00110101100 +11000100011 +01100100110 +10011111001 +10000100001 +10011111001 +01100100110 +11000100011 +00110101100 +00001110000 + +0000111110000 +0001001001000 +0010001000100 +1100001000011 +0111001001110 +1000111110001 +1000001000001 +1000111110001 +0111001001110 +1100001000011 +0010001000100 +0001001001000 +0000111110000 + +000001111100000 +000110010011000 +001000010000100 +110000010000011 +011000010000110 +100110010011001 +100001111100001 +100000010000001 +100001111100001 +100110010011001 +011000010000110 +110000010000011 +001000010000100 +000110010011000 +000001111100000 + +00000011111000000 +00001100100110000 +00010000100001000 +00100000100000100 +11000000100000011 +01110000100001110 +10001100100110001 +10000011111000001 +10000000100000001 +10000011111000001 +10001100100110001 +01110000100001110 +11000000100000011 +00100000100000100 +00010000100001000 +00001100100110000 +00000011111000000 + +0000000111110000000 +0000011001001100000 +0001100001000011000 +0010000001000000100 +1010000001000000101 +0110000001000000110 +0101100001000011010 +1000011001001100001 +1000000111110000001 +1000000001000000001 +1000000111110000001 +1000011001001100001 +0101100001000011010 +0110000001000000110 +1010000001000000101 +0010000001000000100 +0001100001000011000 +0000011001001100000 +0000000111110000000 + +000000001111100000000 +000000110010011000000 +000011000010000110000 +000100000010000001000 +001000000010000000100 +111000000010000000111 +011100000010000001110 +010011000010000110010 +100000110010011000001 +100000001111100000001 +100000000010000000001 +100000001111100000001 +100000110010011000001 +010011000010000110010 +011100000010000001110 +111000000010000000111 +001000000010000000100 +000100000010000001000 +000011000010000110000 +000000110010011000000 +000000001111100000000 + +00000000011111000000000 +00000011100100111000000 +00000100000100000100000 +00011000000100000011000 +00010000000100000001000 +10100000000100000000101 +01100000000100000000110 +01011000000100000011010 +01000110000100001100010 +10000001100100110000001 +10000000011111000000001 +10000000000100000000001 +10000000011111000000001 +10000001100100110000001 +01000110000100001100010 +01011000000100000011010 +01100000000100000000110 +10100000000100000000101 +00010000000100000001000 +00011000000100000011000 +00000100000100000100000 +00000011100100111000000 +00000000011111000000000 + +0000000000111110000000000 +0000000111001001110000000 +0000011000001000001100000 +0000100000001000000010000 +0001000000001000000001000 +0010000000001000000000100 +1110000000001000000000111 +0111000000001000000001110 +0100110000001000000110010 +0100001100001000011000010 +1000000011001001100000001 +1000000000111110000000001 +1000000000001000000000001 +1000000000111110000000001 +1000000011001001100000001 +0100001100001000011000010 +0100110000001000000110010 +0111000000001000000001110 +1110000000001000000000111 +0010000000001000000000100 +0001000000001000000001000 +0000100000001000000010000 +0000011000001000001100000 +0000000111001001110000000 +0000000000111110000000000 + +000000000001111100000000000 +000000001110010011100000000 +000000110000010000011000000 +000001000000010000000100000 +000010000000010000000010000 +000100000000010000000001000 +101000000000010000000000101 +011000000000010000000000110 +010110000000010000000011010 +010001100000010000001100010 +010000011000010000110000010 +100000000110010011000000001 +100000000001111100000000001 +100000000000010000000000001 +100000000001111100000000001 +100000000110010011000000001 +010000011000010000110000010 +010001100000010000001100010 +010110000000010000000011010 +011000000000010000000000110 +101000000000010000000000101 +000100000000010000000001000 +000010000000010000000010000 +000001000000010000000100000 +000000110000010000011000000 +000000001110010011100000000 +000000000001111100000000000 + +00000000000011111000000000000 +00000000011100100111100000000 +00000001100000100000010000000 +00000010000000100000001100000 +00001100000000100000000010000 +00001000000000100000000001000 +00010000000000100000000001000 +11100000000000100000000000111 +00110000000000100000000001110 +01001100000000100000000110010 +01000011000000100000011000010 +01000000110000100001100000010 +10000000001100100110000000001 +10000000000011111000000000001 +10000000000000100000000000001 +10000000000011111000000000001 +10000000001100100110000000001 +01000000110000100001100000010 +01000011000000100000011000010 +01001100000000100000000110010 +00110000000000100000000001110 +11100000000000100000000000111 +00010000000000100000000001000 +00001000000000100000000001000 +00001100000000100000000110000 +00000010000000100000001000000 +00000001100000100000110000000 +00000000011100100111000000000 +00000000000011111000000000000 + +0000000000000111110000000000000 +0000000001111001001111000000000 +0000000010000001000000100000000 +0000001100000001000000011000000 +0000010000000001000000000100000 +0000100000000001000000000010000 +0001000000000001000000000001000 +1001000000000001000000000001001 +0110000000000001000000000000110 +0101100000000001000000000011010 +0100011000000001000000001100010 +0100000110000001000000110000010 +0100000001100001000011000000010 +1000000000011001001100000000001 +1000000000000111110000000000001 +1000000000000001000000000000001 +1000000000000111110000000000001 +1000000000011001001100000000001 +0100000001100001000011000000010 +0100000110000001000000110000010 +0100011000000001000000001100010 +0101100000000001000000000011010 +0110000000000001000000000000110 +1001000000000001000000000001001 +0001000000000001000000000001000 +0000100000000001000000000010000 +0000010000000001000000000100000 +0000001100000001000000011000000 +0000000010000001000000100000000 +0000000001111001001111000000000 +0000000000000111110000000000000 + +00000000000001111110000000000000 +00000000001110010001110000000000 +00000000110000010000001100000000 +00000001000000010000000010000000 +00000110000000010000000001100000 +00001000000000010000000000010000 +00001000000000010000000000010000 +00010000000000010000000000001000 +10100000000000010000000000000110 +01100000000000010000000000001100 +01011000000000010000000000110010 +01000110000000010000000011000010 +01000001100000010000001100000010 +01000000011000010000110000000010 +10000000000110010011000000000001 +10000000000001111100000000000001 +10000000000001111100000000000001 +10000000000110010011000000000001 +01000000011000010000110000000010 +01000001100000010000001100000010 +01000110000000010000000011000010 +01011000000000010000000000110010 +01100000000000010000000000001100 +10100000000000010000000000000110 +00010000000000010000000000001000 +00001000000000010000000000010000 +00001000000000010000000000010000 +00000110000000010000000001100000 +00000001000000010000000010000000 +00000000110000010000001100000000 +00000000001110010001110000000000 +00000000000001111110000000000000 diff --git a/src/VTKViewer/textures/texture9.dat b/src/VTKViewer/textures/texture9.dat new file mode 100644 index 000000000..01fa9ee22 --- /dev/null +++ b/src/VTKViewer/textures/texture9.dat @@ -0,0 +1,284 @@ +100111001 +011000110 +011000110 +100101001 +100010001 +100101001 +011000110 +011000110 +100111001 + +10001110001 +01110001110 +01100000110 +01010001010 +10001010001 +10000100001 +10001010001 +01010001010 +01100000110 +01110001110 +10001110001 + +1000111110001 +0101000001010 +0010000000100 +0101000001010 +0100100010010 +1000010100001 +1000001000001 +1000010100001 +0100100010010 +0101000001010 +0010000000100 +0101000001010 +1000111110001 + +100001111100001 +010110000011010 +001000000000100 +010100000001010 +010010000010010 +100001000100001 +100000101000001 +100000010000001 +100000101000001 +100001000100001 +010010000010010 +010100000001010 +001000000000100 +010110000011010 +100001111100001 + +10000011111000001 +01001100000110010 +00110000000001100 +00110000000001100 +01001000000010010 +01000100000100010 +10000010001000001 +10000001010000001 +10000000100000001 +10000001010000001 +10000010001000001 +01000100000100010 +01001000000010010 +00110000000001100 +00110000000001100 +01001100000110010 +10000011111000001 + +1000000111110000001 +0100011000001100010 +0011100000000011100 +0011000000000001100 +0010100000000010100 +0100010000000100010 +0100001000001000010 +1000000100010000001 +1000000010100000001 +1000000001000000001 +1000000010100000001 +1000000100010000001 +0100001000001000010 +0100010000000100010 +0010100000000010100 +0011000000000001100 +0011100000000011100 +0100011000001100010 +1000000111110000001 + +100000001111100000001 +010000110000011000010 +001011000000000110100 +000100000000000001000 +001010000000000010100 +001001000000000100100 +010000100000001000010 +010000010000010000010 +100000001000100000001 +100000000101000000001 +100000000010000000001 +100000000101000000001 +100000001000100000001 +010000010000010000010 +010000100000001000010 +001001000000000100100 +001010000000000010100 +000100000000000001000 +001011000000000110100 +010000110000011000010 +100000001111100000001 + +10000000011111000000001 +01000011100000111000010 +00100100000000000100100 +00011000000000000011000 +00011000000000000011000 +00100100000000000100100 +01000010000000001000010 +01000001000000010000010 +01000000100000100000010 +10000000010001000000001 +10000000001010000000001 +10000000000100000000001 +10000000001010000000001 +10000000010001000000001 +01000000100000100000010 +01000001000000010000010 +01000010000000001000010 +00100100000000000100100 +00011000000000000011000 +00011000000000000011000 +00100100000000000100100 +01000011100000111000010 +10000000011111000000001 + +1000000000111110000000001 +0100000111000001110000010 +0010011000000000001100100 +0001100000000000000011000 +0001100000000000000011000 +0010010000000000000100100 +0010001000000000001000100 +0100000100000000010000010 +0100000010000000100000010 +0100000001000001000000010 +1000000000100010000000001 +1000000000010100000000001 +1000000000001000000000001 +1000000000010100000000001 +1000000000100010000000001 +0100000001000001000000010 +0100000010000000100000010 +0100000100000000010000010 +0010001000000000001000100 +0010010000000000000100100 +0001100000000000000011000 +0001100000000000000011000 +0010011000000000001100100 +0100000111000001110000010 +1000000000111110000000001 + +100000000001111100000000001 +010000001110000011100000010 +001000110000000000011000100 +000101000000000000000101000 +000010000000000000000010000 +000101000000000000000101000 +001000100000000000001000100 +001000010000000000010000100 +010000001000000000100000010 +010000000100000001000000010 +010000000010000010000000010 +100000000001000100000000001 +100000000000101000000000001 +100000000000010000000000001 +100000000000101000000000001 +100000000001000100000000001 +010000000010000010000000010 +010000000100000001000000010 +010000001000000000100000010 +001000010000000000010000100 +001000100000000000001000100 +000101000000000000000101000 +000010000000000000000010000 +000101000000000000000101000 +001000110000000000011000100 +010000001110000011100000010 +100000000001111100000000001 + +10000000000011111000000000001 +01000000011100000111100000010 +00100001100000000000010000100 +00010010000000000000001101000 +00001100000000000000000010000 +00001100000000000000000101000 +00010010000000000000001001000 +00100001000000000000010000100 +00100000100000000000100000010 +01000000010000000001000000010 +01000000001000000010000000010 +01000000000100000100000000010 +10000000000010001000000000001 +10000000000001010000000000001 +10000000000000100000000000001 +10000000000001010000000000001 +10000000000010001000000000001 +01000000000100000100000000010 +01000000001000000010000000010 +01000000010000000001000000010 +00100000100000000000100000010 +00100001000000000000010000100 +00010010000000000000001001000 +00001100000000000000000101000 +00001100000000000000000110000 +00010010000000000000001001000 +00100001100000000000110000100 +01000000011100000111000000010 +10000000000011111000000000001 + +1000000000000111110000000000001 +0100000001111000001111000000010 +0010000010000000000000100000100 +0001001100000000000000011001000 +0000110000000000000000000110000 +0000110000000000000000000110000 +0001001000000000000000001001000 +0001000100000000000000010001000 +0010000010000000000000100000100 +0100000001000000000001000000010 +0100000000100000000010000000010 +0100000000010000000100000000010 +0100000000001000001000000000010 +1000000000000100010000000000001 +1000000000000010100000000000001 +1000000000000001000000000000001 +1000000000000010100000000000001 +1000000000000100010000000000001 +0100000000001000001000000000010 +0100000000010000000100000000010 +0100000000100000000010000000010 +0100000001000000000001000000010 +0010000010000000000000100000100 +0001000100000000000000010001000 +0001001000000000000000001001000 +0000110000000000000000000110000 +0000110000000000000000000110000 +0001001100000000000000011001000 +0010000010000000000000100000100 +0100000001111000001111000000010 +1000000000000111110000000000001 + +10000000000001111110000000000001 +01000000001110000001110000000010 +00100000110000000000001100000100 +00010001000000000000000010001000 +00001110000000000000000001110000 +00001100000000000000000000110000 +00001010000000000000000001010000 +00010001000000000000000010001000 +00100000100000000000000100000100 +00100000010000000000001000000100 +01000000001000000000010000000010 +01000000000100000000100000000010 +01000000000010000001000000000010 +01000000000001000010000000000010 +10000000000000100100000000000001 +10000000000000011000000000000001 +10000000000000011000000000000001 +10000000000000100100000000000001 +01000000000001000010000000000010 +01000000000010000001000000000010 +01000000000100000000100000000010 +01000000001000000000010000000010 +00100000010000000000001000000100 +00100000100000000000000100000100 +00010001000000000000000010001000 +00001010000000000000000001010000 +00001100000000000000000000110000 +00001110000000000000000001110000 +00010001000000000000000010001000 +00100000110000000000001100000100 +01000000001110000001110000000010 +10000000000001111110000000000001 diff --git a/src/ViewerTools/Makefile.am b/src/ViewerTools/Makefile.am new file mode 100755 index 000000000..ec04f6cdb --- /dev/null +++ b/src/ViewerTools/Makefile.am @@ -0,0 +1,56 @@ +# Copyright (C) 2007-2012 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 +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +lib_LTLIBRARIES = libViewerTools.la + +salomeinclude_HEADERS= \ + ViewerTools.h \ + ViewerTools_CubeAxesDlgBase.h \ + ViewerTools_DialogBase.h \ + ViewerTools_FontWidgetBase.h + +dist_libViewerTools_la_SOURCES= \ + ViewerTools_CubeAxesDlgBase.cxx \ + ViewerTools_DialogBase.cxx \ + ViewerTools_FontWidgetBase.cxx + +MOC_FILES= \ + ViewerTools_CubeAxesDlgBase_moc.cxx \ + ViewerTools_DialogBase_moc.cxx \ + ViewerTools_FontWidgetBase_moc.cxx + +nodist_libViewerTools_la_SOURCES= $(MOC_FILES) + +nodist_salomeres_DATA = \ + ViewerTools_msg_en.qm \ + ViewerTools_msg_fr.qm + +libViewerTools_la_CPPFLAGS = \ + $(QT_INCLUDES) \ + -I$(srcdir)/../Qtx + +libViewerTools_la_LDFLAGS = \ + $(QT_MT_LIBS) + +libViewerTools_la_LIBADD = ../Qtx/libqtx.la diff --git a/src/ViewerTools/ViewerTools.h b/src/ViewerTools/ViewerTools.h new file mode 100644 index 000000000..64e9f26e0 --- /dev/null +++ b/src/ViewerTools/ViewerTools.h @@ -0,0 +1,41 @@ +// Copyright (C) 2007-2012 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 +// + +#ifndef VIEWERTOOLS_H +#define VIEWERTOOLS_H + +#ifdef WIN32 +# if defined VIEWERTOOLS_EXPORTS || defined ViewerTools_EXPORTS +# define VIEWERTOOLS_EXPORT __declspec(dllexport) +# else +# define VIEWERTOOLS_EXPORT __declspec(dllimport) +# endif +#else +# define VIEWERTOOLS_EXPORT +#endif + +#if defined WIN32 +#pragma warning ( disable: 4251 ) +#pragma warning ( disable: 4786 ) +#endif + +#endif diff --git a/src/ViewerTools/ViewerTools_CubeAxesDlgBase.cxx b/src/ViewerTools/ViewerTools_CubeAxesDlgBase.cxx new file mode 100644 index 000000000..1cc2181ef --- /dev/null +++ b/src/ViewerTools/ViewerTools_CubeAxesDlgBase.cxx @@ -0,0 +1,322 @@ +// Copyright (C) 2007-2012 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 +// + +#include "ViewerTools_CubeAxesDlgBase.h" + +#include "ViewerTools_FontWidgetBase.h" + +#include "QtxAction.h" +#include "QtxIntSpinBox.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/*! + * Class : ViewerTools_AxisWidgetBase + * Description : Axis tab widget of the "Graduated axis" dialog box +*/ + +/*! + Constructor +*/ +ViewerTools_AxisWidgetBase::ViewerTools_AxisWidgetBase (QWidget* theParent) +: QFrame(theParent) +{ +} + +/*! + Destructor +*/ +ViewerTools_AxisWidgetBase::~ViewerTools_AxisWidgetBase() +{ +} + +/*! + Initialize controls +*/ +void ViewerTools_AxisWidgetBase::initialize() +{ + QList< QLabel* > aLabels; + + // "Name" grp + + myNameGrp = new QGroupBox(ViewerTools_CubeAxesDlgBase::tr("AXIS_NAME"), this); + myNameGrp->setCheckable( true ); + + QVBoxLayout* aVBox = new QVBoxLayout; + + QHBoxLayout* aHBox = new QHBoxLayout; + aHBox->setSpacing(5); + QLabel* aLabel = new QLabel(ViewerTools_CubeAxesDlgBase::tr("NAME")); + aHBox->addWidget(aLabel); + myAxisName = new QLineEdit; + aHBox->addWidget(myAxisName); + aLabels.append(aLabel); + aVBox->addLayout(aHBox); + + aHBox = new QHBoxLayout; + aHBox->setSpacing(5); + aLabel = new QLabel(ViewerTools_CubeAxesDlgBase::tr("FONT")); + aHBox->addWidget(aLabel); + myNameFont = createFontWidget(myNameGrp); + aHBox->addWidget(myNameFont); + aLabels.append(aLabel); + aVBox->addLayout(aHBox); + + myNameGrp->setLayout(aVBox); + + // "Labels" grp + + myLabelsGrp = new QGroupBox(ViewerTools_CubeAxesDlgBase::tr("LABELS"), this); + myLabelsGrp->setCheckable( true ); + + aVBox = new QVBoxLayout; + + aHBox = new QHBoxLayout; + aHBox->setSpacing(5); + aLabel = new QLabel(ViewerTools_CubeAxesDlgBase::tr("NUMBER")); + aHBox->addWidget(aLabel); + myLabelNumber = new QtxIntSpinBox(2,25,1,myLabelsGrp); + aHBox->addWidget(myLabelNumber); + aLabels.append(aLabel); + aVBox->addLayout(aHBox); + + aHBox = new QHBoxLayout; + aHBox->setSpacing(5); + aLabel = new QLabel(ViewerTools_CubeAxesDlgBase::tr("OFFSET")); + aHBox->addWidget(aLabel); + myLabelOffset = new QtxIntSpinBox(0,100,1,myLabelsGrp); + aHBox->addWidget(myLabelOffset); + aLabels.append(aLabel); + aVBox->addLayout(aHBox); + + aHBox = new QHBoxLayout; + aHBox->setSpacing(5); + aLabel = new QLabel(ViewerTools_CubeAxesDlgBase::tr("FONT")); + aHBox->addWidget(aLabel); + myLabelsFont = createFontWidget(myLabelsGrp); + aHBox->addWidget(myLabelsFont); + aLabels.append(aLabel); + aVBox->addLayout(aHBox); + + myLabelsGrp->setLayout(aVBox); + + // "Tick marks" grp + + myTicksGrp = new QGroupBox(ViewerTools_CubeAxesDlgBase::tr("TICK_MARKS"), this); + myTicksGrp->setCheckable( true ); + + aVBox = new QVBoxLayout; + + aHBox = new QHBoxLayout; + aHBox->setSpacing(5); + aLabel = new QLabel(ViewerTools_CubeAxesDlgBase::tr("LENGTH")); + aHBox->addWidget(aLabel); + myTickLength = new QtxIntSpinBox(0,100,1,myTicksGrp); + aHBox->addWidget(myTickLength); + aLabels.append(aLabel); + aVBox->addLayout(aHBox); + + myTicksGrp->setLayout(aVBox); + + // Layout + + QVBoxLayout* aLay = new QVBoxLayout(this); + aLay->setMargin(5); + aLay->setSpacing(5); + aLay->addWidget(myNameGrp); + aLay->addWidget(myLabelsGrp); + aLay->addWidget(myTicksGrp); + + // init + myNameGrp->setChecked( true ); + myLabelsGrp->setChecked( true ); + myTicksGrp->setChecked( true ); + + // Adjust label widths + QList< QLabel* >::iterator anIter; + int aMaxWidth = 0; + for (anIter = aLabels.begin(); anIter != aLabels.end(); anIter++) + aMaxWidth = qMax(aMaxWidth, (*anIter)->sizeHint().width()); + for (anIter = aLabels.begin(); anIter != aLabels.end(); anIter++) + (*anIter)->setFixedWidth(aMaxWidth); +} + +void ViewerTools_AxisWidgetBase::UseName(const bool toUse) +{ + myNameGrp->setChecked(toUse); +} + +void ViewerTools_AxisWidgetBase::SetName(const QString& theName) +{ + myAxisName->setText(theName); +} + +void ViewerTools_AxisWidgetBase::SetNameFont(const QColor& theColor, + const int theFont, + const bool theIsBold, + const bool theIsItalic, + const bool theIsShadow) +{ + myNameFont->SetData(theColor, theFont, theIsBold, theIsItalic, theIsShadow); +} + +/* + Class : ViewerTools_CubeAxesDlgBase + Description : Dialog for specifying cube axes properties +*/ + +/*! + Constructor +*/ +ViewerTools_CubeAxesDlgBase::ViewerTools_CubeAxesDlgBase(QtxAction* theAction, + QWidget* theParent, + const char* theName): + ViewerTools_DialogBase(theAction, + theParent, + theName) +{ + setWindowTitle(tr("CAPTION")); +} + +/*! + Initialize controls +*/ +void ViewerTools_CubeAxesDlgBase::initialize() +{ + QVBoxLayout* aLay = new QVBoxLayout(this); + aLay->setMargin(5); + aLay->setSpacing(5); + aLay->addWidget(createMainFrame(this)); + aLay->addWidget(createButtonFrame(this)); +} + +/*! + Create frame containing dialog's input fields +*/ +QWidget* ViewerTools_CubeAxesDlgBase::createMainFrame(QWidget* theParent) +{ + QFrame* aFrame = new QFrame(theParent); + + myTabWg = new QTabWidget(aFrame); + + myAxes[ 0 ] = createAxisWidget(myTabWg); + myAxes[ 1 ] = createAxisWidget(myTabWg); + myAxes[ 2 ] = createAxisWidget(myTabWg); + + myTabWg->addTab(myAxes[ 0 ], tr("X_AXIS")); + myTabWg->addTab(myAxes[ 1 ], tr("Y_AXIS")); + myTabWg->addTab(myAxes[ 2 ], tr("Z_AXIS")); + + myIsVisible = new QCheckBox(tr("IS_VISIBLE"), aFrame); + + QVBoxLayout* aLay = new QVBoxLayout(aFrame); + aLay->setMargin(0); + aLay->setSpacing(5); + aLay->addWidget(myTabWg); + aLay->addWidget(myIsVisible); + + return aFrame; +} + +/*! + Create frame containing buttons +*/ +QWidget* ViewerTools_CubeAxesDlgBase::createButtonFrame(QWidget* theParent) +{ + QFrame* aFrame = new QFrame(theParent); + aFrame->setFrameStyle(QFrame::Box | QFrame::Sunken); + + myOkBtn = new QPushButton(tr("BUT_OK"), aFrame); + myApplyBtn = new QPushButton(tr("BUT_APPLY"), aFrame); + myCloseBtn = new QPushButton(tr("BUT_CLOSE"), aFrame); + + QSpacerItem* aSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + + QHBoxLayout* aLay = new QHBoxLayout(aFrame); + aLay->setMargin(5); + aLay->setSpacing(5); + + aLay->addWidget(myOkBtn); + aLay->addWidget(myApplyBtn); + aLay->addItem(aSpacer); + aLay->addWidget(myCloseBtn); + + connect(myOkBtn, SIGNAL(clicked()), SLOT(onOk())); + connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply())); + connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose())); + + return aFrame; +} + +/*! + Destructor +*/ +ViewerTools_CubeAxesDlgBase::~ViewerTools_CubeAxesDlgBase() +{ +} + +/*! + Update dialog fields, connect signals and slots, show dialog +*/ +void ViewerTools_CubeAxesDlgBase::Update() +{ +} + +/*! + Verify validity of entry data +*/ +bool ViewerTools_CubeAxesDlgBase::isValid() const +{ + return true; +} + +/*! + Verify validity of entry data +*/ +bool ViewerTools_CubeAxesDlgBase::onApply() +{ + return true; +} + +/*! + SLOT called when "Ok" button pressed. +*/ +void ViewerTools_CubeAxesDlgBase::onOk() +{ + if (onApply()) + onClose(); +} + +/*! + SLOT: called when "Close" button pressed. Close dialog +*/ +void ViewerTools_CubeAxesDlgBase::onClose() +{ + reject(); +} diff --git a/src/ViewerTools/ViewerTools_CubeAxesDlgBase.h b/src/ViewerTools/ViewerTools_CubeAxesDlgBase.h new file mode 100644 index 000000000..25a6aa2fc --- /dev/null +++ b/src/ViewerTools/ViewerTools_CubeAxesDlgBase.h @@ -0,0 +1,119 @@ +// Copyright (C) 2007-2012 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 +// + +#ifndef VIEWERTOOLS_CUBEAXESDLGBASE_H +#define VIEWERTOOLS_CUBEAXESDLGBASE_H + +#include "ViewerTools_DialogBase.h" + +#include + +class QWidget; +class QPushButton; +class QTabWidget; +class QCheckBox; +class QGroupBox; +class QLineEdit; + +class QtxAction; +class QtxIntSpinBox; + +class ViewerTools_FontWidgetBase; + +/*! + * Class : ViewerTools_AxisWidgetBase + * Description : Axis tab widget of the "Graduated axis" dialog box +*/ +class VIEWERTOOLS_EXPORT ViewerTools_AxisWidgetBase : public QFrame +{ +public: + ViewerTools_AxisWidgetBase( QWidget* ); + ~ViewerTools_AxisWidgetBase(); + + void UseName( const bool ); + void SetName( const QString& ); + void SetNameFont( const QColor&, const int, const bool, const bool, const bool ); + +public: + virtual void initialize(); + +protected: + virtual ViewerTools_FontWidgetBase* createFontWidget( QWidget* ) = 0; + +protected: + // name + QGroupBox* myNameGrp; + QLineEdit* myAxisName; + ViewerTools_FontWidgetBase* myNameFont; + + // labels + QGroupBox* myLabelsGrp; + QtxIntSpinBox* myLabelNumber; + QtxIntSpinBox* myLabelOffset; + ViewerTools_FontWidgetBase* myLabelsFont; + + // tick marks + QGroupBox* myTicksGrp; + QtxIntSpinBox* myTickLength; +}; + +/*! + * Class : ViewerTools_CubeAxesDlgBase + * Description : Dialog for specifying cube axes properties + */ +class VIEWERTOOLS_EXPORT ViewerTools_CubeAxesDlgBase : public ViewerTools_DialogBase +{ + Q_OBJECT + +public: + ViewerTools_CubeAxesDlgBase(QtxAction* theAction, + QWidget* theParent, + const char* theName); + virtual ~ViewerTools_CubeAxesDlgBase(); + + virtual void initialize(); + + virtual void Update(); + +protected slots: + virtual void onOk(); + virtual bool onApply(); + virtual void onClose(); + +protected: + virtual QWidget* createButtonFrame( QWidget* ); + virtual QWidget* createMainFrame ( QWidget* ); + virtual bool isValid() const; + + virtual ViewerTools_AxisWidgetBase* createAxisWidget( QWidget* ) = 0; + +protected: + QTabWidget* myTabWg; + QCheckBox* myIsVisible; + + QPushButton* myOkBtn; + QPushButton* myApplyBtn; + QPushButton* myCloseBtn; + ViewerTools_AxisWidgetBase* myAxes[ 3 ]; +}; + +#endif diff --git a/src/ViewerTools/ViewerTools_DialogBase.cxx b/src/ViewerTools/ViewerTools_DialogBase.cxx new file mode 100644 index 000000000..31b0fdc6d --- /dev/null +++ b/src/ViewerTools/ViewerTools_DialogBase.cxx @@ -0,0 +1,79 @@ +// Copyright (C) 2007-2012 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 +// + +#include "ViewerTools_DialogBase.h" + +#include "QtxAction.h" + +/*! + Constructor +*/ +ViewerTools_DialogBase +::ViewerTools_DialogBase(QtxAction* theAction, + QWidget* theParent, + const char* theName, + bool theModal, + Qt::WindowFlags theWFalgs): + QDialog(theParent, + theWFalgs | Qt::WindowTitleHint | Qt::WindowSystemMenuHint), + myAction(theAction) +{ + setObjectName(theName); + setModal(theModal); + + connect(theParent, SIGNAL(Show( QShowEvent * )), this, SLOT(onParentShow())); + connect(theParent, SIGNAL(Hide( QHideEvent * )), this, SLOT(onParentHide())); +} + +/* + * Destroys the object and frees any allocated resources + */ +ViewerTools_DialogBase +::~ViewerTools_DialogBase() +{ + // no need to delete child widgets, Qt does it all for us +} + +void +ViewerTools_DialogBase +::onParentShow() +{ + if(myAction->isChecked()) + show(); + else + hide(); +} + +void +ViewerTools_DialogBase +::onParentHide() +{ + hide(); +} + +void +ViewerTools_DialogBase +::done( int r ) +{ + myAction->setChecked( false ); + QDialog::done( r ); +} diff --git a/src/ViewerTools/ViewerTools_DialogBase.h b/src/ViewerTools/ViewerTools_DialogBase.h new file mode 100644 index 000000000..7f9a77586 --- /dev/null +++ b/src/ViewerTools/ViewerTools_DialogBase.h @@ -0,0 +1,54 @@ +// Copyright (C) 2007-2012 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 +// + +#ifndef VIEWERTOOLS_DIALOGBASE_H +#define VIEWERTOOLS_DIALOGBASE_H + +#include "ViewerTools.h" + +#include + +class QtxAction; + +class VIEWERTOOLS_EXPORT ViewerTools_DialogBase : public QDialog +{ + Q_OBJECT; + +public: + ViewerTools_DialogBase(QtxAction* theAction, + QWidget* theParent, + const char* theName = "", + bool theModal = FALSE, + Qt::WindowFlags theWFalgs = 0); + + ~ViewerTools_DialogBase(); + +protected slots: + void onParentShow(); + void onParentHide(); + virtual void done( int ); + +protected: + QtxAction* myAction; +}; + +#endif // VIEWERTOOLS_DIALOGBASE_H diff --git a/src/ViewerTools/ViewerTools_FontWidgetBase.cxx b/src/ViewerTools/ViewerTools_FontWidgetBase.cxx new file mode 100644 index 000000000..f78c137d6 --- /dev/null +++ b/src/ViewerTools/ViewerTools_FontWidgetBase.cxx @@ -0,0 +1,128 @@ +// Copyright (C) 2007-2012 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 +// + +#include "ViewerTools_FontWidgetBase.h" + +#include +#include +#include +#include +#include + +/*! + * Class : ViewerTools_FontWidgetBase + * Description : Dialog for specifynig font + */ + +/*! + Constructor +*/ +ViewerTools_FontWidgetBase::ViewerTools_FontWidgetBase( QWidget* theParent ) +: QWidget( theParent ) +{ +} + +/*! + Destructor +*/ +ViewerTools_FontWidgetBase::~ViewerTools_FontWidgetBase() +{ +} + +void ViewerTools_FontWidgetBase::Initialize() +{ + myColorBtn = new QToolButton( this ); + myColorBtn->setMinimumWidth( 20 ); + + myFamily = new QComboBox( this ); + InitializeFamilies(); + + myBold = new QCheckBox( tr( "BOLD" ), this ); + myItalic = new QCheckBox( tr( "ITALIC" ), this ); + myShadow = new QCheckBox( tr( "SHADOW" ), this ); + + QHBoxLayout* aHBLayout = new QHBoxLayout; + aHBLayout->setMargin( 0 ); + aHBLayout->setSpacing( 5 ); + aHBLayout->addWidget(myColorBtn); + aHBLayout->addWidget(myFamily); + aHBLayout->addWidget(myBold); + aHBLayout->addWidget(myItalic); + aHBLayout->addWidget(myShadow); + aHBLayout->addStretch(); + this->setLayout(aHBLayout); + + connect( myColorBtn, SIGNAL( clicked() ), SLOT( onColor() ) ); + + if( myFamily->count() == 0 ) + { + myFamily->hide(); + myBold->hide(); + myItalic->hide(); + myShadow->hide(); + } +} + +void ViewerTools_FontWidgetBase::SetColor( const QColor& theColor ) +{ + QPalette palette; + palette.setColor(myColorBtn->backgroundRole(), theColor); + myColorBtn->setPalette(palette); +} + +QColor ViewerTools_FontWidgetBase::GetColor() const +{ + return myColorBtn->palette().color( myColorBtn->backgroundRole() ); +} + +void ViewerTools_FontWidgetBase::onColor() +{ + QColor aColor = QColorDialog::getColor( GetColor(), this ); + if ( aColor.isValid() ) + SetColor( aColor ); +} + +void ViewerTools_FontWidgetBase::SetData( const QColor& theColor, + const int theFamily, + const bool theBold, + const bool theItalic, + const bool theShadow ) +{ + SetColor( theColor ); + + myBold->setChecked( theBold ); + myItalic->setChecked( theItalic ); + myShadow->setChecked( theShadow ); +} + +void ViewerTools_FontWidgetBase::GetData( QColor& theColor, + int& theFamily, + bool& theBold, + bool& theItalic, + bool& theShadow ) const +{ + theColor = GetColor(); + + theBold = myBold->isChecked(); + theItalic = myItalic->isChecked(); + theShadow = myShadow->isChecked(); +} diff --git a/src/ViewerTools/ViewerTools_FontWidgetBase.h b/src/ViewerTools/ViewerTools_FontWidgetBase.h new file mode 100644 index 000000000..ae4ef3743 --- /dev/null +++ b/src/ViewerTools/ViewerTools_FontWidgetBase.h @@ -0,0 +1,71 @@ +// Copyright (C) 2007-2012 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 +// + +#ifndef VIEWERTOOLS_FONTWIDGETBASE_H +#define VIEWERTOOLS_FONTWIDGETBASE_H + +#include "ViewerTools.h" + +#include + +class QToolButton; +class QComboBox; +class QCheckBox; +class QColor; + +/*! + * Class : ViewerTools_FontWidgetBase + * Description : Dialog for specifying font + */ +class VIEWERTOOLS_EXPORT ViewerTools_FontWidgetBase : public QWidget +{ + Q_OBJECT + +public: + ViewerTools_FontWidgetBase( QWidget* ); + virtual ~ViewerTools_FontWidgetBase(); + + void SetColor( const QColor& ); + QColor GetColor() const; + + virtual void SetData( const QColor&, const int, const bool, const bool, const bool ); + + virtual void GetData( QColor&, int&, bool&, bool&, bool& ) const; + +public: + virtual void Initialize(); + +protected: + virtual void InitializeFamilies() = 0; + +protected slots: + void onColor(); + +protected: + QToolButton* myColorBtn; + QComboBox* myFamily; + QCheckBox* myBold; + QCheckBox* myItalic; + QCheckBox* myShadow; +}; + +#endif diff --git a/src/ViewerTools/resources/ViewerTools_msg_en.ts b/src/ViewerTools/resources/ViewerTools_msg_en.ts new file mode 100644 index 000000000..bfb45c80d --- /dev/null +++ b/src/ViewerTools/resources/ViewerTools_msg_en.ts @@ -0,0 +1,74 @@ + + + + + ViewerTools_CubeAxesDlgBase + + X_AXIS + X axis + + + Y_AXIS + Y axis + + + Z_AXIS + Z axis + + + CAPTION + Graduated axes + + + IS_VISIBLE + Is visible + + + FONT + Font + + + NAME + Name + + + TICK_MARKS + Tick marks + + + LABELS + Labels + + + LENGTH + Length + + + NUMBER + Number + + + OFFSET + Offset + + + AXIS_NAME + Axis name + + + + ViewerTools_FontWidgetBase + + BOLD + Bold + + + ITALIC + Italic + + + SHADOW + Shadow + + + diff --git a/src/ViewerTools/resources/ViewerTools_msg_fr.ts b/src/ViewerTools/resources/ViewerTools_msg_fr.ts new file mode 100755 index 000000000..1fb1f711e --- /dev/null +++ b/src/ViewerTools/resources/ViewerTools_msg_fr.ts @@ -0,0 +1,74 @@ + + + + + ViewerTools_CubeAxesDlgBase + + X_AXIS + Axe X + + + Y_AXIS + Axe Y + + + Z_AXIS + Axe Z + + + CAPTION + Axes gradués + + + IS_VISIBLE + Visible + + + FONT + Couleur + + + NAME + Nom + + + TICK_MARKS + Marques de graduation + + + LABELS + Etiquettes + + + LENGTH + Longueur + + + NUMBER + Nombre + + + OFFSET + Décalage + + + AXIS_NAME + Nom de l'axe + + + + ViewerTools_FontWidgetBase + + BOLD + Gras + + + ITALIC + Italique + + + SHADOW + Ombré + + + diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 000000000..96794db1b --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,23 @@ +# Copyright (C) 2007-2012 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 +# + +SUBDIRS = vtkEDFOverloads dlgfactory diff --git a/tools/dlgfactory/GenericDialog.cxx b/tools/dlgfactory/GenericDialog.cxx new file mode 100644 index 000000000..9b8456674 --- /dev/null +++ b/tools/dlgfactory/GenericDialog.cxx @@ -0,0 +1,29 @@ +#include "GenericDialog.hxx" + +GenericDialog::GenericDialog(QDialog *parent) : QDialog(parent) +{ + ui.setupUi(this); // A faire en premier + + /* + Personnalisez vos widgets ici si nécessaire + Réalisez des connexions supplémentaires entre signaux et slots + */ + + // The slots accept() and reject() are already connected to the + // buttonbox (inherited features) +} + +QFrame * GenericDialog::getPanel() { + return ui.centralPanel; +} + +QDialogButtonBox * GenericDialog::getButtonBox() { + return ui.buttonBox; +} + + +#include +void GenericDialog::accept() { + qDebug() << "accept() is not implemented yet"; + QDialog::accept(); +} diff --git a/tools/dlgfactory/GenericDialog.hxx b/tools/dlgfactory/GenericDialog.hxx new file mode 100644 index 000000000..ee946617d --- /dev/null +++ b/tools/dlgfactory/GenericDialog.hxx @@ -0,0 +1,27 @@ +#ifndef _GenericDialog_HXX +#define _GenericDialog_HXX + +#include +#include "ui_GenericDialog.hxx" + +class GenericDialog : public QDialog +{ + Q_OBJECT + +public: + GenericDialog(QDialog *parent = 0); + + protected: + QFrame * getPanel(); + QDialogButtonBox * getButtonBox(); + + protected slots: + void accept(); + //void reject(); + + private: + Ui_GenericDialog ui; // instance of the class defined in ui_GenericDialog.h +}; + + +#endif // _GenericDialog_HXX diff --git a/tools/dlgfactory/GenericDialog.ui b/tools/dlgfactory/GenericDialog.ui new file mode 100644 index 000000000..1fe7ae99e --- /dev/null +++ b/tools/dlgfactory/GenericDialog.ui @@ -0,0 +1,89 @@ + + GenericDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + GenericDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + GenericDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/tools/dlgfactory/Makefile.am b/tools/dlgfactory/Makefile.am new file mode 100644 index 000000000..c83870fa7 --- /dev/null +++ b/tools/dlgfactory/Makefile.am @@ -0,0 +1,105 @@ +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 : Guillaume Boulant (EDF/R&D) + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# moc-files generation (using MOC) +%_moc.cxx: %.hxx + $(MOC) $< -o $@ + +# Qt form files generation (using UIC) +ui_%.hxx: %.ui + $(UIC) -o $@ $< + +# Program targets +bin_PROGRAMS = qtester gtester + +# QDialog uic files +UIC_FILES_QDIALOG = \ + ui_QDialogTest.hxx + +# QDialog moc files +MOC_FILES_QDIALOG = \ + QDialogTest_moc.cxx + +# GDialog uic files +UIC_FILES_GDIALOG= \ + ui_GenericDialog.hxx \ + ui_GDialogTest.hxx + +# GDialog moc files +MOC_FILES_GDIALOG= \ + GenericDialog_moc.cxx \ + GDialogTest_moc.cxx + +QDIALOG_TEMPLATES = __QDIALOG__.ui __QDIALOG__.hxx __QDIALOG__.cxx +GDIALOG_TEMPLATES = __GDIALOG__.ui __GDIALOG__.hxx __GDIALOG__.cxx + +# generated sources +BUILT_SOURCES = $(UIC_FILES_QDIALOG) $(UIC_FILES_GDIALOG) + +# extra distributed files +EXTRA_DIST += $(QDIALOG_TEMPLATES) $(GDIALOG_TEMPLATES) GenericDialog.ui README.txt dlgfactory.py + +mostlyclean-local: + rm @builddir@/QDialogTest* + rm @builddir@/GDialogTest* + rm -f @builddir@/*_moc.cxx @builddir@/ui_*.hxx + +QDialogTest.hxx QDialogTest.cxx QDialogTest.ui: $(QDIALOG_TEMPLATES) dlgfactory.py + $(srcdir)/dlgfactory.py -s -n QDialogTest -t qdialog + +GDialogTest.hxx GDialogTest.cxx GDialogTest.ui : $(GDIALOG_TEMPLATES) dlgfactory.py + $(srcdir)/dlgfactory.py -s -n GDialogTest -t gdialog + +QT_CXXFLAGS=@QT_INCLUDES@ @QT_MT_INCLUDES@ +QT_LIBS=@QT_LIBS@ + +# QDialog tester +qtester_SOURCES = \ + qtester.cxx +nodist_qtester_SOURCES = \ + QDialogTest.cxx \ + $(MOC_FILES_QDIALOG) \ + $(UIC_FILES_QDIALOG) + +qtester_CPPFLAGS = \ + $(QT_CXXFLAGS) \ + -I. + +qtester_LDFLAGS = \ + $(QT_LIBS) + +gtester_SOURCES = \ + gtester.cxx \ + GenericDialog.hxx \ + GenericDialog.cxx +nodist_gtester_SOURCES = \ + GDialogTest.cxx \ + $(MOC_FILES_GDIALOG) \ + $(UIC_FILES_GDIALOG) + +gtester_CPPFLAGS = \ + $(QT_CXXFLAGS) \ + -I@srcdir@ \ + -I. + +gtester_LDFLAGS = \ + $(QT_LIBS) diff --git a/tools/dlgfactory/README.txt b/tools/dlgfactory/README.txt new file mode 100644 index 000000000..ec1c00559 --- /dev/null +++ b/tools/dlgfactory/README.txt @@ -0,0 +1,12 @@ +This package provides a simple tool to generates the bootstrap files +of a standard Qt dialog. Nothing original neither very smart, but just +help to initiate all this stuff the good way. + +See the header of the script dlgfactory.py for details. + +Some use cases (basic unit test) are given in the files qtester.cxx +and gtester.cxx. The build procedure (when you type make) create test +classes called QDialogTest and GDialogTest and used respectively in +qtester and gtester. + +(gboulant - 26 oct. 2011) diff --git a/tools/dlgfactory/__GDIALOG__.cxx b/tools/dlgfactory/__GDIALOG__.cxx new file mode 100644 index 000000000..705c7213f --- /dev/null +++ b/tools/dlgfactory/__GDIALOG__.cxx @@ -0,0 +1,6 @@ +#include "__CLASSNAME__.hxx" + +__CLASSNAME__::__CLASSNAME__(QDialog *parent) : GenericDialog(parent) +{ + ui.setupUi(this->getPanel()); +} diff --git a/tools/dlgfactory/__GDIALOG__.hxx b/tools/dlgfactory/__GDIALOG__.hxx new file mode 100644 index 000000000..ab805a197 --- /dev/null +++ b/tools/dlgfactory/__GDIALOG__.hxx @@ -0,0 +1,20 @@ +#ifndef ___CLASSNAME___HXX +#define ___CLASSNAME___HXX + +#include +#include "ui___CLASSNAME__.hxx" +#include "GenericDialog.hxx" + +class __CLASSNAME__ : public GenericDialog +{ + Q_OBJECT + + public: + __CLASSNAME__(QDialog *parent = 0); + + private: + Ui___CLASSNAME__ ui; // instance of the class defined in ui___CLASSNAME__.hxx +}; + + +#endif // ___CLASSNAME___HXX diff --git a/tools/dlgfactory/__GDIALOG__.ui b/tools/dlgfactory/__GDIALOG__.ui new file mode 100644 index 000000000..7f5c27dca --- /dev/null +++ b/tools/dlgfactory/__GDIALOG__.ui @@ -0,0 +1,99 @@ + + __CLASSNAME__ + + + + 0 + 0 + 340 + 300 + + + + Form + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + 0 + + + 6 + + + + + Pression : + + + + + + + Température : + + + + + + + + + 0 + + + 6 + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 121 + + + + + + + + + + + diff --git a/tools/dlgfactory/__QDIALOG__.cxx b/tools/dlgfactory/__QDIALOG__.cxx new file mode 100644 index 000000000..32134c395 --- /dev/null +++ b/tools/dlgfactory/__QDIALOG__.cxx @@ -0,0 +1,20 @@ +#include "__CLASSNAME__.hxx" + +__CLASSNAME__::__CLASSNAME__(QDialog *parent) : QDialog(parent) +{ + ui.setupUi(this); // A faire en premier + + /* + Personnalisez vos widgets ici si nécessaire + Réalisez des connexions supplémentaires entre signaux et slots + */ + + // The slots accept() and reject() are already connected to the + // buttonbox (inherited features) +} + +#include +void __CLASSNAME__::accept() { + qDebug() << "accept() is not implemented yet"; + QDialog::accept(); +} diff --git a/tools/dlgfactory/__QDIALOG__.hxx b/tools/dlgfactory/__QDIALOG__.hxx new file mode 100644 index 000000000..3865e170b --- /dev/null +++ b/tools/dlgfactory/__QDIALOG__.hxx @@ -0,0 +1,23 @@ +#ifndef ___CLASSNAME___HXX +#define ___CLASSNAME___HXX + +#include +#include "ui___CLASSNAME__.hxx" + +class __CLASSNAME__ : public QDialog +{ + Q_OBJECT + + public: + __CLASSNAME__(QDialog *parent = 0); + + protected slots: + void accept(); + //void reject(); + + private: + Ui___CLASSNAME__ ui; // instance of the class defined in ui___CLASSNAME__.hxx +}; + + +#endif // ___CLASSNAME___HXX diff --git a/tools/dlgfactory/__QDIALOG__.ui b/tools/dlgfactory/__QDIALOG__.ui new file mode 100644 index 000000000..88cf24de2 --- /dev/null +++ b/tools/dlgfactory/__QDIALOG__.ui @@ -0,0 +1,67 @@ + + __CLASSNAME__ + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 30 + 240 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + buttonBox + accepted() + __CLASSNAME__ + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + __CLASSNAME__ + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/tools/dlgfactory/dlgfactory.py b/tools/dlgfactory/dlgfactory.py new file mode 100755 index 000000000..5eca0eea4 --- /dev/null +++ b/tools/dlgfactory/dlgfactory.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 +# + +import sys, os + +__descr_str = "" +__descr_str += "This script generates a set of files to initiate a dialog Qt window " +__descr_str += "(i.e. MyDialog.ui, MyDialog.hxx and MyDialog.cxx files). " +__descr_str += "The dialog window can be a self-consistent class (i.e. depends only " +__descr_str += "on Qt classes) or a class that inherits class GenericDialog " +__descr_str += "which implementation is provided in this package and " +__descr_str += "which design is defined by the GenericDialog.ui file (editable using " +__descr_str += "the Qt designer). " +__descr_str += "The -t option let you choose between the two possibilities (specify " +__descr_str += "\"-t qdialog\" for the first case, \"-t gdialog\" otherwise)." + +__msg_str = """ +# +# --------------------------------------------------------- +# Generation rules to create moc files from QObject headers +# and form source files from ui files +# --------------------------------------------------------- + +%_moc.cxx: %.hxx + $(MOC) $< -o $@ + +ui_%.hxx: %.ui + $(UIC) -o $@ $< + + +# --------------------------------------------------------- +# Declaration of form files generated by UIC and MOC files +# as BUILT_SOURCES to be used in the building process. +# --------------------------------------------------------- +# +UIC_FILES = \ + ui___CLASSNAME__.hxx +# +MOC_FILES = \ + __CLASSNAME___moc.cxx + +BUILT_SOURCES = $(UIC_FILES) + +# +# --------------------------------------------------------- +# Declaration of sources files to the building process +# --------------------------------------------------------- +# MOC files and UIC files should be added to the list of undistributed +# source files with something like (where should be +# replaced by the name of the product declared by the directive +# lib_LTLIBRARIES): +# +nodist__la_SOURCES += $(MOC_FILES) $(UIC_FILES) + +dist__la_SOURCES += __CLASSNAME__.cxx +salomeinclude_HEADERS += __CLASSNAME__.hxx + +_la_CPPFLAGS = \\ + $(QT_CXXFLAGS) + +_la_LDFLAGS = \\ + $(QT_LIBS) +""" + +if __name__ == "__main__": + from optparse import OptionParser + import shutil, fileinput + + tool_path = os.path.dirname( os.path.abspath( sys.argv[0] ) ) + + parser = OptionParser( description = __descr_str ) + parser.add_option( "-n", action="store", default="TestDialog", dest="className", metavar="className", + help="specify the name of the class (default is TestDialog)" ) + parser.add_option( "-t", action="store", default="qdialog", dest="classType", + choices=["qdialog", "gdialog"], metavar="classType", + help="specify the type of the class (default is qdialog)" ) + parser.add_option( "-v", "--verbose", action="store_true", default=True, dest="verbose", + help="verbose mode" ) + parser.add_option( "-s", "--silent", action="store_false", dest="verbose", + help="silent mode" ) + + (options, args) = parser.parse_args() + className = options.className + classType = options.classType + + for ext in [".cxx", ".hxx", ".ui"]: + file_dest = className + ext + if classType == "qdialog": + file_src = os.path.join( tool_path, "__QDIALOG__" + ext ) + pass + else: + file_src = os.path.join( tool_path, "__GDIALOG__" + ext ) + pass + shutil.copyfile( file_src, file_dest ) + finput = fileinput.FileInput( file_dest, inplace=1 ) + for line in finput: + line = line[:-1] + line = line.replace( "__CLASSNAME__", className ) + print line + pass + + if options.verbose: + print "Note that the following directives should be present in your Makefile.am (or something like that): \n" + print __msg_str.replace( "__CLASSNAME__", className ) + pass + pass + diff --git a/tools/dlgfactory/dlgfactory.sh b/tools/dlgfactory/dlgfactory.sh new file mode 100755 index 000000000..0f127d515 --- /dev/null +++ b/tools/dlgfactory/dlgfactory.sh @@ -0,0 +1,155 @@ +#!/bin/sh +# Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +# +# 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 +# +# +# ================================================================== +#_debut_usage +# +# USAGE: +# +# dlgfactory.sh -n className [-t classType] +# +# +# DESCRIPTION: +# +# This script generates a set of files to initiate a dialog qt window +# (i.e. MyDialog.ui, MyDialog.hxx and MyDialog.cxx files). +# +# The dialog window can be a self-consistent class (i.e. depends only +# on Qt classes) or a classe that inherits from the class +# GenericDialog whose implementation is provided in this package and +# whose design is defined by the GenericDialog.ui file (editable using +# the qt designer). +# +# The -t option let you choose between the two possibilities (specify +# "-t qdialog" for the first case, "-t gdialog" otherwise). +# +# OPTION: +# -n : specify the name of the class (default is TestDialog) +# +# -t : specify the type of the class (default is qdialog) +# +#_fin_usage +# ================================================================== +# + +thisScript=$(which $0) +TOOLDIRNAME=$(dirname $0) + +displayUsage() +{ + cat $thisScript | sed -e '/^#_debut_usage/,/^#_fin_usage/!d' \ + -e '/^#_debut_usage/d' \ + -e '/^#_fin_usage/d' \ + -e 's/^#//g' +} + +# +# Read the options on the command line +# +className=TestDialog +classType=dialog +if [ $# -eq 0 ]; then + displayUsage + exit 1 +else + while [ $# -ne 0 ]; do + case $1 in + -n) + shift; className=$1; shift ;; + -t) + shift; classType=$1; shift ;; + *) + displayUsage;; + esac + done +fi + +if [ "$classType" = "qdialog" ]; then + sed s/__CLASSNAME__/$className/g $TOOLDIRNAME/__QDIALOG__.ui > $className.ui + sed s/__CLASSNAME__/$className/g $TOOLDIRNAME/__QDIALOG__.hxx > $className.hxx + sed s/__CLASSNAME__/$className/g $TOOLDIRNAME/__QDIALOG__.cxx > $className.cxx +else + sed s/__CLASSNAME__/$className/g $TOOLDIRNAME/__GDIALOG__.ui > $className.ui + sed s/__CLASSNAME__/$className/g $TOOLDIRNAME/__GDIALOG__.hxx > $className.hxx + sed s/__CLASSNAME__/$className/g $TOOLDIRNAME/__GDIALOG__.cxx > $className.cxx +fi + +displayMessage() +{ + cat $thisScript | sed -e '/^#_debut_message/,/^#_fin_message/!d' \ + -e '/^#_debut_message/d' \ + -e '/^#_fin_message/d' \ + -e 's/^#//g' \ + -e "s/__CLASSNAME__/$className/g" +} + +#_debut_message +## +## --------------------------------------------------------- +## Generation rules to create moc files from QObject headers +## and form source files from ui files +## --------------------------------------------------------- +## +#%_moc.cxx: %.hxx +# $(MOC) $< -o $@ +# +#ui_%.hxx: %.ui +# $(UIC) -o $@ $< +# +## +## --------------------------------------------------------- +## Declaration of form files generated by UIC and MOC files +## as BUILT_SOURCES to be used in the building process. +## --------------------------------------------------------- +## +#UIC_FILES = \ +# ui___CLASSNAME__.hxx +## +#MOC_FILES = \ +# __CLASSNAME___moc.cxx +# +#BUILT_SOURCES = $(UIC_FILES) +# +## +## --------------------------------------------------------- +## Declaration of sources files to the building process +## --------------------------------------------------------- +## MOC files and UIC files should be added to the list of undistributed +## source files with something like (where should be +## replaced by the name of the product declared by the directive +## lib_LTLIBRARIES): +## +#nodist__la_SOURCES += $(MOC_FILES) $(UIC_FILES) +# +#dist__la_SOURCES += __CLASSNAME__.cxx +#salomeinclude_HEADERS += __CLASSNAME__.hxx +# +#_la_CPPFLAGS = \ +# $(QT_CXXFLAGS) +# +#_la_LDFLAGS = \ +# $(QT_LIBS) + +#_fin_message + +echo "Note that the following directives should be present in your Makefile.am (or something like that):" +echo "" +displayMessage + diff --git a/tools/dlgfactory/gtester.cxx b/tools/dlgfactory/gtester.cxx new file mode 100644 index 000000000..0f636c240 --- /dev/null +++ b/tools/dlgfactory/gtester.cxx @@ -0,0 +1,38 @@ +// Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// +// This program can be used for unit test of dialog box. +// You just have to include the interface file (*.h) and +// use the dialog class as illustrated in the functions TEST_*. +// (gboulant - 12/10/2010) +// +#include +#include +#include "GDialogTest.hxx" + +void TEST_show() { + GDialogTest * dialog = new GDialogTest(); + dialog->show(); +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + TEST_show(); + return app.exec(); +} diff --git a/tools/dlgfactory/qtester.cxx b/tools/dlgfactory/qtester.cxx new file mode 100644 index 000000000..eeb15e5fd --- /dev/null +++ b/tools/dlgfactory/qtester.cxx @@ -0,0 +1,38 @@ +// Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// +// This program can be used for unit test of dialog box. +// You just have to include the interface file (*.h) and +// use the dialog class as illustrated in the functions TEST_*. +// (gboulant - 12/10/2010) +// +#include +#include +#include "QDialogTest.hxx" + +void TEST_show() { + QDialogTest * dialog = new QDialogTest(); + dialog->show(); +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + TEST_show(); + return app.exec(); +} diff --git a/tools/vtkEDFOverloads/Makefile.am b/tools/vtkEDFOverloads/Makefile.am new file mode 100755 index 000000000..8d7853fb2 --- /dev/null +++ b/tools/vtkEDFOverloads/Makefile.am @@ -0,0 +1,40 @@ +# Copyright (C) 2007-2012 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 +# + +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +libparaview_LTLIBRARIES = libvtkEDFOverloads.la +lib_LTLIBRARIES = libvtkTools.la + +salomeinclude_HEADERS = vtkEDFCutter.h \ + vtkEDFFactory.h \ + vtkEDFOverloadsDefines.h + +dist_libvtkEDFOverloads_la_SOURCES = vtkEDFFactory.cxx +dist_libvtkTools_la_SOURCES = vtkEDFCutter.cxx + +libvtkEDFOverloads_la_CPPFLAGS = $(VTK_INCLUDES) +libvtkTools_la_CPPFLAGS = $(VTK_INCLUDES) + +libvtkEDFOverloads_la_LDFLAGS = $(VTK_LIBS) +libvtkEDFOverloads_la_LIBADD = libvtkTools.la +libvtkTools_la_LDFLAGS = $(VTK_LIBS) \ No newline at end of file diff --git a/tools/vtkEDFOverloads/vtkEDFCutter.cxx b/tools/vtkEDFOverloads/vtkEDFCutter.cxx new file mode 100755 index 000000000..3de2a04f8 --- /dev/null +++ b/tools/vtkEDFOverloads/vtkEDFCutter.cxx @@ -0,0 +1,526 @@ +// Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 "vtkEDFCutter.h" + +#include "vtkInformationVector.h" +#include "vtkInformation.h" +#include "vtkSmartPointer.h" +#include "vtkGenericCell.h" +#include "vtkPolyData.h" +#include "vtkObjectFactory.h" +#include "vtkIdTypeArray.h" +#include "vtkCellData.h" +#include "vtkCellArray.h" +#include "vtkIdList.h" + +#include +#include +#include +#include + +class vtkEDFEdge +{ +public : + vtkIdType v0; + vtkIdType v1; + + vtkEDFEdge(vtkIdType a, vtkIdType b) : v0(a), v1(b){} + vtkEDFEdge(){} +}; + +bool operator == (const vtkEDFEdge& e0, const vtkEDFEdge& e1) +{ + return (e0.v0 == e1.v0 && e0.v1 == e1.v1) || + (e0.v1 == e1.v0 && e0.v0 == e1.v1); +} + +bool operator != (const vtkEDFEdge& e0, const vtkEDFEdge& e1) +{ + return !(e0==e1); +} + +bool operator < (const vtkEDFEdge& e0, const vtkEDFEdge& e1) +{ + vtkEDFEdge the_e0; + vtkEDFEdge the_e1; + if(e0.v0 < e0.v1) + { + the_e0.v0 = e0.v0; + the_e0.v1 = e0.v1; + } + else + { + the_e0.v0 = e0.v1; + the_e0.v1 = e0.v0; + } + if(e1.v0 < e1.v1) + { + the_e1.v0 = e1.v0; + the_e1.v1 = e1.v1; + } + else + { + the_e1.v0 = e1.v1; + the_e1.v1 = e1.v0; + } + + if(the_e0.v0 == the_e1.v0) + return (the_e0.v1 < the_e1.v1); + + return the_e0.v0 < the_e1.v0; +} + +vtkStandardNewMacro(vtkEDFCutter); +vtkCxxRevisionMacro(vtkEDFCutter, "0.0"); + +vtkEDFCutter::vtkEDFCutter() +{ + this->OriginalCellIdsName = NULL; +} + +vtkEDFCutter::~vtkEDFCutter() +{ + this->SetOriginalCellIdsName(NULL); +} + +int vtkEDFCutter::RequestData(vtkInformation * request, + vtkInformationVector ** inVector, + vtkInformationVector * outVector) +{ + // get the info objects + vtkInformation *inInfo = inVector[0]->GetInformationObject(0); + vtkInformation *outInfo = outVector->GetInformationObject(0); + + // get the input and output + vtkDataSet *input = vtkDataSet::SafeDownCast( + inInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkSmartPointer cellIdArray = + vtkSmartPointer::New(); + cellIdArray->SetName(this->GetOriginalCellIdsName()); + cellIdArray->SetNumberOfComponents(1); + cellIdArray->SetNumberOfTuples(input->GetNumberOfCells()); + for(vtkIdType id=0; id < cellIdArray->GetNumberOfTuples(); id++) + { + cellIdArray->SetTuple1(id, id); + } + input->GetCellData()->AddArray(cellIdArray); + + int ret = this->Superclass::RequestData(request, inVector, outVector); + + if(ret == 0) + return 0; + + vtkPolyData *output = vtkPolyData::SafeDownCast( + outInfo->Get(vtkDataObject::DATA_OBJECT())); + + vtkSmartPointer tmpOutput; + tmpOutput.TakeReference(output->NewInstance()); + + this->AssembleOutputTriangles(output, tmpOutput); + + output->ShallowCopy(tmpOutput); + + return ret; +} + + +void vtkEDFCutter::AssembleOutputTriangles(vtkPolyData* inpd, + vtkPolyData* outpd) +{ + outpd->ShallowCopy(inpd); + + vtkIdTypeArray* originalCellIds = vtkIdTypeArray::SafeDownCast( + inpd->GetCellData()->GetArray(this->GetOriginalCellIdsName())); + + if(originalCellIds == NULL) + { + return; + } + + outpd->GetCellData()->Initialize(); + outpd->GetCellData()->CopyAllocate(inpd->GetCellData()); + + vtkSmartPointer verts = vtkSmartPointer::New(); + vtkSmartPointer lines = vtkSmartPointer::New(); + vtkSmartPointer polys = vtkSmartPointer::New(); + vtkSmartPointer strips = vtkSmartPointer::New(); + outpd->SetVerts(verts); + outpd->SetLines(lines); + outpd->SetPolys(polys); + outpd->SetStrips(strips); + + for(vtkIdType cellId=0; cellIdGetNumberOfCells(); cellId++) + { + unsigned char type = inpd->GetCellType(cellId); + if(type != VTK_TRIANGLE) + { + vtkIdType npts; + vtkIdType* pts = NULL; + inpd->GetCellPoints(cellId, npts, pts); + vtkIdType newCellId = + outpd->InsertNextCell(type, npts, pts); + outpd->GetCellData()->CopyData(inpd->GetCellData(), cellId, newCellId); + } + else + { + vtkIdType cellIdEnd = cellId+1; + vtkIdType originalCellId = originalCellIds->GetValue(cellId); + while(cellIdEnd < inpd->GetNumberOfCells() && + inpd->GetCellType(cellIdEnd) == VTK_TRIANGLE && + originalCellIds->GetValue(cellIdEnd) == originalCellId) + { + cellIdEnd++; + } + + // all triangles from cellId to cellIdEnd come from the same + // original cell. + + // A batch is composed of triangles which are connected by the edges. + std::map > connectedTriangles; + for(vtkIdType firstCell = cellId; firstCell < cellIdEnd-1; firstCell++) + { + vtkIdType npts; + vtkIdType* pts = NULL; + inpd->GetCellPoints(firstCell, npts, pts); + vtkEDFEdge fe0 = vtkEDFEdge(pts[0], pts[1]); + vtkEDFEdge fe1 = vtkEDFEdge(pts[1], pts[2]); + vtkEDFEdge fe2 = vtkEDFEdge(pts[2], pts[0]); + for(vtkIdType secondCell = firstCell+1; secondCell < cellIdEnd; secondCell++) + { + vtkIdType snpts; + vtkIdType* spts = NULL; + inpd->GetCellPoints(secondCell, snpts, spts); + vtkEDFEdge se0 = vtkEDFEdge(spts[0], spts[1]); + vtkEDFEdge se1 = vtkEDFEdge(spts[1], spts[2]); + vtkEDFEdge se2 = vtkEDFEdge(spts[2], spts[0]); + + if(fe0 == se0 || fe0 == se1 || fe0 == se2 || + fe1 == se0 || fe1 == se1 || fe1 == se2 || + fe2 == se0 || fe2 == se1 || fe2 == se2) + { + connectedTriangles[firstCell].insert(secondCell); + connectedTriangles[secondCell].insert(firstCell); + } + } + } + + std::set visitedCell; + for(vtkIdType id=cellId; id batch; + std::list cellList; + cellList.push_back(id); + while(cellList.size() > 0) + { + vtkIdType currentId = *(cellList.begin()); + batch.insert(currentId); + cellList.pop_front(); + if(connectedTriangles.find(currentId) != connectedTriangles.end()) + { + const std::set& adj = connectedTriangles[currentId]; + std::set::const_iterator it = adj.begin(); + while(it != adj.end()) + { + vtkIdType other = *it; + if(visitedCell.find(other) == visitedCell.end()) + { + cellList.push_back(other); + visitedCell.insert(other); + } + it++; + } + } + } + + + + // then I add this batch to the output, + // creating a unique cell for the whole batch. + + if(batch.size() == 1) + { + vtkIdType tid = *(batch.begin()); + vtkIdType npts; + vtkIdType* pts = NULL; + inpd->GetCellPoints(tid, npts, pts); + vtkIdType newCellId = + outpd->InsertNextCell(VTK_TRIANGLE, npts, pts); + outpd->GetCellData()->CopyData(inpd->GetCellData(), cellId, newCellId); + } + else if(batch.size() == 2) + { // two triangles connected together --> create a VTK_QUAD + vtkIdType fid = *(batch.begin()); + vtkIdType sid = *(batch.rbegin()); + vtkIdType fnpts; + vtkIdType* fpts = NULL; + inpd->GetCellPoints(fid, fnpts, fpts); + vtkIdType snpts; + vtkIdType* spts = NULL; + inpd->GetCellPoints(sid, snpts, spts); + + int findex = 0; + vtkIdType fv = fpts[findex]; + while(((fv == spts[0]) || + (fv == spts[1]) || + (fv == spts[2])) && findex < 3) + { + findex++; + fv = fpts[findex]; + } + if(findex == 3) + {// this is a degenerate case : one of the triangles use + // only 2 vertices + findex = 0; + } + int sindex = 0; + vtkIdType sv = spts[sindex]; + while(((sv == fpts[0]) || + (sv == fpts[1]) || + (sv == fpts[2])) && sindex < 3) + { + sindex++; + sv = spts[sindex]; + } + if(sindex == 3) + {// this is a degenerate case : one of the triangles use + // only 2 vertices + sindex = 0; + } + + vtkIdType pts[4]; + pts[0] = fpts[findex]; + pts[1] = fpts[(findex+1)%3]; + pts[2] = spts[sindex]; + pts[3] = fpts[(findex+2)%3]; + + vtkIdType newCellId = outpd->InsertNextCell(VTK_QUAD, 4, pts); + outpd->GetCellData()->CopyData(inpd->GetCellData(), cellId, newCellId); + } + else + { + std::deque contour; + + std::list toVisit; + std::set visited; + + toVisit.push_back(*(batch.begin())); + + std::set triedAgain; + + while(toVisit.size() > 0) + { + vtkIdType currentId = *(toVisit.begin()); + toVisit.pop_front(); + if(visited.find(currentId) != visited.end()) + continue; + + visited.insert(currentId); + const std::set& adj = connectedTriangles[currentId]; + std::set::const_iterator it = adj.begin(); + while(it != adj.end()) + { + vtkIdType adjid = *it; + it++; + if(visited.find(adjid) != visited.end()) + continue; + + toVisit.push_back(adjid); + } + + vtkIdType npts; + vtkIdType* pts = NULL; + inpd->GetCellPoints(currentId, npts, pts); + vtkEDFEdge edge[3] = {vtkEDFEdge(pts[0], pts[1]), + vtkEDFEdge(pts[1], pts[2]), + vtkEDFEdge(pts[2], pts[0])}; + + // special case : initialization of the contour + if(contour.size() == 0) + { + contour.push_back(edge[0]); + contour.push_back(edge[1]); + contour.push_back(edge[2]); + continue; + } + + // Find which edge of the contour + // is connected to the current triangle + int orient = 0; + std::deque::iterator contourit = contour.begin(); + bool found = false; + while(contourit != contour.end()) + { + vtkEDFEdge& e = *contourit; + for(orient = 0; orient<3; orient++) + { + if(e == edge[orient]) + { + found = true; + break; + } + } + if(found) + break; + + contourit++; + } + if(contourit == contour.end()) + {// this triangle is not connected to the current contour. + // put it back in the queue for later processing + if(triedAgain.find(currentId) == triedAgain.end()) + { + triedAgain.insert(currentId); + toVisit.push_back(currentId); + visited.erase(currentId); + continue; + } + else + { + vtkDebugMacro( << "triangle " << currentId + << "could not be added to the contour of the current batch"); + continue; + } + } + // if I reach this point, I will add the triangle to the contour + // --> the contour will be modified and I can try again + // to add the previously rejected triangles + triedAgain.clear(); + + // Now, merge the edges of the current triangle with + // the contour + vtkEDFEdge& tbeforeedge = edge[(orient+1)%3]; + vtkEDFEdge& tafteredge = edge[(orient+2)%3]; + + std::deque::iterator beforeit; + if(contourit == contour.begin()) + beforeit = contour.end()-1; + else + beforeit = contourit - 1; + vtkEDFEdge& beforeedge = *beforeit; + + std::deque::iterator afterit; + if(contourit == contour.end()-1) + afterit = contour.begin(); + else + afterit = contourit + 1; + vtkEDFEdge& afteredge = *afterit; + + if(beforeedge == tbeforeedge) + { + if(afteredge == tafteredge) + {// in this case, I am adding a triangle that is fully inside + // the contour. I need to remove the three edges from the + // contour. + if(contour.size() == 3) + { + contour.clear(); + } + else + { + std::deque::iterator lastit; + if(afterit == contour.end()-1) + lastit = contour.begin(); + else + lastit = afterit + 1; + + if(lastit < beforeit) + { + contour.erase(beforeit, contour.end()); + contour.erase(contour.begin(), lastit); + } + else + { + contour.erase(beforeit, lastit); + } + } + } + else + {// the edge before is the glued, remove the two adjacent edges + // and add the edge after + if(beforeit == contour.end()-1) + { + contour.erase(beforeit, contour.end()); + contour.erase(contour.begin(), contour.begin()+1); + contour.push_back(tafteredge); + } + else + { + int index = beforeit - contour.begin(); + contour.erase(beforeit, contourit+1); + contour.insert(contour.begin()+index, tafteredge); + } + } + } + else if(afteredge == tafteredge) + {// the edge after is glued, removed the two glued edges and add + // the edge new edge + if(contourit == contour.end() -1) + { + contour.erase(contour.end() - 1); + contour.erase(contour.begin()); + contour.push_back(tbeforeedge); + } + else + { + int index = contourit - contour.begin(); + contour.erase(contourit, afterit+1); + contour.insert(contour.begin()+index, tbeforeedge); + } + } + else + { + int index = contourit - contour.begin(); + contour.erase(contourit); + contour.insert(contour.begin()+index, tbeforeedge); + contour.insert(contour.begin()+index+1, tafteredge); + } + } + vtkSmartPointer ids = vtkSmartPointer::New(); + std::deque::iterator cit = contour.begin(); + while(cit != contour.end()) + { + vtkEDFEdge& e = *cit; + cit++; + ids->InsertNextId(e.v0); + } + + vtkIdType newCellId = outpd->InsertNextCell(VTK_POLYGON, ids); + outpd->GetCellData()->CopyData(inpd->GetCellData(), cellId, newCellId); + } + } + cellId = cellIdEnd - 1; + } + } +} + +void vtkEDFCutter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + + diff --git a/tools/vtkEDFOverloads/vtkEDFCutter.h b/tools/vtkEDFOverloads/vtkEDFCutter.h new file mode 100755 index 000000000..66cc6a9b6 --- /dev/null +++ b/tools/vtkEDFOverloads/vtkEDFCutter.h @@ -0,0 +1,62 @@ +// Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +#ifndef __vtkEDFCutter_h__ +#define __vtkEDFCutter_h__ + +#include "vtkEDFOverloadsDefines.h" +#include "vtkCutter.h" + +class VTKTOOLS_EXPORT vtkEDFCutter : public vtkCutter +{ +public : + static vtkEDFCutter* New(); + vtkTypeRevisionMacro(vtkEDFCutter, vtkCutter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // these ivars + // control the name given to the field in which the ids are written into. If + // set to NULL, then vtkOriginalCellIds or vtkOriginalPointIds (the default) + // is used, respectively. + vtkSetStringMacro(OriginalCellIdsName); + virtual const char *GetOriginalCellIdsName() { + return ( this->OriginalCellIdsName + ? this->OriginalCellIdsName : "vtkOriginalCellIds"); + } + +protected : + virtual int RequestData(vtkInformation *, + vtkInformationVector **, + vtkInformationVector *); + + virtual void AssembleOutputTriangles(vtkPolyData* inpd, + vtkPolyData* outpd); + + char* OriginalCellIdsName; + + vtkEDFCutter(); + ~vtkEDFCutter(); + +private: + vtkEDFCutter(const vtkEDFCutter&); // Not implemented. + void operator=(const vtkEDFCutter&); // Not implemented. +}; + +#endif //__vtkEDFCutter_h__ diff --git a/tools/vtkEDFOverloads/vtkEDFFactory.cxx b/tools/vtkEDFOverloads/vtkEDFFactory.cxx new file mode 100755 index 000000000..5f87f514c --- /dev/null +++ b/tools/vtkEDFOverloads/vtkEDFFactory.cxx @@ -0,0 +1,47 @@ +// Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 "vtkEDFFactory.h" +#include "vtkVersion.h" +#include "vtkEDFCutter.h" + +vtkStandardNewMacro(vtkEDFFactory); + +VTK_CREATE_CREATE_FUNCTION(vtkEDFCutter); + +vtkEDFFactory::vtkEDFFactory() +{ + this->RegisterOverride("vtkCutter", + "vtkEDFCutter", + "MergeTriangles", + 1, + vtkObjectFactoryCreatevtkEDFCutter); +} + +const char* vtkEDFFactory::GetVTKSourceVersion() +{ + return VTK_SOURCE_VERSION; +} + +const char* vtkEDFFactory::GetDescription() +{ + return "VTK EDF Factory"; +} + +VTK_FACTORY_INTERFACE_IMPLEMENT(vtkEDFFactory); diff --git a/tools/vtkEDFOverloads/vtkEDFFactory.h b/tools/vtkEDFOverloads/vtkEDFFactory.h new file mode 100755 index 000000000..6693070dc --- /dev/null +++ b/tools/vtkEDFOverloads/vtkEDFFactory.h @@ -0,0 +1,43 @@ +// Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +#ifndef __vtkEDFFactory_h +#define __vtkEDFFactory_h + +#include "vtkEDFOverloadsDefines.h" +#include "vtkObjectFactory.h" + +class VTKEDF_OVERLOADS_EXPORT vtkEDFFactory : public vtkObjectFactory +{ +public: +// Methods from vtkObject + vtkTypeMacro(vtkEDFFactory,vtkObjectFactory); + static vtkEDFFactory *New(); + + virtual const char* GetVTKSourceVersion(); + virtual const char* GetDescription(); +protected: + vtkEDFFactory(); +private: + vtkEDFFactory(const vtkEDFFactory&); // Not implemented. + void operator=(const vtkEDFFactory&); // Not implemented. +}; + +extern "C" VTK_EXPORT vtkObjectFactory* vtkLoad(); +#endif diff --git a/tools/vtkEDFOverloads/vtkEDFOverloadsDefines.h b/tools/vtkEDFOverloads/vtkEDFOverloadsDefines.h new file mode 100755 index 000000000..83e9348b7 --- /dev/null +++ b/tools/vtkEDFOverloads/vtkEDFOverloadsDefines.h @@ -0,0 +1,41 @@ +// Copyright (C) 2010-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// 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 +// + +#ifndef VTKEDF_OVERLOADS_DEFINES_H +#define VTKEDF_OVERLOADS_DEFINES_H + +#if defined WIN32 +# if defined VTKEDF_OVERLOADS_EXPORTS || defined vtkEDFOverloads_EXPORTS +# define VTKEDF_OVERLOADS_EXPORT __declspec( dllexport ) +# else +# define VTKEDF_OVERLOADS_EXPORT __declspec( dllimport ) +# endif + +# if defined VTKTOOLS_EXPORTS || defined vtkTools_EXPORTS +# define VTKTOOLS_EXPORT __declspec( dllexport ) +# else +# define VTKTOOLS_EXPORT __declspec( dllimport ) +# endif + +#else +# define VTKEDF_OVERLOADS_EXPORT +# define VTKTOOLS_EXPORT +#endif //WIN32 + +#endif //VTKEDF_OVERLOADS_DEFINES_H -- 2.39.2