From 313a04631c63078d01c2f643a53500ec549d034e Mon Sep 17 00:00:00 2001 From: prascle Date: Mon, 14 Apr 2008 09:42:08 +0000 Subject: [PATCH] merge from branch DEV tag mergeto_trunk_04apr08 --- Demo/Makefile.am | 5 +- Demo/echoSrv.cxx | 2 +- Makefile.am | 6 +- Misc/valgrind-python.supp | 29 + NEWS | 811 ++++ adm/unix/config_files/ac_cxx_option.m4 | 3 +- adm/unix/config_files/check_SALOME.m4 | 4 +- adm/unix/config_files/check_boost.m4 | 159 + adm/unix/config_files/check_expat.m4 | 6 +- adm/unix/config_files/check_htmlgen.m4 | 20 +- adm/unix/config_files/check_libxml.m4 | 19 +- adm/unix/config_files/check_omniorb.m4 | 9 +- adm/unix/config_files/check_qt.m4 | 47 +- adm/unix/config_files/thread.m4 | 222 +- adm/unix/make_begin.am | 18 +- adm/unix/make_end.am | 11 +- adm/unix/make_gui_begin.am | 2 + build_configure | 32 +- configure.in.base | 68 +- doc/Doxyfile.in | 9 +- doc/Makefile.am | 37 +- doc/classDiagram.png | Bin 0 -> 71406 bytes doc/createNodeCollaboration.png | Bin 0 -> 56987 bytes doc/engine.dox | 3 +- doc/hmi.dox | 29 + doc/python.dox | 4 +- doc/sequenceCreateNode.png | Bin 0 -> 35038 bytes doc/sources/footer.html | 10 + doc/sources/header.html | 13 + doc/undoCreateNodeCollaboration.png | Bin 0 -> 37887 bytes doc/yacs.dox | 30 +- doc/yacsloader.dox | 95 +- idl/Makefile.am | 25 +- idl/yacsgui.idl | 11 +- src/Makefile.am | 2 +- src/bases/Makefile.am | 3 + src/bases/Test/Makefile.am | 2 + src/bases/YacsTrace.hxx | 2 + src/bases/define.hxx | 3 +- src/bases/yacsconfig.h | 8 + src/engine/Any.cxx | 219 +- src/engine/Any.hxx | 54 +- src/engine/AnyInputPort.cxx | 8 +- src/engine/AnyInputPort.hxx | 2 +- src/engine/Bloc.cxx | 70 +- src/engine/Bloc.hxx | 18 +- src/engine/Catalog.cxx | 60 + src/engine/Catalog.hxx | 54 + src/engine/ComponentDefinition.cxx | 24 + src/engine/ComponentDefinition.hxx | 30 + src/engine/ComponentInstance.cxx | 15 +- src/engine/ComponentInstance.hxx | 15 +- src/engine/ComposedNode.cxx | 492 +- src/engine/ComposedNode.hxx | 61 +- src/engine/ConditionInputPort.cxx | 7 +- src/engine/ConditionInputPort.hxx | 4 +- src/engine/Container.cxx | 9 + src/engine/Container.hxx | 6 + src/engine/DataFlowPort.cxx | 5 - src/engine/DataFlowPort.hxx | 3 +- src/engine/DataNode.cxx | 26 + src/engine/DataNode.hxx | 35 + src/engine/DataPort.cxx | 5 + src/engine/DataPort.hxx | 16 +- src/engine/DataStreamPort.cxx | 14 +- src/engine/DataStreamPort.hxx | 5 +- src/engine/Dispatcher.cxx | 7 +- src/engine/DynParaLoop.cxx | 66 +- src/engine/DynParaLoop.hxx | 18 +- src/engine/ElementaryNode.cxx | 156 +- src/engine/ElementaryNode.hxx | 17 +- src/engine/Executor.cxx | 84 +- src/engine/Executor.hxx | 1 + src/engine/ForEachLoop.cxx | 35 +- src/engine/ForEachLoop.hxx | 18 +- src/engine/ForLoop.cxx | 12 - src/engine/ForLoop.hxx | 4 +- src/engine/InGate.hxx | 1 + src/engine/InPort.cxx | 3 + src/engine/InPort.hxx | 1 + src/engine/InlineNode.hxx | 2 + src/engine/InputDataStreamPort.hxx | 1 + src/engine/InputPort.cxx | 11 +- src/engine/InputPort.hxx | 19 +- src/engine/LinkInfo.cxx | 44 +- src/engine/LinkInfo.hxx | 7 +- src/engine/LogRecord.cxx | 47 + src/engine/LogRecord.hxx | 45 + src/engine/Logger.cxx | 95 + src/engine/Logger.hxx | 39 + src/engine/Loop.cxx | 73 +- src/engine/Loop.hxx | 35 +- src/engine/Makefile.am | 118 +- src/engine/Node.cxx | 182 +- src/engine/Node.hxx | 37 +- src/engine/OptimizerLoop.cxx | 42 +- src/engine/OptimizerLoop.hxx | 12 +- src/engine/OutGate.cxx | 6 + src/engine/OutGate.hxx | 3 +- src/engine/OutPort.cxx | 8 +- src/engine/OutPort.hxx | 3 + src/engine/OutputDataStreamPort.cxx | 17 + src/engine/OutputDataStreamPort.hxx | 1 + src/engine/OutputPort.cxx | 25 +- src/engine/OutputPort.hxx | 3 +- src/engine/Plugin/Makefile.am | 6 + src/engine/Port.cxx | 11 + src/engine/Port.hxx | 20 +- src/engine/Proc.cxx | 147 +- src/engine/Proc.hxx | 23 +- src/engine/RefCounter.cxx | 9 + src/engine/Runtime.cxx | 129 +- src/engine/Runtime.hxx | 23 +- src/engine/ServiceInlineNode.hxx | 1 + src/engine/ServiceNode.cxx | 15 +- src/engine/ServiceNode.hxx | 1 + src/engine/SharedPtr.hxx | 7 + src/engine/StaticDefinedComposedNode.cxx | 14 + src/engine/StaticDefinedComposedNode.hxx | 6 + src/engine/Switch.cxx | 118 +- src/engine/Switch.hxx | 38 +- src/engine/Test/Makefile.am | 12 +- .../Test/RuntimeForEngineIntegrationTest.cxx | 1 + src/engine/Test/ToyNode.cxx | 1 + src/engine/Test/engineIntegrationTest.cxx | 433 +- src/engine/Test/engineIntegrationTest.hxx | 23 + src/engine/Test/engineTest.cxx | 260 +- src/engine/Test/engineTest.hxx | 8 + src/engine/TypeCode.cxx | 200 +- src/engine/TypeCode.hxx | 50 +- src/engine/Visitor.cxx | 1 + src/engine/Visitor.hxx | 5 + src/engine/VisitorSaveSchema.cxx | 296 +- src/engine/VisitorSaveSchema.hxx | 5 + src/engine/VisitorSaveState.cxx | 31 +- src/engine/VisitorSaveState.hxx | 4 + src/engine/WhileLoop.cxx | 16 +- src/engine/WhileLoop.hxx | 8 +- src/engine/engtypemaps.i | 553 +++ src/engine/pilot.i | 1004 +--- src/engine/pypilot.i | 123 + src/gui/Makefile.am | 177 +- src/gui/YACSGui_BlockNodePage.cxx | 698 +++ src/gui/YACSGui_ComponentPage.cxx | 394 ++ src/gui/YACSGui_ContainerPage.cxx | 559 +++ src/gui/YACSGui_DataModel.cxx | 369 +- src/gui/YACSGui_DataModel.h | 40 +- src/gui/YACSGui_DataNodePage.cxx | 2416 ++++++++++ src/gui/YACSGui_DataObject.cxx | 102 +- src/gui/YACSGui_DataObject.h | 41 +- src/gui/YACSGui_DataTypePage.cxx | 388 ++ src/gui/YACSGui_Executor.cxx | 222 +- src/gui/YACSGui_Executor.h | 31 +- src/gui/YACSGui_ForEachLoopNodePage.cxx | 373 ++ src/gui/YACSGui_ForLoopNodePage.cxx | 331 ++ src/gui/YACSGui_Graph.cxx | 749 ++- src/gui/YACSGui_Graph.h | 52 +- src/gui/YACSGui_Graph_1.cxx | 1003 ++++ src/gui/YACSGui_InlineNodePage.cxx | 2188 +++++++++ src/gui/YACSGui_InputPanel.cxx | 1117 +++++ src/gui/YACSGui_InputPanel.h | 1039 +++++ src/gui/YACSGui_LinkPage.cxx | 124 + src/gui/YACSGui_LogViewer.h | 68 + src/gui/YACSGui_Module.cxx | 4063 ++++++++++++++--- src/gui/YACSGui_Module.h | 257 +- src/gui/YACSGui_Node.cxx | 206 +- src/gui/YACSGui_Node.h | 17 +- src/gui/YACSGui_NodePage.cxx | 616 +++ src/gui/YACSGui_Observer.cxx | 201 +- src/gui/YACSGui_Observer.h | 6 +- src/gui/YACSGui_PlusMinusGrp.cxx | 443 ++ src/gui/YACSGui_PlusMinusGrp.h | 162 + src/gui/YACSGui_PropertyPage.cxx | 128 + src/gui/YACSGui_RunMode.cxx | 170 +- src/gui/YACSGui_RunMode.h | 41 +- src/gui/YACSGui_SchemaPage.cxx | 449 ++ src/gui/YACSGui_Selection.cxx | 100 + src/gui/YACSGui_Selection.h | 45 + src/gui/YACSGui_ServiceNodePage.cxx | 1700 +++++++ src/gui/YACSGui_Swig.cxx | 19 +- src/gui/YACSGui_SwitchNodePage.cxx | 984 ++++ src/gui/YACSGui_Table.cxx | 1122 +++++ src/gui/YACSGui_Table.h | 418 ++ src/gui/YACSGui_TreeView.cxx | 2599 +++++++++++ src/gui/YACSGui_TreeView.h | 200 + src/gui/YACSGui_TreeViewItem.cxx | 3035 ++++++++++++ src/gui/YACSGui_TreeViewItem.h | 454 ++ src/gui/YACSGui_WhileLoopNodePage.cxx | 325 ++ src/gui/YACSGui_XMLDriver.cxx | 116 +- src/gui/YACSGui_XMLDriver.h | 119 +- src/gui/YACSGui_YACSORBContainerDialog.cxx | 279 ++ src/gui/blocknodepage.ui | 260 ++ src/gui/componentpage.ui | 169 + src/gui/containerpage.ui | 344 ++ src/gui/datanodepage.ui | 433 ++ src/gui/datatypepage.ui | 160 + src/gui/foreachloopnodepage.ui | 275 ++ src/gui/forloopnodepage.ui | 259 ++ src/gui/inlinenodepage.ui | 397 ++ src/gui/resources/SalomeApp.xml | 13 +- ...CSGuiCatalog.xml.in => YACSCatalog.xml.in} | 4 +- src/gui/resources/YACSGui_images.po | 83 - src/gui/resources/YACSGui_msg_en.po | 325 -- src/gui/resources/YACS_images.po | 276 ++ src/gui/resources/YACS_msg_en.po | 1001 ++++ src/gui/resources/arrange_nodes.png | Bin 0 -> 906 bytes src/gui/resources/block_node.png | Bin 0 -> 703 bytes src/gui/resources/breakpoints.png | Bin 0 -> 867 bytes src/gui/resources/breakpoints_active.png | Bin 0 -> 870 bytes src/gui/resources/component.png | Bin 0 -> 884 bytes .../resources/connect_to_batch_session.png | Bin 0 -> 974 bytes src/gui/resources/container.png | Bin 0 -> 817 bytes src/gui/resources/control_link.png | Bin 0 -> 439 bytes src/gui/resources/control_view.png | Bin 477 -> 532 bytes src/gui/resources/data_link.png | Bin 0 -> 440 bytes src/gui/resources/dataflow_view.png | Bin 0 -> 588 bytes src/gui/resources/datastream_view.png | Bin 0 -> 574 bytes src/gui/resources/execute_in_batch.png | Bin 0 -> 837 bytes src/gui/resources/icon_down.png | Bin 0 -> 149 bytes src/gui/resources/icon_insert.png | Bin 0 -> 184 bytes src/gui/resources/icon_minus.png | Bin 0 -> 173 bytes src/gui/resources/icon_plus.png | Bin 0 -> 197 bytes src/gui/resources/icon_select.png | Bin 0 -> 264 bytes src/gui/resources/icon_text.png | Bin 0 -> 184 bytes src/gui/resources/icon_up.png | Bin 0 -> 151 bytes src/gui/resources/in_port.png | Bin 0 -> 642 bytes src/gui/resources/load_execution_state.png | Bin 0 -> 756 bytes src/gui/resources/loop_node.png | Bin 0 -> 602 bytes src/gui/resources/new_batch_execution.png | Bin 0 -> 709 bytes src/gui/resources/new_block_node.png | Bin 0 -> 462 bytes src/gui/resources/new_corba_component.png | Bin 0 -> 706 bytes src/gui/resources/new_corba_service_node.png | Bin 0 -> 462 bytes src/gui/resources/new_cpp_node.png | Bin 0 -> 462 bytes src/gui/resources/new_edition.png | Bin 0 -> 624 bytes src/gui/resources/new_execution.png | Bin 0 -> 700 bytes src/gui/resources/new_for_loop_node.png | Bin 0 -> 462 bytes src/gui/resources/new_foreach_loop_node.png | Bin 0 -> 462 bytes src/gui/resources/new_from_library_node.png | Bin 0 -> 462 bytes .../resources/new_inline_function_node.png | Bin 0 -> 462 bytes src/gui/resources/new_inline_script_node.png | Bin 0 -> 462 bytes src/gui/resources/new_link.png | Bin 0 -> 430 bytes .../resources/new_nodenode_service_node.png | Bin 0 -> 462 bytes src/gui/resources/new_salome_component.png | Bin 0 -> 706 bytes src/gui/resources/new_salome_service_node.png | Bin 0 -> 462 bytes src/gui/resources/new_salomepy_component.png | Bin 0 -> 706 bytes src/gui/resources/new_service_inline_node.png | Bin 0 -> 462 bytes src/gui/resources/new_switch_loop_node.png | Bin 0 -> 462 bytes src/gui/resources/new_while_loop_node.png | Bin 0 -> 462 bytes src/gui/resources/new_xml_node.png | Bin 0 -> 462 bytes src/gui/resources/node.png | Bin 0 -> 559 bytes src/gui/resources/ob_bloc_node.png | Bin 0 -> 146 bytes src/gui/resources/ob_inline_node.png | Bin 0 -> 162 bytes src/gui/resources/ob_service_node.png | Bin 0 -> 156 bytes src/gui/resources/out_port.png | Bin 0 -> 754 bytes src/gui/resources/pause.png | Bin 0 -> 609 bytes src/gui/resources/reset.png | Bin 0 -> 1321 bytes src/gui/resources/resume.png | Bin 0 -> 879 bytes src/gui/resources/run.png | Bin 987 -> 1017 bytes src/gui/resources/run_active.png | Bin 0 -> 1018 bytes src/gui/resources/run_object.png | Bin 0 -> 619 bytes src/gui/resources/schema.png | Bin 0 -> 800 bytes src/gui/resources/step_by_step.png | Bin 896 -> 981 bytes src/gui/resources/step_by_step_active.png | Bin 0 -> 990 bytes src/gui/resources/stream_link.png | Bin 0 -> 439 bytes src/gui/resources/switch_node.png | Bin 0 -> 641 bytes src/gui/schemapage.ui | 372 ++ src/gui/servicenodepage.ui | 491 ++ src/gui/switchnodepage.ui | 287 ++ src/gui/whileloopnodepage.ui | 263 ++ src/hmi/Makefile.am | 118 + src/hmi/browseCatalog.cxx | 133 + src/hmi/browseCatalog.h | 65 + src/hmi/catalog.ui | 95 + src/hmi/chooseName.cxx | 51 + src/hmi/chooseName.h | 36 + src/hmi/commands.cxx | 86 + src/hmi/commands.hxx | 40 + src/hmi/commandsProc.cxx | 935 ++++ src/hmi/commandsProc.hxx | 400 ++ src/hmi/dichoosename.ui | 215 + src/hmi/editCanvas.cxx | 660 +++ src/hmi/editCanvas.h | 145 + src/hmi/editTree.cxx | 1155 +++++ src/hmi/editTree.h | 188 + src/hmi/guiContext.cxx | 171 + src/hmi/guiContext.hxx | 83 + src/hmi/guiObservers.cxx | 2774 +++++++++++ src/hmi/guiObservers.hxx | 706 +++ src/hmi/main.cxx | 305 ++ src/hmi/mainempty.ui | 444 ++ src/hmi/nodeEdition.cxx | 351 ++ src/hmi/nodeEdition.h | 74 + src/hmi/resources/editcopy.png | Bin 0 -> 248 bytes src/hmi/resources/editcut.png | Bin 0 -> 187 bytes src/hmi/resources/editpaste.png | Bin 0 -> 270 bytes src/hmi/resources/filenew.png | Bin 0 -> 173 bytes src/hmi/resources/fileopen.png | Bin 0 -> 210 bytes src/hmi/resources/filesave.png | Bin 0 -> 217 bytes src/hmi/resources/print.png | Bin 0 -> 725 bytes src/hmi/resources/redo.png | Bin 0 -> 173 bytes src/hmi/resources/searchfind.png | Bin 0 -> 662 bytes src/hmi/resources/undo.png | Bin 0 -> 172 bytes src/hmi/wiedittree.ui | 49 + src/hmi/winodeedition.ui | 161 + src/lineconn2d/Makefile.am | 8 +- src/prs/Makefile.am | 20 +- src/prs/YACSPrs_BlocNode.cxx | 242 +- src/prs/YACSPrs_BlocNode.h | 12 +- src/prs/YACSPrs_Def.h | 3 +- src/prs/YACSPrs_ElementaryNode.cxx | 1317 ++++-- src/prs/YACSPrs_ElementaryNode.h | 74 +- src/prs/YACSPrs_ForEachLoopNode.cxx | 254 +- src/prs/YACSPrs_ForEachLoopNode.h | 8 +- src/prs/YACSPrs_IfNode.cxx | 4 +- src/prs/YACSPrs_IfNode.h | 2 +- src/prs/YACSPrs_InlineNode.cxx | 103 +- src/prs/YACSPrs_InlineNode.h | 2 +- src/prs/YACSPrs_Link.cxx | 301 +- src/prs/YACSPrs_Link.h | 19 +- src/prs/YACSPrs_LoopNode.cxx | 347 +- src/prs/YACSPrs_LoopNode.h | 9 +- src/prs/YACSPrs_ServiceNode.cxx | 133 +- src/prs/YACSPrs_ServiceNode.h | 2 +- src/prs/YACSPrs_SwitchNode.cxx | 398 +- src/prs/YACSPrs_SwitchNode.h | 5 +- src/prs/YACSPrs_toString.cxx | 291 ++ src/prs/YACSPrs_toString.h | 41 + src/prs/resources/YACSPrs_images.po | 21 + src/prs/resources/ledgreen.png | Bin 0 -> 1265 bytes src/prs/resources/ledred.png | Bin 0 -> 1207 bytes src/pyqt/gui/Appli.py | 199 +- src/pyqt/gui/BoxManager.py | 34 + src/pyqt/gui/CItems.py | 170 +- src/pyqt/gui/CONNECTOR.py | 155 + src/pyqt/gui/GraphViewer.py | 154 +- src/pyqt/gui/Item.py | 30 +- src/pyqt/gui/Items.py | 467 +- src/pyqt/gui/PanelManager.py | 13 +- src/pyqt/gui/Tree.py | 69 +- src/pyqt/gui/adapt.py | 2 +- src/pyqt/gui/browser.py | 26 + src/pyqt/gui/browser_catalog.py | 24 + src/pyqt/gui/browser_session.py | 48 + src/pyqt/gui/cataitems.py | 271 ++ src/pyqt/gui/catalog.py | 84 + src/pyqt/gui/graph.py | 430 ++ src/pyqt/gui/logview.py | 46 + src/pyqt/gui/panels.py | 146 + src/pyqt/gui/sessions.py | 57 + src/pyqt/yacsedit.py | 1 + src/runtime/CORBAComponent.cxx | 4 +- src/runtime/CORBAComponent.hxx | 1 - src/runtime/CORBANode.cxx | 347 +- src/runtime/CORBANode.hxx | 3 + src/runtime/CORBAPorts.cxx | 162 +- src/runtime/CORBAPorts.hxx | 11 +- src/runtime/CORBAPythonConv.cxx | 52 +- src/runtime/CalStreamPort.cxx | 20 +- src/runtime/CalStreamPort.hxx | 1 + src/runtime/CppComponent.cxx | 12 +- src/runtime/CppComponent.hxx | 3 +- src/runtime/CppContainer.cxx | 11 +- src/runtime/CppContainer.hxx | 3 +- src/runtime/CppNode.cxx | 2 +- src/runtime/CppNode.hxx | 2 + src/runtime/CppPorts.cxx | 1 + src/runtime/CppPorts.hxx | 2 +- src/runtime/CppPythonConv.cxx | 13 +- src/runtime/Makefile.am | 108 +- src/runtime/NeutralCORBAConv.cxx | 24 +- src/runtime/NeutralCORBAConv.hxx | 2 +- src/runtime/NeutralPythonConv.cxx | 34 +- src/runtime/NeutralPythonConv.hxx | 2 - src/runtime/OutNode.cxx | 121 + src/runtime/OutNode.hxx | 30 + src/runtime/PresetNode.cxx | 91 + src/runtime/PresetNode.hxx | 29 + src/runtime/PresetPorts.cxx | 118 + src/runtime/PresetPorts.hxx | 53 + src/runtime/PyStdout.cxx | 113 + src/runtime/PyStdout.hxx | 16 + src/runtime/PythonCORBAConv.cxx | 54 +- src/runtime/PythonNode.cxx | 43 +- src/runtime/PythonNode.hxx | 2 + src/runtime/PythonPorts.cxx | 89 + src/runtime/PythonPorts.hxx | 7 +- src/runtime/RuntimeSALOME.cxx | 141 +- src/runtime/RuntimeSALOME.hxx | 36 +- src/runtime/SALOMEDispatcher.cxx | 19 +- src/runtime/SALOMEDispatcher.hxx | 4 +- src/runtime/SALOMERuntime.i | 134 +- src/runtime/SalomeComponent.cxx | 37 +- src/runtime/SalomeComponent.hxx | 2 +- src/runtime/SalomeContainer.cxx | 157 +- src/runtime/SalomeContainer.hxx | 9 + src/runtime/SalomeProc.cxx | 1 + src/runtime/SalomeProc.hxx | 1 + src/runtime/SalomePythonComponent.cxx | 1 + src/runtime/SalomePythonNode.cxx | 2 +- src/runtime/SessionCataLoader.cxx | 405 ++ src/runtime/SessionCataLoader.hxx | 32 + src/runtime/StudyNodes.cxx | 415 ++ src/runtime/StudyNodes.hxx | 43 + src/runtime/StudyPorts.cxx | 147 + src/runtime/StudyPorts.hxx | 54 + src/runtime/Test/Makefile.am | 26 +- src/runtime/Test/echo.idl | 1 + src/runtime/Test/echoSrv.cxx | 29 +- src/runtime/Test/echo_clt.cxx | 436 +- src/runtime/Test/runtimeTest.cxx | 12 +- src/runtime/Test/runtimeTest.sh | 10 + src/runtime/TypeConversions.cxx | 404 +- src/runtime/TypeConversions.hxx | 3 +- src/runtime/VisitorSaveSalomeSchema.cxx | 161 + src/runtime/VisitorSaveSalomeSchema.hxx | 28 + src/runtime/XMLCORBAConv.cxx | 12 +- src/runtime/XMLCORBAConv.hxx | 4 +- src/runtime/XMLCppConv.cxx | 10 +- src/runtime/XMLNeutralConv.cxx | 10 +- src/runtime/XMLNode.cxx | 10 +- src/runtime/XMLNode.hxx | 1 + src/runtime/XMLPythonConv.cxx | 9 +- src/salomeloader/ElementPath.py | 196 + src/salomeloader/ElementTree.py | 1254 +++++ src/salomeloader/Makefile.am | 3 +- src/salomeloader/graph.py | 83 + src/salomeloader/salomeloader.py | 742 +-- src/salomeloader/salomeloader.sh | 3 + src/salomeloader/samples/GeomGraph.xml | 496 ++ src/salomeloader/samples/GeomGraphGates.xml | 671 +++ .../samples/GeomGraphGates_py.xml | 754 +++ src/salomeloader/samples/GeomGraph_py.xml | 560 +++ src/salomeloader/samples/Graph_couronne.xml | 836 ++++ src/salomeloader/samples/testvisu20.xml | 494 ++ src/wrappergen/src/Makefile.am | 21 +- src/yacsloader/LoadState.cxx | 2 +- src/yacsloader/Makefile.am | 56 +- src/yacsloader/ProcCataLoader.cxx | 97 + src/yacsloader/ProcCataLoader.hxx | 30 + src/yacsloader/Test/Makefile.am | 32 +- .../Test/YacsLoaderInSessionTest.sh.in | 1 + .../Test/YacsLoaderInSessionTest2.sh.in | 26 +- src/yacsloader/Test/YacsLoaderTest.cxx | 16 + src/yacsloader/Test/YacsLoaderTest.hxx | 2 + src/yacsloader/Test/YacsLoaderTest.sh.in | 3 +- src/yacsloader/Test/echo.idl | 12 + src/yacsloader/Test/echoSrv.cxx | 61 +- src/yacsloader/Test/echoclt.py | 93 + src/yacsloader/Test/testEdit.py | 4 +- src/yacsloader/Test/testLoader.py | 10 +- src/yacsloader/blocParsers.hxx | 412 ++ src/yacsloader/codeParsers.cxx | 7 + src/yacsloader/codeParsers.hxx | 79 + src/yacsloader/containerParsers.cxx | 88 + src/yacsloader/containerParsers.hxx | 84 + src/yacsloader/dataParsers.cxx | 49 + src/yacsloader/dataParsers.hxx | 50 + src/yacsloader/driver.cxx | 95 +- src/yacsloader/linkParsers.hxx | 134 + src/yacsloader/loader.i | 77 +- src/yacsloader/loopParsers.hxx | 483 ++ src/yacsloader/nodeParsers.hxx | 580 +++ src/yacsloader/outputParsers.hxx | 214 + src/yacsloader/parserBase.cxx | 225 + src/yacsloader/parserBase.hxx | 78 + src/yacsloader/parsers.cxx | 2979 +----------- src/yacsloader/parsers.hxx | 75 +- src/yacsloader/portParsers.hxx | 118 + src/yacsloader/presetParsers.hxx | 218 + src/yacsloader/procParsers.hxx | 186 + src/yacsloader/propertyParsers.cxx | 23 + src/yacsloader/propertyParsers.hxx | 40 + src/yacsloader/rootParser.cxx | 44 + src/yacsloader/rootParser.hxx | 25 + src/yacsloader/samples/SchemaIOFile.xml | 43 + .../samples/SchemaInputOutputGeom.xml | 137 + src/yacsloader/samples/datanode0.xml | 36 + src/yacsloader/samples/err0.xml | 39 + src/yacsloader/samples/err1.xml | 41 + src/yacsloader/samples/err2.xml | 40 + src/yacsloader/samples/err3.xml | 66 + src/yacsloader/samples/f.data | 1 + src/yacsloader/samples/file1.xml | 79 + src/yacsloader/samples/gobj1.xml | 130 + src/yacsloader/samples/objref2.xml | 62 + src/yacsloader/samples/struct2.xml | 102 + src/yacsloader/samples/study1.xml | 44 + src/yacsloader/samples/triangle5error.xml | 267 ++ src/yacsloader/switchParsers.hxx | 343 ++ src/yacsloader/typeParsers.cxx | 294 ++ src/yacsloader/typeParsers.hxx | 155 + src/yacsloader/xmlParserBase.hxx | 2 + src/yacsloader/xmlrpcParsers.cxx | 278 ++ src/yacsloader/xmlrpcParsers.hxx | 158 + src/yacsorb/CORBAEngineTest.py | 124 + src/yacsorb/Makefile.am | 80 +- src/yacsorb/{YACSGui.py => YACS.py} | 80 +- src/yacsorb/yacsSrv.cxx | 5 +- src/yacsorb/yacs_clt.cxx | 1 + 499 files changed, 70357 insertions(+), 9128 deletions(-) create mode 100644 adm/unix/config_files/check_boost.m4 create mode 100644 doc/classDiagram.png create mode 100644 doc/createNodeCollaboration.png create mode 100644 doc/hmi.dox create mode 100644 doc/sequenceCreateNode.png create mode 100755 doc/sources/footer.html create mode 100755 doc/sources/header.html create mode 100644 doc/undoCreateNodeCollaboration.png create mode 100644 src/engine/Catalog.cxx create mode 100644 src/engine/Catalog.hxx create mode 100644 src/engine/ComponentDefinition.cxx create mode 100644 src/engine/ComponentDefinition.hxx create mode 100644 src/engine/DataNode.cxx create mode 100644 src/engine/DataNode.hxx create mode 100644 src/engine/LogRecord.cxx create mode 100644 src/engine/LogRecord.hxx create mode 100644 src/engine/Logger.cxx create mode 100644 src/engine/Logger.hxx create mode 100644 src/engine/engtypemaps.i create mode 100644 src/engine/pypilot.i create mode 100644 src/gui/YACSGui_BlockNodePage.cxx create mode 100644 src/gui/YACSGui_ComponentPage.cxx create mode 100644 src/gui/YACSGui_ContainerPage.cxx create mode 100644 src/gui/YACSGui_DataNodePage.cxx create mode 100644 src/gui/YACSGui_DataTypePage.cxx create mode 100644 src/gui/YACSGui_ForEachLoopNodePage.cxx create mode 100644 src/gui/YACSGui_ForLoopNodePage.cxx create mode 100644 src/gui/YACSGui_Graph_1.cxx create mode 100644 src/gui/YACSGui_InlineNodePage.cxx create mode 100644 src/gui/YACSGui_InputPanel.cxx create mode 100644 src/gui/YACSGui_InputPanel.h create mode 100644 src/gui/YACSGui_LinkPage.cxx create mode 100644 src/gui/YACSGui_LogViewer.h create mode 100644 src/gui/YACSGui_NodePage.cxx create mode 100644 src/gui/YACSGui_PlusMinusGrp.cxx create mode 100644 src/gui/YACSGui_PlusMinusGrp.h create mode 100644 src/gui/YACSGui_PropertyPage.cxx create mode 100644 src/gui/YACSGui_SchemaPage.cxx create mode 100644 src/gui/YACSGui_Selection.cxx create mode 100644 src/gui/YACSGui_Selection.h create mode 100644 src/gui/YACSGui_ServiceNodePage.cxx create mode 100644 src/gui/YACSGui_SwitchNodePage.cxx create mode 100644 src/gui/YACSGui_Table.cxx create mode 100644 src/gui/YACSGui_Table.h create mode 100644 src/gui/YACSGui_TreeView.cxx create mode 100644 src/gui/YACSGui_TreeView.h create mode 100644 src/gui/YACSGui_TreeViewItem.cxx create mode 100644 src/gui/YACSGui_TreeViewItem.h create mode 100644 src/gui/YACSGui_WhileLoopNodePage.cxx create mode 100644 src/gui/YACSGui_YACSORBContainerDialog.cxx create mode 100644 src/gui/blocknodepage.ui create mode 100644 src/gui/componentpage.ui create mode 100644 src/gui/containerpage.ui create mode 100644 src/gui/datanodepage.ui create mode 100644 src/gui/datatypepage.ui create mode 100644 src/gui/foreachloopnodepage.ui create mode 100644 src/gui/forloopnodepage.ui create mode 100644 src/gui/inlinenodepage.ui rename src/gui/resources/{YACSGuiCatalog.xml.in => YACSCatalog.xml.in} (87%) delete mode 100755 src/gui/resources/YACSGui_images.po delete mode 100755 src/gui/resources/YACSGui_msg_en.po create mode 100755 src/gui/resources/YACS_images.po create mode 100755 src/gui/resources/YACS_msg_en.po create mode 100644 src/gui/resources/arrange_nodes.png create mode 100644 src/gui/resources/block_node.png create mode 100644 src/gui/resources/breakpoints.png create mode 100644 src/gui/resources/breakpoints_active.png create mode 100644 src/gui/resources/component.png create mode 100644 src/gui/resources/connect_to_batch_session.png create mode 100644 src/gui/resources/container.png create mode 100644 src/gui/resources/control_link.png create mode 100644 src/gui/resources/data_link.png create mode 100644 src/gui/resources/dataflow_view.png create mode 100644 src/gui/resources/datastream_view.png create mode 100644 src/gui/resources/execute_in_batch.png create mode 100644 src/gui/resources/icon_down.png create mode 100755 src/gui/resources/icon_insert.png create mode 100755 src/gui/resources/icon_minus.png create mode 100755 src/gui/resources/icon_plus.png create mode 100755 src/gui/resources/icon_select.png create mode 100755 src/gui/resources/icon_text.png create mode 100644 src/gui/resources/icon_up.png create mode 100644 src/gui/resources/in_port.png create mode 100644 src/gui/resources/load_execution_state.png create mode 100644 src/gui/resources/loop_node.png create mode 100644 src/gui/resources/new_batch_execution.png create mode 100644 src/gui/resources/new_block_node.png create mode 100644 src/gui/resources/new_corba_component.png create mode 100644 src/gui/resources/new_corba_service_node.png create mode 100644 src/gui/resources/new_cpp_node.png create mode 100644 src/gui/resources/new_edition.png create mode 100644 src/gui/resources/new_execution.png create mode 100644 src/gui/resources/new_for_loop_node.png create mode 100644 src/gui/resources/new_foreach_loop_node.png create mode 100644 src/gui/resources/new_from_library_node.png create mode 100644 src/gui/resources/new_inline_function_node.png create mode 100644 src/gui/resources/new_inline_script_node.png create mode 100644 src/gui/resources/new_link.png create mode 100644 src/gui/resources/new_nodenode_service_node.png create mode 100644 src/gui/resources/new_salome_component.png create mode 100644 src/gui/resources/new_salome_service_node.png create mode 100644 src/gui/resources/new_salomepy_component.png create mode 100644 src/gui/resources/new_service_inline_node.png create mode 100644 src/gui/resources/new_switch_loop_node.png create mode 100644 src/gui/resources/new_while_loop_node.png create mode 100644 src/gui/resources/new_xml_node.png create mode 100644 src/gui/resources/node.png create mode 100644 src/gui/resources/ob_bloc_node.png create mode 100644 src/gui/resources/ob_inline_node.png create mode 100644 src/gui/resources/ob_service_node.png create mode 100644 src/gui/resources/out_port.png create mode 100644 src/gui/resources/pause.png create mode 100644 src/gui/resources/reset.png create mode 100644 src/gui/resources/resume.png create mode 100644 src/gui/resources/run_active.png create mode 100644 src/gui/resources/run_object.png create mode 100644 src/gui/resources/schema.png create mode 100644 src/gui/resources/step_by_step_active.png create mode 100644 src/gui/resources/stream_link.png create mode 100644 src/gui/resources/switch_node.png create mode 100644 src/gui/schemapage.ui create mode 100644 src/gui/servicenodepage.ui create mode 100644 src/gui/switchnodepage.ui create mode 100644 src/gui/whileloopnodepage.ui create mode 100644 src/hmi/Makefile.am create mode 100644 src/hmi/browseCatalog.cxx create mode 100644 src/hmi/browseCatalog.h create mode 100644 src/hmi/catalog.ui create mode 100644 src/hmi/chooseName.cxx create mode 100644 src/hmi/chooseName.h create mode 100644 src/hmi/commands.cxx create mode 100644 src/hmi/commands.hxx create mode 100644 src/hmi/commandsProc.cxx create mode 100644 src/hmi/commandsProc.hxx create mode 100644 src/hmi/dichoosename.ui create mode 100644 src/hmi/editCanvas.cxx create mode 100644 src/hmi/editCanvas.h create mode 100644 src/hmi/editTree.cxx create mode 100644 src/hmi/editTree.h create mode 100644 src/hmi/guiContext.cxx create mode 100644 src/hmi/guiContext.hxx create mode 100644 src/hmi/guiObservers.cxx create mode 100644 src/hmi/guiObservers.hxx create mode 100644 src/hmi/main.cxx create mode 100644 src/hmi/mainempty.ui create mode 100644 src/hmi/nodeEdition.cxx create mode 100644 src/hmi/nodeEdition.h create mode 100644 src/hmi/resources/editcopy.png create mode 100644 src/hmi/resources/editcut.png create mode 100644 src/hmi/resources/editpaste.png create mode 100644 src/hmi/resources/filenew.png create mode 100644 src/hmi/resources/fileopen.png create mode 100644 src/hmi/resources/filesave.png create mode 100644 src/hmi/resources/print.png create mode 100644 src/hmi/resources/redo.png create mode 100644 src/hmi/resources/searchfind.png create mode 100644 src/hmi/resources/undo.png create mode 100644 src/hmi/wiedittree.ui create mode 100644 src/hmi/winodeedition.ui create mode 100644 src/prs/YACSPrs_toString.cxx create mode 100644 src/prs/YACSPrs_toString.h create mode 100644 src/prs/resources/ledgreen.png create mode 100644 src/prs/resources/ledred.png create mode 100644 src/pyqt/gui/BoxManager.py create mode 100644 src/pyqt/gui/CONNECTOR.py create mode 100644 src/pyqt/gui/browser.py create mode 100644 src/pyqt/gui/browser_catalog.py create mode 100644 src/pyqt/gui/browser_session.py create mode 100644 src/pyqt/gui/cataitems.py create mode 100644 src/pyqt/gui/catalog.py create mode 100644 src/pyqt/gui/graph.py create mode 100644 src/pyqt/gui/logview.py create mode 100644 src/pyqt/gui/panels.py create mode 100644 src/pyqt/gui/sessions.py create mode 100644 src/runtime/OutNode.cxx create mode 100644 src/runtime/OutNode.hxx create mode 100644 src/runtime/PresetNode.cxx create mode 100644 src/runtime/PresetNode.hxx create mode 100644 src/runtime/PresetPorts.cxx create mode 100644 src/runtime/PresetPorts.hxx create mode 100644 src/runtime/PyStdout.cxx create mode 100644 src/runtime/PyStdout.hxx create mode 100644 src/runtime/SessionCataLoader.cxx create mode 100644 src/runtime/SessionCataLoader.hxx create mode 100644 src/runtime/StudyNodes.cxx create mode 100644 src/runtime/StudyNodes.hxx create mode 100644 src/runtime/StudyPorts.cxx create mode 100644 src/runtime/StudyPorts.hxx create mode 100644 src/runtime/VisitorSaveSalomeSchema.cxx create mode 100644 src/runtime/VisitorSaveSalomeSchema.hxx create mode 100644 src/salomeloader/ElementPath.py create mode 100644 src/salomeloader/ElementTree.py create mode 100644 src/salomeloader/graph.py create mode 100755 src/salomeloader/salomeloader.sh create mode 100644 src/salomeloader/samples/GeomGraph.xml create mode 100644 src/salomeloader/samples/GeomGraphGates.xml create mode 100644 src/salomeloader/samples/GeomGraphGates_py.xml create mode 100644 src/salomeloader/samples/GeomGraph_py.xml create mode 100644 src/salomeloader/samples/Graph_couronne.xml create mode 100644 src/salomeloader/samples/testvisu20.xml create mode 100644 src/yacsloader/ProcCataLoader.cxx create mode 100644 src/yacsloader/ProcCataLoader.hxx create mode 100644 src/yacsloader/Test/echoclt.py create mode 100644 src/yacsloader/blocParsers.hxx create mode 100644 src/yacsloader/codeParsers.cxx create mode 100644 src/yacsloader/codeParsers.hxx create mode 100644 src/yacsloader/containerParsers.cxx create mode 100644 src/yacsloader/containerParsers.hxx create mode 100644 src/yacsloader/dataParsers.cxx create mode 100644 src/yacsloader/dataParsers.hxx create mode 100644 src/yacsloader/linkParsers.hxx create mode 100644 src/yacsloader/loopParsers.hxx create mode 100644 src/yacsloader/nodeParsers.hxx create mode 100644 src/yacsloader/outputParsers.hxx create mode 100644 src/yacsloader/parserBase.cxx create mode 100644 src/yacsloader/parserBase.hxx create mode 100644 src/yacsloader/portParsers.hxx create mode 100644 src/yacsloader/presetParsers.hxx create mode 100644 src/yacsloader/procParsers.hxx create mode 100644 src/yacsloader/propertyParsers.cxx create mode 100644 src/yacsloader/propertyParsers.hxx create mode 100644 src/yacsloader/rootParser.cxx create mode 100644 src/yacsloader/rootParser.hxx create mode 100644 src/yacsloader/samples/SchemaIOFile.xml create mode 100644 src/yacsloader/samples/SchemaInputOutputGeom.xml create mode 100644 src/yacsloader/samples/datanode0.xml create mode 100644 src/yacsloader/samples/err0.xml create mode 100644 src/yacsloader/samples/err1.xml create mode 100644 src/yacsloader/samples/err2.xml create mode 100644 src/yacsloader/samples/err3.xml create mode 100644 src/yacsloader/samples/f.data create mode 100644 src/yacsloader/samples/file1.xml create mode 100644 src/yacsloader/samples/gobj1.xml create mode 100644 src/yacsloader/samples/objref2.xml create mode 100644 src/yacsloader/samples/struct2.xml create mode 100644 src/yacsloader/samples/study1.xml create mode 100644 src/yacsloader/samples/triangle5error.xml create mode 100644 src/yacsloader/switchParsers.hxx create mode 100644 src/yacsloader/typeParsers.cxx create mode 100644 src/yacsloader/typeParsers.hxx create mode 100644 src/yacsloader/xmlrpcParsers.cxx create mode 100644 src/yacsloader/xmlrpcParsers.hxx create mode 100644 src/yacsorb/CORBAEngineTest.py rename src/yacsorb/{YACSGui.py => YACS.py} (71%) diff --git a/Demo/Makefile.am b/Demo/Makefile.am index b29316e4d..b32490c4f 100644 --- a/Demo/Makefile.am +++ b/Demo/Makefile.am @@ -2,11 +2,14 @@ include $(top_srcdir)/adm/unix/make_begin.am BUILT_SOURCES = echoSK.cc schema.xml xmlrpcprog.py bin_PROGRAMS=echoSrv -echoSrv_SOURCES = echoSrv.cxx echoSK.cc +echoSrv_SOURCES = echoSrv.cxx +nodist_echoSrv_SOURCES = echoSK.cc echoSrv_CXXFLAGS = $(OMNIORB_INCLUDES) $(OMNIORB_CXXFLAGS) echoSrv_LDFLAGS = $(OMNIORB_LIBS) AM_CXXFLAGS = $(THREAD_DEF) +EXTRA_DIST = echo.idl schema_orig.xml xmlrpcprog_orig.py + schema.xml:schema_orig.xml cp $(srcdir)/schema_orig.xml schema.xml xmlrpcprog.py:xmlrpcprog_orig.py diff --git a/Demo/echoSrv.cxx b/Demo/echoSrv.cxx index e4752614f..a082cc45d 100644 --- a/Demo/echoSrv.cxx +++ b/Demo/echoSrv.cxx @@ -5,7 +5,7 @@ #include using namespace std; -#define _DEVDEBUG_ +//#define _DEVDEBUG_ #ifdef _DEVDEBUG_ #define MYDEBTRACE {std::cerr << __FILE__ << " [" << __LINE__ << "] : ";} #define DEBTRACE(msg) {MYDEBTRACE; std::cerr<> YACSGui_Graph::update +Graph: ADD node +== aTypeName = N4YACS6ENGINE4BlocE +th. 3050337968 - Trace /home/prascle/SALOME2/YACS/BR_OCC/YACS_SRC/src/gui/YACSGui_Graph.cxx [309] : YACSGui_Graph::update Bloc0 +YACSPrs_ElementaryNode::YACSPrs_ElementaryNode : Bloc0 +YACSPrs_BlocNode::YACSPrs_BlocNode +terminate called after throwing an instance of 'St9bad_alloc' + what(): St9bad_alloc + +comments: OCC: Could you, please, provide a schema sample, on which +this bug is reproduced? +EDF: +I generally load samples/bloc1.xml, and sometimes YACS enters in an infinite loop and consume the memory (swap). +I can't be more precise on the conditions of occurence. +OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 7 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_8jan08) +description: when creating schema from scratch, we do not have panel for node properties unless +we load another existing schema, then come back to the first schema. +comments: OCC: DONE. This functionality will be available from CVS today evening. +---------------------------------------------------------------------------------------------------- +Num-----: 8 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: in python node properties, the port creation works, but the other buttons (arrows...) +have a confusing behaviour, and lead sometimes to sigsegv. + +comments: OCC: DONE. Debugged. +EDF: No more SIGSEGV observed but the behaviour is strange. +Example: +Create a python script or function node, add 3 input dataflow ports a, b, c type int, double, string +Try to select input c. Only one column is selected. Use the arrow up. It looks like only the selected +column is switched with input b, not the entire line. Clik on the other items of the two lines. +Sometimes the entire line is switched (OK) sometimes not... Confusing behaviour, not always the same. +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 9 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: in python node properties, changing the name leads to abort +/home/prascle/SALOME2/YACS/BR_OCC/YACS_SRC/src/hmi/guiObservers.cxx [1038] : SubjectElementaryNode::addInputPort( 0x8552168, int, sds ) +terminate called after throwing an instance of 'YACS::Exception' + what(): node PyFunctiona is not a child of node bloc1.xml + +comments: OCC: Could you, please, provide a test scenario to reproduce +this bug? +EDF: +launch YACSGui +create new schema schema1 +add an inline script node +load samples/bloc1.xml +return to schema schema1 +in Node properties, create an inputport p and an outputport q (dataflow, double), +change PyScript0 in PyScripta and apply: +OCC: DONE +EDF: +Still observed a SIGSEGV when trying to rename a python node created following example 8 above. +(not systematic). +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 10 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_8jan08) +description: Node placement looks OK when there are no blocs, but there are problems of placement of +nodes inside the bloc (nodes are outside). When there are two levels of blocks (see bloc1.xml), +same problem, and the bloc in the inner level is not movable. When we move the outer bloc +to englobe the inner bloc, the canvas flickers. The rezize of the bloc have a very strange behaviour. +comments: OCC: Could you, please, provide a schema sample, on which +this bug is reproduced? +EDF: samples/bloc1.xml +EDF: Node placement from BR_OCC (january 7, 2008) works far better. I remove ordering in the BR_DEV +version (january 8, 2008) because it is possible to have link loops in YACS with loop nodes. See +yacsloader/samples/legendre7.xml. +---------------------------------------------------------------------------------------------------- +Num-----: 11 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_8jan08) +description: after loading bschema.xml, ports are not visibles in the node properties panel +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 12 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_8jan08) +description: in edition, Selection is not possible from canvas (highlight in tree, open properties...) +and selection in tree has no action on canvas. +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 13 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: When the bloc properties is open, there is a button to add nodes, that does not work. +(remove seems possible) +comments: OCC: Could you, please, provide a test scenario to reproduce +this bug? +EDF: +launch YACSGui +create new schema schema1 +add a block +load samples/bloc1.xml (to activate node properties) +return to schema schema1 +in bloc properties, Direct Children + (for add node) +a line number 1 appears in Direct Children with an empty node name +I don't know what to do after... +IMPORTANT NOTE: prefered way is to have a popup menu (add nodes) at bloc item in tree view (see 2). +Either the '+' button activate the same menu, or it must be grayed or removed. +OCC: DONE (see2) +EDF: button '+' in bloc properties, Direct Children is still active, it is still possible to try +to remove nodes from other buttons, with effect only on the property pannel. ==> this must be at least +grayed or removed if inactive) +EDF: I have finally understood the use of '+' button and selection, to move (reparent) a node, +idem with '-' button. It is not obvious to find how it works, but it works! +The main problem is if we forget to apply, there is no warning. +I don't know if it is possible to have tooltips on such buttons (or other kind of help) +comments: OCC: DONE, tooltips were added +EDF: still problems (unnecessary warning, abort) with warnings on apply on certain cases +scenario: Create several nodes and a block, move a node to the bloc and click on this node without apply. +abort on OK. +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 14 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: In general, there are too much buttons or menus that have no action, or very unclear. +these buttons must be either removed, or grayed if they corresponds to something in development. +comments: OCC: DONE +EDF: Still a list of confusing buttons or menus without effect or with an unknown behaviour... +OCC: Could you, please, provide a list of such buttons and menus? +EDF(PR): OK I will try to make some snapshots and mark the things I don't understand. +EDF: Well, you already have done a lot of cleaning in the last versions. There are still a few +things remaining. +1 buttons data flow view and data stream view do nothing (comment in source until implementation) +2 idem in schema property panel +3 menu create node/node node service does nothing (grayed or comment in source until implementation) +4 menu create node/from library does nothing (to be removed) +5 menu create node, from a component instance item in tree (does nothing, could be useful, to check) +6 search in python script, property panel does not work with qscintilla. Not very useful, could be + removed. +7 in execution mode, button "remote run, control" could be removed, provided execution mode radio buttons + and "stop on error" check button exist somewhere (the existing button "stop on error" is not clear: + is it a toggle ?). It should be possible to start an execution in a mode and switch to another mode + at any time during the execution (step by step / breakpoints / without stop). +EDF: 1,2,3,4,6: OK --- 5,7: NOK +comments: OCC: +5 DONE: 1) It is possible now to create a Salome service node +from a Salome component instance item selected in the edition tree +view. In such a case, we take the first method name from the catalog"s +service map as a default service for the created node. This method may +be changed later with help of the property page of service node. 2) It +is possible to create a Corba service node from a Corba component +instance selected in the edition tree view. But in such a case I have a +question: How can I retrieve a list of services from Corba component +instance? Is it possible? +EDF: CORBA nodes are not a priority. SALOME node are created with the first method, +but it is now impossible to change the method (that was too complicated and dangerous). +It still could be use as it is for components with one method. +7 DONE: The modes of schema execution ( without stop / breakpoints / +step by step ) were moved to the exclusive group of toggle buttons on +the execution toolbar. "Stop on error" toggle button is placed on the +execution toolbar too. The "remote run, control" button was removed. +EDF: execution mode left only in menu, not in toolbar (confusing: not an action) +---------------------------------------------------------------------------------------------------- +Num-----: 15 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: No tree view nor canvas for salome SUPERV files +comments: OCC: DONE +EDF: Loading seems OK for edition (tree view, canvas...) but execution tree view is not visible. + +---------------------------------------------------------------------------------------------------- +Num-----: 16 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08, but related bugs: 13) +description: When editing a node (for instance a python script), if we switch on another node without +apply, everything is lost... +(in guidemo, I used a qt stack of widget for properties, so each item have it's own instance. No specific +action necessary to keep values of each widget). Either something similar is reproduced, or a state +of modification is generated to ask for apply/cancel before switch (may be difficult to implement +properly...) +comments: OCC: OK, we will try to implement the second way: warn the user if he selects another object +without applying modifications (if modifications were really done) for the current object. +In such a case we will provide two possibilities: Apply - to apply modifications for the current object +and switch selection to the choosen object, Cancel - to lose modifications for the current object and +switch selection to the choosen object. Is it suitable for you? +EDF: yes +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 17 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: Confusing behaviour, when switching from execution to edition and reverse. +Example: create a new schema with 2 python script nodes, one producing to outputs double(a,b), the other +with 2 input double (a,b) and an output double (c) (script: c=a+b), create the 2 links a->a b->b and execute. +return to edition and create a third script node (r=p*q) and connect its inputs to outputs from the +previous nodes. +If you create a new execution (click on object browser, Schema1) you got the 3 nodes without the new links. +you have first to make apply on schema properties in edition : A state of modification is needed to ask +for apply changes before execution. +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 18 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: When switching from execution to edition and reverse, each execution may correspond to a modified +schema. Now, all executions are under the same item in object browser. There is no way to retrieve a +particular version of the schema corresponding to an execution. +The best thing to do is to create a new schema entry in object browser at the first modification of +an already executed schema, or, better, to force an explicit (visible) copy of an executed schema to allow +modifications. +comments: OCC: As we understand correctly, you want to have a possibility to open the schema corresponding +to any run object in the edition state (i.e. to create a new schema object in the object browser, +edition tree view and 2D view for it) to continue its modification and after that to create a new run object +based on the modified schema and execute it taking into account the last modifications. Is it right? +If yes, we think, that it may be done with help of e.g. "New edition" popup menu item on the run object +in the object browser (and/or the same toolbar button, as it was done for creation of a new execution). +EDF(PR): Yes, I think it is OK. To be complete, when a schema is executed, it must be impossible to modify +it without copy,to keep the coherence between the schema and it's execution. +comments: OCC: DONE +EDF: The schema is still modifiable after execution, but it is always possible to retreive the original +with "new edition" popup menu on execuction item (OK) +---------------------------------------------------------------------------------------------------- +Num-----: 19 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_10jan08) +description: abort on switch edition, menu add node, python node: + Switch::getChildByShortName : no default node defined for switch of name Switch0 +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 20 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: when export, save before execution... an incomplete schema there must be checks and warnings +comments: EDF: the error log is given on schema item in tree +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 21 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: when modifying 2 output ports, type double to int, in a pyscript node, only one modif +is taken into account when apply. +comments: OCC: Could you, please, provide a test scenario to reproduce this bug? +EDF: For instance, create a new schema, a pyscript node, add 2 inputs ports a and b type double and apply. +Then, change both type to int then apply, WITHOUT cliking elsewhere between the last combo box for type and +the apply button. +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 22 +status--: OK (not reproduced on BR_DEV mergefrom_BR_PR_29jan08) +description: abort on selection in canvas (after problem 21 above): +YACSGui_TreeView.cxx 474 if ( YACSGui_ReferenceViewItem* aRefItem = dynamic_cast( theItem ) ) +segfault in dynamic_cast +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 23 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: when zoom to fit area, click in a bloc, the bloc moves instead of an aera selection, +release the mouse button leads sometimes to abort. +comments: OCC: DONE +EDF: it works, but it looks like that it is not easy to do! +---------------------------------------------------------------------------------------------------- +Num-----: 24 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: schema is not automatically checked before execution +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 25 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: DSC ports are not displayed in node properties panel (for instance samples/calcium4) +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 26 +priority: 0 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08, item 4 remaining, and 5 to improve) +description: It must be possible to use data types from other nodes already loaded, or to get them +from catalogs. For instance, use GEOM_Object in a python node. +comments: + - 1 - the list of availables data types in ports must be updated +with all data types already available in the data types list of the +current schema, +OCC: DONE: At the current moment there are two ways to choose a port data +type: +1a) if the data type is a simple type the user can set it, even it is not +publicated in the edition tree view with help of combo box +available for the "Type" column in the edition mode; +1b) the complex data types may be choosen with help of the selection +control available for the "Type" column in the edition mode; in such a +case the user can pick directly a data type in the edition tree view. + - 2 - by default the list contains only simple types : bool, int, +double, string (other types are not usable in a generic form, they +must be specialised) OCC: DONE. + - 3 - the data type list of the schema is automatically updated +when importing nodes from catalogs. OCC: it is already done, because +of the edition tree view updates on importing nodes from catalog in +order to show all available data types inside the current schema. + - 4 - it should be possible also to specifically import a +particular data type from a catalog, by means of a popup on Data Types +Container in edition tree view. OCC: DONE. + - 5 - note that import node from catalog is not restricted to +SALOME service nodes. all kind of nodes can be imported from catalogs, +even python script nodes, taken from catalogs built apon other +schemas. + + With this approach list of data types does not grow too fast and +the combo box could still be used (warning, complex data types have +long names...). + Another possibility is to allow to pick directly a data type in a +catalog in the port definition, but it is not possible with the combo +box... +EDF: 5 DONE, with a problem of canvas representation when import composed nodes, that can only +be solved now by export and reimport the schema. The tree view for catalog from proc must reflect +the proc schema hierarchy (otherwise there could be confusion with nodes of the same name) +---------------------------------------------------------------------------------------------------- +Num-----: 27 +priority: 0 +status--: NOK +description: input ports must not be initialised automatically by default. +comments: +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 28 +status--: NOK +description: data nodes in and out, study in and study out, to implement +(to be created by the way of popup menu put in study, get from study, with path stored) +comments: +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 0 +status--: NOK +description: +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 1001 +priority: 1 +status--: NOK +description: only container "FactoryServerPy" works on OCN tests, instead of a C++ container. C++ +container works at EDF: There is a problem with the OCN distribution that may compromise SALOME +Application deployement. +comments: OCC: Could you, please, specify the launch options for YACSContainer? +EDF: Head of BR_DEV or BR_PR works with YACSContainer at EDF (with SALOME V4.1.0rc1 ou rc2) : +try, and please provide detailed diagnostic if it does not work on your configuration. +EDF: Is this working now ? +---------------------------------------------------------------------------------------------------- +Num-----: 1002 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: in create node menu, node node service is confusing. It is better to create a +service node, then to associate it with another node with which the component instance is shared. +comments: OCC: DONE. There are two ways now to set component to the +SALOME service node: with help of selection control from Input Panel +for the SALOME service node the user can set the component to the +selected service node 1) by selection a SALOME component in the +edition tree view, 2) by selection an another SALOME service node in +the edition tree view. +EDF: not clear without component instance names, it seems it does not work: +create a new schema with to salome service nodes from AddComponent. One instance of AddComponent is +created by default on DefaultContainer, for each node. OK. +It is not possible to change the component instance of node 2 to the other component instance +(selection control does nothing). +---------------------------------------------------------------------------------------------------- +Num-----: 1003 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: Is it possible to keep the center of the view at the same place when zooming the canvas ? +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 1004 +priority: 1 +status--: OK ( BR_DEV mergefrom_BR_PR_14feb08 : we keep the two kinds of default containers) +description: a default container is explicitely created when creating a component, but not when we +import a a schema. In YACS Engine, there is an implicit default container when nothing is defined. +There must not be two kind of default containers. +comments: +EDF: A possibility is to create explicitely a default container in YACS Engine and XML file. Not yet +decided, nothing to do now. +---------------------------------------------------------------------------------------------------- +Num-----: 1005 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_29jan08) +description: Mismatch in container names. We must distinguish: +- the name in YACS schema and xml file, useful to distinguish process (memory context). Lets call it + "Definition Name". +- the effective name of the container in execution (localhost/factoryServer) useful to retreive the + container with naming service, and particular to an execution. Lets call it "Execution Name". +The term "Definition Name" and "Execution Name" are used here for explanation, they may not be the appropriate +terms for gui. +in tree view, container must be referenced by it's definition name (lets say A, B, C) and not by it's +execution name (localhost/factoryServer). +Container properties panel must give the to names. The execution name (localhost/factoryServer) and +hostname can stay empty (resource manager job). +comments: EDF: Done +---------------------------------------------------------------------------------------------------- +Num-----: 1006 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08 - notes on 3,4, see above #13,#26) +description: popup menu item missing on tree view. +1 under Container directory: create a container definition +2 under Nodes directory: create a node +3 under Data Types directory: import a data type from catalog (required for use in a python node, for + instance) +4 under a salome node, create a node (here, it is easy to define a create a node corresponding to + a service of the same component instance (see 1002). +comments: +EDF : 1,2 done (on BR_PR branch) +---------------------------------------------------------------------------------------------------- +Num-----: 1007 +priority: 1 +status--: NOK +description: instead of having a dialog at execution to define the properties of the YACS Engine +container, put the parameters on the schema properties panel for execution. +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 1008 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: When switching from edition to execution, nodes and link arrangements are lost. +idem for view (zoom, panning). +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 1009 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: There is nothing to show the validity of a graph in edition, node by node. +A recursive validation node by node is required in engine (will probably be developed soon). +When this information will be available, it have to be represented in Gui (different color for items +in tree view, for instance). +When a node is modified, local impact on graph validity must be recomputed (Engine) and displayed +(gui notification). +comments: EDF DONE +---------------------------------------------------------------------------------------------------- +Num-----: 1010 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08, a little problem remains, node is not moveable) +description: in edition, when adding a node in a block, do not reorganize automatically nodes +(the user may prefer his own placement); do not resize the bloc, unless it is too small. +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 1011 +priority: 1 +status--: OK (checked on BR_DEV mergefrom_BR_PR_14feb08) +description: When adding a link between to nodes in a block, canvas is not always udpdated. +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 1012 +priority: 1 +status--: OK +description: in node properties, value type always set to double when clicking (must stay to its value) +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 1013 +priority: 1 +status--: NOK +description: Nodes with data stream ports must only be available by import from catalogs +comments: +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 1 +status--: NOK +description: +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 2001 +priority: 2 +status--: OK (checked on BR_DEV mergefrom_BR_PR_8jan08) +description: control gates on tree are useless, we can use directly the node itself. +(the idea is to have a lighter tree) +comments: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 2002 +priority: 2 +status--: NOK (checked on BR_DEV mergefrom_BR_PR_8jan08) +description: Link redrawing is globally OK, but sometimes the links are not visible because very +near the blocs borders. +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 2003 +priority: 2 +status--: NOK +description: strange behaviour to check +access to SALOME_ResourcesManager while browsing salome services in edition (calcium4) +access to Subject::detach when clicking in canvas : edition widget destroyed then recreated ? +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 2004 +priority: 2 +status--: NOK +description: add a panel property on a link: information on from node and to node. +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 2005 +priority: 2 +status--: NOK +description: add a panel property on Data Types: type id, content, associated classes... +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 2006 +priority: 2 +status--: NOK +description: +comments: +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 2 +status--: NOK +description: +comments: +---------------------------------------------------------------------------------------------------- + + +Problems detected by OCC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +---------------------------------------------------------------------------------------------------- +Num-----: 1 +priority: 0 +status--: OK +description: + -- Import test_schema.xml + -- Select "psnode14" => press "Apply" in opened dialog box +Result: Crash of application +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 2 +priority: 0 +status--: OK +description: + -- Import test_schema.xml + -- Select "psnode34" => press "Apply" in opened dialog box +Result: Fatal error (reference to object) +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 3 +priority: 0 +status--: OK +description: + -- Import test_schema.xml + -- Select "psnode33" => assign "Input Ports/p1../Value"=10, "Input Ports/obj../Value"=20 + -- Press "Apply" in opened dialog box +Result: Fatal error +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 4 +priority: 0 +status--: OK +description: Tree View isn't updated after changing of name of SALOME +component and old name of it is shown inspite of new name is stored in corresponding dialog box +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 5 +priority: 0 +status--: OK +description: + -- Import test_schema.xml + -- Select "bb1" => modify its parameters as: Case id Node name + 5 psnode33 + default n2 + 7 psnode32 + -- Press Apply button (warning message about deletion of "n2" is shown) + -- Press Yess button +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 6 +priority: 0 +status--: OK +description: + -- Import test_schema.xml + -- Select block node "bbb" => modify its parameters as: + · Delete "node4" from first line + · Create new line by "+" pressing + · Add "nnode0" + -- Press Apply button +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 7 +priority: 0 +status--: OK +description: + -- Import test_schema_last.xml + -- Select node "node1" => modify its parameters as: + · Change name + · Assign new valyes to X and Y + -- Press Apply button + -- Select in 2D Viewer block node"Sb1", for which previous node belongs +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 8 +priority: 0 +status--: OK +description: + -- Import schema bloc1.xml + -- Select b1 node + -- Add empty "Direct Children" row and press Apply button +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 9 +priority: 0 +status--: OK +description: + -- Import schema bloc1.xml + -- Select node1 + -- Add row for "Input Ports" + -- Select the row + -- Click "->" +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 10 +priority: 0 +status--: OK +description: + -- Import schema bloc1.xml + -- Select link inside node "b1" - popup - Add Point + -- If there is no fatal error SIGSEGV after this step - try next: popup - Delete Point +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 11 +priority: 0 +status--: OK +description: + -- Launch application + -- File - New + -- Activate YACS + -- Import schema => the "Import Schema" dialog is opened +Result: confusing "data" in "File name" and "Quick path" fields +comments: OCC: DONE. Fixed in YACS module by calling SUIT_FileDlg::getFileName(...) method with +correct arguments and setting the DATA_DIR environment variable to the directory +with schema samples. +---------------------------------------------------------------------------------------------------- +Num-----: 12 +priority: 0 +status--: OK +description: + -- Import schema double1.xml + -- Fit all +Result: three red broken links are in the viewer +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 13 +priority: 0 +status--: OK, but +description: + -- Import schema bloc1.xml + -- Fit all + -- Select node "b1" + -- Click "Apply" in the appeared "Input Panel" +BUG: node "b2" jumps on "node1" inside the "b1" +comments: OCC: DONE, but it is needed to avoid canvas flickers +---------------------------------------------------------------------------------------------------- +Num-----: 14 +priority: 0 +status--: OK +description: + -- Import forloop1.xml (any other graph) + -- Delete loop node (any other node) + -- Close 2D viewer +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 15 +priority: 0 +status--: OK +description: + -- Import bloc1.xml + -- Select node1 + -- Rename node1 as node3 + -- Select b1 block node + -- Add a new line for a new children with help of + button + -- Select node3 as a new child node + -- Press Apply button +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 16 +priority: 0 +status--: OK +description: Show log messages (error messages during schema import) in the Message Log +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 17 +priority: 0 +status--: OK +description: + -- Import test_schema.xml + -- Select bbb.b1 foreach loop node + -- Delete this node +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: 18 +priority: 0 +status--: NOK +description: Not systematic: change (activate) 2D view with help of tabs. +comments: +---------------------------------------------------------------------------------------------------- +Num-----: 19 +priority: 0 +status--: OK +description: + -- Import, for example, fschema.xml + -- Create a new execution + -- First of all try to activate popup menu on the node1 item in the + execution tree view +Result: SIGSEGV +comments: OCC: DONE +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 0 +status--: NOK +description: +comments: +---------------------------------------------------------------------------------------------------- +Num-----: +priority: 0 +status--: NOK +description: +comments: +---------------------------------------------------------------------------------------------------- diff --git a/adm/unix/config_files/ac_cxx_option.m4 b/adm/unix/config_files/ac_cxx_option.m4 index d1f43ea6a..33316314d 100644 --- a/adm/unix/config_files/ac_cxx_option.m4 +++ b/adm/unix/config_files/ac_cxx_option.m4 @@ -30,7 +30,8 @@ AC_DEFUN([AC_CXX_OPTION], [ cat > conftest.cxx < conftest.log 2>&1 + $CXX -o a.out $1 conftest.cxx > conftest.log 2>&1 + rm -f a.out var=`echo $1 | sed -e "s, .*$,," | sed -e "s,^-,,"` #CCRT if ! grep -e $var conftest.log > /dev/null 2>&1 ; then if grep -e $var conftest.log > /dev/null 2>&1 ; then diff --git a/adm/unix/config_files/check_SALOME.m4 b/adm/unix/config_files/check_SALOME.m4 index d3a43d675..9b40f827f 100644 --- a/adm/unix/config_files/check_SALOME.m4 +++ b/adm/unix/config_files/check_SALOME.m4 @@ -83,8 +83,8 @@ GUI_LDFLAGS="" GUI_CXXFLAGS="" AC_ARG_WITH(gui, - --with-salome_gui=DIR root directory path of SALOME GUI installation, - SALOME_GUI_DIR="$withval",SALOME_GUI_DIR="") + [ --with-gui=DIR root directory path of SALOME GUI installation], + [SALOME_GUI_DIR="$withval"],[SALOME_GUI_DIR=""]) if test "x${SALOME_GUI_DIR}" = "x" ; then # no --with-gui-dir option used diff --git a/adm/unix/config_files/check_boost.m4 b/adm/unix/config_files/check_boost.m4 new file mode 100644 index 000000000..27ae50c73 --- /dev/null +++ b/adm/unix/config_files/check_boost.m4 @@ -0,0 +1,159 @@ +dnl Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +dnl CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +dnl +dnl See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +dnl +dnl +dnl +AC_DEFUN([CHECK_BOOST],[ + +AC_CHECKING(for BOOST Library) + +AC_REQUIRE([ENABLE_PTHREADS])dnl + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +BOOST_CPPFLAGS="" +BOOST_LIBSUFFIX="-mt" +BOOST_LIBS="" + +AC_CHECKING(for BOOST location) +AC_ARG_WITH(boost, + [AC_HELP_STRING([--with-boost=DIR],[root directory path to BOOST library installation])], + [BOOSTDIR="$withval" + AC_MSG_RESULT("select $withval as path to BOOST library") + ]) + +if test "x${BOOSTDIR}" = "x" ; then + BOOSTDIR="/usr" +fi + +AC_MSG_RESULT(\$BOOSTDIR = ${BOOSTDIR}) + +CPPFLAGS_old="${CPPFLAGS}" +LIBS_old=$LIBS + +if test "x${BOOSTDIR}" != "x" ; then + BOOST_CPPFLAGS="-I${BOOSTDIR}/include" + BOOST_LIBS="-L${BOOSTDIR}/lib${LIB_LOCATION_SUFFIX}" +fi + +if test "x${BOOSTDIR}" = "x/usr" ; then + BOOST_CPPFLAGS="" + BOOST_LIBS="" +fi + +boost_ok=no +boost_headers_ok=no +boost_binaries_ok=no + +dnl BOOST headers +AC_CHECKING(for BOOST headers) +CPPFLAGS="${CPPFLAGS_old} ${BOOST_CPPFLAGS}" + +boost_include_dir_ok=yes +if test "x${BOOSTDIR}" != "x" ; then + AC_CHECK_FILE(${BOOSTDIR}/include/boost/shared_ptr.hpp, + boost_include_dir_ok=yes, + boost_include_dir_ok=no) +fi + +BOOST_PROGRAM_OPTIONS_LIB=no +if test "x${boost_include_dir_ok}" = "xyes" ; then + AC_CHECK_FILE(${BOOSTDIR}/include/boost/program_options.hpp, + BOOST_PROGRAM_OPTIONS_LIB=yes, + BOOST_PROGRAM_OPTIONS_LIB=no) +fi +AC_MSG_RESULT(for boost program_options tool: $BOOST_PROGRAM_OPTIONS_LIB) + +if test "x${boost_include_dir_ok}" = "xyes" ; then + AC_TRY_COMPILE([#include ], + [boost::shared_ptr(new int)], + boost_headers_ok=yes, + boost_headers_ok=no) +fi + +if test "x${boost_headers_ok}" = "xno" ; then + BOOST_CPPFLAGS="BOOST_CPPFLAGS_NOT_DEFINED" +else + AC_MSG_RESULT(\$BOOST_CPPFLAGS = ${BOOST_CPPFLAGS}) +fi +AC_MSG_RESULT(for boost headers: $boost_headers_ok) + +if test "x${boost_headers_ok}" = "xyes" ; then + dnl BOOST binaries + AC_CHECKING(for BOOST binaries) + boost_lib_dir_ok=yes + if test "x${BOOSTDIR}" != "x" ; then + AC_CHECK_FILE(${BOOSTDIR}/lib${LIB_LOCATION_SUFFIX}/libboost_thread${BOOST_LIBSUFFIX}.so, + boost_lib_dir_ok=yes, + boost_lib_dir_ok=no) + if test "x${boost_lib_dir_ok}" = "xno" ; then + BOOST_LIBSUFFIX="" + AC_CHECK_FILE(${BOOSTDIR}/lib${LIB_LOCATION_SUFFIX}/libboost_thread${BOOST_LIBSUFFIX}.so, + boost_lib_dir_ok=yes, + boost_lib_dir_ok=no) + fi + fi + if test "x${boost_lib_dir_ok}" = "xyes" ; then + LIBS="${LIBS_old} ${BOOST_LIBS} -lboost_thread${BOOST_LIBSUFFIX}" + AC_TRY_LINK([#include ], + [struct TBody{ void operator()(){} }; boost::thread(TBody())], + boost_binaries_ok=yes, + boost_binaries_ok=no) + if test "x${boost_binaries_ok}" = "xno" ; then + BOOST_LIBSUFFIX="" + LIBS="${LIBS_old} ${BOOST_LIBS} -lboost_thread${BOOST_LIBSUFFIX}" + AC_TRY_LINK([#include ], + [struct TBody{ void operator()(){} }; boost::thread(TBody())], + boost_binaries_ok=yes, + boost_binaries_ok=no) + fi + fi +fi + +if test "x${boost_binaries_ok}" = "xno" ; then + BOOST_LIBS="BOOST_LIBS_NOT_FOUND" + BOOST_LIBSUFFIX="-not-defined" +else + AC_MSG_RESULT(\$BOOST_LIBSUFFIX = ${BOOST_LIBSUFFIX}) + AC_MSG_RESULT(\$BOOST_LIBS = ${BOOST_LIBS}) +fi +AC_MSG_RESULT(for boost binaries: $boost_binaries_ok) + +CPPFLAGS="${CPPFLAGS_old}" +LIBS="${LIBS_old}" + +if test "x${boost_headers_ok}" = "xyes" ; then + if test "x${boost_binaries_ok}" = "xyes" ; then + boost_ok=yes + fi +fi + +AC_MSG_RESULT(for boost: $boost_ok) + +AC_SUBST(BOOST_CPPFLAGS) +AC_SUBST(BOOST_LIBSUFFIX) +AC_SUBST(BOOST_LIBS) +AC_SUBST(BOOST_PROGRAM_OPTIONS_LIB) + +AC_LANG_RESTORE + +])dnl + + diff --git a/adm/unix/config_files/check_expat.m4 b/adm/unix/config_files/check_expat.m4 index 98bb5d18e..679e357ec 100644 --- a/adm/unix/config_files/check_expat.m4 +++ b/adm/unix/config_files/check_expat.m4 @@ -3,17 +3,21 @@ AC_DEFUN([AC_CHECK_EXPAT],[ AC_CHECKING(for expat) +EXPAT_INCLUDES= AC_CHECK_HEADER(expat.h,expat_ok="yes",expat_ok="no") if test "x$expat_ok" = "xyes" then + EXPAT_LIBS="-lexpat" + LIBS_old=$LIBS AC_CHECK_LIB(expat,XML_ExpatVersionInfo, LIBS="-lexpat $LIBS",,) + LIBS=$LIBS_old fi AC_MSG_RESULT(for expat: $expat_ok) -EXPAT_LIBS=$LIBS AC_SUBST(EXPAT_LIBS) +AC_SUBST(EXPAT_INCLUDES) ])dnl dnl diff --git a/adm/unix/config_files/check_htmlgen.m4 b/adm/unix/config_files/check_htmlgen.m4 index 7130999b3..80a47984e 100644 --- a/adm/unix/config_files/check_htmlgen.m4 +++ b/adm/unix/config_files/check_htmlgen.m4 @@ -41,7 +41,7 @@ then DOXYGEN_WITH_PYTHON=yes DOXYGEN_WITH_STL=yes ;; - [1-9].[5-9]*) + [[1-9]].[[5-9]]*) DOXYGEN_WITH_PYTHON=yes DOXYGEN_WITH_STL=yes ;; @@ -60,8 +60,12 @@ dnl AC_SUBST(DOXYGEN) AC_SUBST(GRAPHVIZHOME) AC_SUBST(GRAPHVIZ_CPPFLAGS) AC_SUBST(GRAPHVIZ_LDFLAGS) +AC_SUBST(GRAPHVIZ_LIBADD) GRAPHVIZ_CPPFLAGS="" GRAPHVIZ_LDFLAGS="" +GRAPHVIZ_LIBADD="" + +AC_CHECKING([graphviz configuration]) graphviz_ok=yes dnl were is graphviz ? @@ -70,10 +74,24 @@ if test "x$DOT" = "x" ; then AC_MSG_WARN(graphviz not found) graphviz_ok=no else + GRAPHVIZ_PREFIX=`echo $DOT | sed -e "s,[[^/]]*$,,;s,/$,,;s,^$,.,"` + GRAPHVIZ_PREFIX=`echo $GRAPHVIZ_PREFIX | sed -e "s,[[^/]]*$,,;s,/$,,;s,^$,.,"` + GRAPHVIZHOME=$GRAPHVIZ_PREFIX + GRAPHVIZ_CPPFLAGS="-I${GRAPHVIZHOME}/include/graphviz" GRAPHVIZ_LDFLAGS="-L${GRAPHVIZHOME}/lib/graphviz" fi dnl AC_SUBST(DOT) +CPPFLAGS_old=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $GRAPHVIZ_CPPFLAGS" +old_graphviz="yes" +AC_CHECK_HEADERS(dotneato.h, old_graphviz="yes", old_graphviz="no") +if test "x$old_graphviz" = "xyes" ; then + GRAPHVIZ_LIBADD="-ldotneato" +else + GRAPHVIZ_LIBADD="-lgvc" +fi +CPPFLAGS=$CPPFLAGS_old AC_PATH_PROG(LATEX,latex) if test "x$LATEX" = "x" ; then diff --git a/adm/unix/config_files/check_libxml.m4 b/adm/unix/config_files/check_libxml.m4 index bc43b4902..eaa329e14 100644 --- a/adm/unix/config_files/check_libxml.m4 +++ b/adm/unix/config_files/check_libxml.m4 @@ -3,17 +3,27 @@ AC_DEFUN([AC_CHECK_LIBXML],[ AC_CHECKING(for libxml) +CPPFLAGS_old=$CPPFLAGS +CXXFLAGS_old=$CXXFLAGS + # Custom location of libxml2 package can be specified # thorugh LIBXML_DIR variable if test "x$LIBXML_DIR" != "x" then CPPFLAGS="$CPPFLAGS -I$LIBXML_DIR/include/libxml2" CXXFLAGS="$CXXFLAGS -I$LIBXML_DIR/include/libxml2" - TMPLIBS="-L$LIBXML_DIR/lib -lxml2 $LIBS" + if test "x$LIBXML_DIR" = "x/usr" + then + TMPLIBS="-lxml2 $LIBS" + else + TMPLIBS="-L$LIBXML_DIR/lib -lxml2 $LIBS" + fi + LIBXML_INCLUDES="-I$LIBXML_DIR/include/libxml2" else CPPFLAGS="$CPPFLAGS -I/usr/include/libxml2" CXXFLAGS="$CXXFLAGS -I/usr/include/libxml2" TMPLIBS="-lxml2 $LIBS" + LIBXML_INCLUDES="-I/usr/include/libxml2" fi AC_CHECK_HEADER(libxml/parser.h,libxml_ok="yes",libxml_ok="no") @@ -28,13 +38,16 @@ fi if test "x$libxml_ok" = "xyes" then - LIBS=$TMPLIBS + LIBXML_LIBS=$TMPLIBS fi AC_MSG_RESULT(for libxml: $libxml_ok) -LIBXML_LIBS=$LIBS +CXXFLAGS=$CXXFLAGS_old +CPPFLAGS=$CPPFLAGS_old + AC_SUBST(LIBXML_LIBS) +AC_SUBST(LIBXML_INCLUDES) ])dnl dnl diff --git a/adm/unix/config_files/check_omniorb.m4 b/adm/unix/config_files/check_omniorb.m4 index 33c322c37..516f7aec0 100644 --- a/adm/unix/config_files/check_omniorb.m4 +++ b/adm/unix/config_files/check_omniorb.m4 @@ -17,7 +17,7 @@ AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_PATH_PROG(OMNIORB_IDL, omniidl) -if test "xOMNIORB_IDL" = "x" +if test "x$OMNIORB_IDL" = "x" then omniORB_ok=no AC_MSG_RESULT(omniORB binaries not in PATH variable) @@ -85,19 +85,19 @@ then AC_LANG_CPLUSPLUS AC_CHECK_HEADER(CORBA.h,omniORB_ok="yes",omniORB_ok="no") -dnl CPPFLAGS=$CPPFLAGS_old + CPPFLAGS=$CPPFLAGS_old fi -dnl omniORB_ok=yes - if test "x$omniORB_ok" = "xyes" then if test "x$OMNIORB_LIB" = "x/usr/lib" then OMNIORB_LDFLAGS="" + OMNIORB_RFLAGS="" else OMNIORB_LDFLAGS="-L$OMNIORB_LIB" + OMNIORB_RFLAGS="-R$OMNIORB_LIB" fi LIBS_old=$LIBS @@ -141,6 +141,7 @@ then OMNIORB_LIBS="$OMNIORB_LIBS -lCOS${OMNIORB_VERSION}" OMNIORB_LIBS="$OMNIORB_LIBS -lCOSDynamic${OMNIORB_VERSION}" OMNIORB_LIBS="$OMNIORB_LIBS -lomnithread" + OMNIORB_LIBS="$OMNIORB_LIBS ${OMNIORB_RFLAGS}" if test $OMNIORB_VERSION = 3 ; then OMNIORB_LIBS="$OMNIORB_LIBS -ltcpwrapGK" fi diff --git a/adm/unix/config_files/check_qt.m4 b/adm/unix/config_files/check_qt.m4 index 0472d93dd..ab2eff148 100755 --- a/adm/unix/config_files/check_qt.m4 +++ b/adm/unix/config_files/check_qt.m4 @@ -127,7 +127,9 @@ then fi CXXFLAGS_old=$CXXFLAGS + CPPFLAGS_old=$CPPFLAGS CXXFLAGS="$CXXFLAGS $QT_INCLUDES" + CPPFLAGS="$CPPFLAGS $QT_INCLUDES" AC_CACHE_VAL(salome_cv_lib_qt,[ AC_TRY_LINK( @@ -164,25 +166,50 @@ then AC_MSG_RESULT(QTDIR environment variable may be wrong) else AC_MSG_RESULT(yes) - QT_LIBS="-L$QTDIR/lib -lqt-mt" - QT_MT_LIBS="-L$QTDIR/lib -lqt-mt" + QT_LDFLAGS="-L$QTDIR/lib" + QT_LIBADD=" -lqt-mt" + QT_MT_LDFLAGS="-L$QTDIR/lib" + QT_MT_LIBADD=" -lqt-mt" fi # END: for CCRT else AC_MSG_RESULT(yes) + QT_LIBADD=" -lqt-mt" + QT_MT_LIBADD=" -lqt-mt" if test "x$QTDIR" = "x/usr" then - QT_LIBS=" -lqt-mt" - QT_MT_LIBS=" -lqt-mt" + QT_LDFLAGS="" + QT_MT_LDFLAGS="" else - QT_LIBS="-L$QTDIR/lib${LIB_LOCATION_SUFFIX} -lqt-mt" - QT_MT_LIBS="-L$QTDIR/lib${LIB_LOCATION_SUFFIX} -lqt-mt" + QT_LDFLAGS="-L$QTDIR/lib${LIB_LOCATION_SUFFIX}" + QT_MT_LDFLAGS="-L$QTDIR/lib${LIB_LOCATION_SUFFIX}" fi fi + AC_SUBST(QSCINTILLA_CCPFLAGS) + AC_SUBST(QSCINTILLA_LIBADD) + QSCINTILLA_CCPFLAGS="" + QSCINTILLA_LIBADD="" + + AC_LANG_CPLUSPLUS + CPPFLAGS="$CPPFLAGS -I$QTDIR/include/qscintilla" + AC_CHECK_HEADERS(qextscintilla.h, qscintilla="yes", qscintilla="no") + if test "x$qscintilla" = "xyes" ; then + QSCINTILLA_CCPFLAGS="-I$QTDIR/include/qscintilla" + QSCINTILLA_LIBADD="-lqscintilla" + else + CPPFLAGS="$CPPFLAGS -I/usr/include/qscintilla" + AC_CHECK_HEADERS(/usr/include/qscintilla/qextscintilla.h, + [qscintilla="yes"; QSCINTILLA_CCPFLAGS="-I/usr/include/qscintilla"; QSCINTILLA_LIBADD="-lqscintilla"], + [qscintilla="no"]) + fi + if test "x$qscintilla" = "xyes" ; then + AC_DEFINE(HAVE_QEXTSCINTILLA_H,,[With scintilla]) + fi + LIBS=$LIBS_old CXXFLAGS=$CXXFLAGS_old - + CPPFLAGS=$CPPFLAGS_old fi AC_SUBST(MOC) @@ -191,8 +218,10 @@ AC_SUBST(UIC) AC_SUBST(QT_ROOT) AC_SUBST(QT_INCLUDES) AC_SUBST(QT_MT_INCLUDES) -AC_SUBST(QT_LIBS) -AC_SUBST(QT_MT_LIBS) +AC_SUBST(QT_LDFLAGS) +AC_SUBST(QT_MT_LDFLAGS) +AC_SUBST(QT_LIBADD) +AC_SUBST(QT_MT_LIBADD) AC_SUBST(QT_VERS) AC_LANG_RESTORE diff --git a/adm/unix/config_files/thread.m4 b/adm/unix/config_files/thread.m4 index 4724dbc61..e607e13e9 100755 --- a/adm/unix/config_files/thread.m4 +++ b/adm/unix/config_files/thread.m4 @@ -1,4 +1,4 @@ -# Check presence of "CPPUNIT" product presence +# Check presence of "threads" # # Author : Anthony GEAY (CEA, 2006) # @@ -22,3 +22,223 @@ AC_LANG_RESTORE AC_MSG_RESULT(for THREADs: $thread_ok) ])dnl + +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all, and "pthread-config" +# which is a program returning the flags for the Pth emulation library. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case "${host_cpu}-${host_os}" in + *linux*) + + # On linux "none" works, but boost requires -pthread, so, try first "-pthread" +acx_pthread_flags="-pthread pthreads none -Kthread -kthread lthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + ;; + + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthread or + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + pthread-config) + AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) + if test x"$acx_pthread_config" = xno; then continue; fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: threads are created detached by default + # and the JOINABLE attribute has a nonstandard name (UNDETACHED). + AC_MSG_CHECKING([for joinable pthread attribute]) + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_JOINABLE;], + ok=PTHREAD_CREATE_JOINABLE, ok=unknown) + if test x"$ok" = xunknown; then + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_UNDETACHED;], + ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) + fi + if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then + AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, + [Define to the necessary symbol if this constant + uses a non-standard name on your system.]) + fi + AC_MSG_RESULT(${ok}) + if test x"$ok" = xunknown; then + AC_MSG_WARN([we do not know how to create joinable pthreads]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with cc_r + AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD + + +AC_DEFUN([ENABLE_PTHREADS],[ +AC_REQUIRE([ACX_PTHREAD]) + +if test x"$enable_pthreads_done" != xyes; then + if test x"$acx_pthread_ok" = xyes; then + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" + LIBS="$LIBS $PTHREAD_LIBS" + threads_ok=yes + else + threads_ok=no + fi + enable_pthreads_done=yes +fi +])dnl diff --git a/adm/unix/make_begin.am b/adm/unix/make_begin.am index 928083b95..4ca69a14c 100755 --- a/adm/unix/make_begin.am +++ b/adm/unix/make_begin.am @@ -3,16 +3,18 @@ ## # Standard directory for installation -salomeincludedir = $(includedir)/@PACKAGE@ -libdir = $(prefix)/lib@LIB_LOCATION_SUFFIX@/@PACKAGE@ -bindir = $(prefix)/bin/@PACKAGE@ +salomeincludedir = $(includedir)/salome +libdir = $(prefix)/lib@LIB_LOCATION_SUFFIX@/salome +bindir = $(prefix)/bin/salome salomescriptdir = $(bindir) +salomepythondir = $(pythondir)/salome +salomepyexecdir = $(pyexecdir)/salome # Directory for installing idl files -salomeidldir = $(prefix)/idl/@PACKAGE@ +salomeidldir = $(prefix)/idl/salome # Directory for installing resource files -salomeresdir = $(prefix)/share/@PACKAGE@/resources/@MODULE_NAME@ +salomeresdir = $(prefix)/share/salome/resources/@MODULE_NAME@ # Directories for installing admin files admlocaldir = $(prefix)/adm_local @@ -20,12 +22,10 @@ admlocalunixdir = $(admlocaldir)/unix admlocalm4dir = $(admlocaldir)/unix/config_files # Shared modules installation directory -sharedpkgpythondir =$(pkgpythondir)/shared_modules +sharedpkgpythondir =$(salomepythondir)/shared_modules # Documentation directory -docdir = $(datadir)/doc/@PACKAGE@ - -EXTRA_DIST = $(wildcard $(srcdir)/*.hxx) $(wildcard $(srcdir)/*.h) +docdir = $(datadir)/doc/salome # Gui specific makefile variable (not needed for base, engine, runtime parts) # To improve diff --git a/adm/unix/make_end.am b/adm/unix/make_end.am index 5102c67ee..feb991451 100755 --- a/adm/unix/make_end.am +++ b/adm/unix/make_end.am @@ -10,14 +10,11 @@ SUFFIXES += .i WRAP.cxx .idl .hh SK.cc _idl.py .iWRAP.cxx : $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) $(MYSWIG_FLAGS) -o $@ $< -.idlSK.cc: - $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx $< - -.idl.hh: - $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx $< +%SK.cc %.hh:%.idl + $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) $(IDLCXXFLAGS) -bcxx $< .idl_idl.py: - $(OMNIORB_IDL) -bpython $(IDLPYFLAGS) $< + $(OMNIORB_IDL) $(OMNIORB_IDLPYFLAGS) $(IDLPYFLAGS) $< # -------------------------------------------- # *.h --> *_moc.cxx @@ -26,7 +23,7 @@ SUFFIXES += .i WRAP.cxx .idl .hh SK.cc _idl.py SUFFIXES += .h _moc.cxx .h_moc.cxx : - $(MOC) -o $@ $< + $(MOC) -p . -o $@ $< clean-local-h2Moc : rm -f *_moc.cxx diff --git a/adm/unix/make_gui_begin.am b/adm/unix/make_gui_begin.am index fa551e451..aa0aa2291 100755 --- a/adm/unix/make_gui_begin.am +++ b/adm/unix/make_gui_begin.am @@ -1,5 +1,7 @@ # .qm translator files and icons +POFILES = +ICONS = QMFILES = $(POFILES:%.po=%.qm) #resourcesdir = $(pkgdatadir)/resources #resources_DATA = $(QMFILES) $(ICONS) diff --git a/build_configure b/build_configure index c690a8974..3758a6070 100755 --- a/build_configure +++ b/build_configure @@ -1,12 +1,6 @@ #! /bin/sh # -- -# -PROJECT="salome" -VERSION=4.0.0 -XVERSION=0x040000 -MODULE_NAME="yacsgui" - # -- ORIG_DIR=`pwd` run() { @@ -26,40 +20,16 @@ run() { CONF_DIR=`echo $0 | sed -e "s,[^/]*$,,;s,/$,,;s,^$,.,"` cd ${CONF_DIR} -# -- -# -- list all Makefile.am in Makefile.am.list -./rfind . Makefile.am > Makefile.am.list - # -- # -- configure.in construction rm -f configure.in touch configure.in -#echo "AC_INIT(src)" >> configure.in -echo "AC_INIT($PROJECT,$VERSION)" >> configure.in -echo "RELEASE=$VERSION" >> configure.in -echo "PROJECT=$PROJECT" >> configure.in -echo "PACKAGE=$PROJECT" >> configure.in -echo "MODULE_NAME=$MODULE_NAME" >> configure.in cat configure.in.base >> configure.in -echo "AC_OUTPUT([ \\" >> configure.in - -sed -e 's,\.am, \\,' -e 's,\.\/,,' Makefile.am.list >> configure.in - -echo " src/yacsloader/Test/YacsLoaderTest.sh \\" >> configure.in -echo " src/yacsloader/Test/YacsLoaderInSessionTest.sh \\" >> configure.in -echo " src/yacsloader/Test/YacsLoaderInSessionTest2.sh \\" >> configure.in -echo " src/yacsloader/Test/display.sh \\" >> configure.in -echo " src/yacsloader/Test/config_appli.xml \\" >> configure.in -echo " src/gui/resources/YACSGuiCatalog.xml \\" >> configure.in -echo " doc/Doxyfile \\" >> configure.in - -echo "])" >> configure.in - # -- -run "libtoolize" +run "libtoolize --force --copy --automake" run "aclocal -I adm/unix/config_files" run "autoheader -I adm/unix/config_files" run "autoconf" diff --git a/configure.in.base b/configure.in.base index a1abc8946..caeb12aca 100644 --- a/configure.in.base +++ b/configure.in.base @@ -3,7 +3,21 @@ # Author : Anthony Geay (CEA) # -- # ----------------------------------------------------------------------------- -# + +AC_INIT([Salome2 Project], [4.1.1], [paul.rascle@edf.fr], [SalomeYacs]) +AM_INIT_AUTOMAKE([tar-pax]) +AC_CONFIG_HEADER(yacs_config.h) + +# set up MODULE_NAME variable for dynamic construction of directories (resources, etc.) +MODULE_NAME=yacs +AC_SUBST(MODULE_NAME) + +XVERSION=0x040101 +AC_SUBST(XVERSION) + +RELEASE=$VERSION +AC_SUBST(RELEASE) + # This function return on stdout the absolute path of the filename in # argument. Exemple: # $ filename="../KERNEL_SRC/configure @@ -34,12 +48,6 @@ echo Build root directory : $ROOT_BUILDDIR AC_ENABLE_DEBUG(yes) AC_DISABLE_PRODUCTION -AC_SUBST(RELEASE) -AC_SUBST(MODULE_NAME) -AC_SUBST(PACKAGE) - -AM_INIT_AUTOMAKE($PROJECT, $RELEASE) -AC_CONFIG_HEADER(yacs_config.h) #Linker options AC_CANONICAL_BUILD @@ -48,6 +56,11 @@ AC_LINKER_OPTIONS #Mandatory products AC_PROG_CXX AM_PROG_LIBTOOL + +AC_CHECK_LIB(dl,dlopen) + +ENABLE_PTHREADS + AM_PATH_PYTHON(2.3) AC_PYTHON_DEVEL python_ok=yes @@ -55,6 +68,7 @@ CHECK_THREAD AC_CHECK_OMNIORB AC_CHECK_EXPAT AC_CHECK_LIBXML +CHECK_BOOST #Optional products AC_PROG_SWIG(1.3.17) @@ -91,7 +105,9 @@ echo "Configuration Options Summary:" echo echo "Mandatory products:" echo " Threads ................ : $thread_ok" +echo " Boost .................. : $boost_ok" echo " OmniOrb (CORBA) ........ : $omniORB_ok" +echo " OmniOrbpy (CORBA) ...... : $omniORBpy_ok" echo " Python ................. : $python_ok" echo " Expat .................. : $expat_ok" echo " libxml ................. : $libxml_ok" @@ -118,9 +134,47 @@ fi if test "x$python_ok" = "xno"; then AC_MSG_ERROR([Python is required],1) fi +if test "x$omniORBpy_ok" = "xno"; then + AC_MSG_ERROR([OmniOrbpy is required],1) +fi if test "x$expat_ok" = "xno"; then AC_MSG_ERROR([Expat is required],1) fi if test "x$libxml_ok" = "xno"; then AC_MSG_ERROR([Libxml is required],1) fi + + +AC_OUTPUT([ \ + Makefile \ + Demo/Makefile \ + doc/Makefile \ + idl/Makefile \ + src/Makefile \ + src/bases/Makefile \ + src/bases/Test/Makefile \ + src/engine/Makefile \ + src/engine/Plugin/Makefile \ + src/engine/Test/Makefile \ + src/gui/Makefile \ + src/hmi/Makefile \ + src/lineconn2d/Makefile \ + src/prs/Makefile \ + src/pyqt/Makefile \ + src/runtime/Makefile \ + src/runtime/Test/Makefile \ + src/salomeloader/Makefile \ + src/wrappergen/Makefile \ + src/wrappergen/src/Makefile \ + src/yacsloader/Makefile \ + src/yacsloader/Test/Makefile \ + src/yacsorb/Makefile \ + src/yacsloader/Test/YacsLoaderTest.sh \ + src/yacsloader/Test/YacsLoaderInSessionTest.sh \ + src/yacsloader/Test/YacsLoaderInSessionTest2.sh \ + src/yacsloader/Test/display.sh \ + src/yacsloader/Test/config_appli.xml \ + src/gui/resources/YACSCatalog.xml \ + doc/Doxyfile \ +]) + diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 67bf37ac4..879d14757 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -90,6 +90,7 @@ INPUT = \ @top_srcdir@/src/yacsloader \ @top_srcdir@/src/yacsorb \ @top_srcdir@/src/gui \ + @top_srcdir@/src/hmi \ @top_srcdir@/src/lineconn2d \ @top_srcdir@/src/prs \ @top_srcdir@/src/pyqt @@ -157,8 +158,8 @@ VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = NO -COLS_IN_ALPHA_INDEX = 5 +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 2 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output @@ -166,8 +167,8 @@ IGNORE_PREFIX = GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = +HTML_HEADER = @top_srcdir@/doc/sources/header.html +HTML_FOOTER = @top_srcdir@/doc/sources/footer.html HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO diff --git a/doc/Makefile.am b/doc/Makefile.am index f20fa1066..32fa6b21f 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,12 +1,35 @@ include $(top_srcdir)/adm/unix/make_begin.am -docs: +html/main.html:yacs.dox doxygen -install-data-local:docs - $(INSTALL) -d $(docdir)/gui/YACSGui; - cp -rf $(top_builddir)/doc/html/* $(docdir)/gui/YACSGui; - cp -rf $(top_builddir)/doc/html/index.html $(docdir)/gui/YACSGui/index.htm; - cp -rf $(top_srcdir)/src/yacsloader/samples $(docdir)/gui/YACSGui; - rm -rf $(docdir)/gui/YACSGui/samples/CVS; +DOXFILES= bases.dox engine.dox hmi.dox python.dox runtime.dox yacs.dox yacsloader.dox + +EXTRA_DIST= html $(DOXFILES) + +install-data-local:html/main.html + $(INSTALL) -d $(DESTDIR)$(docdir)/gui/YACS; + if test -d "html"; then b=; else b="$(srcdir)/"; fi; \ + find $$b"html" -name "*.*" -exec cp -rf {} $(DESTDIR)$(docdir)/gui/YACS ';' ; \ + cp -rf $(DESTDIR)$(docdir)/gui/YACS/index.html $(DESTDIR)$(docdir)/gui/YACS/index.htm; \ + cp -rf $(top_srcdir)/src/yacsloader/samples $(DESTDIR)$(docdir)/gui/YACS; \ + rm -rf $(DESTDIR)$(docdir)/gui/YACS/samples/CVS; + +uninstall-local: + chmod -R +w $(DESTDIR)$(docdir)/gui/YACS + find $(DESTDIR)$(docdir) -name "*.html" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.jpg" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.map" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.md5" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.png" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.gif" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.css" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.js*" -type f -exec rm -rf {} \; + find $(DESTDIR)$(docdir) -name "*.jpeg*" -type f -exec rm -rf {} \; + rm -rf $(DESTDIR)$(docdir)/gui/YACS/samples + rm -rf $(DESTDIR)$(docdir)/gui/YACS/index.htm + +clean-local: + if test -d "html"; then rm -rf html ; fi + diff --git a/doc/classDiagram.png b/doc/classDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..220d7ffb44c94b5cd19ff365386d551768522bf4 GIT binary patch literal 71406 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 literal 0 HcmV?d00001 diff --git a/doc/engine.dox b/doc/engine.dox index 1eb4dec30..d978afa9a 100644 --- a/doc/engine.dox +++ b/doc/engine.dox @@ -19,8 +19,7 @@ graphs of execution independently from the context (\ref engine_runtime) the gra \section basic_concepts Basic concepts in YACS::ENGINE -The understanding of YACS::ENGINE implementation needs a well -knowledge of the following concepts : +The understanding of YACS::ENGINE implementation needs a good knowledge of the basic concepts (\subpage engineConcepts): - \ref engine_node - \ref engine_ports diff --git a/doc/hmi.dox b/doc/hmi.dox new file mode 100644 index 000000000..393202213 --- /dev/null +++ b/doc/hmi.dox @@ -0,0 +1,29 @@ +/*! \page gui_design GUI design + + +\section Goals +\arg Provide a general mechanism for the synchronisation of several views (tree views, 2D canvas views, edition dialogs). +\arg Provide an interface of YACS::ENGINE for edition with a general mechanism for undo-redo. +\arg Be as independent as possible of Qt (and SALOME), to avoid problems in Qt4 migration, and allow a potential re-use of YACS GUI outside SALOME. + +For the first goal, a subject/observers design pattern is used: several observers can attach or detach themselves to/from the subject. The subject send update events to the lists of observers. The subject does not know the implementation of the observers. The observers correspond to the different views in our case. +If a selection event occurs in a view (select a node, for instance), a select event is sent to the corresponding subject. The subject sends selection events to all its observers. +If a modification is generated in a view, (request to add a node, for example), the request is sent to the subject. The subject deals with the creation of the node, then sends update events to observers. + +For the second goal, a command design pattern is used: each action is stored in a command object witch provides execute() and reverse() methods. All necessary information for execute and undo the action must be stored in the command object. +Commands are put in a stack of commands. Undo actions consists in depiling the stack. + +The following UML graphs corresponds approximately to the actual implementation, however, the generals principles are the same. + +\image html classDiagram.png "class diagram: subject/observers and command stack design patterns" + +The collaboration diagram below shows all the interactions between objects during a node creation. From left to right, we have 5 groups of objects, which are: YACS Engine, Commands, Subjects, and 2 Observers (a Tree View and a Canvas View). + +\image html createNodeCollaboration.png "Collaboration diagram for create node" + +\image html sequenceCreateNode.png "Sequence diagram for create node" + +\image html undoCreateNodeCollaboration.png "Collaboration diagram for undo create node" + +*/ + diff --git a/doc/python.dox b/doc/python.dox index f486e5b14..a844033ed 100644 --- a/doc/python.dox +++ b/doc/python.dox @@ -13,8 +13,8 @@ them in a unique dynamic library and link the modules with it. \section python_exception Exception wrapping In swig, exception can be wrapped either by declaring throw in interface file (.i) or by declaring an exception handler. -A generic exception handler has been declared so throw declarations must -be removed to not wrap exceptions two times. +A generic exception handler has been declared and automatic generation has been +desactivated (SWIG option -noexcept). \section python_gil Global Interpreter Lock For some methods we need to release the Python GIL. diff --git a/doc/sequenceCreateNode.png b/doc/sequenceCreateNode.png new file mode 100644 index 0000000000000000000000000000000000000000..926295da0e43da4da4c0d711e3bb4dbdecd49328 GIT binary patch literal 35038 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 literal 0 HcmV?d00001 diff --git a/doc/sources/footer.html b/doc/sources/footer.html new file mode 100755 index 000000000..56d52a61a --- /dev/null +++ b/doc/sources/footer.html @@ -0,0 +1,10 @@ + + + + + +
+
Copyright © 2003-2007 CEA, EDF
+
+ + diff --git a/doc/sources/header.html b/doc/sources/header.html new file mode 100755 index 000000000..bddc997ec --- /dev/null +++ b/doc/sources/header.html @@ -0,0 +1,13 @@ + + + + + $title + + + +
+
+SALOME documentation central +
+
diff --git a/doc/undoCreateNodeCollaboration.png b/doc/undoCreateNodeCollaboration.png new file mode 100644 index 0000000000000000000000000000000000000000..28cec4940b535524f4752fd3493e893fdf9dfabe GIT binary patch literal 37887 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 IQ{%V)3%#B|L;wH) literal 0 HcmV?d00001 diff --git a/doc/yacs.dox b/doc/yacs.dox index 9ea5a8bf0..0c8179629 100644 --- a/doc/yacs.dox +++ b/doc/yacs.dox @@ -30,33 +30,33 @@ \section Packages - %YACS is composed of four packages - - \ref bases : common base classes (threads,...) and constants - - \ref engine : calculation schema generic classes (calculation nodes, control nodes, + %YACS is composed of several packages + - \subpage bases : common base classes (threads,...) and constants + - \subpage engine : calculation schema generic classes (calculation nodes, control nodes, control and data flow links, ...) - - \ref runtime : implementation of generic calculation nodes for Salome platform - - \ref xml_loader : XML reader for generic calculation schema + - \subpage runtime : implementation of generic calculation nodes for Salome platform + - \subpage xml_loader : XML reader for generic calculation schema + - \subpage gui_design : Graphic User Interface design - A Python API is provided by wrapping with swig : \ref python + A Python API is provided by wrapping with swig : \subpage python \section Building For building %YACS, you need some prerequisites - - g++ 3.3 or more (mandatory) + - g++ 4.1 or more (mandatory) - libxml2 (mandatory) - expat (mandatory) - - omniorb (mandatory) + - omniorb 4.1 or more (mandatory) - python 2.3 and + (mandatory) - - swig 1.3.24 (optional) + - swig 1.3.31 (mandatory) - cppunits (optional, for unit tests only) - - Salome 3.2.x (optional) - - DSC Salome Extension (optional) + - Salome 4.1.x (optional) If you want to install %YACS for SALOME, you need to set environment variable: \b KERNEL_ROOT_DIR. - If you want to install %YACS for Dsc Salome Extension, you need to set environment - variable: \b PARALLEL_KERNEL_ROOT_DIR. + If you want to install %YACS with SALOME GUI, you need to set environment + variable: \b GUI_ROOT_DIR. The building process is the traditional configure/make/make install: - configure --prefix=path_to_install @@ -68,8 +68,8 @@ Then you can run a small demo in Demo directory: - cd Demo - make - - launch the echoSrv server : echoSrv& (if the omniorb name server is not - running you need to launch it : omniNames& should be enough) + - launch the echoSrv server : ./echoSrv& (if the omniorb name server is not + running you need to launch it : omniNames -start -logdir /tmp & should be enough) - run yacs supervisor with the schema.xml file : ../src/yacsloader/driver schema.xml Finally you can install yacs: diff --git a/doc/yacsloader.dox b/doc/yacsloader.dox index 1309a0bc6..147a2cf17 100644 --- a/doc/yacsloader.dox +++ b/doc/yacsloader.dox @@ -3,57 +3,18 @@ \section toc Table of contents - \ref loader_intro - - \ref loader_programming - \ref loader_use - \ref loader_file + - \ref loader_programming \section loader_intro Introduction -The yacs loader is a class that can be used to load a calculation schema -in memory by reading and parsing a XML file describing it. - -\section loader_programming Programming with the yacs loader class - -To use the yacs loader class, first create a specific runtime (here a Salome one). - -Then you can create an instance of the yacsloader class and call -the load method with the name of the XML file as argument. - -The call to the method will return a calculation schema (instance of the Proc class). - -\code -#include "RuntimeSALOME.hxx" -#include "parser.hxx" - -YACS::ENGINE::RuntimeSALOME::setRuntime(); -YACS::YACSLoader loader; - -YACS::ENGINE::Proc* p=loader.load("file.xml"); - -\endcode - -You can then dump to a file a graphviz diagram by calling the writeDot -method on the schema. - -\code -#include - -std::ofstream f("proc.dot"); -p->writeDot(f); -f.close(); -\endcode - -You can display the diagram with: dot -Tpng proc.dot |display. - -And then execute the schema with an Executor. - -\code -#include "Executor.hxx" - -YACS::ENGINE::Executor executor; -executor.RunW(p); -\endcode +The yacsloader module provides several software elements : + - a C++ class that can be used to load a calculation schema in memory by reading and parsing a XML file + describing it (see \ref loader_programming). + - an executable named driver that can be used to load and execute (see \ref loader_use) a calculation + schema given as a XML file (see \ref loader_file). \section loader_use Using the yacs driver @@ -88,7 +49,7 @@ To define a calculation schema, simply open a proc tag \endcode -All following definitions must be put betwween these tags. +All following definitions must be put between these tags. \subsection loader_types Defining data types A calculation schema is composed of interconnected calculation nodes. @@ -637,5 +598,47 @@ A minimal but almost complete example : \endcode +\section loader_programming Programming with the yacs loader class + +To use the yacs loader class, first create a specific runtime (here a Salome one). + +Then you can create an instance of the yacsloader class and call +the load method with the name of the XML file as argument. + +The call to the method will return a calculation schema (instance of the Proc class). + +\code +#include "RuntimeSALOME.hxx" +#include "parser.hxx" + +YACS::ENGINE::RuntimeSALOME::setRuntime(); +YACS::YACSLoader loader; + +YACS::ENGINE::Proc* p=loader.load("file.xml"); + +\endcode + +You can then dump to a file a graphviz diagram by calling the writeDot +method on the schema. + +\code +#include + +std::ofstream f("proc.dot"); +p->writeDot(f); +f.close(); +\endcode + +You can display the diagram with: dot -Tpng proc.dot |display. + +And then execute the schema with an Executor. + +\code +#include "Executor.hxx" + +YACS::ENGINE::Executor executor; +executor.RunW(p); +\endcode + */ diff --git a/idl/Makefile.am b/idl/Makefile.am index 0994d10e9..d3f7b29a2 100644 --- a/idl/Makefile.am +++ b/idl/Makefile.am @@ -3,21 +3,34 @@ include $(top_srcdir)/adm/unix/make_begin.am IDL_FILES = yacsgui.idl IDL_SRC = yacsguiSK.cc -BUILT_SOURCES = $(IDL_SRC) yacsgui_idl.py +BUILT_SOURCES = $(IDL_SRC) yacsgui.hh -OMNIORB_IDL+= -I$(KERNEL_ROOT_DIR)/idl/salome -I$(GUI_ROOT_DIR)/idl/salome +IDLCXXFLAGS = -I$(KERNEL_ROOT_DIR)/idl/salome -I$(GUI_ROOT_DIR)/idl/salome -IDLPYFLAGS = \ - -I$(KERNEL_ROOT_DIR)/idl/salome +IDLPYFLAGS = -I$(KERNEL_ROOT_DIR)/idl/salome + +EXTRA_DIST = $(IDL_FILES) install-exec-local: install-pyidl +uninstall-local: + rm -rf $(DESTDIR)$(salomepythondir)/yacsgui_idl.py + rm -rf $(DESTDIR)$(salomepythondir)/YACS_ORB + rm -rf $(DESTDIR)$(salomepythondir)/YACS_ORB__POA + install-pyidl: $(IDL_FILES) - $(INSTALL) -d $(pkgpythondir) + $(INSTALL) -d $(DESTDIR)$(salomepythondir) @for file in $^ dummy; do \ if [ $$file != "dummy" ]; then \ - $(OMNIORB_IDL) -bpython $(IDLPYFLAGS) -C$(pkgpythondir) $$file ; \ + $(OMNIORB_IDL) -bpython $(IDLPYFLAGS) -C$(DESTDIR)$(salomepythondir) $$file ; \ fi ; \ done ; +dist-hook: + rm -f $(distdir)/yacsguiSK.cc + rm -f $(distdir)/yacsgui.hh + +clean-local: + rm -rf YACS_ORB YACS_ORB__POA yacsgui.hh yacsgui_idl.py yacsguiSK.cc + include $(top_srcdir)/adm/unix/make_end.am diff --git a/idl/yacsgui.idl b/idl/yacsgui.idl index d44727f38..debcfb7d5 100644 --- a/idl/yacsgui.idl +++ b/idl/yacsgui.idl @@ -7,7 +7,7 @@ // SALOME Engine interface for execution in a SALOME Container -module YACSGui_ORB +module YACS_ORB { enum executionMode { CONTINUE, STEPBYSTEP, STOPBEFORENODES }; @@ -23,12 +23,18 @@ module YACSGui_ORB { long getNodeState(in long numid); string getXMLState(in long numid); + string getInPortValue(in long nodeNumid, in string portName); + string getOutPortValue(in long nodeNumid, in string portName); + string getErrorDetails(in long nodeNumid); + string getErrorReport(in long nodeNumid); + string getContainerLog(in long nodeNumid); long getExecutorState(); void getIds(out longArray numids,out stringArray names); longArray getNumIds(); stringArray getNames(); void Run(); + void RunFromState(in string xmlfile); void addObserver(in Observer obs,in long numid, in string event); void setExecMode(in executionMode mode); void setListOfBreakPoints(in stringArray listOfBreakPoints); @@ -39,9 +45,10 @@ module YACSGui_ORB void stopExecution(); boolean saveState(in string xmlFile); void setStopOnError(in boolean dumpRequested, in string xmlFile); + void unsetStopOnError(); }; - interface YACSGui_Gen : Engines::Component, SALOMEDS::Driver + interface YACS_Gen : Engines::Component, SALOMEDS::Driver { ProcExec LoadProc(in string xmlFile); string convertSupervFile(in string xmlFile); diff --git a/src/Makefile.am b/src/Makefile.am index 08b52a4c9..d27bbc781 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ if HAS_GUI -SUBDIRS = bases engine runtime wrappergen yacsloader yacsorb pyqt lineconn2d prs gui +SUBDIRS = bases engine runtime wrappergen yacsloader yacsorb salomeloader pyqt hmi lineconn2d prs gui else SUBDIRS = bases engine runtime wrappergen yacsloader yacsorb salomeloader endif diff --git a/src/bases/Makefile.am b/src/bases/Makefile.am index 8fbbbfff8..81205c439 100644 --- a/src/bases/Makefile.am +++ b/src/bases/Makefile.am @@ -35,8 +35,11 @@ salomeinclude_HEADERS = \ Thread.hxx \ ThreadPT.hxx \ YacsTrace.hxx \ + yacsconfig.h \ $(__dummy__) AM_CXXFLAGS = $(THREAD_DEF) +EXTRA_DIST=ThreadPT.cxx DrivenConditionPT.cxx MutexPT.cxx SemaphorePT.cxx DynLibLoaderGNU.cxx + include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/bases/Test/Makefile.am b/src/bases/Test/Makefile.am index 16e0dae16..eb2417eff 100644 --- a/src/bases/Test/Makefile.am +++ b/src/bases/Test/Makefile.am @@ -27,4 +27,6 @@ TestBases_CXXFLAGS = $(THREAD_DEF) $(CPPUNIT_INCLUDES) -I$(srcdir)/.. TESTS = InitTests TestBases +EXTRA_DIST = BasicMainTest.hxx basesTest.hxx UnitTestsResult.hxx + include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/bases/YacsTrace.hxx b/src/bases/YacsTrace.hxx index 3147de71a..34bde59d1 100644 --- a/src/bases/YacsTrace.hxx +++ b/src/bases/YacsTrace.hxx @@ -1,6 +1,8 @@ #ifndef __YACSTRACE_HXX__ #define __YACSTRACE_HXX__ +#include + #ifdef _DEVDEBUG_ #define DEBTRACE(msg) {std::cerr<kind(),Sequence); } +AnyPtr AtomAny::operator[](const char *key) const throw(Exception) +{ + throw Exception("AtomAny::operator[] : try to get a part of a partitionned data whereas atomical."); +} + bool AtomAny::operator ==(const Any& other) const { if(!_type->isA(other.getType())) @@ -272,9 +277,21 @@ ComposedAny::ComposedAny(const ComposedAny& other):Any(other) { } -ComposedAny::ComposedAny(TypeCode* type):Any(type) +ComposedAny::ComposedAny(TypeCode* type, bool isNew):Any(type) { - _type->decrRef(); + if(isNew) + _type->decrRef(); +} + +AnyPtr ComposedAny::operator[](const char *key) const throw(Exception) +{ + throw Exception("AtomAny::operator[] : try to get a part of a partitionned data not localizable by a string."); +} + +void ComposedAny::checkTypeOf(const Any *elem) const throw(Exception) +{ + if(!elem->getType()->isA(_type->contentType())) + throw Exception("ComposedAny::checkTypeOf : invalid type."); } int ComposedAny::getIntValue() const throw(Exception) @@ -436,13 +453,14 @@ bool SequenceAny::operator ==(const Any& other) const return true; } -void SequenceAny::setEltAtRank(int i, const Any *elem) +void SequenceAny::setEltAtRank(int i, const Any *elem) throw(Exception) { + checkTypeOf(elem); _alloc.destroy(_alloc._start+i*_alloc._sizeOf1Elm,_type->contentType()); _alloc.construct(_alloc._start+i*_alloc._sizeOf1Elm,elem); } -AnyPtr SequenceAny::operator[](int i) const +AnyPtr SequenceAny::operator[](int i) const throw(Exception) { return _type->contentType()->getOrBuildAnyFromZippedData(_alloc._start+i*_alloc._sizeOf1Elm); } @@ -630,16 +648,29 @@ char *SequenceAny::performCpy(char *srcStart, char *srcFinish, char *destStart) ArrayAny::~ArrayAny() { + const TypeCode *subType=_type->contentType(); + unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq(); + unsigned int size=((TypeCodeArray *)_type)->getStaticLgth(); + char *tmp=_data; + for(unsigned i=0;idestroyZippedAny(tmp); delete [] _data; } -ArrayAny::ArrayAny(char *data, TypeCodeArray * type):ComposedAny(type),_data(0) +ArrayAny::ArrayAny(const TypeCode *typeOfContent, unsigned int lgth):ComposedAny(new TypeCodeArray("","",typeOfContent,lgth)) +{ + _data=new char[_type->getSizeInByteOfAnyReprInSeq()]; + for(unsigned int i=0;i<_type->getSizeInByteOfAnyReprInSeq();i++) + _data[i]='\0'; +} + +ArrayAny::ArrayAny(char *data, TypeCodeArray * type):ComposedAny(type,false),_data(0) { _data=new char[_type->getSizeInByteOfAnyReprInSeq()]; const TypeCode *subType=_type->contentType(); unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq(); for(unsigned i=0;igetStaticLgth();i++) - subType->putReprAtPlace(_data+i*sizePerContent,data+i*sizePerContent,true); + subType->putReprAtPlace(_data+i*sizePerContent,data+i*sizePerContent,false); } ArrayAny::ArrayAny(const ArrayAny& other):ComposedAny(other) @@ -700,6 +731,14 @@ ArrayAny::ArrayAny(const std::vector& val):ComposedAny(new TypeCode } } +void ArrayAny::setEltAtRank(int i, const Any *elem) throw(Exception) +{ + checkTypeOf(elem); + const TypeCode *subType=_type->contentType(); + subType->destroyZippedAny(_data+i*subType->getSizeInByteOfAnyReprInSeq()); + elem->putMyReprAtPlace(_data+i*subType->getSizeInByteOfAnyReprInSeq()); +} + bool ArrayAny::operator ==(const Any& other) const { if(!_type->isA(other.getType())) @@ -711,13 +750,18 @@ bool ArrayAny::operator ==(const Any& other) const return true; } -AnyPtr ArrayAny::operator[](int i) const +AnyPtr ArrayAny::operator[](int i) const throw(Exception) { const TypeCode *subType=_type->contentType(); unsigned sizePerContent=subType->getSizeInByteOfAnyReprInSeq(); if(i<0 || i>=((TypeCodeArray *)_type)->getStaticLgth()) throw Exception("Trying to access to an invalid index in an Any Tuple"); - return _type->getOrBuildAnyFromZippedData(_data+i*sizePerContent); + return _type->contentType()->getOrBuildAnyFromZippedData(_data+i*sizePerContent); +} + +unsigned int ArrayAny::size() const +{ + return ((TypeCodeArray *)_type)->getStaticLgth(); } Any *ArrayAny::clone() const @@ -725,6 +769,11 @@ Any *ArrayAny::clone() const return new ArrayAny(*this); } +ArrayAny *ArrayAny::New(const TypeCode *typeOfContent, unsigned int lgth) +{ + return new ArrayAny(typeOfContent,lgth); +} + void ArrayAny::putMyReprAtPlace(char *data) const { const TypeCode *subType=_type->contentType(); @@ -752,7 +801,6 @@ void ArrayAny::destroyReprAtPlace(char *data, const TypeCodeArray *type) AnyPtr ArrayAny::getOrBuildFromData(char *data, const TypeCodeArray *type) { Any *ret; - type->incrRef(); ret=new ArrayAny(data,(TypeCodeArray *)type); return AnyPtr(ret); } @@ -762,3 +810,154 @@ bool ArrayAny::takeInChargeStorageOf(TypeCode *type) DynType typ=type->kind(); return (typ==Array); } + +Any *StructAny::clone() const +{ + return new StructAny(*this); +} + +bool StructAny::operator ==(const Any& other) const +{ + if(!_type->isA(other.getType())) + return false; + const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type; + vector< pair >::const_iterator iter; + for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++) + if(!((*(*this)[(*iter).first.c_str()]==(*other[(*iter).first.c_str()])))) + return false; + return true; +} + +AnyPtr StructAny::operator[](int i) const throw(Exception) +{ + const char what[]="StructAny::operator[](int i) : Struct key are strings not integers."; + throw Exception(what); +} + +AnyPtr StructAny::operator[](const char *key) const throw(Exception) +{ + const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type; + char *whereToGet=_data; + vector< pair >::const_iterator iter; + for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++) + if((*iter).first!=key) + whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + else + break; + if(iter==typeC->_members.end()) + { + string what("Unexisting key \""); what+=key; what+="\" for struct extraction."; + throw Exception(what); + } + return (*iter).second->getOrBuildAnyFromZippedData(whereToGet); +} + +void StructAny::setEltAtRank(int i, const Any *elem) throw(Exception) +{ + const char what[]="Struct key are strings not integers."; + throw Exception(what); +} + +void StructAny::setEltAtRank(const char *key, const Any *elem) throw(Exception) +{ + const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type; + unsigned offset; + const TypeCode *tcOnKey=typeC->getMember(key,offset); + if(!tcOnKey) + throw Exception("StructAny::setEltAtRank : invalid key given."); + if(!elem->getType()->isA(tcOnKey)) + throw Exception("StructAny::setEltAtRank : invalid data type on the specified given key."); + tcOnKey->destroyZippedAny(_data+offset); + elem->putMyReprAtPlace(_data+offset); +} + +void StructAny::putMyReprAtPlace(char *data) const +{ + const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type; + unsigned offset=0; + vector< pair >::const_iterator iter; + for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++) + { + (*iter).second->putReprAtPlace(data+offset,_data+offset,false); + offset+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + } +} + +void StructAny::putReprAtPlace(char *data, const char *src, const TypeCodeStruct *type, bool deepCpy) +{ + unsigned offset=0; + vector< pair >::const_iterator iter; + for(iter=type->_members.begin();iter!=type->_members.end();iter++) + { + (*iter).second->putReprAtPlace(data+offset,src+offset,deepCpy); + offset+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + } +} + +void StructAny::destroyReprAtPlace(char *data, const TypeCodeStruct *type) +{ + char *whereToGet=data; + vector< pair >::const_iterator iter; + for(iter=type->_members.begin();iter!=type->_members.end();iter++) + { + (*iter).second->destroyZippedAny(whereToGet); + whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + } +} + +AnyPtr StructAny::getOrBuildFromData(char *data, const TypeCodeStruct *type) +{ + Any *ret; + ret=new StructAny(data,(TypeCodeStruct *)type); + return AnyPtr(ret); +} + +StructAny::~StructAny() +{ + const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type; + vector< pair >::const_iterator iter; + char *whereToGet=_data; + for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++) + { + (*iter).second->destroyZippedAny(whereToGet); + whereToGet+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + } + delete [] _data; +} + +StructAny::StructAny(TypeCodeStruct *type):ComposedAny(type,false) +{ + _data=new char[_type->getSizeInByteOfAnyReprInSeq()]; + for(unsigned int i=0;i<_type->getSizeInByteOfAnyReprInSeq();i++) + _data[i]='\0'; +} + +StructAny::StructAny(const StructAny& other):ComposedAny(other) +{ + _data=new char[_type->getSizeInByteOfAnyReprInSeq()]; + const TypeCodeStruct *typeC=(const TypeCodeStruct *)_type; + vector< pair >::const_iterator iter; + unsigned offset=0; + for(iter=typeC->_members.begin();iter!=typeC->_members.end();iter++) + { + (*iter).second->putReprAtPlace(_data+offset,other._data+offset,true); + offset+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + } +} + +StructAny::StructAny(char *data, TypeCodeStruct * type):ComposedAny(type,false),_data(0) +{ + _data=new char[_type->getSizeInByteOfAnyReprInSeq()]; + vector< pair >::const_iterator iter; + unsigned offset=0; + for(iter=type->_members.begin();iter!=type->_members.end();iter++) + { + (*iter).second->putReprAtPlace(_data+offset,data+offset,false); + offset+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + } +} + +StructAny *StructAny::New(TypeCodeStruct *type) +{ + return new StructAny(type); +} diff --git a/src/engine/Any.hxx b/src/engine/Any.hxx index bff224ec0..f78a39d48 100644 --- a/src/engine/Any.hxx +++ b/src/engine/Any.hxx @@ -16,8 +16,10 @@ namespace YACS class TypeCode; class SeqAlloc; class ArrayAny; + class StructAny; class SequenceAny; class TypeCodeArray; + class TypeCodeStruct; typedef void (*Deallocator)(void *); class StringOnHeap @@ -47,12 +49,15 @@ namespace YACS class Any : public RefCounter { friend class SeqAlloc; + friend class ArrayAny; + friend class StructAny; friend class SequenceAny; public: const TypeCode *getType() const { return _type; } //for convenience methods virtual Any *clone() const = 0; - virtual AnyPtr operator[](int i) const = 0; + virtual AnyPtr operator[](int i) const throw(Exception) = 0; + virtual AnyPtr operator[](const char *key) const throw(Exception) = 0; virtual bool operator ==(const Any& other) const = 0; virtual int getIntValue() const throw(Exception) = 0; virtual bool getBoolValue() const throw(Exception) = 0; @@ -87,7 +92,8 @@ namespace YACS template static AtomAny *New(T val) { return new AtomAny(val); } static AtomAny *New(char *val, Deallocator dealloc); - AnyPtr operator[](int i) const; + AnyPtr operator[](int i) const throw(Exception); + AnyPtr operator[](const char *key) const throw(Exception); bool operator ==(const Any& other) const; int getIntValue() const throw(Exception); bool getBoolValue() const throw(Exception); @@ -138,9 +144,14 @@ namespace YACS class ComposedAny : public Any { + public: + virtual void setEltAtRank(int i, const Any *elem) throw(Exception) = 0; + AnyPtr operator[](const char *key) const throw(Exception); protected: ComposedAny(const ComposedAny& other); - ComposedAny(TypeCode* type); + ComposedAny(TypeCode* type, bool isNew=true); + protected: + void checkTypeOf(const Any *elem) const throw(Exception); private://error methods called during incorrect runtime extraction int getIntValue() const throw(Exception); bool getBoolValue() const throw(Exception); @@ -159,8 +170,8 @@ namespace YACS unsigned int size() const { return _alloc.size(); } void pushBack(const Any *elem); bool operator ==(const Any& other) const; - void setEltAtRank(int i, const Any *elem); - AnyPtr operator[](int i) const; + void setEltAtRank(int i, const Any *elem) throw(Exception); + AnyPtr operator[](int i) const throw(Exception); Any *clone() const; template static SequenceAny *New(const std::vector& vec); @@ -198,13 +209,16 @@ namespace YACS { friend class TypeCodeArray; public: + void setEltAtRank(int i, const Any *elem) throw(Exception); bool operator ==(const Any& other) const; - AnyPtr operator[](int i) const; + AnyPtr operator[](int i) const throw(Exception); + unsigned int size() const; Any *clone() const; template static ArrayAny *New(const std::vector& vec); template static ArrayAny *New(const T *val, unsigned int lgth); + static ArrayAny *New(const TypeCode *typeOfContent, unsigned int lgth); protected: void putMyReprAtPlace(char *data) const; static void putReprAtPlace(char *data, const char *src, const TypeCodeArray *type, bool deepCpy); @@ -213,6 +227,7 @@ namespace YACS static bool takeInChargeStorageOf(TypeCode *type); private: ~ArrayAny(); + ArrayAny(const TypeCode *typeOfContent, unsigned int lgth); ArrayAny(char *data, TypeCodeArray * type); ArrayAny(const ArrayAny& other); ArrayAny(const int *val, unsigned int lgth); @@ -225,6 +240,33 @@ namespace YACS char *_data; }; + typedef SharedPtr StructAnyPtr; + + class StructAny : public ComposedAny + { + friend class TypeCodeStruct; + public: + Any *clone() const; + bool operator ==(const Any& other) const; + static StructAny *New(TypeCodeStruct *type); + AnyPtr operator[](int i) const throw(Exception); + AnyPtr operator[](const char *key) const throw(Exception); + void setEltAtRank(int i, const Any *elem) throw(Exception); + void setEltAtRank(const char *key, const Any *elem) throw(Exception); + protected: + void putMyReprAtPlace(char *data) const; + static void putReprAtPlace(char *data, const char *src, const TypeCodeStruct *type, bool deepCpy); + static void destroyReprAtPlace(char *data, const TypeCodeStruct *type); + static AnyPtr getOrBuildFromData(char *data, const TypeCodeStruct *type); + private: + ~StructAny(); + StructAny(TypeCodeStruct *type); + StructAny(const StructAny& other); + StructAny(char *data, TypeCodeStruct * type); + private: + char *_data; + }; + template SequenceAny *SequenceAny::New(T *val, unsigned int lgth, Deallocator deAlloc) { diff --git a/src/engine/AnyInputPort.cxx b/src/engine/AnyInputPort.cxx index 3a0e898c4..7aa5602ae 100644 --- a/src/engine/AnyInputPort.cxx +++ b/src/engine/AnyInputPort.cxx @@ -1,4 +1,5 @@ #include "AnyInputPort.hxx" +#include "TypeCode.hxx" #include #include @@ -66,13 +67,8 @@ bool AnyInputPort::isEmpty() return !_value; } -void *AnyInputPort::get() const throw(Exception) +void *AnyInputPort::get() const { - if(!_value) - { - std::string what="AnyInputPort::get : no value currently in input whith name \""; what+=_name; what+="\""; - throw Exception(what); - } return (void *)_value; } diff --git a/src/engine/AnyInputPort.hxx b/src/engine/AnyInputPort.hxx index 074172c5d..ed9d9581a 100644 --- a/src/engine/AnyInputPort.hxx +++ b/src/engine/AnyInputPort.hxx @@ -19,7 +19,7 @@ namespace YACS Any *getValue() const { return _value; } int getIntValue() const { return _value->getIntValue(); } void put(Any *data); - void *get() const throw(Exception); + void *get() const; virtual bool isEmpty(); void put(const void *data) throw(ConversionException); InputPort *clone(Node *newHelder) const; diff --git a/src/engine/Bloc.cxx b/src/engine/Bloc.cxx index 129d88aa9..e34d3952a 100644 --- a/src/engine/Bloc.cxx +++ b/src/engine/Bloc.cxx @@ -7,13 +7,16 @@ #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; using namespace std; Bloc::Bloc(const Bloc& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_fwLinks(0),_bwLinks(0) { - for(set::const_iterator iter=other._setOfNode.begin();iter!=other._setOfNode.end();iter++) - _setOfNode.insert((*iter)->simpleClone(this,editionOnly)); + for(list::const_iterator iter=other._setOfNode.begin();iter!=other._setOfNode.end();iter++) + _setOfNode.push_back((*iter)->simpleClone(this,editionOnly)); //CF Linking vector< pair > cfLinksToReproduce=other.getSetOfInternalCFLinks(); vector< pair >::iterator iter1=cfLinksToReproduce.begin(); @@ -36,7 +39,7 @@ Bloc::Bloc(const std::string& name):StaticDefinedComposedNode(name),_fwLinks(0), Bloc::~Bloc() { - for(set::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) delete *iter; delete _fwLinks; delete _bwLinks; @@ -51,7 +54,7 @@ Bloc::~Bloc() void Bloc::init(bool start) { Node::init(start); - for(set::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) (*iter)->init(start); } @@ -72,7 +75,7 @@ bool Bloc::isFinished() int Bloc::getNumberOfCFLinks() const { int ret=0; - for(set::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) ret+=(*iter)->getOutGate()->getNbOfInGatesConnected(); return ret; } @@ -95,7 +98,7 @@ void Bloc::getReadyTasks(std::vector& tasks) */ if(_state==YACS::TOACTIVATE ) setState(YACS::ACTIVATED); if(_state==YACS::TOACTIVATE || _state==YACS::ACTIVATED) - for(set::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) (*iter)->getReadyTasks(tasks); } @@ -112,7 +115,7 @@ void Bloc::exUpdateState() if(_inGate.exIsReady()) { setState(YACS::TOACTIVATE); - for(set::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) if((*iter)->exIsControlReady()) (*iter)->exUpdateState(); } @@ -147,6 +150,8 @@ bool Bloc::edAddChild(Node *node) throw(Exception) string what = "Bloc::edAddChild: node is not orphan: "; what += node->getName(); throw Exception(what); } + + checkNoCrossHierachyWith(node); if(isNameAlreadyUsed(node->getName())) { @@ -154,10 +159,14 @@ bool Bloc::edAddChild(Node *node) throw(Exception) what+=" already exists in the scope of "; what+=_name; throw Exception(what); } - + node->_father=this; - _setOfNode.insert(node); + _setOfNode.push_back(node); + //should we also set _modified flag for node ?? ComposedNode *iter=node->_father; + //set the _modified flag so that latter on edUpdateState (eventually called by isValid) refresh state + //better call it at end + modified(); return true; } @@ -169,17 +178,17 @@ bool Bloc::edAddChild(Node *node) throw(Exception) void Bloc::edRemoveChild(Node *node) throw(Exception) { StaticDefinedComposedNode::edRemoveChild(node); - _setOfNode.erase(node); -} - -std::set Bloc::edGetDirectDescendants() const -{ - return _setOfNode; + list::iterator iter=find(_setOfNode.begin(),_setOfNode.end(),node); + if(iter!=_setOfNode.end()) + { + _setOfNode.erase(iter); + modified(); + } } Node *Bloc::getChildByShortName(const std::string& name) const throw(Exception) { - for (set::const_iterator iter = _setOfNode.begin(); iter != _setOfNode.end(); iter++) + for (list::const_iterator iter = _setOfNode.begin(); iter != _setOfNode.end(); iter++) if ((*iter)->getName() == name) return (*iter); string what("node "); what+= name ; what+=" is not a child of Bloc "; what += getName(); @@ -192,7 +201,7 @@ void Bloc::selectRunnableTasks(std::vector& tasks) bool Bloc::areAllSubNodesDone() const { - for(set::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) { if((*iter)->_state == YACS::DONE)continue; if((*iter)->_state == YACS::DISABLED)continue; @@ -203,7 +212,7 @@ bool Bloc::areAllSubNodesDone() const bool Bloc::areAllSubNodesFinished() const { - for(set::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) { if((*iter)->_state == YACS::DONE)continue; if((*iter)->_state == YACS::FAILED)continue; @@ -217,7 +226,7 @@ bool Bloc::areAllSubNodesFinished() const bool Bloc::isNameAlreadyUsed(const std::string& name) const { - for(set::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) if((*iter)->getName()==name) return true; return false; @@ -255,7 +264,7 @@ void Bloc::checkNoCyclePassingThrough(Node *node) throw(Exception) std::vector< std::pair > Bloc::getSetOfInternalCFLinks() const { vector< pair > ret; - for(set::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) { set outCFLinksOfCurNode=(*iter)->_outGate.edSetInGate(); for(set::iterator iter2=outCFLinksOfCurNode.begin();iter2!=outCFLinksOfCurNode.end();iter2++) @@ -274,6 +283,7 @@ std::vector< std::pair > Bloc::getSetOfInternalCFLinks() co */ YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node) { + DEBTRACE("Bloc::updateStateOnFinishedEventFrom: " << node->getName()); //ASSERT(node->_father==this) if(areAllSubNodesFinished()) { @@ -295,7 +305,7 @@ YACS::Event Bloc::updateStateOnFinishedEventFrom(Node *node) catch(YACS::Exception& ex) { //The node has failed to propagate. It must be put in error - std::cerr << "Bloc::updateStateOnFinishedEventFrom: " << ex.what() << std::endl; + DEBTRACE("Bloc::updateStateOnFinishedEventFrom: " << ex.what()); // notify the node it has failed node->exForwardFailed(); setState(YACS::FAILED); @@ -324,11 +334,11 @@ YACS::Event Bloc::updateStateOnFailedEventFrom(Node *node) return YACS::NOEVENT; } -void Bloc::writeDot(std::ostream &os) +void Bloc::writeDot(std::ostream &os) const { os << " subgraph cluster_" << getId() << " {\n" ; - setnodes=getChildren(); - for(set::const_iterator iter=nodes.begin();iter!=nodes.end();iter++) + listnodes=getChildren(); + for(list::const_iterator iter=nodes.begin();iter!=nodes.end();iter++) { (*iter)->writeDot(os); string p=(*iter)->getId(); @@ -365,10 +375,10 @@ void Bloc::performCFComputations(LinkInfo& info) const _fwLinks=new map >; _bwLinks=new map >; map > accelStr; - for(set::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) findAllNodesStartingFrom(*iter,(*_fwLinks)[*iter],accelStr,info); accelStr.clear(); - for(set::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) findAllNodesStartingFrom(*iter,(*_bwLinks)[*iter],accelStr,info); } @@ -390,9 +400,9 @@ void Bloc::destructCFComputations(LinkInfo& info) const * \param info out parameter beeing informed about eventual errors. */ void Bloc::checkControlDependancy(OutPort *start, InPort *end, bool cross, - std::map < ComposedNode *, std::list < OutPort * > >& fw, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, std::vector& fwCross, - std::map< ComposedNode *, std::list < OutPort *> >& bw, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, LinkInfo& info) const { if(!cross) @@ -443,7 +453,7 @@ bool Bloc::arePossiblyRunnableAtSameTime(Node *start, Node *end) const * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port. * \param direction If true : forward direction else backward direction. */ -void Bloc::checkCFLinks(const std::list< OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const +void Bloc::checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const { if(alreadyFed==FREE_ST || alreadyFed==FED_ST) { @@ -467,7 +477,7 @@ void Bloc::checkCFLinks(const std::list< OutPort *>& starts, InputPort *end, uns void Bloc::initComputation() const { - for(set::iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) + for(list::const_iterator iter=_setOfNode.begin();iter!=_setOfNode.end();iter++) { (*iter)->_colour=White; (*iter)->getInGate()->exReset(); diff --git a/src/engine/Bloc.hxx b/src/engine/Bloc.hxx index cdf5daee6..26c48271e 100644 --- a/src/engine/Bloc.hxx +++ b/src/engine/Bloc.hxx @@ -17,7 +17,7 @@ namespace YACS class Bloc : public StaticDefinedComposedNode { protected: - std::set _setOfNode;//OWNERSHIP OF ALL NODES + std::list _setOfNode;//OWNERSHIP OF ALL NODES //! For internal calculations mutable std::map > *_fwLinks; //! For internal calculations @@ -33,18 +33,20 @@ namespace YACS void init(bool start=true); void getReadyTasks(std::vector& tasks); void exUpdateState(); - bool edAddChild(Node *node) throw(Exception); + //Node* DISOWNnode is a SWIG notation to indicate that the ownership of the node is transfered to C++ + bool edAddChild(Node *DISOWNnode) throw(Exception); void edRemoveChild(Node *node) throw(Exception); - std::set getChildren() { return _setOfNode; } - std::set edGetDirectDescendants() const; + std::list getChildren() const { return _setOfNode; } + std::list edGetDirectDescendants() const { return _setOfNode; } Node *getChildByShortName(const std::string& name) const throw(Exception); void selectRunnableTasks(std::vector& tasks); - virtual void writeDot(std::ostream &os); + virtual void writeDot(std::ostream &os) const; void accept(Visitor *visitor); template void findAllPathsStartingFrom(Node *start, std::list< std::vector >& vec, std::map >& accelStr) const; template void findAllNodesStartingFrom(Node *start, std::set& result, std::map >& accelStr, LinkInfo& info) const; + virtual std::string typeName() {return "YACS__ENGINE__Bloc";} protected: bool areAllSubNodesFinished() const; bool areAllSubNodesDone() const; @@ -57,13 +59,13 @@ namespace YACS void performCFComputations(LinkInfo& info) const; void destructCFComputations(LinkInfo& info) const; void checkControlDependancy(OutPort *start, InPort *end, bool cross, - std::map < ComposedNode *, std::list < OutPort * > >& fw, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, std::vector& fwCross, - std::map< ComposedNode *, std::list < OutPort *> >& bw, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, LinkInfo& info) const; bool areLinked(Node *start, Node *end, bool fw) const; bool arePossiblyRunnableAtSameTime(Node *start, Node *end) const; - void checkCFLinks(const std::list< OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; + void checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; static void verdictForOkAndUseless1(const std::map >& pool, InputPort *end, const std::vector& candidates, unsigned char& alreadyFed, bool direction, LinkInfo& info); static void verdictForCollapses(const std::map >& pool, InputPort *end, const std::set& candidates, diff --git a/src/engine/Catalog.cxx b/src/engine/Catalog.cxx new file mode 100644 index 000000000..8834440c9 --- /dev/null +++ b/src/engine/Catalog.cxx @@ -0,0 +1,60 @@ +#include "Catalog.hxx" +#include "ComponentDefinition.hxx" +#include "TypeCode.hxx" +#include "Node.hxx" +#include "ComposedNode.hxx" + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace std; +using namespace YACS::ENGINE; + +Catalog::Catalog(const std::string& name):_name(name) +{ +} + +Catalog::~Catalog() +{ + DEBTRACE("Catalog::~Catalog"); + //decref type codes in map + std::map::iterator pt; + for(pt=_typeMap.begin();pt!=_typeMap.end();pt++) + ((*pt).second)->decrRef(); + + //get rid of component definitions in map + std::map::const_iterator lt; + for(lt=_componentMap.begin();lt!=_componentMap.end();lt++) + delete (*lt).second; + + //get rid of nodes in map + std::map::const_iterator nt; + for(nt=_nodeMap.begin();nt!=_nodeMap.end();nt++) + delete (*nt).second; + + //get rid of composed nodes in map + std::map::const_iterator ct; + for(ct=_composednodeMap.begin();ct!=_composednodeMap.end();ct++) + delete (*ct).second; + +} + +CatalogLoader::CatalogLoader():_path("proto") +{ +} + +CatalogLoader::CatalogLoader(const std::string& path):_path(path) +{ +} + +CatalogLoader::~CatalogLoader() +{ + DEBTRACE("CatalogLoader::~CatalogLoader"); +} + +void CatalogLoader::load(Catalog* cata,const std::string& path) +{ + CatalogLoader* CL=newLoader(path); + CL->loadCata(cata); + delete CL; +} diff --git a/src/engine/Catalog.hxx b/src/engine/Catalog.hxx new file mode 100644 index 000000000..6b036f2a0 --- /dev/null +++ b/src/engine/Catalog.hxx @@ -0,0 +1,54 @@ +#ifndef __CATALOG_HXX__ +#define __CATALOG_HXX__ + +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class TypeCode; + class ComponentDefinition; + class Node; + class ComposedNode; +/*! \brief class for YACS catalogs. + * + * + */ + class Catalog + { + public: + Catalog(const std::string& name); + virtual ~Catalog(); + const std::string& getName() const { return _name; } + std::string getErrors(){return _errors;} + void setErrors(const std::string& errors){_errors=errors;} + std::map _typeMap; + std::map _componentMap; + std::map _nodeMap; + std::map _composednodeMap; + protected: + std::string _name; + std::string _errors; + }; + +/*! \brief class for YACS catalog loader. + * + */ + class CatalogLoader + { + public: + CatalogLoader(); + CatalogLoader(const std::string& path); + virtual ~CatalogLoader(); + virtual CatalogLoader* newLoader(const std::string& path)=0 ; + virtual void loadCata(Catalog* cata)=0 ; + virtual void load(Catalog* cata,const std::string& path) ; + protected: + std::string _path; + }; + } +} + +#endif diff --git a/src/engine/ComponentDefinition.cxx b/src/engine/ComponentDefinition.cxx new file mode 100644 index 000000000..8ce0890d3 --- /dev/null +++ b/src/engine/ComponentDefinition.cxx @@ -0,0 +1,24 @@ +#include "ComponentDefinition.hxx" +#include "ServiceNode.hxx" + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; +using namespace std; + +ComponentDefinition::ComponentDefinition(const std::string& name):_name(name) +{ +} + +ComponentDefinition::~ComponentDefinition() +{ + DEBTRACE("ComponentDefinition::~ComponentDefinition"); + //get rid of service nodes in map + std::map::const_iterator lt; + for(lt=_serviceMap.begin();lt!=_serviceMap.end();lt++) + delete (*lt).second; +} + diff --git a/src/engine/ComponentDefinition.hxx b/src/engine/ComponentDefinition.hxx new file mode 100644 index 000000000..5d42dbf20 --- /dev/null +++ b/src/engine/ComponentDefinition.hxx @@ -0,0 +1,30 @@ +#ifndef __COMPONENTDEFINITION_HXX__ +#define __COMPONENTDEFINITION_HXX__ + +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class ServiceNode; + +/*! \brief Base class for component definition. + * + * + */ + class ComponentDefinition + { + public: + ComponentDefinition(const std::string& name); + const std::string& getName() const { return _name; } + virtual ~ComponentDefinition(); + std::map _serviceMap; + protected: + std::string _name; + }; + } +} + +#endif diff --git a/src/engine/ComponentInstance.cxx b/src/engine/ComponentInstance.cxx index 374c0cb37..9e5d4925f 100644 --- a/src/engine/ComponentInstance.cxx +++ b/src/engine/ComponentInstance.cxx @@ -2,6 +2,7 @@ #include "Container.hxx" #include +#include //#define _DEVDEBUG_ #include "YacsTrace.hxx" @@ -10,6 +11,8 @@ using namespace YACS::ENGINE; using namespace std; const char ComponentInstance::KIND[]=""; +int ComponentInstance::_total = 0; + const char ComponentInstance::NULL_FILE_REPR[]="No repr specified for ComponentInstance"; @@ -26,14 +29,22 @@ void ComponentInstance::setContainer(Container *cont) _container->incrRef(); } -ComponentInstance::ComponentInstance(const std::string& name):_name(name),_isAttachedOnCloning(false),_container(0) +ComponentInstance::ComponentInstance(const std::string& name):_compoName(name),_isAttachedOnCloning(false),_container(0) { + _numId = _total++; + stringstream instName; + instName << _compoName << "_" << _numId; + _instanceName = instName.str(); } -ComponentInstance::ComponentInstance(const ComponentInstance& other):_name(other._name), +ComponentInstance::ComponentInstance(const ComponentInstance& other):_compoName(other._compoName), _container(0), _isAttachedOnCloning(other._isAttachedOnCloning) { + _numId = _total++; + stringstream instName; + instName << _compoName << "_" << _numId; + _instanceName = instName.str(); if(other._container) _container=other._container->clone(); } diff --git a/src/engine/ComponentInstance.hxx b/src/engine/ComponentInstance.hxx index 4ffc12273..792ed9e5c 100644 --- a/src/engine/ComponentInstance.hxx +++ b/src/engine/ComponentInstance.hxx @@ -15,7 +15,6 @@ namespace YACS /*! \brief Base class for all component instances. * - * \ingroup Nodes * * This is an abstract class that must be specialized in runtime. * Specialized classes must provide implementation for loading of @@ -34,8 +33,10 @@ namespace YACS public: ComponentInstance(const std::string& name); ComponentInstance(const ComponentInstance& other); - const std::string& getName() const { return _name; } - void setContainer(Container *cont); + const std::string& getCompoName() const { return _compoName; } + const std::string& getInstanceName() const { return _instanceName; } + int getNumId() const { return _numId; } + virtual void setContainer(Container *cont); Container *getContainer() const { return _container; } //! Load the component instance virtual void load() = 0; @@ -59,12 +60,16 @@ namespace YACS virtual std::string getKind() const; static const char KIND[]; protected: - //! \b WARNING : _name has a strong semantic. It discriminates ComponentInstance instances each other. - std::string _name; + //! \b WARNING : _compoName identify only the component type. + std::string _compoName; + //! \b WARNING : _InstanceName has a strong semantic. It discriminates ComponentInstance instances each other. + std::string _instanceName; + int _numId; Container *_container; mutable bool _isAttachedOnCloning; protected: static const char NULL_FILE_REPR[]; + static int _total; }; } } diff --git a/src/engine/ComposedNode.cxx b/src/engine/ComposedNode.cxx index 37ef52c88..79ea65e48 100644 --- a/src/engine/ComposedNode.cxx +++ b/src/engine/ComposedNode.cxx @@ -12,6 +12,8 @@ #include #include #include +#include +#include //#define _DEVDEBUG_ #include "YacsTrace.hxx" @@ -37,7 +39,7 @@ void ComposedNode::performDuplicationOfPlacement(const Node& other) { const ComposedNode &otherC=*(dynamic_cast(&other)); DeploymentTree treeToDup=otherC.getDeploymentTree(); - set< ElementaryNode * > clones=otherC.getRecursiveConstituents(); + list< ElementaryNode * > clones=otherC.getRecursiveConstituents(); vector conts=treeToDup.getAllContainers(); for(vector::iterator iterCt=conts.begin();iterCt!=conts.end();iterCt++) { @@ -53,7 +55,7 @@ void ComposedNode::performDuplicationOfPlacement(const Node& other) for(vector::iterator iterT=tasks.begin();iterT!=tasks.end();iterT++) { //No risk for static cast : appendTask called by ComposedNode. - set< ElementaryNode * >::iterator res=clones.find((ElementaryNode *)(*iterT)); + list< ElementaryNode * >::iterator res=find(clones.begin(),clones.end(),(ElementaryNode *)(*iterT)); //No risk here to because called only on cloning process... ServiceNode *nodeC=(ServiceNode *)getChildByName(otherC.getChildName(*res)); nodeC->setComponent(curCloned); @@ -89,28 +91,12 @@ std::string ComposedNode::getTaskName(Task *task) const return getChildName(dynamic_cast(task)); } -bool ComposedNode::operator>(const ComposedNode& other) const -{ - const ComposedNode *iter=_father; - while(iter!=0 && iter!=&other) - iter=iter->_father; - return iter==0; -} - -bool ComposedNode::operator<(const ComposedNode& other) const -{ - const ComposedNode *iter=other._father; - while(iter!=0 && iter!=this) - iter=iter->_father; - return iter==0; -} - //! Essentially for test. Use checkDeploymentTree instead to be sure that returned DeploymentTree is consistent. DeploymentTree ComposedNode::getDeploymentTree() const { DeploymentTree ret; - set< ElementaryNode * > tasks=getRecursiveConstituents(); - for(set< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++) + list< ElementaryNode * > tasks=getRecursiveConstituents(); + for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++) ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this)); return ret; } @@ -122,8 +108,8 @@ DeploymentTree ComposedNode::getDeploymentTree() const DeploymentTree ComposedNode::checkDeploymentTree(bool deep) const throw(Exception) { DeploymentTree ret; - set< ElementaryNode * > tasks=getRecursiveConstituents(); - for(set< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++) + list< ElementaryNode * > tasks=getRecursiveConstituents(); + for(list< ElementaryNode * >::iterator iter=tasks.begin();iter!=tasks.end();iter++) { switch(ret.appendTask(*iter,(*iter)->getDynClonerIfExists(this))) { @@ -203,6 +189,7 @@ void ComposedNode::notifyFrom(const Task *sender, //* I : task emitting event bool ComposedNode::edAddLink(OutPort *start, InPort *end) throw(Exception) { + DEBTRACE("ComposedNode::edAddLink"); set represented; start->getAllRepresented(represented); @@ -216,8 +203,8 @@ bool ComposedNode::edAddLink(OutPort *start, InPort *end) throw(Exception) if(start->isAlreadyLinkedWith(end)) return false; ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode()); - set allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr); - set allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr); + list allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr); + list allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr); checkInMyDescendance(lwstCmnAnctr); lwstCmnAnctr->checkLinkPossibility(start,allAscendanceOfNodeStart,end,allAscendanceOfNodeEnd); ComposedNode *iterS; @@ -273,6 +260,8 @@ bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(Exception) } if(n2 == father) throw Exception("Back link authorized only in special context (loop for example)"); + + bool ret= edAddLink(start,end); if(n1 != father) { //add a control link only if nodes are not in the same descendance @@ -282,9 +271,20 @@ bool ComposedNode::edAddDFLink(OutPort *start, InPort *end) throw(Exception) n1=n1->getFather(); while(n2->getFather() != father) n2=n2->getFather(); - edAddCFLink(n1,n2); + try + { + edAddCFLink(n1,n2); + } + catch (Exception& ex) + { + // --- remove DF link already created in case of cycle dtection + DEBTRACE("Cycle detected, remove CF link"); + if(start->isAlreadyLinkedWith(end)) + edRemoveLink(start, end); + throw ex; + } } - return edAddLink(start,end); + return ret; } //! Add a controlflow link between two control ports. @@ -313,7 +313,17 @@ bool ComposedNode::edAddLink(OutGate *start, InGate *end) throw(Exception) } bool ret=start->edAddInGate(end); if(ret) - checkNoCyclePassingThrough(end->getNode()); + try + { + checkNoCyclePassingThrough(end->getNode()); + } + catch (Exception& ex) + { + // --- remove created CF link in case of cycle detection + DEBTRACE("Cycle detected, remove CF link"); + edRemoveCFLink(start->getNode(), end->getNode()); + throw ex; + } return ret; } @@ -347,30 +357,54 @@ void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(Exception) throw Exception("ComposedNode::edRemoveLink : unexisting link"); ComposedNode* lwstCmnAnctr=getLowestCommonAncestor(start->getNode(),end->getNode()); checkInMyDescendance(lwstCmnAnctr); - set allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr); - set allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr); + list allAscendanceOfNodeStart=start->getNode()->getAllAscendanceOf(lwstCmnAnctr); + list allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr); // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created ComposedNode *iterS=start->getNode()->_father; pair currentPortO(start,start); vector > > needsToDestroyO; - while(iterS!=lwstCmnAnctr) + + Node *nodeOTemp=start->getNode(); + if(*nodeOTemp<*lwstCmnAnctr) { - OutPort *tmp=currentPortO.first; - iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd); - needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair (tmp,currentPortO.first))); - iterS=iterS->_father; + iterS=nodeOTemp->_father; + while(iterS!=lwstCmnAnctr) + { + if (!iterS) + { + stringstream what; + what << "ComposedNode::edRemoveLink: " + << start->getNode()->getName() << "." <getName() << "->" + << end->getNode()->getName() << "." << end->getName(); + throw Exception(what.str()); + } + OutPort *tmp=currentPortO.first; + iterS->getDelegateOf(currentPortO, end, allAscendanceOfNodeEnd); + needsToDestroyO.push_back(pair< ComposedNode * , pair < OutPort* , OutPort *> >(iterS,pair (tmp,currentPortO.first))); + iterS=iterS->_father; + } } - - iterS=end->getNode()->_father; + Node *nodeTemp=end->getNode(); InPort * currentPortI=end; - while(iterS!=lwstCmnAnctr) + if(*nodeTemp<*lwstCmnAnctr) { - iterS->getDelegateOf(currentPortI, start, allAscendanceOfNodeStart); - iterS=iterS->_father; + iterS=nodeTemp->_father; + while(iterS!=lwstCmnAnctr) + { + if (!iterS) + { + stringstream what; + what << "ComposedNode::edRemoveLink: " + << start->getNode()->getName() << "." <getName() << "->" + << end->getNode()->getName() << "." << end->getName(); + throw Exception(what.str()); + } + iterS->getDelegateOf(currentPortI, start, allAscendanceOfNodeStart); + iterS=iterS->_father; + } } - // --- End of test for evt intermediate ports created (currentPortO.first)->removeInPort(currentPortI,false); @@ -385,12 +419,16 @@ void ComposedNode::edRemoveLink(OutPort *start, InPort *end) throw(Exception) vector > >::reverse_iterator iter; for(iter=needsToDestroyO.rbegin();iter!=needsToDestroyO.rend();iter++) (*iter).first->releaseDelegateOf(((*iter).second).first, ((*iter).second).second, end,allAscendanceOfNodeEnd); - iterS=end->getNode()->_father; - currentPortI=end; - while(iterS!=lwstCmnAnctr) + nodeTemp=end->getNode(); + if(*nodeTemp<*lwstCmnAnctr) { - iterS->releaseDelegateOf(currentPortI, start, allAscendanceOfNodeStart); - iterS=iterS->_father; + iterS=end->getNode()->_father; + currentPortI=end; + while(iterS!=lwstCmnAnctr) + { + iterS->releaseDelegateOf(currentPortI, start, allAscendanceOfNodeStart); + iterS=iterS->_father; + } } } @@ -415,6 +453,8 @@ void ComposedNode::edRemoveChild(Node *node) throw(Exception) } node->edDisconnectAllLinksWithMe(); node->_father = 0; + //set _modified flag so edUpdateState() can refresh state + modified(); } //! Splits name globalName in 2 parts using separator. @@ -488,19 +528,15 @@ void ComposedNode::checkConsistency(LinkInfo& info) const throw(Exception) list setOfInToTest=getSetOfInputPort(); for(list::iterator iter1=setOfInToTest.begin();iter1!=setOfInToTest.end();iter1++) { - map > candidateForAdvCheck;//key is physical OutPort, value semantic OutPort behind. + vector candidateForAdvCheck; set outPorts=(*iter1)->edSetOutPort(); //Filtering among outPorts, which of them, are candidates to fill *iter1 at the current scope. for(set::iterator iter2=outPorts.begin();iter2!=outPorts.end();iter2++) { - set repr; - (*iter2)->getAllRepresented(repr); - for(set::iterator iter3=repr.begin();iter3!=repr.end();iter3++) - { - ComposedNode *manager=getLowestCommonAncestor((*iter3)->getNode(),(*iter1)->getNode()); - if(isInMyDescendance(manager)) - candidateForAdvCheck[*iter2].push_back(*iter3); - } + (*iter2)->checkConsistency(info); + ComposedNode *manager=getLowestCommonAncestor((*iter2)->getNode(),(*iter1)->getNode()); + if(isInMyDescendance(manager)) + candidateForAdvCheck.push_back(*iter2); } if(!candidateForAdvCheck.empty()) //End of filtering. Now regarding CF constraints for the current InPutPort. @@ -513,11 +549,30 @@ void ComposedNode::checkConsistency(LinkInfo& info) const throw(Exception) destructCFComputations(info); } +/*! + * This method check that G1 <- G2 <- G3 <- G1 does not happened. + * Typically called by methods that set a hierarchy (Bloc::edAddChild, Loop::edSetNode, ...). + */ +void ComposedNode::checkNoCrossHierachyWith(Node *node) const throw (Exception) +{ + ComposedNode *nodeC=dynamic_cast(node); + if(!nodeC) + return ; + list ascendants=getAllAscendanceOf(); + if(find(ascendants.begin(),ascendants.end(),nodeC)!=ascendants.end()) + { + const char what[]="ComposedNode::checkNoCrossHierachyWith : ComposedNode with name \""; + string stream(what); stream+=node->getName(); stream+="\" is already in hierarchy ascendance of node with name \""; + stream+=_name; stream+="\" ; So it can't be now in its descendance !"; + throw Exception(stream); + } +} + //! perform \b recursively all CF computations. void ComposedNode::performCFComputations(LinkInfo& info) const { - set nodes=edGetDirectDescendants(); - for(set::iterator iter=nodes.begin();iter!=nodes.end();iter++) + list nodes=edGetDirectDescendants(); + for(list::iterator iter=nodes.begin();iter!=nodes.end();iter++) if(dynamic_cast(*iter)) ((ComposedNode *)(*iter))->performCFComputations(info); } @@ -525,38 +580,46 @@ void ComposedNode::performCFComputations(LinkInfo& info) const //! destroy \b recursively all results of initial computations. void ComposedNode::destructCFComputations(LinkInfo& info) const { - set nodes=edGetDirectDescendants(); - for(set::iterator iter=nodes.begin();iter!=nodes.end();iter++) + list nodes=edGetDirectDescendants(); + for(list::iterator iter=nodes.begin();iter!=nodes.end();iter++) if(dynamic_cast(*iter)) ((ComposedNode *)(*iter))->destructCFComputations(info); } +/*! + * Returns the lowest Node (Elementary or Composed) (is sense of hierachy level ( operator< ) ) containing all 'ports'. + * Typically use in consistency computation. + * Precondition : 'ports' \b must contain at least one element. All elements of 'ports' should be in descendance of 'this'. + */ +Node *ComposedNode::getLowestNodeDealingAll(const std::list& ports) const +{ + list< OutPort *>::const_iterator iter=ports.begin(); + Node *ret=(*iter)->getNode(); + iter++; + for(;iter!=ports.end();iter++) + { + Node *tmp=(*iter)->getNode(); + if(*tmp>*ret) + ret=tmp; + } + return ret; +} + /*! * call it only for 'starts' to 'end' links \b DEALED by 'this'. */ -void ComposedNode::checkLinksCoherenceRegardingControl(const std::map >& starts, InputPort *end, LinkInfo& info) const throw(Exception) +void ComposedNode::checkLinksCoherenceRegardingControl(const std::vector& starts, InputPort *end, LinkInfo& info) const throw(Exception) { - map < ComposedNode *, list > outputs;//forward link classical + map < ComposedNode *, list, SortHierarc > outputs;//forward link classical vector outputsCross;//forward link cross - map < ComposedNode *, list > outputsBw;//backward - map >::const_iterator iter1; - vector::const_iterator iter2; + map < ComposedNode *, list, SortHierarc > outputsBw;//backward + vector::const_iterator iter1; + //vector history=((*iter1).second)[0]->calculateHistoryOfLinkWith(end); + //DataPort *cross=DataPort::isCrossingType(history); for(iter1=starts.begin();iter1!=starts.end();iter1++) { - DataPort *cross; - if((*iter1).second[0]==(*iter1).first)//Little optimisation. Representant (key) is equal to first value -> crossing impossible. - { - ComposedNode *manager=getLowestCommonAncestor(((*iter1).first)->getNode(),end->getNode()); - manager->checkControlDependancy((*iter1).first, end, false, outputs, outputsCross, outputsBw, info); - } - else - for(iter2=(*iter1).second.begin();iter2!=(*iter1).second.end();iter2++) - { - ComposedNode *manager=getLowestCommonAncestor(((*iter1).first)->getNode(),end->getNode()); - vector history=((*iter1).second)[0]->calculateHistoryOfLinkWith(end); - cross=DataPort::isCrossingType(history); - manager->checkControlDependancy(*iter2, end, cross!=0, outputs, outputsCross, outputsBw, info); - } + ComposedNode *manager=getLowestCommonAncestor((*iter1)->getNode(),end->getNode()); + manager->checkControlDependancy((*iter1), end, false, outputs, outputsCross, outputsBw, info); } //Ok now let's regarding outputs all combinations : (outputs.size())*(outputs.size()-1)/2 unsigned char isAlreadyFed=FREE_ST; @@ -568,7 +631,7 @@ void ComposedNode::checkLinksCoherenceRegardingControl(const std::map::const_iterator iter1=outputsCross.begin();iter1!=(outputsCross.end()-2);iter1++) info.pushErrLink(*iter1,end,E_COLLAPSE_DS); } - map < ComposedNode *, list >::iterator iter3=outputs.begin(); + map < ComposedNode *, list, SortHierarc >::iterator iter3=outputs.begin(); for(;iter3!=outputs.end();iter3++) ((*iter3).first)->checkCFLinks((*iter3).second,end,isAlreadyFed,true,info); if(isAlreadyFed==FREE_ST) @@ -576,24 +639,55 @@ void ComposedNode::checkLinksCoherenceRegardingControl(const std::map >::reverse_iterator iter5=outputsBw.rbegin(); + map < ComposedNode *, list, SortHierarc >::reverse_iterator iter5=outputsBw.rbegin(); for(;iter5!=outputsBw.rend();iter5++) ((*iter5).first)->checkCFLinks((*iter5).second,end,isAlreadyFed,false,info); } /*! - * \param cross indicates if start -> end link is a DS link behind. - * \param fw out parameter. - * \param fwCross out parameter storing links where a cross has been detected. - * \param bw out parameter where backward links are stored. + * Internal method during CF links. This méthode is in charge to statuate on links consistency in the case that no control flow defined by user + * is set. */ -void ComposedNode::checkControlDependancy(OutPort *start, InPort *end, bool cross, - std::map < ComposedNode *, std::list < OutPort * > >& fw, - std::vector& fwCross, - std::map< ComposedNode *, std::list < OutPort *> >& bw, - LinkInfo& info) const +void ComposedNode::solveObviousOrDelegateCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const { - throw Exception("ComposedNode::checkControlDependancy : Internal error occured - should never been called !"); + static const char what[]="ComposedNode::solveObviousOrDelegateCFLinks : Internal error occured - uncorrect hierarchy detected !"; + if(starts.size()==1) + { + if(alreadyFed==FREE_ST) + { + if(!direction) + info.pushInfoLink(*(starts.begin()),end,I_BACK); + alreadyFed=FED_ST; + } + else if(alreadyFed==FED_ST) + info.pushInfoLink(*(starts.begin()),end,direction ? I_USELESS : I_BACK_USELESS); + else + info.pushErrLink(*(starts.begin()),end,E_COLLAPSE_DFDS); + } + else + { + Node *levelOfDecision=getLowestNodeDealingAll(starts); + if(levelOfDecision==this) + throw Exception(what); + if(dynamic_cast(levelOfDecision)) + { + WarnReason reason; + if(alreadyFed==FREE_ST || alreadyFed==FED_ST) + { + if(alreadyFed==FREE_ST) + { + reason=direction ? W_COLLAPSE_EL : W_BACK_COLLAPSE_EL; + alreadyFed=FED_ST; + } + else + reason=direction ? W_COLLAPSE_EL_AND_USELESS : W_BACK_COLLAPSE_EL_AND_USELESS; + for(list< OutPort *>::const_iterator iter=starts.begin();iter!=starts.end();iter++) + info.pushWarnLink(*iter,end,reason); + } + } + else + ((ComposedNode *)levelOfDecision)->checkCFLinks(starts,end,alreadyFed,direction,info); + } } /*! @@ -601,9 +695,30 @@ void ComposedNode::checkControlDependancy(OutPort *start, InPort *end, bool cros * \param alreadyFed in/out parameter. Indicates if 'end' ports is already and surely set or fed by an another port. * \param direction If true : forward direction else backward direction. */ -void ComposedNode::checkCFLinks(const std::list< OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const -{ - throw Exception("ComposedNode::checkCFLinks : Internal error occured - should never been called !"); +void ComposedNode::checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const +{ + static const char what[]="ComposedNode::checkCFLinks : Internal error occured - uncorrect hierarchy detected !"; + Node *nodeEnd=isInMyDescendance(end->getNode()); + if(!nodeEnd) + return solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info); + //This case is typically dedicated when direct son is ElementaryNode and self link is defined on this. + if(!dynamic_cast(nodeEnd)) + throw Exception(what); + list< OutPort *>::const_iterator iter=starts.begin(); + Node *nodeStart=(*iter)->getNode(); + iter++; + if(nodeEnd!=nodeStart) + throw Exception(what); + for(;iter!=starts.end();iter++) + if((*iter)->getNode()!=nodeStart) + throw Exception(what); + //Ok at this step we are sure that we have back links on the same elementary node. + if(starts.size()>1) + for(iter=starts.begin();iter!=starts.end();iter++) + info.pushWarnLink(*iter,end,W_BACK_COLLAPSE_EL); + else//here no need to look at 'alreadyFed' var because it is waranteed to be equal to FREE_ST by construction. + info.pushInfoLink(*(starts.begin()),end,I_BACK); + alreadyFed=FED_ST; } std::vector< std::pair > ComposedNode::getSetOfLinksComingInCurrentScope() const @@ -672,33 +787,39 @@ std::set ComposedNode::getAllInPortsComingFromOutsideOfCurrentScope() void ComposedNode::edDisconnectAllLinksWithMe() { //CF + DEBTRACE("-"); Node::edDisconnectAllLinksWithMe(); //Leaving part + DEBTRACE("--"); vector< pair > linksToDestroy=getSetOfLinksLeavingCurrentScope(); vector< pair >::iterator iter; for(iter=linksToDestroy.begin();iter!=linksToDestroy.end();iter++) - (*iter).first->removeInPort((*iter).second,true); + { + DEBTRACE("---"); + (*iter).first->removeInPort((*iter).second,true); + } //Arriving part vector< pair > linksToDestroy2=getSetOfLinksComingInCurrentScope(); vector< pair >::iterator iter2; for(iter2=linksToDestroy2.begin();iter2!=linksToDestroy2.end();iter2++) - (*iter2).second->removeInPort((*iter2).first,true); + { + DEBTRACE("----"); + (*iter2).second->removeInPort((*iter2).first,true); + } } -ComposedNode *ComposedNode::getRootNode() throw(Exception) +ComposedNode *ComposedNode::getRootNode() const throw(Exception) { if(!_father) - return this; + return (ComposedNode *)this; return Node::getRootNode(); } -bool ComposedNode::isNodeAlreadyAggregated(Node *node) const +//! Check that Node 'node' is already a direct son of this. +bool ComposedNode::isNodeAlreadyAggregated(const Node *node) const { - set nodeAncestors = node->getAllAscendanceOf(); - if ( nodeAncestors.find((ComposedNode*)this) == nodeAncestors.end() ) - return false; - else - return true; + list nodeAncestors = node->getAllAscendanceOf(); + return find(nodeAncestors.begin(),nodeAncestors.end(),(ComposedNode *)this)!=nodeAncestors.end(); } //! Returns the parent of a node that is the direct child of this node @@ -728,9 +849,9 @@ Node *ComposedNode::isInMyDescendance(Node *nodeToTest) const return 0; } -string ComposedNode::getChildName(Node* node) const throw(Exception) +string ComposedNode::getChildName(const Node* node) const throw(Exception) { - string nodeName = node->getQualifiedName(); + string nodeName=node->getQualifiedName(); if (!isNodeAlreadyAggregated(node)) { if (node->getName() == "thisIsAFakeNode") @@ -745,7 +866,7 @@ string ComposedNode::getChildName(Node* node) const throw(Exception) } } - Node *father = node->_father; + const Node *father = node->_father; while (father != this) { nodeName = father->getQualifiedName() + SEP_CHAR_BTW_LEVEL + nodeName; @@ -842,60 +963,59 @@ ComposedNode *ComposedNode::getLowestCommonAncestor(Node *node1, Node *node2) th return *iter; } -set ComposedNode::getRecursiveConstituents() const +list ComposedNode::getRecursiveConstituents() const { - set ret; - set setOfNode=edGetDirectDescendants(); - for(set::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + list ret; + list setOfNode=edGetDirectDescendants(); + for(list::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) { - set myCurrentSet=(*iter)->getRecursiveConstituents(); - ret.insert(myCurrentSet.begin(),myCurrentSet.end()); + list myCurrentSet=(*iter)->getRecursiveConstituents(); + ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end()); } return ret; } -set ComposedNode::getAllRecursiveConstituents() +//! Idem getAllRecursiveNodes, but this node is NOT included. +list ComposedNode::getAllRecursiveConstituents() { - set ret; - set setOfNode=edGetDirectDescendants(); - for(set::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + list ret; + list setOfNode=edGetDirectDescendants(); + for(list::const_iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) { if ( dynamic_cast (*iter) ) { - set myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveConstituents(); - ret.insert(myCurrentSet.begin(),myCurrentSet.end()); - ret.insert(*iter); + list myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveConstituents(); + ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end()); + ret.push_back(*iter); } else { - set myCurrentSet=(*iter)->getRecursiveConstituents(); - ret.insert(myCurrentSet.begin(),myCurrentSet.end()); + list myCurrentSet=(*iter)->getRecursiveConstituents(); + ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end()); } } return ret; } //! Get all children nodes elementary and composed including this node -set ComposedNode::getAllRecursiveNodes() +list ComposedNode::getAllRecursiveNodes() { - set ret; - set setOfNode=edGetDirectDescendants(); - for(set::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + list ret; + list setOfNode=edGetDirectDescendants(); + for(list::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) { if ( dynamic_cast (*iter) ) { - set myCurrentSet=(*iter)->getRecursiveConstituents(); - ret.insert(myCurrentSet.begin(),myCurrentSet.end()); - //ret.insert(*iter); + list myCurrentSet=(*iter)->getRecursiveConstituents(); + ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end()); } else { - set myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveNodes(); - ret.insert(myCurrentSet.begin(),myCurrentSet.end()); - //ret.insert(*iter); + list myCurrentSet=((ComposedNode*)(*iter))->getAllRecursiveNodes(); + ret.insert(ret.end(),myCurrentSet.begin(),myCurrentSet.end()); } } - ret.insert(this); + ret.push_back(this); return ret; } @@ -916,27 +1036,27 @@ string ComposedNode::getOutPortName(const OutPort *outPort) const throw (Excepti int ComposedNode::getNumberOfInputPorts() const { - set constituents=edGetDirectDescendants(); + list constituents=edGetDirectDescendants(); int ret=0; - for(set::iterator iter=constituents.begin();iter!=constituents.end();iter++) + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) ret+=(*iter)->getNumberOfInputPorts(); return ret; } int ComposedNode::getNumberOfOutputPorts() const { - set constituents=edGetDirectDescendants(); + list constituents=edGetDirectDescendants(); int ret=0; - for(set::iterator iter=constituents.begin();iter!=constituents.end();iter++) + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) ret+=(*iter)->getNumberOfOutputPorts(); return ret; } list ComposedNode::getSetOfInputPort() const { - set constituents=edGetDirectDescendants(); + list constituents=edGetDirectDescendants(); list ret; - for(set::iterator iter=constituents.begin();iter!=constituents.end();iter++) + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) { list currentsPorts=(*iter)->getSetOfInputPort(); ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end()); @@ -946,9 +1066,9 @@ list ComposedNode::getSetOfInputPort() const list ComposedNode::getSetOfOutputPort() const { - set constituents=edGetDirectDescendants(); + list constituents=edGetDirectDescendants(); list ret; - for(set::iterator iter=constituents.begin();iter!=constituents.end();iter++) + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) { list currentsPorts=(*iter)->getSetOfOutputPort(); ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end()); @@ -958,9 +1078,9 @@ list ComposedNode::getSetOfOutputPort() const list ComposedNode::getSetOfInputDataStreamPort() const { - set constituents=edGetDirectDescendants(); + list constituents=edGetDirectDescendants(); list ret; - for(set::iterator iter=constituents.begin();iter!=constituents.end();iter++) + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) { list currentsPorts=(*iter)->getSetOfInputDataStreamPort(); ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end()); @@ -970,9 +1090,9 @@ list ComposedNode::getSetOfInputDataStreamPort() const list ComposedNode::getSetOfOutputDataStreamPort() const { - set constituents=edGetDirectDescendants(); + list constituents=edGetDirectDescendants(); list ret; - for(set::iterator iter=constituents.begin();iter!=constituents.end();iter++) + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) { list currentsPorts=(*iter)->getSetOfOutputDataStreamPort(); ret.insert(ret.end(),currentsPorts.begin(),currentsPorts.end()); @@ -1143,14 +1263,14 @@ YACS::Event ComposedNode::updateStateOnFailedEventFrom(Node *node) return YACS::ABORT; } -void ComposedNode::checkLinkPossibility(OutPort *start, const std::set& pointsOfViewStart, - InPort *end, const std::set& pointsOfViewEnd) throw(Exception) +void ComposedNode::checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) throw(Exception) { if((dynamic_cast(start) or dynamic_cast(end)) and (dynamic_cast(start) or dynamic_cast(end))) {//cross protocol required : deeper check needed bool isOK=false; - set::iterator iter; + list::const_iterator iter; for(iter=pointsOfViewStart.begin();iter!=pointsOfViewStart.end() and !isOK;iter++) isOK=(*iter)->isRepeatedUnpredictablySeveralTimes(); for(iter=pointsOfViewEnd.begin();iter!=pointsOfViewEnd.end() and !isOK;iter++) @@ -1160,27 +1280,27 @@ void ComposedNode::checkLinkPossibility(OutPort *start, const std::set& pointsOfView) +void ComposedNode::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) { } -void ComposedNode::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) +void ComposedNode::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) { } -void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception) +void ComposedNode::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception) { } -void ComposedNode::getDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) throw(Exception) +void ComposedNode::getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) throw(Exception) { } -void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception) +void ComposedNode::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception) { } -void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception) +void ComposedNode::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception) { } @@ -1190,8 +1310,8 @@ void ComposedNode::loaded() void ComposedNode::accept(Visitor *visitor) { - set constituents=edGetDirectDescendants(); - for(set::iterator iter=constituents.begin(); iter!=constituents.end(); iter++) + list constituents=edGetDirectDescendants(); + for(list::iterator iter=constituents.begin(); iter!=constituents.end(); iter++) { (*iter)->accept(visitor); } @@ -1208,3 +1328,67 @@ std::list ComposedNode::getLocalOutputPorts() const { std::list lop; return lop; // empty list } + +bool ComposedNode::isNameAlreadyUsed(const std::string& name) const +{ + return false; +} + +void ComposedNode::edUpdateState() +{ + DEBTRACE("ComposedNode::edUpdateState(): " << _state << " " << _modified); + YACS::StatesForNode state=YACS::READY; + + //update children if needed + list constituents=edGetDirectDescendants(); + for(list::iterator iter=constituents.begin(); iter!=constituents.end(); iter++) + { + if(!(*iter)->isValid()) + state=YACS::INVALID; + } + if(state != _state) + setState(state); + _modified=0; +} + +std::string ComposedNode::getErrorReport() +{ + DEBTRACE("ComposedNode::getErrorReport: " << getName() << " " << _state); + YACS::StatesForNode effectiveState=getEffectiveState(); + if(effectiveState == YACS::READY || effectiveState == YACS::DONE) + return ""; + + std::string report="\n" ; + if(_errorDetails != "") + report=report+_errorDetails+"\n"; + + list constituents=edGetDirectDescendants(); + for(list::iterator iter=constituents.begin(); iter!=constituents.end(); iter++) + { + std::string rep=(*iter)->getErrorReport(); + if(rep != "") + { + report=report+rep+"\n"; + } + } + report=report+""; + return report; +} + + + diff --git a/src/engine/ComposedNode.hxx b/src/engine/ComposedNode.hxx index 1082ae90b..7cfc4902e 100644 --- a/src/engine/ComposedNode.hxx +++ b/src/engine/ComposedNode.hxx @@ -13,6 +13,7 @@ namespace YACS namespace ENGINE { class Bloc; + class Loop; class InPort; class OutPort; class LinkInfo; @@ -21,6 +22,7 @@ namespace YACS class ComposedNode : public Node, public Scheduler { friend class Bloc; + friend class Loop; friend class OutPort; friend class ElementaryNode; protected: @@ -36,8 +38,6 @@ namespace YACS std::string getName() const; std::string getTaskName(Task *task) const; DeploymentTree getDeploymentTree() const; - bool operator>(const ComposedNode& other) const; - bool operator<(const ComposedNode& other) const; DeploymentTree checkDeploymentTree(bool deep) const throw(Exception); std::vector getNextTasks(bool& isMore); virtual bool isPlacementPredictableB4Run() const = 0; @@ -50,10 +50,10 @@ namespace YACS void edRemoveLink(OutPort *start, InPort *end) throw(Exception); void edRemoveLink(OutGate *start, InGate *end) throw(Exception); virtual bool isRepeatedUnpredictablySeveralTimes() const { return false; } - virtual std::set edGetDirectDescendants() const = 0; - std::set getRecursiveConstituents() const; - std::set getAllRecursiveNodes(); - virtual std::set getAllRecursiveConstituents(); // first implementation + virtual std::list edGetDirectDescendants() const = 0; + std::list getRecursiveConstituents() const; + std::list getAllRecursiveNodes(); + virtual std::list getAllRecursiveConstituents(); // first implementation std::string getInPortName(const InPort *) const throw (Exception); std::string getOutPortName(const OutPort *) const throw (Exception); // @@ -73,19 +73,31 @@ namespace YACS InputDataStreamPort *getInputDataStreamPort(const std::string& name) const throw(Exception); OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) const throw(Exception); std::vector< std::pair > getSetOfInternalLinks() const; - std::vector< std::pair > getSetOfLinksLeavingCurrentScope() const; + virtual std::vector< std::pair > getSetOfLinksLeavingCurrentScope() const; void checkConsistency(LinkInfo& info) const throw(Exception); virtual std::vector< std::pair > getSetOfLinksComingInCurrentScope() const; + virtual std::string typeName() {return "YACS__ENGINE__ComposedNode";} + virtual void edUpdateState(); + virtual std::string getErrorReport(); // - ComposedNode *getRootNode() throw(Exception); - bool isNodeAlreadyAggregated(Node *node) const; + ComposedNode *getRootNode() const throw(Exception); + bool isNodeAlreadyAggregated(const Node *node) const; + virtual bool isNameAlreadyUsed(const std::string& name) const; Node *isInMyDescendance(Node *nodeToTest) const; - std::string getChildName(Node* node) const throw(Exception); + std::string getChildName(const Node* node) const throw(Exception); virtual std::string getMyQualifiedName(const Node *directSon) const; Node *getChildByName(const std::string& name) const throw(Exception); static ComposedNode *getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception); void loaded(); void accept(Visitor *visitor); + protected: + struct SortHierarc + { + bool operator()(ComposedNode *n1, ComposedNode *n2) const + { + return *n1<*n2; + } + }; protected: void edDisconnectAllLinksWithMe(); static bool splitNamesBySep(const std::string& globalName, const char separator[], @@ -96,29 +108,32 @@ namespace YACS virtual YACS::Event updateStateOnStartEventFrom(Node *node);//transition 3 doc P.R virtual YACS::Event updateStateOnFinishedEventFrom(Node *node) = 0;//transition 9 doc P.R. virtual YACS::Event updateStateOnFailedEventFrom(Node *node);//transition 9 doc P.R. - virtual void checkLinkPossibility(OutPort *start, const std::set& pointsOfViewStart, - InPort *end, const std::set& pointsOfViewEnd) throw(Exception); - virtual void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView); - virtual void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView); - virtual void getDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception); - virtual void getDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); - virtual void releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception); - virtual void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); + virtual void checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) throw(Exception); + virtual void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView); + virtual void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView); + virtual void getDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception); + virtual void getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); + virtual void releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception); + virtual void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); virtual void checkNoCyclePassingThrough(Node *node) throw(Exception) = 0; void checkInMyDescendance(Node *nodeToTest) const throw(Exception); template std::string getPortName(const PORT * port) const throw (Exception); //For CF Computations + void checkNoCrossHierachyWith(Node *node) const throw (Exception); virtual void performCFComputations(LinkInfo& info) const; virtual void destructCFComputations(LinkInfo& info) const; - void checkLinksCoherenceRegardingControl(const std::map >& starts, + Node *getLowestNodeDealingAll(const std::list& ports) const; + void checkLinksCoherenceRegardingControl(const std::vector& starts, InputPort *end, LinkInfo& info) const throw(Exception); virtual void checkControlDependancy(OutPort *start, InPort *end, bool cross, - std::map < ComposedNode *, std::list < OutPort * > >& fw, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, std::vector& fwCross, - std::map< ComposedNode *, std::list < OutPort *> >& bw, - LinkInfo& info) const; - virtual void checkCFLinks(const std::list< OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const = 0; + void solveObviousOrDelegateCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; + virtual void checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; protected: //For internal calculations. static const unsigned char FED_ST = 2; diff --git a/src/engine/ConditionInputPort.cxx b/src/engine/ConditionInputPort.cxx index 41c215e08..8cc4f3e95 100644 --- a/src/engine/ConditionInputPort.cxx +++ b/src/engine/ConditionInputPort.cxx @@ -76,13 +76,8 @@ void ConditionInputPort::edNotifyDereferencedBy(OutPort *fromPort) InputPort::edNotifyDereferencedBy(fromPort); } -void *ConditionInputPort::get() const throw(Exception) +void *ConditionInputPort::get() const { - if(!_value) - { - std::string what="ConditionInputPort::get : no value currently in input whith name \""; what+=_name; what+="\""; - throw Exception(what); - } return (void *)_value; } diff --git a/src/engine/ConditionInputPort.hxx b/src/engine/ConditionInputPort.hxx index 468bb5cb9..92910722e 100644 --- a/src/engine/ConditionInputPort.hxx +++ b/src/engine/ConditionInputPort.hxx @@ -23,13 +23,13 @@ namespace YACS bool isLinkedOutOfScope() const; void edNotifyReferencedBy(OutPort *fromPort); void edNotifyDereferencedBy(OutPort *fromPort); - void *get() const throw(Exception); + void *get() const; void put(const void *data) throw(ConversionException); std::string dump(); protected: Any *_value; public: - bool getValue() const { return _value->getBoolValue(); } + bool getValue() const { return (_value ? _value->getBoolValue() : false); } }; } } diff --git a/src/engine/Container.cxx b/src/engine/Container.cxx index 802fe1dda..b7d093fe8 100644 --- a/src/engine/Container.cxx +++ b/src/engine/Container.cxx @@ -52,3 +52,12 @@ std::string Container::getProperty(const std::string& name) return _propertyMap[name]; } +void Container::setProperties(std::map properties) +{ + _propertyMap.clear(); + std::map::iterator it; + for (it = properties.begin(); it != properties.end(); ++it) + { + setProperty((*it).first, (*it).second); // setProperty virtual and derived + } +} diff --git a/src/engine/Container.hxx b/src/engine/Container.hxx index afa558ab9..05d025561 100644 --- a/src/engine/Container.hxx +++ b/src/engine/Container.hxx @@ -35,7 +35,13 @@ namespace YACS virtual void checkCapabilityToDealWith(const ComponentInstance *inst) const throw(Exception) = 0; virtual void setProperty(const std::string& name,const std::string& value); virtual std::string getProperty(const std::string& name); + std::map getProperties() { return _propertyMap; }; + virtual void setProperties(std::map properties); + std::string getName() const { return _name; }; + //! \b WARNING ! name is used in edition to identify different containers, it is not the runtime name of the container + void setName(std::string name) { _name = name; }; protected: + std::string _name; mutable bool _isAttachedOnCloning; std::map _propertyMap; }; diff --git a/src/engine/DataFlowPort.cxx b/src/engine/DataFlowPort.cxx index 6e749ff79..cc0c23a50 100644 --- a/src/engine/DataFlowPort.cxx +++ b/src/engine/DataFlowPort.cxx @@ -21,8 +21,3 @@ string DataFlowPort::getNameOfTypeOfCurrentInstance() const { return NAME; } - -bool DataFlowPort::isDifferentTypeOf(const DataPort *other) const -{ - return (dynamic_cast(other))==0; -} diff --git a/src/engine/DataFlowPort.hxx b/src/engine/DataFlowPort.hxx index 77ba805f5..96ee8244f 100644 --- a/src/engine/DataFlowPort.hxx +++ b/src/engine/DataFlowPort.hxx @@ -18,8 +18,9 @@ namespace YACS DataFlowPort(const std::string& name, Node *node, TypeCode* type); public: std::string getNameOfTypeOfCurrentInstance() const; - bool isDifferentTypeOf(const DataPort *other) const; + TypeOfChannel getTypeOfChannel() const { return DATAFLOW; } virtual ~DataFlowPort(); + virtual std::string typeName() {return "YACS__ENGINE__DataFlowPort";} }; } } diff --git a/src/engine/DataNode.cxx b/src/engine/DataNode.cxx new file mode 100644 index 000000000..5ad00653b --- /dev/null +++ b/src/engine/DataNode.cxx @@ -0,0 +1,26 @@ +#include "DataNode.hxx" + +namespace YACS +{ + namespace ENGINE + { + DataNode::~DataNode() + { + } + void DataNode::setData(InputPort* port,std::string& data) + { + } + void DataNode::setData(OutputPort* port,std::string& data) + { + } + void DataNode::setRef(std::string& ref) + { + _ref=ref; + } + std::string DataNode::getRef() + { + return _ref; + } + } +} + diff --git a/src/engine/DataNode.hxx b/src/engine/DataNode.hxx new file mode 100644 index 000000000..c389e362e --- /dev/null +++ b/src/engine/DataNode.hxx @@ -0,0 +1,35 @@ +#ifndef __DATANODE_HXX__ +#define __DATANODE_HXX__ + +#include "ElementaryNode.hxx" +#include + +namespace YACS +{ + namespace ENGINE + { +/*! \brief Class for data parameters specification + * + * \ingroup Nodes + * + */ + class DataNode : public ElementaryNode + { + protected: + DataNode(const DataNode& other, ComposedNode *father) + :ElementaryNode(other,father){ } + DataNode(const std::string& name):ElementaryNode(name) { } + public: + virtual void setData(InputPort* port ,std::string& data); + virtual void setData(OutputPort* port ,std::string& data); + virtual void setRef(std::string& ref); + virtual std::string getRef(); + virtual ~DataNode(); + virtual std::string typeName() {return "YACS__ENGINE__DataNode";} + protected: + std::string _ref; + }; + } +} + +#endif diff --git a/src/engine/DataPort.cxx b/src/engine/DataPort.cxx index ef679fea9..1c12fb73f 100644 --- a/src/engine/DataPort.cxx +++ b/src/engine/DataPort.cxx @@ -1,4 +1,5 @@ #include "DataPort.hxx" +#include "TypeCode.hxx" #include using namespace YACS::ENGINE; @@ -35,6 +36,10 @@ string DataPort::getNameOfTypeOfCurrentInstance() const return NAME; } +bool DataPort::isDifferentTypeOf(const DataPort *other) const +{ + return getTypeOfChannel()!=other->getTypeOfChannel(); +} /*! * If in historyOfLink different type of Port are detected : The first one (by starting from the end of 'historyOfLink') diff --git a/src/engine/DataPort.hxx b/src/engine/DataPort.hxx index 96b546412..195162d99 100644 --- a/src/engine/DataPort.hxx +++ b/src/engine/DataPort.hxx @@ -2,11 +2,21 @@ #define __DATAPORT_HXX__ #include "Port.hxx" +#include "Exception.hxx" +#include namespace YACS { namespace ENGINE { + class TypeCode; + + typedef enum + { + DATAFLOW, + DATASTREAM + } TypeOfChannel; + class DataPort : public virtual Port { protected: @@ -22,9 +32,13 @@ namespace YACS TypeCode* edGetType() const { return _type; } void edSetType(TypeCode* type); std::string getName() const { return _name; } + void setName( std::string theName ) { _name = theName; } std::string getNameOfTypeOfCurrentInstance() const; - virtual bool isDifferentTypeOf(const DataPort *other) const = 0; + //! returns type of channel the port will use for data exchange on runtime : DATAFLOW or DATASTREAM. + virtual TypeOfChannel getTypeOfChannel() const = 0; + bool isDifferentTypeOf(const DataPort *other) const; virtual void edRemoveAllLinksLinkedWithMe() throw(Exception) = 0; + virtual std::string typeName() {return "YACS__ENGINE__DataPort";} public: static DataPort *isCrossingType(const std::vector& historyOfLink); }; diff --git a/src/engine/DataStreamPort.cxx b/src/engine/DataStreamPort.cxx index 016471985..07715720e 100644 --- a/src/engine/DataStreamPort.cxx +++ b/src/engine/DataStreamPort.cxx @@ -23,11 +23,6 @@ string DataStreamPort::getNameOfTypeOfCurrentInstance() const return NAME; } -bool DataStreamPort::isDifferentTypeOf(const DataPort *other) const -{ - return (dynamic_cast(other))==0; -} - void DataStreamPort::setProperty(const std::string& name, const std::string& value) { _propertyMap[name]=value; @@ -41,3 +36,12 @@ void DataStreamPort::initPortProperties() { } +void DataStreamPort::setProperties(std::map properties) +{ + _propertyMap.clear(); + std::map::iterator it; + for (it = properties.begin(); it != properties.end(); ++it) + { + setProperty((*it).first, (*it).second); // setProperty virtual and derived + } +} diff --git a/src/engine/DataStreamPort.hxx b/src/engine/DataStreamPort.hxx index 2556d8ad8..fac9ebe8d 100644 --- a/src/engine/DataStreamPort.hxx +++ b/src/engine/DataStreamPort.hxx @@ -2,7 +2,6 @@ #define __DATASTREAMPORT_HXX__ #include "DataPort.hxx" -#include "TypeCode.hxx" #include #include @@ -21,12 +20,14 @@ namespace YACS std::map _propertyMap; public: std::string getNameOfTypeOfCurrentInstance() const; - bool isDifferentTypeOf(const DataPort *other) const; + TypeOfChannel getTypeOfChannel() const { return DATASTREAM; } virtual void setProperty(const std::string& name,const std::string& value); + virtual void setProperties(std::map properties); virtual std::string getProperty(const std::string& name); std::map getPropertyMap() const { return _propertyMap; } virtual void initPortProperties(); virtual ~DataStreamPort(); + virtual std::string typeName() {return "YACS__ENGINE__DataStreamPort";} }; } } diff --git a/src/engine/Dispatcher.cxx b/src/engine/Dispatcher.cxx index 581100bbc..f93490670 100644 --- a/src/engine/Dispatcher.cxx +++ b/src/engine/Dispatcher.cxx @@ -2,6 +2,9 @@ #include "Node.hxx" #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; Observer::~Observer() @@ -10,7 +13,7 @@ Observer::~Observer() void Observer::notifyObserver(Node* object, const std::string& event) { - std::cerr << "notifyObserver " << event << object << std::endl; + DEBTRACE("notifyObserver " << event << object ); } Dispatcher* Dispatcher::_singleton = 0; @@ -52,7 +55,7 @@ void Dispatcher::printObservers() void Dispatcher::dispatch(Node* object, const std::string& event) { - //std::cerr << "Dispatcher::dispatch " << event << std::endl; + DEBTRACE("Dispatcher::dispatch " << event ); typedef std::set::iterator jt; std::pair key(object,event); if(_observers.count(key) != 0) diff --git a/src/engine/DynParaLoop.cxx b/src/engine/DynParaLoop.cxx index 3fa713db0..4d3ec98db 100644 --- a/src/engine/DynParaLoop.cxx +++ b/src/engine/DynParaLoop.cxx @@ -1,6 +1,6 @@ #include "DynParaLoop.hxx" +#include "LinkInfo.hxx" #include "OutPort.hxx" -#include //#define _DEVDEBUG_ #include "YacsTrace.hxx" @@ -88,10 +88,13 @@ Node *DynParaLoop::edSetNode(Node *node) throw Exception(what); } } + checkNoCrossHierachyWith(node); ComposedNode::edRemoveChild(_node); Node *ret=_node; _node=node; _node->_father=this; + //set _modified flag so that edUpdateState can refresh state + modified(); return ret; } @@ -126,10 +129,12 @@ Node *DynParaLoop::edSetInitNode(Node *node) throw Exception(what); } } + checkNoCrossHierachyWith(node); edRemoveChild(_initNode); Node *ret=_initNode; _initNode=node; _initNode->_father=this; + modified(); return ret; } @@ -205,13 +210,13 @@ void DynParaLoop::edRemoveChild(Node *node) throw(Exception) _initNode=0; } -std::set DynParaLoop::edGetDirectDescendants() const +std::list DynParaLoop::edGetDirectDescendants() const { - set ret; + list ret; if(_node) - ret.insert(_node); + ret.push_back(_node); if(_initNode) - ret.insert(_initNode); + ret.push_back(_initNode); return ret; } @@ -222,6 +227,13 @@ std::list DynParaLoop::getSetOfInputPort() const return ret; } +std::list DynParaLoop::getLocalInputPorts() const +{ + list ret=ComposedNode::getLocalInputPorts(); + ret.push_back((InputPort *)&_nbOfBranches); + return ret; +} + unsigned DynParaLoop::getNumberOfBranchesCreatedDyn() const throw(Exception) { if(_execNodes.empty()) @@ -346,14 +358,14 @@ void DynParaLoop::forceMultiplicity(unsigned value) _nbOfBranches.edInit((int)value); } -void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) +void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) { string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance!=InputPort::NAME) throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop this is not possible"); } -void DynParaLoop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) +void DynParaLoop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) { if(_initNode) if(isInMyDescendance(port.first->getNode())==_initNode) @@ -362,6 +374,46 @@ void DynParaLoop::buildDelegateOf(std::pair& port, InPort throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : splitted port must be link within the scope of ForEachLoop node it belongs to."); } +void DynParaLoop::checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const +{ + const char what[]="DynParaLoop::checkCFLinks : internal error."; + //First dealing checkCFLinks forwarding... + if(isInMyDescendance(end->getNode())==0)//no chance that _splittedPort is in starts due to buildDelegate. + solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info); + else + {//no forwarding here. + if(starts.size()!=1) + throw Exception(what); + //ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled. + if(*(starts.begin())!=&_splittedPort) + throw Exception(what); + if(alreadyFed==FREE_ST) + alreadyFed=FED_ST; + else if(alreadyFed==FED_ST) + {//Shame ! splittedPort fills a port already fed... + info.pushInfoLink(*(starts.begin()),end,I_USELESS); + } + } +} + +/*! + * \param cross indicates if start -> end link is a DS link behind. + * \param fw out parameter. + * \param fwCross out parameter storing links where a cross has been detected. + * \param bw out parameter where backward links are stored. + */ +void DynParaLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const +{ + if(start==&_splittedPort) + fw[(ComposedNode *)this].push_back(start); + else + throw Exception("DynParaLoop::checkControlDependancy : Internal error occured - should never been called !"); +} + /*! * \note : For a given name 'name' of port in absolute form from this, returns the corresponding InputPort instance of the * port for the branch # 'branchNb'. The port can be part of _node or _initNode if it exists (if 'initNodeAdmitted' is true). diff --git a/src/engine/DynParaLoop.hxx b/src/engine/DynParaLoop.hxx index 6978a6995..639499c2a 100644 --- a/src/engine/DynParaLoop.hxx +++ b/src/engine/DynParaLoop.hxx @@ -58,8 +58,9 @@ namespace YACS public: Node *edRemoveNode(); Node *edRemoveInitNode(); - Node *edSetNode(Node *node); - Node *edSetInitNode(Node *node); + //Node* DISOWNnode is a SWIG notation to indicate that the ownership of the node is transfered to C++ + Node *edSetNode(Node *DISOWNnode); + Node *edSetInitNode(Node *DISOWNnode); void init(bool start=true); InputPort *edGetNbOfBranchesPort() { return &_nbOfBranches; } int getNumberOfInputPorts() const; @@ -73,8 +74,9 @@ namespace YACS //! For the moment false is returned : impovement about it coming soon. bool isPlacementPredictableB4Run() const; void edRemoveChild(Node *node) throw(Exception); - std::set edGetDirectDescendants() const; + std::list edGetDirectDescendants() const; std::list getSetOfInputPort() const; + std::list getLocalInputPorts() const; unsigned getNumberOfBranchesCreatedDyn() const throw(Exception); Node *getChildByShortName(const std::string& name) const throw(Exception); Node *getChildByNameExec(const std::string& name, unsigned id) const throw(Exception); @@ -82,8 +84,14 @@ namespace YACS bool isMultiplicitySpecified(unsigned& value) const; void forceMultiplicity(unsigned value); protected: - void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView); - void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView); + void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView); + void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView); + void checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; + void checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const; protected: void cleanDynGraph(); void prepareInputsFromOutOfScope(int branchNb); diff --git a/src/engine/ElementaryNode.cxx b/src/engine/ElementaryNode.cxx index ad1fb4144..921047e0e 100644 --- a/src/engine/ElementaryNode.cxx +++ b/src/engine/ElementaryNode.cxx @@ -8,6 +8,9 @@ #include "Visitor.hxx" #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; using namespace std; @@ -56,9 +59,9 @@ void ElementaryNode::init(bool start) return; } if(start) //complete initialization - setState(YACS::INITED); + setState(YACS::READY); else //partial initialization (inside a loop) - _state=YACS::LOADED; + setState(YACS::LOADED); } bool ElementaryNode::isDeployable() const @@ -78,18 +81,22 @@ YACS::StatesForNode ElementaryNode::getState() const void ElementaryNode::exUpdateState() { + DEBTRACE("ElementaryNode::exUpdateState: " << getName() << " " << _state ); if(_state==YACS::DISABLED)return; if(_inGate.exIsReady()) if(areAllInputPortsValid()) - if(_state == YACS::INITED) - setState(YACS::TOLOAD); - else - setState(YACS::TOACTIVATE); + { + if(_state == YACS::READY) + ensureLoading(); + else if(_state == YACS::LOADED) + setState(YACS::TOACTIVATE); + } else { string what("ElementaryNode::exUpdateState : Invalid graph given : Node with name \""); what+=_name; what+="\" ready to run whereas some inputports are not set correctly\nCheck coherence DF/CF"; setState(YACS::INTERNALERR); + _errorDetails=what; throw Exception(what); } } @@ -140,6 +147,32 @@ std::set ElementaryNode::getAllInPortsComingFromOutsideOfCurrentScope( return ret; } +std::vector< std::pair > ElementaryNode::getSetOfLinksLeavingCurrentScope() const +{ + vector< pair > ret; + std::set ports=getAllOutPortsLeavingCurrentScope(); + for(set::iterator iter2=ports.begin();iter2!=ports.end();iter2++) + { + set temp2=(*iter2)->edSetInPort(); + for(set::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++) + ret.push_back(pair(*iter2,*iter3)); + } + return ret; +} + +std::vector< std::pair > ElementaryNode::getSetOfLinksComingInCurrentScope() const +{ + vector< pair > ret; + set ports=getAllInPortsComingFromOutsideOfCurrentScope(); + for(set::iterator iter2=ports.begin();iter2!=ports.end();iter2++) + { + set temp2=(*iter2)->edSetOutPort(); + for(set::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++) + ret.push_back(pair(*iter2,*iter3)); + } + return ret; +} + InputDataStreamPort *ElementaryNode::getInputDataStreamPort(const std::string& name) const throw(Exception) { return getPort(name,_setOfInputDataStreamPort); @@ -192,6 +225,7 @@ bool ElementaryNode::areAllInputPortsValid() const void ElementaryNode::getReadyTasks(std::vector& tasks) { + DEBTRACE("ElementaryNode::getReadyTasks: " << getName() << " " << _state); if(_state==YACS::TOACTIVATE or _state==YACS::TOLOAD) tasks.push_back(this); } @@ -202,6 +236,7 @@ void ElementaryNode::getReadyTasks(std::vector& tasks) void ElementaryNode::edRemovePort(Port *port) throw(Exception) { + DEBTRACE("ElementaryNode::edRemovePort "); if(port->getNode()!=this) throw Exception("ElementaryNode::edRemovePort : Port is not held by this"); string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance(); @@ -216,16 +251,17 @@ void ElementaryNode::edRemovePort(Port *port) throw(Exception) else throw Exception("ElementaryNode::edRemovePort : unknown port type"); delete port; + modified(); } /** * @return a set with only this node. (Same method in composed nodes) */ -set ElementaryNode::getRecursiveConstituents() const +list ElementaryNode::getRecursiveConstituents() const { - set ret; - ret.insert((ElementaryNode *)this); + list ret; + ret.push_back((ElementaryNode *)this); return ret; } @@ -237,6 +273,7 @@ Node *ElementaryNode::getChildByName(const std::string& name) const throw(Except void ElementaryNode::checkBasicConsistency() const throw(Exception) { + DEBTRACE("ElementaryNode::checkBasicConsistency"); list::const_iterator iter; for(iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++) (*iter)->checkBasicConsistency(); @@ -250,6 +287,11 @@ ComposedNode *ElementaryNode::getDynClonerIfExists(const ComposedNode *levelToSt return 0; } +InputPort *ElementaryNode::createInputPort(const std::string& inputPortName, TypeCode* type) +{ + return getRuntime()->createInputPort(inputPortName, _implementation, this, type); +} + /** * the input port is also published recursively in ancestors because it may be visible from everywhere. * WARNING: CHECK CASE OF BLOC: ONLY INPUT PORTS NOT INTERNALLY CONNECTED MUST BE VISIBLE. @@ -260,15 +302,23 @@ InputPort *ElementaryNode::edAddInputPort(const std::string& inputPortName, Type InputPort *ret = 0; if (edCheckAddPort(inputPortName,_setOfInputPort,type)) { - ret = getRuntime()->createInputPort(inputPortName, _implementation, this, type); + ret = createInputPort(inputPortName, type); _setOfInputPort.push_back(ret); + modified(); + /* ComposedNode *iter=_father; while(iter) iter=iter->_father; + */ } return ret; } +OutputPort *ElementaryNode::createOutputPort(const std::string& outputPortName, TypeCode* type) +{ + return getRuntime()->createOutputPort(outputPortName, _implementation, this, type); +} + /** * TO SOLVE : The output port is not published in father. Father must create an output port. * for now, publication is done the same way as input ports @@ -279,33 +329,48 @@ OutputPort *ElementaryNode::edAddOutputPort(const std::string& outputPortName, T OutputPort *ret =0; if (edCheckAddPort(outputPortName,_setOfOutputPort,type)) { - ret = getRuntime()->createOutputPort(outputPortName, _implementation, this, type); + ret = createOutputPort(outputPortName, type); _setOfOutputPort.push_back(ret); + modified(); + /* ComposedNode *iter=_father; while(iter) iter=iter->_father; + */ } return ret; } +InputDataStreamPort *ElementaryNode::createInputDataStreamPort(const std::string& inputPortDSName, TypeCode* type) +{ + return getRuntime()->createInputDataStreamPort(inputPortDSName, this, type); +} + InputDataStreamPort *ElementaryNode::edAddInputDataStreamPort(const std::string& inputPortDSName, TypeCode* type) throw(Exception) { InputDataStreamPort *ret = 0; if (edCheckAddPort(inputPortDSName,_setOfInputDataStreamPort,type)) { - ret = getRuntime()->createInputDataStreamPort(inputPortDSName, this, type); + ret = createInputDataStreamPort(inputPortDSName, type); _setOfInputDataStreamPort.push_back(ret); + modified(); } return ret; } +OutputDataStreamPort *ElementaryNode::createOutputDataStreamPort(const std::string& outputPortDSName, TypeCode* type) +{ + return getRuntime()->createOutputDataStreamPort(outputPortDSName, this, type); +} + OutputDataStreamPort *ElementaryNode::edAddOutputDataStreamPort(const std::string& outputPortDSName, TypeCode* type) throw(Exception) { OutputDataStreamPort *ret = 0; if (edCheckAddPort(outputPortDSName,_setOfOutputDataStreamPort,type)) { - ret = getRuntime()->createOutputDataStreamPort(outputPortDSName, this, type); + ret = createOutputDataStreamPort(outputPortDSName, type); _setOfOutputDataStreamPort.push_back(ret); + modified(); } return ret; } @@ -363,10 +428,73 @@ void ElementaryNode::aborted() */ void ElementaryNode::loaded() { - setState(TOACTIVATE); + setState(LOADED); + if(_inGate.exIsReady()) + if(areAllInputPortsValid()) + setState(TOACTIVATE); } void ElementaryNode::accept(Visitor *visitor) { visitor->visitElementaryNode(this); } + +//! Give a description of error when node status is ERROR +/*! + * + */ +std::string ElementaryNode::getErrorDetails() +{ + return _errorDetails; +} + +void ElementaryNode::edUpdateState() +{ + DEBTRACE("ElementaryNode::edUpdateState: " << getName()); + YACS::StatesForNode state=YACS::READY; + try + { + checkBasicConsistency(); + _errorDetails=""; + } + catch(Exception& e) + { + state=YACS::INVALID; + _errorDetails=e.what(); + } + DEBTRACE("ElementaryNode::edUpdateState: " << _errorDetails); + if(state != _state) + setState(state); + _modified=0; +} + +//! Put this node into TOLOAD state when possible +/*! + * Can be called by another ElementaryNode that is connected to this one by a datastream link + * These 2 nodes must be loaded at the same time as they are coupled + * It's the other node which requests this node loading + */ +void ElementaryNode::ensureLoading() +{ + DEBTRACE("ElementaryNode::ensureLoading: " << getName()); + if(_state != YACS::READY) + return; + setState(YACS::TOLOAD); + + // request loading for all nodes connected to this one by datastream link + // Be careful that nodes can be connected in a loop. Put first this node in TOLOAD state to break the loop + std::list::iterator iter; + for(iter = _setOfOutputDataStreamPort.begin(); iter != _setOfOutputDataStreamPort.end(); iter++) + { + OutputDataStreamPort *port=(OutputDataStreamPort *)*iter; + std::set ports=port->edSetInPort(); + std::set::iterator iterout; + for(iterout=ports.begin();iterout != ports.end(); iterout++) + { + Node* node= (*iterout)->getNode(); + node->ensureLoading(); + } + } + /* + */ +} diff --git a/src/engine/ElementaryNode.hxx b/src/engine/ElementaryNode.hxx index 3e4cb5391..aecf8efbc 100644 --- a/src/engine/ElementaryNode.hxx +++ b/src/engine/ElementaryNode.hxx @@ -1,7 +1,6 @@ #ifndef __ELEMENTARYNODE_HXX__ #define __ELEMENTARYNODE_HXX__ -#include "TypeCode.hxx" #include "Node.hxx" #include "Task.hxx" #include "define.hxx" @@ -11,6 +10,7 @@ namespace YACS { namespace ENGINE { + class TypeCode; class Port; class InputPort; class OutputPort; @@ -39,9 +39,9 @@ namespace YACS YACS::StatesForNode getState() const; void getReadyTasks(std::vector& tasks); void edRemovePort(Port *port) throw(Exception); - std::set getRecursiveConstituents() const; + std::list getRecursiveConstituents() const; Node *getChildByName(const std::string& name) const throw(Exception); - void checkBasicConsistency() const throw(Exception); + virtual void checkBasicConsistency() const throw(Exception); ComposedNode *getDynClonerIfExists(const ComposedNode *levelToStop) const; int getNumberOfInputPorts() const; int getNumberOfOutputPorts() const; @@ -55,20 +55,31 @@ namespace YACS std::list getLocalOutputPorts() const { return _setOfOutputPort; } std::set getAllOutPortsLeavingCurrentScope() const; std::set getAllInPortsComingFromOutsideOfCurrentScope() const; + virtual std::vector< std::pair > getSetOfLinksLeavingCurrentScope() const; + virtual std::vector< std::pair > getSetOfLinksComingInCurrentScope() const; std::list getSetOfInputDataStreamPort() const { return _setOfInputDataStreamPort; } std::list getSetOfOutputDataStreamPort() const { return _setOfOutputDataStreamPort; } InputDataStreamPort *getInputDataStreamPort(const std::string& name) const throw(Exception); OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) const throw(Exception); + virtual InputPort *createInputPort(const std::string& inputPortName, TypeCode* type); + virtual OutputPort *createOutputPort(const std::string& outputPortName, TypeCode* type); + virtual InputDataStreamPort *createInputDataStreamPort(const std::string& inputPortDSName, TypeCode* type); + virtual OutputDataStreamPort *createOutputDataStreamPort(const std::string& outputPortDSName, TypeCode* type); virtual InputPort *edAddInputPort(const std::string& inputPortName, TypeCode* type) throw(Exception); virtual OutputPort *edAddOutputPort(const std::string& outputPortName, TypeCode* type) throw(Exception); virtual InputDataStreamPort *edAddInputDataStreamPort(const std::string& inputPortDSName, TypeCode* type) throw(Exception); virtual OutputDataStreamPort *edAddOutputDataStreamPort(const std::string& outputPortDSName, TypeCode* type) throw(Exception); + virtual std::string typeName() {return "YACS__ENGINE__ElementaryNode";} + virtual void edUpdateState(); + virtual void ensureLoading(); + //run part void begin(); bool isReady(); void finished(); void aborted(); void loaded(); + virtual std::string getErrorDetails(); virtual void initService() { } virtual void connectService() { } virtual void disconnectService() { } diff --git a/src/engine/Executor.cxx b/src/engine/Executor.cxx index 9cabe6c6f..eaec94266 100644 --- a/src/engine/Executor.cxx +++ b/src/engine/Executor.cxx @@ -198,8 +198,18 @@ void Executor::RunB(Scheduler *graph,int debug, bool fromScratch) if (fromScratch) { - graph->init(); - graph->exUpdateState(); + try + { + graph->init(); + graph->exUpdateState(); + } + catch(Exception& ex) + { + DEBTRACE("exception: "<< (ex.what())); + _executorState = YACS::FINISHED; + sendEvent("executor"); + throw; + } } _executorState = YACS::INITIALISED; sendEvent("executor"); @@ -284,7 +294,7 @@ void Executor::RunB(Scheduler *graph,int debug, bool fromScratch) } _mutexForSchedulerUpdate.unlock(); } // --- End of critical section - if ( _dumpOnErrorRequested && _errorDetected && !_isRunningunderExternalControl) + if ( _dumpOnErrorRequested && _errorDetected) { saveState(_dumpErrorFile); } @@ -328,6 +338,20 @@ void Executor::setStopOnError(bool dumpRequested, std::string xmlFile) if (dumpRequested && xmlFile.empty()) throw YACS::Exception("dump on error requested and no filename given for dump"); _mutexForSchedulerUpdate.unlock(); + DEBTRACE("_dumpErrorFile " << _dumpErrorFile << " " << _dumpOnErrorRequested); + } // --- End of critical section +} + +//! ask to do not stop execution on nodes found in error +/*! + */ + +void Executor::unsetStopOnError() +{ + { // --- Critical section + _mutexForSchedulerUpdate.lock(); + _stopOnErrorRequested=false; + _mutexForSchedulerUpdate.unlock(); } // --- End of critical section } @@ -521,7 +545,7 @@ bool Executor::setStepsToExecute(std::list listToExecute) void Executor::waitPause() { - DEBTRACE("Executor::waitPause()"); + DEBTRACE("Executor::waitPause()" << _executorState); { // --- Critical section _mutexForSchedulerUpdate.lock(); _isRunningunderExternalControl=true; @@ -578,7 +602,7 @@ bool Executor::loadState() } -static int isfile(char *filename) +static int isfile(const char *filename) { struct stat buf; if (stat(filename, &buf) != 0) @@ -606,7 +630,8 @@ void Executor::_displayDot(Scheduler *graph) std::ofstream g("titi"); ((ComposedNode*)graph)->writeDot(g); g.close(); - if(isfile("display.sh")) + const char displayScript[]="display.sh"; + if(isfile(displayScript)) system("sh display.sh"); else system("dot -Tpng titi|display -delay 5"); @@ -740,7 +765,10 @@ void Executor::loadTask(Task *task) }//End of critical section try { + traceExec(task, "load"); task->load(); + traceExec(task, "initService"); + task->initService(); } catch(Exception& ex) { @@ -773,37 +801,7 @@ void Executor::loadTask(Task *task) void Executor::launchTasks(std::vector& tasks) { vector::iterator iter; - //First phase, initialize the execution - for(iter=tasks.begin();iter!=tasks.end();iter++) - { - if((*iter)->getState() != YACS::TOACTIVATE)continue; - try - { - (*iter)->initService(); - traceExec(*iter, "initService"); - } - catch(Exception& ex) - { - std::cerr << ex.what() << std::endl; - {//Critical section - _mutexForSchedulerUpdate.lock(); - (*iter)->aborted(); - _mainSched->notifyFrom(*iter,YACS::ABORT); - _mutexForSchedulerUpdate.unlock(); - }//End of critical section - } - catch(...) - { - std::cerr << "Problem in initService" << std::endl; - {//Critical section - _mutexForSchedulerUpdate.lock(); - (*iter)->aborted(); - _mainSched->notifyFrom(*iter,YACS::ABORT); - _mutexForSchedulerUpdate.unlock(); - }//End of critical section - } - } - //Second phase, make datastream connections + //First phase, make datastream connections for(iter=tasks.begin();iter!=tasks.end();iter++) { if((*iter)->getState() != YACS::TOACTIVATE)continue; @@ -833,12 +831,9 @@ void Executor::launchTasks(std::vector& tasks) }//End of critical section } } - //Third phase, execute each task in a thread + //Second phase, execute each task in a thread for(iter=tasks.begin();iter!=tasks.end();iter++) { - DEBTRACE("before _semForMaxThreads.wait " << _semThreadCnt); - _semForMaxThreads.wait(); - _semThreadCnt -= 1; launchTask(*iter); } } @@ -856,6 +851,11 @@ void Executor::launchTask(Task *task) { DEBTRACE("Executor::launchTask(Task *task)"); if(task->getState() != YACS::TOACTIVATE)return; + + DEBTRACE("before _semForMaxThreads.wait " << _semThreadCnt); + _semForMaxThreads.wait(); + _semThreadCnt -= 1; + void **args=new void *[3]; args[0]=(void *)task; args[1]=(void *)_mainSched; @@ -1001,7 +1001,7 @@ void *Executor::functionForTaskExecution(void *arg) if (execInst->_stopOnErrorRequested) { execInst->_execMode = YACS::STEPBYSTEP; - if (!execInst->_isRunningunderExternalControl) execInst->_isOKToEnd = true; + execInst->_isOKToEnd = true; } task->aborted(); } diff --git a/src/engine/Executor.hxx b/src/engine/Executor.hxx index 233e23278..a7e6aaa4c 100644 --- a/src/engine/Executor.hxx +++ b/src/engine/Executor.hxx @@ -77,6 +77,7 @@ namespace YACS int getNbOfThreads(); void displayDot(Scheduler *graph); void setStopOnError(bool dumpRequested=false, std::string xmlFile=""); + void unsetStopOnError(); void waitPause(); protected: bool checkBreakPoints(); diff --git a/src/engine/ForEachLoop.cxx b/src/engine/ForEachLoop.cxx index b9b4484e0..68bc73e95 100644 --- a/src/engine/ForEachLoop.cxx +++ b/src/engine/ForEachLoop.cxx @@ -1,4 +1,5 @@ #include "ForEachLoop.hxx" +#include "TypeCode.hxx" #include "Visitor.hxx" #include #include @@ -89,7 +90,8 @@ int AnySplitOutputPort::removeInPort(InPort *inPort, bool forward) throw(Excepti { bool ret=OutputPort::removeInPort(inPort,forward); if(_repr) - _repr->removeInPort(_intercptr,forward); + if(_setOfInputPort.empty()) + _repr->removeInPort(_intercptr,forward); return ret; } @@ -414,11 +416,6 @@ int ForEachLoop::getNumberOfInputPorts() const return DynParaLoop::getNumberOfInputPorts()+1; } -void ForEachLoop::checkConsistency(ComposedNode *pointOfView) const throw(Exception) -{ - //TO DO -} - void ForEachLoop::checkNoCyclePassingThrough(Node *node) throw(Exception) { //TO DO @@ -435,6 +432,13 @@ std::list ForEachLoop::getSetOfInputPort() const return ret; } +std::list ForEachLoop::getLocalInputPorts() const +{ + list ret=DynParaLoop::getLocalInputPorts(); + ret.push_back((InputPort *)&_splitterNode._dataPortToDispatch); + return ret; +} + InputPort *ForEachLoop::getInputPort(const std::string& name) const throw(Exception) { if(name==SplitterNode::NAME_OF_SEQUENCE_INPUT) @@ -521,7 +525,7 @@ YACS::Event ForEachLoop::updateStateOnFinishedEventFrom(Node *node) return YACS::NOEVENT; } -void ForEachLoop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) +void ForEachLoop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) { DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView); string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance(); @@ -555,7 +559,7 @@ void ForEachLoop::buildDelegateOf(std::pair& port, InPort throw Exception("ForEachLoop::buildDelegateOf : not implemented for DS because not specified"); } -void ForEachLoop::getDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) throw(Exception) +void ForEachLoop::getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) throw(Exception) { string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance==OutputPort::NAME) @@ -576,7 +580,7 @@ void ForEachLoop::getDelegateOf(std::pair& port, InPort *f throw Exception("ForEachLoop::getDelegateOf : not implemented because not specified"); } -void ForEachLoop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception) +void ForEachLoop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception) { string typeOfPortInstance=portDwn->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance==OutputPort::NAME) @@ -661,8 +665,8 @@ void ForEachLoop::createOutputOutOfScopeInterceptors(int branchNb) } } -void ForEachLoop::checkLinkPossibility(OutPort *start, const std::set& pointsOfViewStart, - InPort *end, const std::set& pointsOfViewEnd) throw(Exception) +void ForEachLoop::checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) throw(Exception) { if(isInMyDescendance(start->getNode())==_node) throw Exception("ForEachLoop::checkLinkPossibility : A link from work node to init node not permitted"); @@ -685,12 +689,15 @@ void ForEachLoop::accept(Visitor *visitor) /*! * \param os : the output stream */ -void ForEachLoop::writeDot(std::ostream &os) +void ForEachLoop::writeDot(std::ostream &os) const { os << " subgraph cluster_" << getId() << " {\n" ; //only one node in a loop - _node->writeDot(os); - os << getId() << " -> " << _node->getId() << ";\n"; + if(_node) + { + _node->writeDot(os); + os << getId() << " -> " << _node->getId() << ";\n"; + } os << "}\n" ; os << getId() << "[fillcolor=\"" ; YACS::StatesForNode state=getEffectiveState(); diff --git a/src/engine/ForEachLoop.hxx b/src/engine/ForEachLoop.hxx index 13f52f2bd..7fb29bd43 100644 --- a/src/engine/ForEachLoop.hxx +++ b/src/engine/ForEachLoop.hxx @@ -5,7 +5,6 @@ #include "DynParaLoop.hxx" #include "OutputPort.hxx" #include "InputPort.hxx" -#include "TypeCode.hxx" #include "AnyInputPort.hxx" namespace YACS @@ -15,6 +14,8 @@ namespace YACS class ForEachLoop; class SplitterNode; class AnySplitOutputPort; + class TypeCode; + class TypeCodeSeq; class InterceptorInputPort : public AnyInputPort { @@ -129,12 +130,12 @@ namespace YACS void getReadyTasks(std::vector& tasks); int getNumberOfInputPorts() const; // - void checkConsistency(ComposedNode *pointOfView) const throw(Exception); void checkNoCyclePassingThrough(Node *node) throw(Exception); void selectRunnableTasks(std::vector& tasks); // unsigned getExecCurrentId() const { return _execCurrentId; } // for update progress bar on GUI part std::list getSetOfInputPort() const; + std::list getLocalInputPorts() const; InputPort *edGetSeqOfSamplesPort() { return &_splitterNode._dataPortToDispatch; } InputPort *getInputPort(const std::string& name) const throw(Exception); OutPort *getOutPort(const std::string& name) const throw(Exception); @@ -142,15 +143,16 @@ namespace YACS Node *getChildByShortName(const std::string& name) const throw(Exception); std::list getLocalOutputPorts() const; void accept(Visitor *visitor); - void writeDot(std::ostream &os); + void writeDot(std::ostream &os) const; + virtual std::string typeName() {return "YACS__ENGINE__ForEachLoop";} protected: Node *simpleClone(ComposedNode *father, bool editionOnly=true) const; - void checkLinkPossibility(OutPort *start, const std::set& pointsOfViewStart, - InPort *end, const std::set& pointsOfViewEnd) throw(Exception); + void checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) throw(Exception); YACS::Event updateStateOnFinishedEventFrom(Node *node); - void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView); - void getDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); - void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); + void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView); + void getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); + void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); protected: void cleanDynGraph(); void pushAllSequenceValues(); diff --git a/src/engine/ForLoop.cxx b/src/engine/ForLoop.cxx index 23e36ceb9..1089a898b 100644 --- a/src/engine/ForLoop.cxx +++ b/src/engine/ForLoop.cxx @@ -23,18 +23,6 @@ Node *ForLoop::simpleClone(ComposedNode *father, bool editionOnly) const return new ForLoop(*this,father,editionOnly); } -int ForLoop::getNumberOfInputPorts() const -{ - return StaticDefinedComposedNode::getNumberOfInputPorts()+1; -} - -std::list ForLoop::getSetOfInputPort() const -{ - list ret=StaticDefinedComposedNode::getSetOfInputPort(); - ret.push_back((InputPort *)&_nbOfTimesPort); - return ret; -} - InputPort* ForLoop::getInputPort(const std::string& name) const throw(Exception) { if(name == NAME_OF_NSTEPS_NUMBER)return (InputPort*)&_nbOfTimesPort; diff --git a/src/engine/ForLoop.hxx b/src/engine/ForLoop.hxx index a595e0c6e..fc0166c58 100644 --- a/src/engine/ForLoop.hxx +++ b/src/engine/ForLoop.hxx @@ -26,12 +26,12 @@ namespace YACS void exUpdateState(); void init(bool start=true); InputPort *edGetNbOfTimesInputPort() { return &_nbOfTimesPort; } - int getNumberOfInputPorts() const; Node *simpleClone(ComposedNode *father, bool editionOnly=true) const; - std::list getSetOfInputPort() const; InputPort* getInputPort(const std::string& name) const throw(Exception); std::list getLocalInputPorts() const; virtual void accept(Visitor *visitor); + InputPort *getDecisionPort() const { return (InputPort *)&_nbOfTimesPort; } + virtual std::string typeName() {return "YACS__ENGINE__ForLoop";} protected: YACS::Event updateStateOnFinishedEventFrom(Node *node); }; diff --git a/src/engine/InGate.hxx b/src/engine/InGate.hxx index bf6dc8dd1..7715d6238 100644 --- a/src/engine/InGate.hxx +++ b/src/engine/InGate.hxx @@ -37,6 +37,7 @@ namespace YACS bool exIsReady() const; std::list getBackLinks(); void setPrecursorDone(OutGate *from); + virtual std::string typeName() {return "YACS__ENGINE__InGate";} }; } } diff --git a/src/engine/InPort.cxx b/src/engine/InPort.cxx index 5adca23f5..146099f6b 100644 --- a/src/engine/InPort.cxx +++ b/src/engine/InPort.cxx @@ -37,6 +37,7 @@ void InPort::edRemoveAllLinksLinkedWithMe() throw(Exception) _node->getRootNode()->edRemoveLink(*iter2,this); } _backLinks.clear(); + modified(); } //! Returns \b physical backlinks \b NOT user backlinks. @@ -48,11 +49,13 @@ std::set InPort::edSetOutPort() const void InPort::edNotifyReferencedBy(OutPort *fromPort) { _backLinks.insert(fromPort); + modified(); } void InPort::edNotifyDereferencedBy(OutPort *fromPort) { _backLinks.erase(fromPort); + modified(); } void InPort::getAllRepresentants(std::set& repr) const diff --git a/src/engine/InPort.hxx b/src/engine/InPort.hxx index 3860a2470..e179d8beb 100644 --- a/src/engine/InPort.hxx +++ b/src/engine/InPort.hxx @@ -43,6 +43,7 @@ namespace YACS virtual int edGetNumberOfLinks() const; virtual std::set edSetOutPort() const; virtual ~InPort(); + virtual std::string typeName() {return "YACS__ENGINE__InPort";} protected: InPort(const InPort& other, Node *newHelder); InPort(const std::string& name, Node *node, TypeCode* type); diff --git a/src/engine/InlineNode.hxx b/src/engine/InlineNode.hxx index 9253406d1..d6a7c16c7 100644 --- a/src/engine/InlineNode.hxx +++ b/src/engine/InlineNode.hxx @@ -41,6 +41,7 @@ namespace YACS { throw Exception("Not implemented");}; virtual void accept(Visitor *visitor); virtual ~InlineNode(); + virtual std::string typeName() {return "YACS__ENGINE__InlineNode";} protected: std::string _script; }; @@ -72,6 +73,7 @@ namespace YACS virtual std::string getFname() { return _fname; } void accept(Visitor *visitor); virtual ~InlineFuncNode(); + virtual std::string typeName() {return "YACS__ENGINE__InlineFuncNode";} protected: std::string _fname; }; diff --git a/src/engine/InputDataStreamPort.hxx b/src/engine/InputDataStreamPort.hxx index 1f4768b17..1272c18d9 100644 --- a/src/engine/InputDataStreamPort.hxx +++ b/src/engine/InputDataStreamPort.hxx @@ -23,6 +23,7 @@ namespace YACS virtual ~InputDataStreamPort(); virtual std::string getNameOfTypeOfCurrentInstance() const; virtual InputDataStreamPort *clone(Node *newHelder) const; + virtual std::string typeName() {return "YACS__ENGINE__InputDataStreamPort";} }; } } diff --git a/src/engine/InputPort.cxx b/src/engine/InputPort.cxx index 37af33bfe..4072e7e01 100644 --- a/src/engine/InputPort.cxx +++ b/src/engine/InputPort.cxx @@ -72,6 +72,7 @@ void InputPort::edInit(Any *value) if(manuallySet!=this) delete manuallySet; exSaveInit(); + modified(); } void InputPort::edInit(const std::string& impl,const void* value) @@ -81,6 +82,7 @@ void InputPort::edInit(const std::string& impl,const void* value) if(manuallySet!=this) delete manuallySet; exSaveInit(); + modified(); } //! Removes eventually previous manual initialisation. @@ -91,7 +93,7 @@ void InputPort::edRemoveManInit() _initValue=0; } -//! Check basisically that this port has one chance to be specified on time. It's a necessary condition \b not \b sufficient at all. +//! Check basically that this port has one chance to be specified on time. It's a necessary condition \b not \b sufficient at all. void InputPort::checkBasicConsistency() const throw(Exception) { if(!edIsManuallyInitialized() and _backLinks.size()==0 ) @@ -173,12 +175,16 @@ void ProxyPort::exSaveInit() _port->exSaveInit(); } +#ifdef NOCOVARIANT +InPort *ProxyPort::getPublicRepresentant() +#else InputPort *ProxyPort::getPublicRepresentant() +#endif { return _port->getPublicRepresentant(); } -void *ProxyPort::get() const throw(Exception) +void *ProxyPort::get() const { return _port->get(); } @@ -190,5 +196,6 @@ void ProxyPort::put(const void *data) throw(ConversionException) void ProxyPort::getAllRepresentants(std::set& repr) const { + DEBTRACE("ProxyPort::getAllRepresentants"); _port->getAllRepresentants(repr); } diff --git a/src/engine/InputPort.hxx b/src/engine/InputPort.hxx index c6b5840e8..1ba66e943 100644 --- a/src/engine/InputPort.hxx +++ b/src/engine/InputPort.hxx @@ -4,9 +4,9 @@ #include "Any.hxx" #include "InPort.hxx" #include "Runtime.hxx" -#include "TypeCode.hxx" #include "DataFlowPort.hxx" #include "ConversionException.hxx" +#include "yacsconfig.h" #include @@ -31,7 +31,11 @@ namespace YACS std::string getNameOfTypeOfCurrentInstance() const; //! returns the final physical port behind 'this'. +#ifdef NOCOVARIANT + virtual InPort *getPublicRepresentant() { return this; } +#else virtual InputPort *getPublicRepresentant() { return this; } +#endif virtual bool isIntermediate() const { return false; } virtual bool edIsManuallyInitialized() const; //!soon deprecated @@ -42,17 +46,18 @@ namespace YACS void edInit(Any *value); void edInit(const std::string& impl,const void* value); virtual void edRemoveManInit(); - void checkBasicConsistency() const throw(Exception); + virtual void checkBasicConsistency() const throw(Exception); virtual void exInit(bool start); virtual void exSaveInit() = 0; virtual void exRestoreInit() = 0; virtual InputPort *clone(Node *newHelder) const = 0; virtual bool isEmpty(); - virtual void *get() const throw(Exception) = 0; + virtual void *get() const = 0; virtual void put(const void *data) throw(ConversionException) = 0; virtual std::string dump(); virtual void setStringRef(std::string strRef); + virtual std::string typeName() {return "YACS__ENGINE__InputPort";} protected: InputPort(const InputPort& other, Node *newHelder); InputPort(const std::string& name, Node *node, TypeCode* type); @@ -77,14 +82,19 @@ namespace YACS void edNotifyReferencedBy(OutPort *fromPort); void edNotifyDereferencedBy(OutPort *fromPort); std::set edSetOutPort() const; +#ifdef NOCOVARIANT + InPort *getPublicRepresentant(); +#else InputPort *getPublicRepresentant(); - void *get() const throw(Exception); +#endif + void *get() const; virtual void put(const void *data) throw(ConversionException) ; int edGetNumberOfLinks() const; bool isIntermediate() const { return true; } void exRestoreInit(); void exSaveInit(); void getAllRepresentants(std::set& repr) const; + virtual std::string typeName() {return "YACS__ENGINE__ProxyPort";} protected: InputPort* _port; }; @@ -100,6 +110,7 @@ namespace YACS delete manuallySet; any->decrRef(); exSaveInit(); + modified(); } } } diff --git a/src/engine/LinkInfo.cxx b/src/engine/LinkInfo.cxx index 4885ec708..550126b57 100644 --- a/src/engine/LinkInfo.cxx +++ b/src/engine/LinkInfo.cxx @@ -1,5 +1,5 @@ #include "LinkInfo.hxx" -#include "ComposedNode.hxx" +#include "Switch.hxx" #include @@ -23,6 +23,7 @@ void LinkInfo::clearAll() _infos.clear(); _collapse.clear(); _errors.clear(); + _errorsOnSwitchCases.clear(); } void LinkInfo::startCollapseTransac() @@ -34,10 +35,12 @@ void LinkInfo::endCollapseTransac() throw(Exception) { if(--_level==0) { - if(_levelOfInfo==ALL_STOP_ASAP or _levelOfInfo==ERR_ONLY_DONT_STOP) - throw Exception(getErrRepr()); if(_levelOfInfo==ALL_STOP_ASAP) - throw Exception(getWarnRepr()); + if(areWarningsOrErrors()) + throw(getGlobalRepr()); + else if(_levelOfInfo==WARN_ONLY_DONT_STOP) + if(getNumberOfWarnLinksGrp(W_ALL)!=0) + throw Exception(getErrRepr()); } } @@ -70,7 +73,15 @@ void LinkInfo::pushErrLink(OutPort *semStart, InPort *end, ErrReason reason) thr else _errors[reason].push_back(pair(semStart,end)); if(_level==0) - if(_levelOfInfo==ALL_STOP_ASAP or _levelOfInfo==ERR_ONLY_DONT_STOP) + if(_levelOfInfo==ALL_STOP_ASAP or _levelOfInfo==WARN_ONLY_DONT_STOP) + throw Exception(getErrRepr()); +} + +void LinkInfo::pushErrSwitch(CollectorSwOutPort *collector) throw(Exception) +{ + _errorsOnSwitchCases.push_back(collector); + if(_level==0) + if(_levelOfInfo==ALL_STOP_ASAP or _levelOfInfo==WARN_ONLY_DONT_STOP) throw Exception(getErrRepr()); } @@ -124,7 +135,7 @@ std::string LinkInfo::getInfoRepr() const set< pair >::const_iterator iter3; for(iter3=_uselessLinks.begin();iter3!=_uselessLinks.end();iter3++) { - stream << getStringReprOfI(I_USELESS) << " between \"" << _pov->getChildName((*iter3).first); + stream << "Useless CF link between \"" << _pov->getChildName((*iter3).first); stream << "\" and \"" << _pov->getChildName((*iter3).second) << "\"." << endl; } return stream.str(); @@ -161,16 +172,29 @@ std::string LinkInfo::getErrRepr() const for(iter2=_errors.begin();iter2!=_errors.end();iter2++) for(vector< pair >::const_iterator iter3=(*iter2).second.begin();iter3!=(*iter2).second.end();iter3++) stream << getStringReprOfE((*iter2).first) << " between \"" <<_pov->getOutPortName((*iter3).first) << "\" and \"" << _pov->getInPortName((*iter3).second) << endl; + for(vector::const_iterator iter3=_errorsOnSwitchCases.begin();iter3!=_errorsOnSwitchCases.end();iter3++) + (*iter3)->getHumanReprOfIncompleteCases(stream); return stream.str(); } +bool LinkInfo::areWarningsOrErrors() const +{ + return (getNumberOfWarnLinksGrp(W_ALL)!=0) || (getNumberOfErrLinks(E_ALL)!=0) || !_unsetInPort.empty() || !_onlyBackDefined.empty(); +} + /*! * If 'reason'==I_ALL returns nummmber of types of links info whereas it returns number of info per type. */ unsigned LinkInfo::getNumberOfInfoLinks(InfoReason reason) const { if(reason==I_ALL) - return _infos.size()+_uselessLinks.size(); + { + map > >::const_iterator iter=_infos.begin(); + unsigned val=0; + for(;iter!=_infos.end();iter++) + val+=(*iter).second.size(); + return val+_uselessLinks.size(); + } if(reason==I_CF_USELESS) return _uselessLinks.size(); else @@ -203,11 +227,13 @@ unsigned LinkInfo::getNumberOfWarnLinksGrp(WarnReason reason) const unsigned LinkInfo::getNumberOfErrLinks(ErrReason reason) const { if(reason==E_ALL) - return _errors.size()+_onlyBackDefined.size()+_unsetInPort.size(); + return _errors.size()+_onlyBackDefined.size()+_unsetInPort.size()+_errorsOnSwitchCases.size(); else if(reason==E_NEVER_SET_INPUTPORT) return _unsetInPort.size(); else if(reason==E_ONLY_BACKWARD_DEFINED) return _onlyBackDefined.size(); + else if(reason==E_UNCOMPLETE_SW) + return _errorsOnSwitchCases.size(); else { map > >::const_iterator iter=_errors.find(reason); @@ -265,7 +291,7 @@ std::string LinkInfo::getStringReprOfI(InfoReason reason) switch(reason) { case I_USELESS: - ret="Useless CF"; + ret="Useless DF"; break; case I_BACK: ret="Back"; diff --git a/src/engine/LinkInfo.hxx b/src/engine/LinkInfo.hxx index 554fd31ca..9025cf045 100644 --- a/src/engine/LinkInfo.hxx +++ b/src/engine/LinkInfo.hxx @@ -18,6 +18,7 @@ namespace YACS class OutGate; class OutPort; class ComposedNode; + class CollectorSwOutPort; typedef enum { @@ -51,6 +52,7 @@ namespace YACS E_COLLAPSE_DFDS = 244, E_COLLAPSE_DS = 245, E_UNPREDICTABLE_FED = 246, + E_UNCOMPLETE_SW =247, E_ALL = 249 } ErrReason; @@ -69,6 +71,7 @@ namespace YACS std::map > > _infos; std::map > > > _collapse; std::map > > _errors; + std::vector _errorsOnSwitchCases; public: LinkInfo(unsigned char level); void clearAll(); @@ -78,6 +81,7 @@ namespace YACS void pushInfoLink(OutPort *semStart, InPort *end, InfoReason reason); void pushWarnLink(OutPort *semStart, InPort *end, WarnReason reason); void pushErrLink(OutPort *semStart, InPort *end, ErrReason reason) throw(Exception); + void pushErrSwitch(CollectorSwOutPort *collector) throw(Exception); void pushUselessCFLink(Node *start, Node *end); void takeDecision() const throw(Exception); //Typically methods for high level use. @@ -85,6 +89,7 @@ namespace YACS std::string getInfoRepr() const; std::string getWarnRepr() const; std::string getErrRepr() const; + bool areWarningsOrErrors() const; unsigned getNumberOfInfoLinks(InfoReason reason) const; unsigned getNumberOfWarnLinksGrp(WarnReason reason) const; unsigned getNumberOfErrLinks(ErrReason reason) const; @@ -100,7 +105,7 @@ namespace YACS public: static const unsigned char ALL_STOP_ASAP = 1; static const unsigned char ALL_DONT_STOP = 2; - static const unsigned char ERR_ONLY_DONT_STOP = 3; + static const unsigned char WARN_ONLY_DONT_STOP = 3; }; } } diff --git a/src/engine/LogRecord.cxx b/src/engine/LogRecord.cxx new file mode 100644 index 000000000..bb7b377c5 --- /dev/null +++ b/src/engine/LogRecord.cxx @@ -0,0 +1,47 @@ +#include "LogRecord.hxx" + +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; + +LogRecord::LogRecord(const std::string& name,int level,const std::string& message, const char* file, int line) + :_loggerName(name),_level(level),_message(message),_fileName((char*)file),_line(line) +{ +} + +LogRecord::~LogRecord() +{ +} + +std::string LogRecord::getLevelName(int level) +{ + switch(level) + { + case FATAL: + return "FATAL"; + case ERROR: + return "ERROR"; + case WARNING: + return "WARNING"; + case INFO: + return "INFO"; + case DEBUG: + return "DEBUG"; + default: + return "NOTSET"; + } +} + +std::string LogRecord::getStr() +{ + std::stringstream msg; + msg << "LogRecord: " << _loggerName << ":" << getLevelName(_level) << ":" << _message; + if(_fileName != "") + msg << " (" << _fileName << ":" << _line << ")"; + return msg.str(); +} + diff --git a/src/engine/LogRecord.hxx b/src/engine/LogRecord.hxx new file mode 100644 index 000000000..ea4696aa7 --- /dev/null +++ b/src/engine/LogRecord.hxx @@ -0,0 +1,45 @@ +#ifndef _LOGRECORD_HXX_ +#define _LOGRECORD_HXX_ + +#include + +namespace YACS +{ + namespace ENGINE + { +/*! \brief Class for logging record + * + */ + class LogRecord + { + public: + typedef int LogLevel; + static const LogLevel FATAL = 50; + static const LogLevel ERROR = 40; + static const LogLevel WARNING = 30; + static const LogLevel INFO = 20; + static const LogLevel DEBUG = 10; + static const LogLevel NOTSET = 0; + + LogRecord(const std::string& name,int level,const std::string& message, const char* file, int line); + virtual ~LogRecord(); + /** The logger name. */ + const std::string _loggerName; + /** The message of logging record */ + const std::string _message; + /** Level of logging record */ + int _level; + /** filename of logging record */ + char* _fileName; + /** line number of logging record */ + int _line; + virtual std::string getLevelName(int level); + + virtual std::string getStr(); + + protected: + }; + } +} + +#endif diff --git a/src/engine/Logger.cxx b/src/engine/Logger.cxx new file mode 100644 index 000000000..c79a54754 --- /dev/null +++ b/src/engine/Logger.cxx @@ -0,0 +1,95 @@ +#include "Logger.hxx" +#include "LogRecord.hxx" + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; + +Logger::Logger(const std::string& name):_name(name) +{ +} + +Logger::~Logger() +{ + reset(); +} + +const std::string& Logger::getName() +{ + return _name; +} + +void Logger::log(int level,const std::string& message,const char* filename,int line) +{ + LogRecord* record=makeRecord(getName(),level,message,filename,line); + handle(record); +} + +void Logger::error(const std::string& message,const char* filename,int line) +{ + log(LogRecord::ERROR,message,filename,line); +} + +void Logger::fatal(const std::string& message,const char* filename,int line) +{ + log(LogRecord::FATAL,message,filename,line); +} + +void Logger::warning(const std::string& message,const char* filename,int line) +{ + log(LogRecord::WARNING,message,filename,line); +} + +LogRecord* Logger::makeRecord(const std::string& name,int level,const std::string& message,const char* filename,int line) +{ + return new LogRecord(name,level,message,filename,line); +} + +void Logger::handle(LogRecord* record) +{ + _records.push_back(record); +} + +void Logger::reset() +{ + std::vector::iterator it; + for( it = _records.begin(); it != _records.end(); it++) + { + delete (*it); + } + _records.clear(); +} + +std::string Logger::getStr() +{ + std::vector::iterator it; + std::string msg; + for( it = _records.begin(); it != _records.end(); it++) + { + msg=msg + (*it)->getStr() + '\n'; + } + return msg; +} + +bool Logger::isEmpty() +{ + return _records.size() == 0; +} + +bool Logger::hasErrors() +{ + bool ret=false; + std::vector::iterator it; + for( it = _records.begin(); it != _records.end(); it++) + { + if((*it)->_level > LogRecord::WARNING) + { + ret=true; + break; + } + } + return ret; +} diff --git a/src/engine/Logger.hxx b/src/engine/Logger.hxx new file mode 100644 index 000000000..56301f41f --- /dev/null +++ b/src/engine/Logger.hxx @@ -0,0 +1,39 @@ +#ifndef _LOGGER_HXX_ +#define _LOGGER_HXX_ + +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class LogRecord; + +/*! \brief Class for logging error messages + * + */ + class Logger + { + public: + Logger(const std::string& name); + virtual ~Logger(); + virtual const std::string& getName(); + virtual void log(int level,const std::string& message,const char* filename,int line); + virtual void error(const std::string& message,const char* filename,int line); + virtual void fatal(const std::string& message,const char* filename,int line); + virtual void warning(const std::string& message,const char* filename,int line); + virtual LogRecord* makeRecord(const std::string& name,int level,const std::string& message,const char* filename,int line); + virtual void handle(LogRecord* record); + virtual void reset(); + virtual std::string getStr(); + virtual bool isEmpty(); + virtual bool hasErrors(); + protected: + std::string _name; + std::vector _records; + }; + } +} + +#endif diff --git a/src/engine/Loop.cxx b/src/engine/Loop.cxx index 344a59c4b..a94e6f925 100644 --- a/src/engine/Loop.cxx +++ b/src/engine/Loop.cxx @@ -3,6 +3,7 @@ #include "OutputPort.hxx" #include "InputDataStreamPort.hxx" #include "OutputDataStreamPort.hxx" +#include "LinkInfo.hxx" #include "Runtime.hxx" #include "Visitor.hxx" #include @@ -266,7 +267,7 @@ void FakeNodeForLoop::finished() _loop->setState(YACS::DONE); } -Loop::Loop(const Loop& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_nbOfTurns(0),_nodeForNullTurnOfLoops(0) +Loop::Loop(const Loop& other, ComposedNode *father, bool editionOnly):StaticDefinedComposedNode(other,father),_nbOfTurns(0),_nodeForNullTurnOfLoops(0),_node(0) { if(other._node) _node=other._node->simpleClone(this,editionOnly); @@ -310,10 +311,13 @@ Node *Loop::edSetNode(Node *node) throw Exception(what); } } + checkNoCrossHierachyWith(node); StaticDefinedComposedNode::edRemoveChild(_node); Node *ret=_node; _node=node; _node->_father=this; + //set _modified flag so that edUpdateState() can refresh state + modified(); return ret; } @@ -362,16 +366,24 @@ void Loop::selectRunnableTasks(std::vector& tasks) { } -std::set Loop::edGetDirectDescendants() const +std::list Loop::edGetDirectDescendants() const { - set ret; + list ret; if(_node) - ret.insert(_node); + ret.push_back(_node); return ret; } -void Loop::checkConsistency(ComposedNode *pointOfView) const throw(Exception) +std::list Loop::getSetOfInputPort() const { + list ret=StaticDefinedComposedNode::getSetOfInputPort(); + ret.push_back(getDecisionPort()); + return ret; +} + +int Loop::getNumberOfInputPorts() const +{ + return StaticDefinedComposedNode::getNumberOfInputPorts()+1; } Node *Loop::getChildByShortName(const std::string& name) const throw(Exception) @@ -392,7 +404,7 @@ TypeCode* Loop::MappingDS2DF(TypeCode* type) throw(Exception) return type; } -void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) +void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) { string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance!=InputPort::NAME or @@ -417,7 +429,7 @@ void Loop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::se port=(*iter)->getInputDataStreamPort(""); } -void Loop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) +void Loop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) { string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance!=OutputPort::NAME or @@ -449,7 +461,7 @@ void Loop::buildDelegateOf(std::pair& port, InPort *finalT port.first=(*iter)->getOutputDataStreamPort(""); } -void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception) +void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception) { string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance!=InputPort::NAME or @@ -472,7 +484,7 @@ void Loop::getDelegateOf(InPort * & port, OutPort *initialStart, const std::set< } void Loop::getDelegateOf(std::pair& port, InPort *finalTarget, - const std::set& pointsOfView) throw(Exception) + const std::list& pointsOfView) throw(Exception) { string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance!=OutputPort::NAME or @@ -494,7 +506,7 @@ void Loop::getDelegateOf(std::pair& port, InPort *finalTar port.first=(*iter)->getOutputDataStreamPort(""); } -void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception) +void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception) { string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance(); if(typeOfPortInstance!=InputPort::NAME or @@ -524,7 +536,7 @@ void Loop::releaseDelegateOf(InPort * & port, OutPort *initialStart, const std:: } } -void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception) +void Loop::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception) { if(portDwn==portUp) return ; @@ -545,16 +557,28 @@ void Loop::checkNoCyclePassingThrough(Node *node) throw(Exception) //throw Exception("Loop::checkNoCyclePassingThrough : Internal error occured"); } +void Loop::checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const +{ + Node *nodeEnd=end->getNode(); + if(nodeEnd==this) + {//In this case 'end' port is a special port of this (for exemple ForLoop::_nbOfTimesPort) + //ASSERT(!direction) see Loop::checkControlDependancy (bw only) + solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info); + } + else + StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info); +} + /*! * \note : States if a DF port must be considered on an upper level in hierarchy as a DS port or not from 'pointsOfView' observers. * \return : * - True : a traduction DF->DS has to be done * - False : no traduction needed */ -bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::set& pointsOfView) +bool Loop::isNecessaryToBuildSpecificDelegateDF2DS(const std::list& pointsOfView) { bool ret=false; - for(set::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++) + for(list::const_iterator iter=pointsOfView.begin();iter!=pointsOfView.end() && !ret;iter++) ret=(*iter)->isRepeatedUnpredictablySeveralTimes(); return ret; } @@ -577,12 +601,15 @@ bool Loop::edAddDFLink(OutPort *start, InPort *end) throw(Exception) /*! * \param os : the output stream */ -void Loop::writeDot(std::ostream &os) +void Loop::writeDot(std::ostream &os) const { os << " subgraph cluster_" << getId() << " {\n" ; //only one node in a loop - _node->writeDot(os); - os << getId() << " -> " << _node->getId() << ";\n"; + if(_node) + { + _node->writeDot(os); + os << getId() << " -> " << _node->getId() << ";\n"; + } os << "}\n" ; os << getId() << "[fillcolor=\"" ; YACS::StatesForNode state=getEffectiveState(); @@ -597,6 +624,20 @@ void Loop::accept(Visitor *visitor) visitor->visitLoop(this); } +void Loop::checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const +{ + //First testing if end==getDecisionPort. This is the only case possible in theory. + if(end!=getDecisionPort()) + return StaticDefinedComposedNode::checkControlDependancy(start,end,cross,fw,fwCross,bw,info); + if(cross) + throw Exception("Internal error occured - cross type link detected on decision port of a loop. Forbidden !"); + fw[(ComposedNode *)this].push_back(start); +} + /*! * For use only when loading a previously saved execution */ diff --git a/src/engine/Loop.hxx b/src/engine/Loop.hxx index 6a6caedd9..25b0886b6 100644 --- a/src/engine/Loop.hxx +++ b/src/engine/Loop.hxx @@ -11,6 +11,7 @@ namespace YACS { namespace ENGINE { + void NbDoneLoader(Loop* node, int val); class Loop; class ForLoop; class WhileLoop; @@ -138,32 +139,42 @@ namespace YACS ~Loop(); void init(bool start=true); int getNbOfTurns() const { return _nbOfTurns; } - Node *edSetNode(Node *node); + //Node* DISOWNnode is a SWIG notation to indicate that the ownership of the node is transfered to C++ + Node *edSetNode(Node *DISOWNnode); Node *edRemoveNode(); + //! Returns the port which value is used to take decision about the continuation of the loop. + virtual InputPort *getDecisionPort() const = 0; void getReadyTasks(std::vector& tasks); void edRemoveChild(Node *node) throw(Exception); bool isRepeatedUnpredictablySeveralTimes() const { return true; } void selectRunnableTasks(std::vector& tasks); - std::set edGetDirectDescendants() const; - void checkConsistency(ComposedNode *pointOfView) const throw(Exception); + std::list edGetDirectDescendants() const; + std::list getSetOfInputPort() const; + int getNumberOfInputPorts() const; Node *getChildByShortName(const std::string& name) const throw(Exception); static TypeCode* MappingDF2DS(TypeCode* type) throw(Exception); static TypeCode* MappingDS2DF(TypeCode* type) throw(Exception); virtual bool edAddDFLink(OutPort *start, InPort *end) throw(Exception); - void writeDot(std::ostream &os); + void writeDot(std::ostream &os) const; virtual void accept(Visitor *visitor); + virtual std::string typeName() {return "YACS__ENGINE__Loop";} protected: - void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView); - void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView); - void getDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception); - void getDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); - void releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) throw(Exception); - void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); + void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView); + void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView); + void getDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception); + void getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); + void releaseDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) throw(Exception); + void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); void checkNoCyclePassingThrough(Node *node) throw(Exception); - static bool isNecessaryToBuildSpecificDelegateDF2DS(const std::set& pointsOfView); + void checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const; + void checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; + static bool isNecessaryToBuildSpecificDelegateDF2DS(const std::list& pointsOfView); }; - void NbDoneLoader(Loop* node, int val); } } diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index 250466b18..5d188a1b6 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -2,9 +2,9 @@ include $(top_srcdir)/adm/unix/make_begin.am SUBDIRS = Plugin Test -lib_LTLIBRARIES = libYACSEngine.la +lib_LTLIBRARIES = libYACSlibEngine.la -libYACSEngine_la_SOURCES = \ +libYACSlibEngine_la_SOURCES = \ TypeCode.cxx \ RefCounter.cxx \ LinkInfo.cxx \ @@ -53,94 +53,88 @@ libYACSEngine_la_SOURCES = \ Dispatcher.cxx \ Container.cxx \ DeploymentTree.cxx \ + Logger.cxx \ + LogRecord.cxx \ + Catalog.cxx \ + ComponentDefinition.cxx \ + DataNode.cxx \ $(__dummy__) salomeinclude_HEADERS = \ - Any.hxx \ - AnyInputPort.hxx \ - Bloc.hxx \ - ComponentInstance.hxx \ - ComposedNode.hxx \ - ConditionInputPort.hxx \ - Container.hxx \ - ConversionException.hxx \ - DataFlowPort.hxx \ - DataPort.hxx \ - DataStreamPort.hxx \ - DeploymentTree.hxx \ - Dispatcher.hxx \ - DynParaLoop.hxx \ - ElementaryNode.hxx \ - Executor.hxx \ - ExecutorSwig.hxx \ - ForEachLoop.hxx \ - ForLoop.hxx \ - InGate.hxx \ - InlineNode.hxx \ - InPort.hxx \ - InputDataStreamPort.hxx \ - InputPort.hxx \ - InvalidExtractionException.hxx \ - LinkInfo.hxx \ - Loop.hxx \ - Node.hxx \ - OptimizerAlg.hxx \ - OptimizerLoop.hxx \ - OutGate.hxx \ - OutPort.hxx \ - OutputDataStreamPort.hxx \ - OutputPort.hxx \ - Pool.hxx \ - Port.hxx \ - Proc.hxx \ - RefCounter.hxx \ - Runtime.hxx \ - Scheduler.hxx \ - ServiceInlineNode.hxx \ - ServiceNode.hxx \ - SharedPtr.hxx \ - StaticDefinedComposedNode.hxx \ - Switch.hxx \ - Task.hxx \ - TypeCode.hxx \ - Visitor.hxx \ - VisitorSaveSchema.hxx \ - VisitorSaveState.hxx \ - WhileLoop.hxx \ +Any.hxx AnyInputPort.hxx Bloc.hxx Catalog.hxx ComponentDefinition.hxx \ +ComponentInstance.hxx ComposedNode.hxx ConditionInputPort.hxx Container.hxx ConversionException.hxx \ +DataFlowPort.hxx DataNode.hxx DataPort.hxx DataStreamPort.hxx DeploymentTree.hxx \ +Dispatcher.hxx DynParaLoop.hxx ElementaryNode.hxx Executor.hxx ExecutorSwig.hxx \ +ForEachLoop.hxx ForLoop.hxx InGate.hxx InlineNode.hxx InPort.hxx \ +InputDataStreamPort.hxx InputPort.hxx InvalidExtractionException.hxx LinkInfo.hxx Logger.hxx \ +LogRecord.hxx Loop.hxx Node.hxx OptimizerAlg.hxx OptimizerLoop.hxx \ +OutGate.hxx OutPort.hxx OutputDataStreamPort.hxx OutputPort.hxx Pool.hxx \ +Port.hxx Proc.hxx RefCounter.hxx Runtime.hxx Scheduler.hxx \ +ServiceInlineNode.hxx ServiceNode.hxx SharedPtr.hxx StaticDefinedComposedNode.hxx Switch.hxx \ +Task.hxx TypeCode.hxx Visitor.hxx VisitorSaveSchema.hxx VisitorSaveState.hxx \ +WhileLoop.hxx \ $(__dummy__) -EXTRA_libYACSEngine_la_SOURCES = \ +EXTRA_libYACSlibEngine_la_SOURCES = \ $(__dummy__) -libYACSEngine_la_LIBADD = ../bases/libYACSBases.la +libYACSlibEngine_la_LIBADD = ../bases/libYACSBases.la +libYACSlibEngine_la_LDFLAGS = -pthread -lpthread -ldl AM_CXXFLAGS = $(THREAD_DEF) \ -I$(srcdir)/../bases -BUILT_SOURCES = pilotWRAP.cxx +BUILT_SOURCES = pilotWRAP.cxx pypilotWRAP.cxx pypilotWRAP.h MYSWIG_FLAGS = -noexcept -I$(srcdir)/../bases -pkgpython_PYTHON = pilot.py -pkgpyexec_LTLIBRARIES = _pilot.la - -pilotWRAP.cxx:pilot.i InlineNode.hxx ServiceNode.hxx - $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) $(MYSWIG_FLAGS) -o $@ $< +salomepython_PYTHON = pilot.py pypilot.py +salomepyexec_LTLIBRARIES = _pilot.la _pypilot.la + +SWIGINCLUDES=Any.hxx DeploymentTree.hxx InputDataStreamPort.hxx OutPort.hxx SharedPtr.hxx \ +AnyInputPort.hxx Dispatcher.hxx InputPort.hxx OutputDataStreamPort.hxx StaticDefinedComposedNode.hxx \ +Bloc.hxx DynParaLoop.hxx InvalidExtractionException.hxx OutputPort.hxx Switch.hxx \ +ComponentInstance.hxx ElementaryNode.hxx LinkInfo.hxx Pool.hxx Task.hxx \ +ComposedNode.hxx Executor.hxx Logger.hxx Port.hxx TypeCode.hxx \ +ConditionInputPort.hxx ExecutorSwig.hxx LogRecord.hxx Proc.hxx Visitor.hxx \ +Container.hxx ForEachLoop.hxx Loop.hxx RefCounter.hxx VisitorSaveSchema.hxx \ +ConversionException.hxx ForLoop.hxx Node.hxx Runtime.hxx VisitorSaveState.hxx \ +DataFlowPort.hxx InGate.hxx OptimizerAlg.hxx Scheduler.hxx WhileLoop.hxx \ +DataPort.hxx InlineNode.hxx OptimizerLoop.hxx ServiceInlineNode.hxx ComponentDefinition.hxx \ +DataStreamPort.hxx InPort.hxx OutGate.hxx ServiceNode.hxx Catalog.hxx \ +../bases/yacsconfig.h engtypemaps.i + +pilotWRAP.cxx:pilot.i $(SWIGINCLUDES) + $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) $(MYSWIG_FLAGS) -o pilotWRAP.cxx $(srcdir)/pilot.i _pilot_la_SOURCES = \ pilotWRAP.cxx \ ExecutorSwig.cxx + _pilot_la_CXXFLAGS = \ $(THREAD_DEF) \ $(PYTHON_CPPFLAGS) \ + $(OMNIORB_INCLUDES) \ + $(OMNIORB_CXXFLAGS) \ -I$(srcdir)/../bases _pilot_la_LDFLAGS = -module -_pilot_la_LIBADD = libYACSEngine.la +_pilot_la_LIBADD = libYACSlibEngine.la $(OMNIORB_LIBS) + +pypilotWRAP.cxx pypilotWRAP.h: pypilot.i pilot.i $(SWIGINCLUDES) + $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) $(MYSWIG_FLAGS) -o pypilotWRAP.cxx $(srcdir)/pypilot.i + +_pypilot_la_SOURCES = pypilotWRAP.cxx +_pypilot_la_CXXFLAGS = $(THREAD_DEF) $(PYTHON_CPPFLAGS) $(OMNIORB_INCLUDES) $(OMNIORB_CXXFLAGS) -I$(srcdir)/../bases +_pypilot_la_LDFLAGS = -module +_pypilot_la_LIBADD = libYACSlibEngine.la $(OMNIORB_LIBS) +EXTRA_DIST = pilot.i pypilot.i engtypemaps.i pypilotWRAP.h +clean-local: + rm -f pypilot.py* pypilotWRAP.* include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/engine/Node.cxx b/src/engine/Node.cxx index 1febe8749..5f16e433b 100644 --- a/src/engine/Node.cxx +++ b/src/engine/Node.cxx @@ -18,8 +18,8 @@ const char Node::SEP_CHAR_IN_PORT[]="."; int Node::_total = 0; std::map Node::idMap; -Node::Node(const std::string& name):_name(name),_inGate(this),_outGate(this),_father(0),_state(YACS::INITED), - _implementation(Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME) +Node::Node(const std::string& name):_name(name),_inGate(this),_outGate(this),_father(0),_state(YACS::READY), + _implementation(Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME),_modified(1) { // Should be protected by lock ?? _numId = _total++; @@ -27,8 +27,8 @@ Node::Node(const std::string& name):_name(name),_inGate(this),_outGate(this),_fa } Node::Node(const Node& other, ComposedNode *father):_inGate(this),_outGate(this),_name(other._name),_father(father), - _state(YACS::INITED),_implementation(other._implementation), - _propertyMap(other._propertyMap) + _state(YACS::READY),_implementation(other._implementation), + _propertyMap(other._propertyMap),_modified(other._modified) { _numId = _total++; idMap[_numId]=this; @@ -51,7 +51,7 @@ void Node::init(bool start) exDisabledState(); // to refresh propagation of DISABLED state return; } - setState(YACS::INITED); + setState(YACS::READY); } Node *Node::clone(ComposedNode *father, bool editionOnly) const @@ -61,6 +61,29 @@ Node *Node::clone(ComposedNode *father, bool editionOnly) const return ret; } +//! Change the name of the node +/*! + * raise an exception if the name is already used in the scope of its father + * \param name : the new name + */ +void Node::setName(const std::string& name) +{ + if(_father) + { + if(_father->isNameAlreadyUsed(name)) + { + if ( _father->getChildByName(name) != this ) + { + std::string what("Name "); + what+=name; + what+=" already exists in the scope of "; what+=_father->getName(); + throw Exception(what); + } + } + } + _name=name; +} + /** * get the set of all nodes connected to the outGate */ @@ -79,13 +102,13 @@ bool Node::exIsControlReady() const return _inGate.exIsReady(); } +//! Update the node state /*! * \note : Update the '_state' attribute. * Typically called by 'this->_inGate' when 'this->_inGate' is ready. * * Called by InGate::exNotifyFromPrecursor */ - void Node::exUpdateState() { if(_state==YACS::DISABLED)return; @@ -179,16 +202,32 @@ std::list Node::getSetOfOutPort() const * @return ascendancy, direct father first in set. */ -std::set Node::getAllAscendanceOf(ComposedNode *levelToStop) +std::list Node::getAllAscendanceOf(ComposedNode *levelToStop) const { - set ret; + list ret; if(this==levelToStop) return ret; for(ComposedNode *iter=_father;iter!=levelToStop && iter!=0; iter=iter->_father) - ret.insert(iter); + ret.push_back(iter); return ret; } +bool Node::operator>(const Node& other) const +{ + const ComposedNode *iter=other._father; + while(iter!=0 && iter!=this) + iter=iter->_father; + return iter==this; +} + +bool Node::operator<(const Node& other) const +{ + const ComposedNode *iter=_father; + while(iter!=0 && iter!=(&other)) + iter=iter->_father; + return iter==(&other); +} + /** * @return Implementation of node: C++, Python, CORBA... * _implementation is set by a derived class in a Runtime @@ -196,7 +235,7 @@ std::set Node::getAllAscendanceOf(ComposedNode *levelToStop) * Potential problem with Ports attached to composed Nodes... */ -string Node::getImplementation() +string Node::getImplementation() const { return _implementation; } @@ -246,14 +285,14 @@ void Node::edDisconnectAllLinksWithMe() _outGate.edDisconnectAllLinksFromMe(); } -ComposedNode *Node::getRootNode() throw(Exception) +ComposedNode *Node::getRootNode() const throw(Exception) { if(!_father) throw Exception("No root node"); ComposedNode *iter=_father; while(iter->_father) iter=iter->_father; - return iter; + return (ComposedNode *)iter; } /** @@ -284,7 +323,7 @@ ComposedNode *Node::checkHavingCommonFather(Node *node1, Node *node2) throw(Exce throw Exception("check failed : nodes have not the same father"); } -const std::string Node::getId() +const std::string Node::getId() const { std::string id=getRootNode()->getName(); if(getRootNode() != this) @@ -308,12 +347,12 @@ void Node::setProperty(const std::string& name, const std::string& value) * * The node state is stored in a private attribute _state. * This state is relative to its father state : a node with a - * TOACTIVATE state with a father node in a INITED state is not - * to activate. Its effective state is only INITED. + * TOACTIVATE state with a father node in a READY state is not + * to activate. Its effective state is only READY. * This method returns the effective state of the node taking * into account that of its father. */ -YACS::StatesForNode Node::getEffectiveState() +YACS::StatesForNode Node::getEffectiveState() const { if(!_father) //the root node return _state; @@ -327,7 +366,7 @@ YACS::StatesForNode Node::getEffectiveState() * \param node: the node which effective state is queried * \return the effective node state */ -YACS::StatesForNode Node::getEffectiveState(Node* node) +YACS::StatesForNode Node::getEffectiveState(const Node* node) const { if(node->getState()==YACS::DISABLED) return YACS::DISABLED; @@ -335,10 +374,10 @@ YACS::StatesForNode Node::getEffectiveState(Node* node) YACS::StatesForNode effectiveState=getEffectiveState(); switch(effectiveState) { - case YACS::INITED: - return YACS::INITED; + case YACS::READY: + return YACS::READY; case YACS::TOACTIVATE: - return YACS::INITED; + return YACS::READY; case YACS::DISABLED: return YACS::DISABLED; case YACS::ERROR: @@ -353,11 +392,11 @@ YACS::StatesForNode Node::getEffectiveState(Node* node) * \param state : the node state * \return the associated color */ -std::string Node::getColorState(YACS::StatesForNode state) +std::string Node::getColorState(YACS::StatesForNode state) const { switch(state) { - case YACS::INITED: + case YACS::READY: return "pink"; case YACS::TOLOAD: return "magenta"; @@ -386,7 +425,7 @@ std::string Node::getColorState(YACS::StatesForNode state) /*! * \param os : the input stream */ -void Node::writeDot(std::ostream &os) +void Node::writeDot(std::ostream &os) const { os << getId() << "[fillcolor=\"" ; YACS::StatesForNode state=getEffectiveState(); @@ -423,6 +462,7 @@ int Node::getNumId() */ void Node::setState(YACS::StatesForNode theState) { + DEBTRACE("Node::setState: " << getName() << " " << theState); _state = theState; // emit notification to all observers registered with the dispatcher on any change of the node's state sendEvent("status"); @@ -434,6 +474,7 @@ void Node::setState(YACS::StatesForNode theState) */ void Node::sendEvent(const std::string& event) { + DEBTRACE("Node::sendEvent " << event); Dispatcher* disp=Dispatcher::getDispatcher(); disp->dispatch(this,event); } @@ -446,3 +487,98 @@ void YACS::ENGINE::StateLoader(Node* node, YACS::StatesForNode state) { node->setState(state); } + +//! indicates if the node is valid (returns 1) or not (returns 0) +/*! + * This method is useful when editing a schema. It has no meaning in execution. + * When a node is edited, its modified method must be called so when isValid is called, its state + * is updated (call to edUpdateState) before returning the validity check + */ +int Node::isValid() +{ + if(_modified) + edUpdateState(); + if(_state > YACS::INVALID) + return 1; + else + return 0; +} + +//! update the status of the node +/*! + * Only useful when editing a schema + * Do nothing in base Node : to implement in derived classes + */ +void Node::edUpdateState() +{ + DEBTRACE("Node::edUpdateState(): " << _modified); + _modified=0; +} + +//! returns a string that contains an error report if the node is in error +/*! + * + */ +std::string Node::getErrorReport() +{ + if(getState()==YACS::DISABLED) + return "\n"; + + YACS::StatesForNode effectiveState=getEffectiveState(); + + DEBTRACE("Node::getErrorReport: " << getName() << " " << effectiveState << " " << _errorDetails); + if(effectiveState == YACS::READY || effectiveState == YACS::DONE) + return ""; + + std::string report="\n" ; + report=report+_errorDetails; + report=report+"\n"; + return report; +} + +//! returns a string that contains the name of the container log file if it exists +/*! + * Do nothing here. To subclass + */ +std::string Node::getContainerLog() +{ + return ""; +} + +//! Sets Node in modified state and its father if it exists +/*! + * + */ +void Node::modified() +{ + DEBTRACE("Node::modified() " << getName()); + _modified=1; + if(_father) + _father->modified(); +} + +//! Put this node into TOLOAD state when possible +/*! + * + */ +void Node::ensureLoading() +{ + if(_state == YACS::READY) + setState(YACS::TOLOAD); +} diff --git a/src/engine/Node.hxx b/src/engine/Node.hxx index 7f72ee2a0..4daf597b0 100644 --- a/src/engine/Node.hxx +++ b/src/engine/Node.hxx @@ -15,6 +15,7 @@ namespace YACS { namespace ENGINE { + void StateLoader(Node* node, YACS::StatesForNode state); class Task; class InPort; class OutPort; @@ -56,6 +57,8 @@ namespace YACS std::string _name; ComposedNode *_father; YACS::StatesForNode _state; + int _modified; + std::string _errorDetails; static const char SEP_CHAR_IN_PORT[]; static int _total; int _numId; @@ -73,22 +76,23 @@ namespace YACS Node *clone(ComposedNode *father, bool editionOnly=true) const; void setState(YACS::StatesForNode theState); // To centralize state changes virtual YACS::StatesForNode getState() const { return _state; } - virtual YACS::StatesForNode getEffectiveState(); - virtual YACS::StatesForNode getEffectiveState(Node*); - std::string getColorState(YACS::StatesForNode state); + virtual YACS::StatesForNode getEffectiveState() const; + virtual YACS::StatesForNode getEffectiveState(const Node*) const; + std::string getColorState(YACS::StatesForNode state) const; InGate *getInGate() { return &_inGate; } OutGate *getOutGate() { return &_outGate; } const std::string& getName() const { return _name; } + void setName(const std::string& name); ComposedNode * getFather() const { return _father; } - const std::string getId(); + const std::string getId() const; bool exIsControlReady() const; std::set getOutNodes() const; - virtual void writeDot(std::ostream &os); + virtual void writeDot(std::ostream &os) const; virtual void exUpdateState(); virtual void exFailedState(); virtual void exDisabledState(); virtual void getReadyTasks(std::vector& tasks) = 0; - virtual std::set getRecursiveConstituents() const = 0; + virtual std::list getRecursiveConstituents() const = 0; virtual int getNumberOfInputPorts() const = 0; virtual int getNumberOfOutputPorts() const = 0; std::list getSetOfInPort() const; @@ -107,13 +111,17 @@ namespace YACS virtual OutPort *getOutPort(const std::string& name) const throw(Exception); virtual std::set getAllOutPortsLeavingCurrentScope() const = 0; virtual std::set getAllInPortsComingFromOutsideOfCurrentScope() const = 0; + virtual std::vector< std::pair > getSetOfLinksLeavingCurrentScope() const = 0; + virtual std::vector< std::pair > getSetOfLinksComingInCurrentScope() const =0; virtual InputPort *getInputPort(const std::string& name) const throw(Exception) = 0; virtual OutputPort *getOutputPort(const std::string& name) const throw(Exception) = 0; virtual InputDataStreamPort *getInputDataStreamPort(const std::string& name) const throw(Exception) = 0; virtual OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) const throw(Exception) = 0; - std::set getAllAscendanceOf(ComposedNode *levelToStop = 0); - std::string getImplementation(); - virtual ComposedNode *getRootNode() throw(Exception); + std::list getAllAscendanceOf(ComposedNode *levelToStop = 0) const; + bool operator>(const Node& other) const; + bool operator<(const Node& other) const; + std::string getImplementation() const; + virtual ComposedNode *getRootNode() const throw(Exception); virtual void setProperty(const std::string& name,const std::string& value); virtual Node *getChildByName(const std::string& name) const throw(Exception) = 0; virtual void accept(Visitor *visitor) = 0; @@ -121,6 +129,16 @@ namespace YACS int getNumId(); virtual void sendEvent(const std::string& event); static std::map idMap; + virtual std::string typeName() {return "YACS__ENGINE__Node";} + virtual std::string getErrorDetails(){return _errorDetails;}; + virtual void setErrorDetails(const std::string& error){_errorDetails=error;}; + virtual void modified(); + virtual int isModified(){return _modified;} + virtual int isValid(); + virtual void edUpdateState(); + virtual std::string getErrorReport(); + virtual std::string getContainerLog(); + virtual void ensureLoading(); protected: virtual void exForwardFailed(); virtual void exForwardFinished(); @@ -129,7 +147,6 @@ namespace YACS static ComposedNode *checkHavingCommonFather(Node *node1, Node *node2) throw(Exception); }; - void StateLoader(Node* node, YACS::StatesForNode state); } } diff --git a/src/engine/OptimizerLoop.cxx b/src/engine/OptimizerLoop.cxx index f1ded1304..1d30beb7d 100644 --- a/src/engine/OptimizerLoop.cxx +++ b/src/engine/OptimizerLoop.cxx @@ -8,7 +8,7 @@ using namespace std; const char FakeNodeForOptimizerLoop::NAME[]="thisIsAFakeNode"; -const int OptimizerLoop::NOT_RUNNING_BRANCH_ID=-1979020617; +const int OptimizerLoop::NOT_RUNNING_BRANCH_ID=-1973012217; const char OptimizerLoop::NAME_OF_FILENAME_INPUT[]="FileNameInitAlg"; @@ -295,6 +295,14 @@ std::list OptimizerLoop::getSetOfInputPort() const return ret; } +std::list OptimizerLoop::getLocalInputPorts() const +{ + list ret=DynParaLoop::getLocalInputPorts(); + ret.push_back((InputPort *)&_portForInitFile); + ret.push_back((InputPort *)&_retPortForOutPool); + return ret; +} + void OptimizerLoop::selectRunnableTasks(std::vector& tasks) { } @@ -375,18 +383,14 @@ void OptimizerLoop::checkNoCyclePassingThrough(Node *node) throw(Exception) { } -void OptimizerLoop::checkConsistency(ComposedNode *pointOfView) const throw(Exception) -{ -} - -void OptimizerLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView) +void OptimizerLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView) { DynParaLoop::buildDelegateOf(port,initialStart,pointsOfView); if(port==&_retPortForOutPool) throw Exception("OptimizerLoop::buildDelegateOf : uncorrect OptimizerLoop link : out pool port must be linked within the scope of OptimizerLoop node it belongs to."); } -void OptimizerLoop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) +void OptimizerLoop::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) { DynParaLoop::buildDelegateOf(port,finalTarget,pointsOfView); string typeOfPortInstance=(port.first)->getNameOfTypeOfCurrentInstance(); @@ -394,6 +398,26 @@ void OptimizerLoop::buildDelegateOf(std::pair& port, InPor throw Exception("OptimizerLoop::buildDelegateOf : not implemented for DS because not specified "); } +void OptimizerLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const +{ + if(end==&_retPortForOutPool) + fw[(ComposedNode *)this].push_back(start); + else + DynParaLoop::checkControlDependancy(start,end,cross,fw,fwCross,bw,info); +} + +void OptimizerLoop::checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const +{ + if(end==&_retPortForOutPool) + solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info); + else + DynParaLoop::checkCFLinks(starts,end,alreadyFed,direction,info); +} + void OptimizerLoop::cleanInterceptors() { //the destruction of interceptors whereas some running nodes can push value on them can lead to SIG SEGV. @@ -488,7 +512,11 @@ void OptimizerLoop::initInterceptors(unsigned nbOfBr) const set& links=portC->getSetOfPhyLinks(); for(set::const_iterator iter2=links.begin();iter2!=links.end();iter2++) { +#ifdef NOCOVARIANT + InputPort *reprCur=dynamic_cast((*iter2)->getPublicRepresentant()); +#else InputPort *reprCur=(*iter2)->getPublicRepresentant(); +#endif if(!isInMyDescendance(reprCur->getNode())) {//here we've got an out of scope link : Let's intercept it if(_interceptors.find(reprCur)==_interceptors.end()) diff --git a/src/engine/OptimizerLoop.hxx b/src/engine/OptimizerLoop.hxx index 2ad819615..f289233a7 100644 --- a/src/engine/OptimizerLoop.hxx +++ b/src/engine/OptimizerLoop.hxx @@ -91,14 +91,20 @@ namespace YACS InputPort *edGetPortForInitFile() { return &_portForInitFile; } InputPort *getInputPort(const std::string& name) const throw(Exception); std::list getSetOfInputPort() const; + std::list getLocalInputPorts() const; void selectRunnableTasks(std::vector& tasks); void getReadyTasks(std::vector& tasks); YACS::Event updateStateOnFinishedEventFrom(Node *node); void checkNoCyclePassingThrough(Node *node) throw(Exception); - void checkConsistency(ComposedNode *pointOfView) const throw(Exception); protected: - void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set& pointsOfView); - void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView); + void buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list& pointsOfView); + void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView); + void checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const; + void checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; protected: void cleanInterceptors(); void launchMaxOfSamples(bool first); diff --git a/src/engine/OutGate.cxx b/src/engine/OutGate.cxx index 18683cec9..2367252cc 100644 --- a/src/engine/OutGate.cxx +++ b/src/engine/OutGate.cxx @@ -67,6 +67,8 @@ bool OutGate::edAddInGate(InGate *inGate) { inGate->edAppendPrecursor(this); _setOfInGate[inGate]=false; + modified(); + inGate->modified(); return true; } else @@ -90,6 +92,8 @@ void OutGate::edRemoveInGate(InGate *inGate, bool coherenceWithInGate) throw(Exc _setOfInGate.erase(iter); if(coherenceWithInGate) inGate->edRemovePrecursor(this); + modified(); + inGate->modified(); break; } if(iter==_setOfInGate.end()) @@ -106,6 +110,8 @@ void OutGate::edRemoveInGateOneWay(InGate *inGate) _setOfInGate.erase(iter); inGate->edRemovePrecursor(this); found=true; + modified(); + inGate->modified(); } } diff --git a/src/engine/OutGate.hxx b/src/engine/OutGate.hxx index 18694094a..7126186db 100644 --- a/src/engine/OutGate.hxx +++ b/src/engine/OutGate.hxx @@ -34,9 +34,10 @@ namespace YACS std::set edSetInGate() const; void edRemoveInGate(InGate *inGate, bool coherenceWithInGate=true) throw(Exception); int getNbOfInGatesConnected() const; + bool isAlreadyInSet(InGate *inGate) const; + virtual std::string typeName() {return "YACS__ENGINE__OutGate";} protected: void edRemoveInGateOneWay(InGate *inGate); - bool isAlreadyInSet(InGate *inGate) const; }; } } diff --git a/src/engine/OutPort.cxx b/src/engine/OutPort.cxx index c21f6c985..276195598 100644 --- a/src/engine/OutPort.cxx +++ b/src/engine/OutPort.cxx @@ -19,6 +19,10 @@ OutPort::~OutPort() { } +void OutPort::checkConsistency(LinkInfo& info) const +{ +} + void OutPort::getAllRepresented(std::set& represented) const { represented.insert((OutPort *)this); @@ -35,8 +39,8 @@ std::vector OutPort::calculateHistoryOfLinkWith(InPort *end) throw Exception("ComposedNode::edRemoveLink : unexisting link"); vector ret; ComposedNode* lwstCmnAnctr=ComposedNode::getLowestCommonAncestor(getNode(),end->getNode()); - set allAscendanceOfNodeStart=getNode()->getAllAscendanceOf(lwstCmnAnctr); - set allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr); + list allAscendanceOfNodeStart=getNode()->getAllAscendanceOf(lwstCmnAnctr); + list allAscendanceOfNodeEnd=end->getNode()->getAllAscendanceOf(lwstCmnAnctr); // --- Part of test if the link from 'start' to 'end' really exist particulary all eventually intermediate ports created diff --git a/src/engine/OutPort.hxx b/src/engine/OutPort.hxx index 177ca3c03..0dec8538e 100644 --- a/src/engine/OutPort.hxx +++ b/src/engine/OutPort.hxx @@ -12,12 +12,14 @@ namespace YACS namespace ENGINE { class InPort; + class LinkInfo; class OutPort : public virtual DataPort { protected: OutPort(const OutPort& other, Node *newHelder); OutPort(const std::string& name, Node *node, TypeCode* type); public: + virtual void checkConsistency(LinkInfo& info) const; virtual int edGetNumberOfOutLinks() const; virtual std::set edSetInPort() const = 0; virtual bool isAlreadyLinkedWith(InPort *with) const = 0; @@ -26,6 +28,7 @@ namespace YACS virtual int removeInPort(InPort *inPort, bool forward) throw(Exception) = 0; virtual ~OutPort(); std::vector calculateHistoryOfLinkWith(InPort *end); + virtual std::string typeName() {return "YACS__ENGINE__OutPort";} }; } } diff --git a/src/engine/OutputDataStreamPort.cxx b/src/engine/OutputDataStreamPort.cxx index c81c35656..cb2674c48 100644 --- a/src/engine/OutputDataStreamPort.cxx +++ b/src/engine/OutputDataStreamPort.cxx @@ -2,8 +2,12 @@ #include "InputDataStreamPort.hxx" #include "ComposedNode.hxx" #include "InPort.hxx" +#include "TypeCode.hxx" #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; using namespace std; @@ -63,8 +67,17 @@ string OutputDataStreamPort::getNameOfTypeOfCurrentInstance() const bool OutputDataStreamPort::edAddInputDataStreamPort(InputDataStreamPort *port) throw(ConversionException) { + DEBTRACE("OutputDataStreamPort::edAddInputDataStreamPort"); if(!isAlreadyInSet(port)) { + if(!port->edGetType()->isAdaptable(edGetType())) + { + string what="Can not connect 2 ports with incompatible types : "; + what=what+ port->edGetType()->id(); + what=what+" is not a "; + what=what+ edGetType()->id(); + throw ConversionException(what); + } _setOfInputDataStreamPort.insert(port); return true; } @@ -87,7 +100,9 @@ int OutputDataStreamPort::edRemoveInputDataStreamPort(InputDataStreamPort *inPor set::iterator iter=_setOfInputDataStreamPort.find(inPort); if(iter!=_setOfInputDataStreamPort.end()) { + (*iter)->modified(); _setOfInputDataStreamPort.erase(iter); + modified(); return edGetNumberOfOutLinks(); } else @@ -97,6 +112,7 @@ int OutputDataStreamPort::edRemoveInputDataStreamPort(InputDataStreamPort *inPor bool OutputDataStreamPort::addInPort(InPort *inPort) throw(Exception) { + DEBTRACE("OutputDataStreamPort::addInPort"); if(inPort->getNameOfTypeOfCurrentInstance()!=InputDataStreamPort::NAME) { string what="not compatible type of port requested during building of link FROM "; @@ -117,6 +133,7 @@ void OutputDataStreamPort::edRemoveAllLinksLinkedWithMe() throw(Exception) int OutputDataStreamPort::removeInPort(InPort *inPort, bool forward) throw(Exception) { + DEBTRACE("OutputDataStreamPort::removeInPort"); if(inPort->getNameOfTypeOfCurrentInstance()!=InputDataStreamPort::NAME && !forward) { string what="not compatible type of port requested during destruction of for link FROM "; diff --git a/src/engine/OutputDataStreamPort.hxx b/src/engine/OutputDataStreamPort.hxx index 5eca25a06..a5232c27a 100644 --- a/src/engine/OutputDataStreamPort.hxx +++ b/src/engine/OutputDataStreamPort.hxx @@ -34,6 +34,7 @@ namespace YACS int edRemoveInputDataStreamPort(InputDataStreamPort *inPort, bool forward) throw(Exception); void edRemoveAllLinksLinkedWithMe() throw(Exception); int removeInPort(InPort *inPort, bool forward) throw(Exception); + virtual std::string typeName() {return "YACS__ENGINE__OutputDataStreamPort";} private: bool isAlreadyInSet(InputDataStreamPort *inPort) const; }; diff --git a/src/engine/OutputPort.cxx b/src/engine/OutputPort.cxx index 7a3e62a12..8541f84f9 100644 --- a/src/engine/OutputPort.cxx +++ b/src/engine/OutputPort.cxx @@ -54,12 +54,15 @@ void OutputPort::put(const void *data) throw(ConversionException) */ bool OutputPort::edAddInputPort(InputPort *phyPort) throw(Exception) { + DEBTRACE("OutputPort::edAddInputPort"); if(!isAlreadyInSet(phyPort)) { InputPort *pwrap = getRuntime()->adapt(phyPort, _node->getImplementation(), this->edGetType()); _setOfInputPort.insert(pwrap); + modified(); + phyPort->modified(); return true; } else @@ -77,22 +80,32 @@ int OutputPort::edRemoveInputPort(InputPort *inputPort, bool forward) throw(Exce { set s; inputPort->getAllRepresentants(s); + DEBTRACE("+++"); for(set::iterator iter=s.begin();iter!=s.end();iter++) - _node->getRootNode()->edRemoveLink(this,*iter); + { + DEBTRACE("---"); + _node->getRootNode()->edRemoveLink(this,*iter); + } return -1; } else { +#ifdef NOCOVARIANT + InPort *publicRepr=inputPort->getPublicRepresentant(); +#else InputPort *publicRepr=inputPort->getPublicRepresentant(); +#endif set::iterator iter; for(iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++) if((*iter)->getPublicRepresentant()==publicRepr) break; if(iter!=_setOfInputPort.end()) { + (*iter)->modified(); if((*iter)->isIntermediate()) delete (*iter); _setOfInputPort.erase(iter); + modified(); return edGetNumberOfOutLinks(); } else @@ -131,7 +144,11 @@ bool OutputPort::isAlreadyLinkedWith(InPort *with) const bool OutputPort::isAlreadyInSet(InputPort *inputPort) const { +#ifdef NOCOVARIANT + InPort *publicRepr=inputPort->getPublicRepresentant(); +#else InputPort *publicRepr=inputPort->getPublicRepresentant(); +#endif for(set::const_iterator iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++) if((*iter)->getPublicRepresentant()==publicRepr) return true; @@ -143,6 +160,7 @@ bool OutputPort::isAlreadyInSet(InputPort *inputPort) const */ bool OutputPort::addInPort(InPort *inPort) throw(Exception) { + DEBTRACE("OutputPort::addInPort"); if(inPort->getNameOfTypeOfCurrentInstance()!=InputPort::NAME) { string what="not compatible type of port requested during building of link FROM "; @@ -186,3 +204,8 @@ const std::set& OutputPort::getSetOfPhyLinks() const { return _setOfInputPort; } + +//! Check validity of output port. Nothing on base class +void OutputPort::checkBasicConsistency() const throw(Exception) +{ +} diff --git a/src/engine/OutputPort.hxx b/src/engine/OutputPort.hxx index 1d2b0e949..ae166acff 100644 --- a/src/engine/OutputPort.hxx +++ b/src/engine/OutputPort.hxx @@ -2,7 +2,6 @@ #define __OUTPUTPORT_HXX__ #include "OutPort.hxx" -#include "TypeCode.hxx" #include "DataFlowPort.hxx" #include "ConversionException.hxx" @@ -38,10 +37,12 @@ namespace YACS bool addInPort(InPort *inPort) throw(Exception); void edRemoveAllLinksLinkedWithMe() throw(Exception);//entry point for forward port deletion virtual void exInit(); + virtual void checkBasicConsistency() const throw(Exception); virtual OutputPort *clone(Node *newHelder) const = 0; virtual std::string dump(); virtual void put(const void *data) throw(ConversionException); + virtual std::string typeName() {return "YACS__ENGINE__OutputPort";} protected: OutputPort(const OutputPort& other, Node *newHelder); diff --git a/src/engine/Plugin/Makefile.am b/src/engine/Plugin/Makefile.am index 10abb72bc..6fdd41f64 100644 --- a/src/engine/Plugin/Makefile.am +++ b/src/engine/Plugin/Makefile.am @@ -12,4 +12,10 @@ libPluginSimplex_la_CXXFLAGS = $(THREAD_DEF) \ -I$(srcdir)/.. \ -I$(srcdir)/../../bases +EXTRA_DIST = \ +aleas.hxx critere.hxx decode.hxx distrib.hxx fonction.hxx \ +local.hxx maestro.hxx PluginSimplex.hxx point.hxx saclass.hxx \ +saemul.hxx salomesup.hxx salomevent.hxx sasimpl.hxx simplex.hxx \ +solution.hxx saconst.h + include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/engine/Port.cxx b/src/engine/Port.cxx index 9476c5100..0b54f88a6 100644 --- a/src/engine/Port.cxx +++ b/src/engine/Port.cxx @@ -1,9 +1,13 @@ #include "Port.hxx" +#include "Node.hxx" #include using namespace YACS::ENGINE; using namespace std; +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + const char Port::NAME[]="Port"; int Port::_total = 0; @@ -26,3 +30,10 @@ string Port::getNameOfTypeOfCurrentInstance() const { return NAME; } + +void Port::modified() +{ + DEBTRACE("Port::modified()"); + if(_node) + _node->modified(); +} diff --git a/src/engine/Port.hxx b/src/engine/Port.hxx index b886c0155..94ae2d288 100644 --- a/src/engine/Port.hxx +++ b/src/engine/Port.hxx @@ -1,23 +1,23 @@ #ifndef __PORT_HXX__ #define __PORT_HXX__ -#include "TypeCode.hxx" #include - -/** - * Not instanciable class that factorizes all basic data and behaviours relative - * to the in and out interfaces of all nodes. - * End-user should neither instanciate a sub-class of 'Port' - * nore call other methods than accessor. - */ - namespace YACS { namespace ENGINE { class Node; +/*! \brief Base class for all ports + * + * Not instanciable class that factorizes all basic data and behaviours relative + * to the in and out interfaces of all nodes. + * End-user should neither instanciate a sub-class of 'Port' + * nor call other methods than accessor. + * + * \ingroup Ports + */ class Port { public: @@ -25,6 +25,8 @@ namespace YACS Node *getNode() const { return _node; } virtual std::string getNameOfTypeOfCurrentInstance() const; int getNumId() const { return _id; } + virtual std::string typeName() {return "YACS__ENGINE__Port";} + void modified(); protected: Port(Node *node); Port(const Port& other, Node *newHelder); diff --git a/src/engine/Proc.cxx b/src/engine/Proc.cxx index 0e9e92805..9ccc9415d 100644 --- a/src/engine/Proc.cxx +++ b/src/engine/Proc.cxx @@ -1,6 +1,11 @@ #include "Proc.hxx" +#include "ElementaryNode.hxx" #include "Runtime.hxx" #include "Container.hxx" +#include "InputPort.hxx" +#include "OutputPort.hxx" +#include "TypeCode.hxx" +#include "Logger.hxx" #include "Visitor.hxx" #include #include @@ -8,10 +13,10 @@ //#define _DEVDEBUG_ #include "YacsTrace.hxx" -using namespace YACS::ENGINE; using namespace std; +using namespace YACS::ENGINE; -Proc::Proc(const std::string& name):Bloc(name) +Proc::Proc(const std::string& name):Bloc(name),_edition(false) { Runtime *theRuntime=getRuntime(); DEBTRACE("theRuntime->_tc_double->ref: " << theRuntime->_tc_double->getRefCnt()); @@ -33,6 +38,7 @@ Proc::Proc(const std::string& name):Bloc(name) Proc::~Proc() { + DEBTRACE("Proc::~Proc"); //for the moment all nodes are owned, so no need to manage their destruction //nodeMap, inlineMap, serviceMap will be cleared automatically //but we need to destroy TypeCodes @@ -44,9 +50,14 @@ Proc::~Proc() std::map::const_iterator it; for(it=containerMap.begin();it!=containerMap.end();it++) ((*it).second)->decrRef(); + + //get rid of loggers in logger map + std::map::const_iterator lt; + for(lt=_loggers.begin();lt!=_loggers.end();lt++) + delete (*lt).second; } -void Proc::writeDot(std::ostream &os) +void Proc::writeDot(std::ostream &os) const { os << "digraph " << getQualifiedName() << " {\n" ; os << "node [ style=\"filled\" ];\n" ; @@ -153,12 +164,97 @@ std::string Proc::getXMLState(int numId) return msg.str(); } +std::string Proc::getInPortValue(int nodeNumId, std::string portName) +{ + DEBTRACE("Proc::getInPortValue " << nodeNumId << " " << portName); + stringstream msg; + if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0) + { + msg << "unknown node id: " << nodeNumId << ""; + return msg.str(); + } + try + { + YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId]; + InputPort * inputPort = node->getInputPort(portName); + return inputPort->dump(); + } + catch(YACS::Exception& ex) + { + DEBTRACE("Proc::getInPortValue " << ex.what()); + msg << "" << ex.what() << ""; + return msg.str(); + } +} + +std::string Proc::getOutPortValue(int nodeNumId, std::string portName) +{ + DEBTRACE("Proc::getOutPortValue " << nodeNumId << " " << portName); + stringstream msg; + if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0) + { + msg << "unknown node id: " << nodeNumId << ""; + return msg.str(); + } + try + { + YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId]; + OutputPort * outputPort = node->getOutputPort(portName); + return outputPort->dump(); + } + catch(YACS::Exception& ex) + { + DEBTRACE("Proc::getOutPortValue " << ex.what()); + msg << "" << ex.what() << ""; + return msg.str(); + } +} + +std::string Proc::getNodeErrorDetails(int nodeNumId) +{ + DEBTRACE("Proc::getNodeErrorDetails " << nodeNumId); + stringstream msg; + if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0) + { + msg << "Unknown node id " << nodeNumId; + return msg.str(); + } + YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId]; + return node->getErrorDetails(); +} + +std::string Proc::getNodeErrorReport(int nodeNumId) +{ + DEBTRACE("Proc::getNodeErrorReport " << nodeNumId); + stringstream msg; + if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0) + { + msg << "Unknown node id " << nodeNumId; + return msg.str(); + } + YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId]; + return node->getErrorReport(); +} + +std::string Proc::getNodeContainerLog(int nodeNumId) +{ + DEBTRACE("Proc::getNodeContainerLog " << nodeNumId); + stringstream msg; + if(YACS::ENGINE::Node::idMap.count(nodeNumId) == 0) + { + msg << "Unknown node id " << nodeNumId; + return msg.str(); + } + YACS::ENGINE::Node* node = YACS::ENGINE::Node::idMap[nodeNumId]; + return node->getContainerLog(); +} + std::list Proc::getNumIds() { - set nodes = getAllRecursiveConstituents(); + list nodes = getAllRecursiveConstituents(); int len = nodes.size(); list numids; - for( set::const_iterator iter = nodes.begin(); + for( list::const_iterator iter = nodes.begin(); iter != nodes.end(); iter++) { numids.push_back((*iter)->getNumId()); @@ -169,10 +265,10 @@ std::list Proc::getNumIds() std::list Proc::getIds() { - set nodes = getAllRecursiveConstituents(); + list nodes = getAllRecursiveConstituents(); int len = nodes.size(); list ids; - for( set::const_iterator iter = nodes.begin(); + for( list::const_iterator iter = nodes.begin(); iter != nodes.end(); iter++) { ids.push_back(getChildName(*iter)); @@ -180,3 +276,40 @@ std::list Proc::getIds() ids.push_back("_root_"); return ids; } + +Logger *Proc::getLogger(const std::string& name) +{ + Logger* logger; + LoggerMap::const_iterator it = _loggers.find(name); + + if (it != _loggers.end()) + { + logger = it->second; + } + else + { + logger = new Logger(name); + _loggers[name]=logger; + } + return logger; +} + +void Proc::setEdition(bool edition) +{ + DEBTRACE("Proc::setEdition: " << edition); + _edition=edition; + if(_edition) + edUpdateState(); +} +//! Sets Proc in modified state and update state if in edition mode +/*! + * + */ +void Proc::modified() +{ + DEBTRACE("Proc::modified() " << _edition); + _modified=1; + if(_edition) + edUpdateState(); +} + diff --git a/src/engine/Proc.hxx b/src/engine/Proc.hxx index 77518b8de..8b2fb9ab2 100644 --- a/src/engine/Proc.hxx +++ b/src/engine/Proc.hxx @@ -5,6 +5,7 @@ #include #include #include +#include namespace YACS { @@ -15,6 +16,8 @@ namespace YACS class InlineNode; class ServiceNode; class Container; + class ComponentInstance; + class Logger; class Proc: public Bloc { @@ -32,19 +35,37 @@ namespace YACS virtual void accept(Visitor *visitor); YACS::StatesForNode getNodeState(int numId); + std::string getInPortValue(int nodeNumId, std::string portName); + std::string getOutPortValue(int nodeNumId, std::string portName); + std::string getNodeErrorDetails(int nodeNumId); + std::string getNodeErrorReport(int nodeNumId); + std::string getNodeContainerLog(int nodeNumId); std::string getXMLState(int numId); std::list getNumIds(); std::list getIds(); + virtual Logger *getLogger(const std::string& name); - virtual void writeDot(std::ostream &os); + virtual void writeDot(std::ostream &os) const; void setName(const std::string& name); // Used by GUI to display graph name + virtual std::string typeName() {return "YACS__ENGINE__Proc";} + friend std::ostream & operator<< ( std::ostream &os, const Proc& p); std::map nodeMap; std::map serviceMap; std::map inlineMap; std::map typeMap; std::map containerMap; + std::map, ComponentInstance*> componentInstanceMap; std::vector names; + + typedef std::map LoggerMap; + LoggerMap _loggers; + virtual bool getEdition(){return _edition;} + virtual void setEdition(bool edition); + virtual void modified(); + protected: + bool _edition; + }; } } diff --git a/src/engine/RefCounter.cxx b/src/engine/RefCounter.cxx index a38f41590..cb86136ee 100644 --- a/src/engine/RefCounter.cxx +++ b/src/engine/RefCounter.cxx @@ -1,4 +1,7 @@ #include "RefCounter.hxx" + +#include "Mutex.hxx" + //#define REFCNT #include @@ -11,20 +14,26 @@ using namespace YACS::ENGINE; unsigned int RefCounter::_totalCnt=0; +static YACS::BASES::Mutex _globalMutexForTS; + void RefCounter::incrRef() const { + _globalMutexForTS.lock(); #ifdef REFCNT RefCounter::_totalCnt++; #endif _cnt++; + _globalMutexForTS.unlock(); } bool RefCounter::decrRef() { + _globalMutexForTS.lock(); #ifdef REFCNT RefCounter::_totalCnt--; #endif bool ret=(--_cnt==0); + _globalMutexForTS.unlock(); if(ret) delete this; return ret; diff --git a/src/engine/Runtime.cxx b/src/engine/Runtime.cxx index b8d44d381..6bfae8368 100644 --- a/src/engine/Runtime.cxx +++ b/src/engine/Runtime.cxx @@ -9,6 +9,9 @@ #include "Proc.hxx" #include "InputDataStreamPort.hxx" #include "OutputDataStreamPort.hxx" +#include "Catalog.hxx" +#include "TypeCode.hxx" + #include //#define _DEVDEBUG_ @@ -18,14 +21,14 @@ using namespace YACS::ENGINE; using namespace std; Runtime* Runtime::_singleton = 0; +TypeCode* Runtime::_tc_double = 0; +TypeCode* Runtime::_tc_int = 0; +TypeCode* Runtime::_tc_bool = 0; +TypeCode* Runtime::_tc_string = 0; +TypeCode* Runtime::_tc_file = 0; // --- init typecodes for edInit with C++ Any -TypeCode *Runtime::_tc_double = new TypeCode(Double); -TypeCode *Runtime::_tc_int = new TypeCode(Int); -TypeCode *Runtime::_tc_bool = new TypeCode(Bool); -TypeCode *Runtime::_tc_string = new TypeCode(String); -TypeCode *Runtime::_tc_file = new TypeCodeObjref("file", "file"); const char Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME[]="Neutral"; @@ -38,8 +41,46 @@ Runtime* YACS::ENGINE::getRuntime() throw(Exception) return Runtime::_singleton; } +Runtime::Runtime() +{ + DEBTRACE("Runtime::Runtime"); + Runtime::_tc_double = new TypeCode(Double); + Runtime::_tc_int = new TypeCode(Int); + Runtime::_tc_bool = new TypeCode(Bool); + Runtime::_tc_string = new TypeCode(String); + Runtime::_tc_file = new TypeCodeObjref("file", "file"); + DEBTRACE( "_tc_double refcnt: " << Runtime::_tc_double->getRefCnt() ); + DEBTRACE( "_tc_int refcnt: " << Runtime::_tc_int->getRefCnt() ); + DEBTRACE( "_tc_bool refcnt: " << Runtime::_tc_bool->getRefCnt() ); + DEBTRACE( "_tc_string refcnt: " << Runtime::_tc_string->getRefCnt() ); + DEBTRACE( "_tc_file refcnt: " << Runtime::_tc_file->getRefCnt() ); + _builtinCatalog = new Catalog("builtins"); + _builtinCatalog->_composednodeMap["Bloc"]=new Bloc("Bloc"); + _builtinCatalog->_composednodeMap["Switch"]=new Switch("Switch"); + _builtinCatalog->_composednodeMap["WhileLoop"]=new WhileLoop("WhileLoop"); + _builtinCatalog->_composednodeMap["ForLoop"]=new ForLoop("ForLoop"); + _builtinCatalog->_composednodeMap["ForEachLoopDouble"]=new ForEachLoop("ForEachLoopDouble",Runtime::_tc_double); + std::map& typeMap=_builtinCatalog->_typeMap; + Runtime::_tc_double->incrRef(); + typeMap["double"]=Runtime::_tc_double; + Runtime::_tc_int->incrRef(); + typeMap["int"]=Runtime::_tc_int; + Runtime::_tc_bool->incrRef(); + typeMap["bool"]=Runtime::_tc_bool; + Runtime::_tc_string->incrRef(); + typeMap["string"]=Runtime::_tc_string; + Runtime::_tc_file->incrRef(); + typeMap["file"]=Runtime::_tc_file; +} + +void Runtime::removeRuntime() +{ + delete this; +} + Runtime::~Runtime() { + delete _builtinCatalog; DEBTRACE( "_tc_double refcnt: " << Runtime::_tc_double->getRefCnt() ); DEBTRACE( "_tc_int refcnt: " << Runtime::_tc_int->getRefCnt() ); DEBTRACE( "_tc_bool refcnt: " << Runtime::_tc_bool->getRefCnt() ); @@ -50,10 +91,22 @@ Runtime::~Runtime() Runtime::_tc_bool->decrRef(); Runtime::_tc_string->decrRef(); Runtime::_tc_file->decrRef(); + for(std::vector::const_iterator it=_catalogs.begin();it !=_catalogs.end();it++) + delete (*it); Runtime::_singleton=0; DEBTRACE( "Total YACS::ENGINE::Refcount: " << RefCounter::_totalCnt ); } +DataNode* Runtime::createInDataNode(const std::string& kind,const std::string& name) +{ + throw Exception("InDataNode factory not implemented"); +} + +DataNode* Runtime::createOutDataNode(const std::string& kind,const std::string& name) +{ + throw Exception("OutDataNode factory not implemented"); +} + InlineFuncNode* Runtime::createFuncNode(const std::string& kind,const std::string& name) { throw Exception("FuncNode factory not implemented"); @@ -129,3 +182,69 @@ OutputDataStreamPort* Runtime::createOutputDataStreamPort(const std::string& nam { return new OutputDataStreamPort(name,node,type); } + +//! Load a catalog of calculation to use as factory +/*! + * \param sourceKind: the kind of catalog source. It depends on runtime. It could be a file, a server, a directory + * \param path: the path to the catalog. + * \return the loaded Catalog + */ +Catalog* Runtime::loadCatalog(const std::string& sourceKind,const std::string& path) +{ + if (_catalogLoaderFactoryMap.find(sourceKind) == _catalogLoaderFactoryMap.end()) + { + throw Exception("This type of catalog loader does not exist: " + sourceKind); + } + else + { + Catalog* cata=new Catalog(path); + CatalogLoader* proto=_catalogLoaderFactoryMap[sourceKind]; + proto->load(cata,path); + return cata; + } +} + +//! Add a catalog loader factory to the map _catalogLoaderFactoryMap under the name name +/*! + * \param name: name under which the factory is registered + * \param factory: the factory + */ +void Runtime::setCatalogLoaderFactory(const std::string& name, CatalogLoader* factory) +{ + _catalogLoaderFactoryMap[name]=factory; +} + +//! Get the catalog of base nodes (elementary and composed) +/*! + * \return the builtin Catalog + */ +Catalog* Runtime::getBuiltinCatalog() +{ + return _builtinCatalog; +} + +//! Add a catalog of types and nodes to the runtime +/*! + * These catalogs are searched when calling getTypeCode method + */ +void Runtime::addCatalog(Catalog* catalog) +{ + _catalogs.push_back(catalog); +} + +//! Get a typecode by its name from runtime catalogs +/*! + * \return the typecode if it exists or NULL + */ +TypeCode* Runtime::getTypeCode(const std::string& name) +{ + if (_builtinCatalog->_typeMap.count(name) != 0) + return _builtinCatalog->_typeMap[name]; + for(std::vector::const_iterator it=_catalogs.begin();it !=_catalogs.end();it++) + { + if ((*it)->_typeMap.count(name) != 0) + return (*it)->_typeMap[name]; + } + return 0; +} + diff --git a/src/engine/Runtime.hxx b/src/engine/Runtime.hxx index 2e8b65f0f..1453f5c43 100644 --- a/src/engine/Runtime.hxx +++ b/src/engine/Runtime.hxx @@ -6,14 +6,14 @@ #include #include #include +#include namespace YACS { namespace ENGINE { class Runtime; - - Runtime* getRuntime() throw(Exception); // singleton creation + Runtime* getRuntime() throw(Exception); class InputPort; class OutputPort; @@ -24,6 +24,7 @@ namespace YACS class InlineNode; class InlineFuncNode; class ServiceNode; + class DataNode; class Container; class ServiceInlineNode; class ComponentInstance; @@ -34,6 +35,8 @@ namespace YACS class TypeCode; class InputDataStreamPort; class OutputDataStreamPort; + class Catalog; + class CatalogLoader; class Runtime { @@ -42,12 +45,15 @@ namespace YACS virtual void init() { } virtual void fini() { } + virtual Catalog* loadCatalog(const std::string& sourceKind,const std::string& path); virtual InlineFuncNode* createFuncNode(const std::string& kind,const std::string& name); virtual InlineNode* createScriptNode(const std::string& kind,const std::string& name); virtual ServiceNode* createRefNode(const std::string& kind,const std::string& name); virtual ServiceNode* createCompoNode(const std::string& kind,const std::string& name); virtual ServiceInlineNode *createSInlineNode(const std::string& kind, const std::string& name); + virtual DataNode* createInDataNode(const std::string& kind,const std::string& name); + virtual DataNode* createOutDataNode(const std::string& kind,const std::string& name); virtual ComponentInstance* createComponentInstance(const std::string& name, const std::string& kind=""); @@ -79,6 +85,7 @@ namespace YACS virtual InputPort* adapt(InputPort* source, const std::string& impl, TypeCode * type) throw (ConversionException) = 0; + virtual void removeRuntime(); virtual ~Runtime(); public: static const char RUNTIME_ENGINE_INTERACTION_IMPL_NAME[]; @@ -87,12 +94,20 @@ namespace YACS static YACS::ENGINE::TypeCode *_tc_bool; static YACS::ENGINE::TypeCode *_tc_string; static YACS::ENGINE::TypeCode *_tc_file; + virtual void setCatalogLoaderFactory(const std::string& name, CatalogLoader* factory); + std::map _catalogLoaderFactoryMap; + Catalog* getBuiltinCatalog(); + virtual void addCatalog(Catalog* catalog); + virtual TypeCode* getTypeCode(const std::string& name); + protected: static Runtime* _singleton; - Runtime() { } + Runtime(); std::set _setOfImplementation; - + Catalog* _builtinCatalog; + std::vector _catalogs; }; + } } #endif diff --git a/src/engine/ServiceInlineNode.hxx b/src/engine/ServiceInlineNode.hxx index 638008777..31df18965 100644 --- a/src/engine/ServiceInlineNode.hxx +++ b/src/engine/ServiceInlineNode.hxx @@ -19,6 +19,7 @@ namespace YACS void setScript (const std::string &script); std::string getScript() const; void accept(Visitor *visitor); + virtual std::string typeName() {return "YACS__ENGINE__ServiceInlineNode";} protected: std::string _script; }; diff --git a/src/engine/ServiceNode.cxx b/src/engine/ServiceNode.cxx index 2b4e4bca8..cf2c3fbeb 100644 --- a/src/engine/ServiceNode.cxx +++ b/src/engine/ServiceNode.cxx @@ -47,12 +47,23 @@ void ServiceNode::load() if(_component) { if(!_component->isLoaded()) - _component->load(); + { + try + { + _component->load(); + } + catch(Exception& e) + { + _errorDetails=e.what(); + throw e; + } + } } else { std::string what("ServiceNode::load : a load operation requested on ServiceNode called \""); what+=_name; what+="\" with no component specified."; + _errorDetails=what; throw Exception(what); } } @@ -105,7 +116,7 @@ void ServiceNode::setComponent(ComponentInstance* compo) throw(Exception) } _component->incrRef(); } - assert(_component); + //assert(_component); } //! Associate a new component instance to this service node diff --git a/src/engine/ServiceNode.hxx b/src/engine/ServiceNode.hxx index d8b687d2c..1f2bf104f 100644 --- a/src/engine/ServiceNode.hxx +++ b/src/engine/ServiceNode.hxx @@ -44,6 +44,7 @@ namespace YACS */ virtual std::string getKind() const; static const char KIND[]; + virtual std::string typeName() {return "YACS__ENGINE__ServiceNode";} protected: ComponentInstance* _component; std::string _method; diff --git a/src/engine/SharedPtr.hxx b/src/engine/SharedPtr.hxx index 6091dd315..5b3135f2d 100644 --- a/src/engine/SharedPtr.hxx +++ b/src/engine/SharedPtr.hxx @@ -25,6 +25,7 @@ public: operator T &() { return *_ptr; } operator const T &() const { return *_ptr; } SharedPtr operator[](int i) const; + SharedPtr operator[](const char *key) const; }; template @@ -41,4 +42,10 @@ SharedPtr SharedPtr::operator[](int i) const return (*_ptr)[i]; } +template +SharedPtr SharedPtr::operator[](const char *key) const +{ + return (*_ptr)[key]; +} + #endif diff --git a/src/engine/StaticDefinedComposedNode.cxx b/src/engine/StaticDefinedComposedNode.cxx index 8edca1f83..6def8e140 100644 --- a/src/engine/StaticDefinedComposedNode.cxx +++ b/src/engine/StaticDefinedComposedNode.cxx @@ -1,4 +1,6 @@ #include "StaticDefinedComposedNode.hxx" +#include "OutPort.hxx" +#include "InPort.hxx" using namespace std; using namespace YACS::ENGINE; @@ -26,3 +28,15 @@ void StaticDefinedComposedNode::forceMultiplicity(unsigned value) { //no sense for this class } + +void StaticDefinedComposedNode::checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const +{ + if(start->getNode()==end->getNode()) + bw[(ComposedNode *)this].push_back(start); + else + throw Exception("Internal error occured - dealing an unexpected link !"); +} diff --git a/src/engine/StaticDefinedComposedNode.hxx b/src/engine/StaticDefinedComposedNode.hxx index a59551b14..4baac0a80 100644 --- a/src/engine/StaticDefinedComposedNode.hxx +++ b/src/engine/StaticDefinedComposedNode.hxx @@ -20,6 +20,12 @@ namespace YACS bool isPlacementPredictableB4Run() const; bool isMultiplicitySpecified(unsigned& value) const; void forceMultiplicity(unsigned value); + protected: + void checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw, + LinkInfo& info) const; }; } } diff --git a/src/engine/Switch.cxx b/src/engine/Switch.cxx index af2442f45..1c6b18ef0 100644 --- a/src/engine/Switch.cxx +++ b/src/engine/Switch.cxx @@ -1,5 +1,6 @@ #include "Switch.hxx" #include "Visitor.hxx" +#include "LinkInfo.hxx" #include #include @@ -9,7 +10,7 @@ using namespace YACS::ENGINE; using namespace std; const char Switch::DEFAULT_NODE_NAME[]="default"; -const int Switch::ID_FOR_DEFAULT_NODE=-1979020617; +const int Switch::ID_FOR_DEFAULT_NODE=-1973012217; const char Switch::SELECTOR_INPUTPORT_NAME[]="select"; int CollectorSwOutPort::edGetNumberOfOutLinks() const @@ -45,9 +46,9 @@ void CollectorSwOutPort::edRemoveAllLinksLinkedWithMe() throw(Exception) ((*pt).second)->removeInPort(_consumer,true); } -bool CollectorSwOutPort::isDifferentTypeOf(const DataPort *other) const +TypeOfChannel CollectorSwOutPort::getTypeOfChannel() const { - return (*(_potentialProducers.begin())).second->isDifferentTypeOf(other); + return (*(_potentialProducers.begin())).second->getTypeOfChannel(); } void CollectorSwOutPort::getAllRepresented(std::set& represented) const @@ -168,10 +169,23 @@ bool CollectorSwOutPort::checkManagementOfPort(OutPort *port) throw(Exception) throw Exception("CollectorSwOutPort::checkManagementOfPort : unexported port"); } -void CollectorSwOutPort::checkCompletenessOfCases() const throw(Exception) +/*! + * Called by Switch::checkCFLinks. + */ +void CollectorSwOutPort::checkConsistency(LinkInfo& info) const +{ + if(((Switch *)_node)->getNbOfCases()!=_potentialProducers.size()) + info.pushErrSwitch((CollectorSwOutPort *)this); + for(map::const_iterator iter=_potentialProducers.begin();iter!=_potentialProducers.end();iter++) + (*iter).second->checkConsistency(info); +} + +/*! + * Called by LinkInfo::getErrRepr to have a comprehensible message on throw. + * When called, typically checkCompletenessOfCases has detected that some potential producers were laking... + */ +void CollectorSwOutPort::getHumanReprOfIncompleteCases(std::ostream& stream) const { - if(((Switch *)_node)->getNbOfCases()==_potentialProducers.size()) - return ;//Ok all of cases treats _consumer. set lackingCases; for(map< int ,Node * >::const_iterator iter=((Switch *)_node)->_mapOfNode.begin();iter!=((Switch *)_node)->_mapOfNode.end();iter++) { @@ -179,12 +193,12 @@ void CollectorSwOutPort::checkCompletenessOfCases() const throw(Exception) lackingCases.insert((*iter).first); } ostringstream streamForExc; - streamForExc << "CollectorSwOutPort::checkCompletenessOfCases : For link to " << _consumer->getName() << " of node " << _consumer->getNode()->getName() - << " the cases of switch node named " << _node->getName() - << " do not define links for following cases ids :"; + stream << "For link to " << _consumer->getName() << " of node " << _consumer->getNode()->getName() + << " the cases of switch node named " << _node->getName() + << " do not define links for following cases ids :"; for(set::iterator iter=lackingCases.begin();iter!=lackingCases.end();iter++) - streamForExc << Switch::getRepresentationOfCase(*iter) << " "; - throw Exception(streamForExc.str()); + stream << Switch::getRepresentationOfCase(*iter) << " "; + stream << endl; } FakeNodeForSwitch::FakeNodeForSwitch(Switch *sw, bool normalFinish, bool internalError):ElementaryNode("thisIsAFakeNode"), @@ -350,12 +364,12 @@ void Switch::selectRunnableTasks(std::vector& tasks) { } -set Switch::edGetDirectDescendants() const +list Switch::edGetDirectDescendants() const { - set ret; + list ret; for(map< int , Node * >::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++) if((*iter).second) - ret.insert((*iter).second); + ret.push_back((*iter).second); return ret; } @@ -384,6 +398,13 @@ std::list Switch::getSetOfInputPort() const return ret; } + +std::list Switch::getLocalInputPorts() const +{ + list ret=StaticDefinedComposedNode::getLocalInputPorts(); + ret.push_back((InputPort *)&_condition); + return ret; +} OutPort *Switch::getOutPort(const std::string& name) const throw(Exception) { for(map::const_iterator iter=_outPortsCollector.begin();iter!=_outPortsCollector.end();iter++) @@ -402,12 +423,6 @@ InputPort *Switch::getInputPort(const std::string& name) const throw(Exception) return StaticDefinedComposedNode::getInputPort(name); } -void Switch::checkConsistency(ComposedNode *pointOfView) const throw(Exception) -{ - for(map::const_iterator iter=_outPortsCollector.begin();iter!=_outPortsCollector.end();iter++) - (*iter).second->checkCompletenessOfCases(); -} - Node *Switch::getChildByShortName(const std::string& name) const throw(Exception) { if(name==DEFAULT_NODE_NAME) @@ -470,8 +485,10 @@ Node *Switch::edSetNode(int caseId, Node *node) throw(Exception) throw Exception("Switch::edSetNode : null node cannot be set as a case in switch node"); if(node->_father!=0) throw Exception("Switch::edSetNode : node already held by another father"); + checkNoCrossHierachyWith(node); node->_father=this; map< int , Node * >::iterator iter=_mapOfNode.find(caseId); + modified(); if(iter==_mapOfNode.end()) { _mapOfNode[caseId]=node; @@ -507,14 +524,33 @@ std::set Switch::getAllInPortsComingFromOutsideOfCurrentScope() const return ret; } -std::vector< std::pair > Switch::getSetOfLinksComingInCurrentScope() const +void Switch::checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const { - vector< std::pair > ret=StaticDefinedComposedNode::getSetOfLinksComingInCurrentScope(); - set temp2=_condition.edSetOutPort(); - for(set::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++) - if(!isInMyDescendance((*iter3)->getNode())) - ret.push_back(pair((InPort *)&_condition,*iter3)); - return ret; + map::const_iterator iter=_outPortsCollector.find(end); + if(iter!=_outPortsCollector.end()) + { + set represented; + (*iter).second->getAllRepresented(represented); + list others; + for(list::const_iterator iter2=starts.begin();iter2!=starts.end();iter2++) + if(represented.find(*iter2)==represented.end()) + others.push_back(*iter2); + if(others.empty()) + alreadyFed=FED_ST; + else + StaticDefinedComposedNode::checkCFLinks(others,end,alreadyFed,direction,info);//should never happend; + } + else + StaticDefinedComposedNode::checkCFLinks(starts,end,alreadyFed,direction,info); +} + +void Switch::checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * > >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *> >& bw, + LinkInfo& info) const +{ + throw Exception("Switch::checkControlDependancy : a link was dectected between 2 cases of a switch. Impossible !"); } void Switch::checkNoCyclePassingThrough(Node *node) throw(Exception) @@ -522,13 +558,13 @@ void Switch::checkNoCyclePassingThrough(Node *node) throw(Exception) throw Exception("Switch::checkNoCyclePassingThrough : uncorrect control flow link relative to switch"); } -void Switch::checkLinkPossibility(OutPort *start, const std::set& pointsOfViewStart, - InPort *end, const std::set& pointsOfViewEnd) throw(Exception) +void Switch::checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) throw(Exception) { throw Exception("Switch::checkLinkPossibility : A link between 2 different cases of a same Switch requested -> Impossible"); } -void Switch::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) +void Switch::buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) { map::iterator result=_outPortsCollector.find(finalTarget); CollectorSwOutPort *newCollector; @@ -545,7 +581,7 @@ void Switch::buildDelegateOf(std::pair& port, InPort *fina port.first=newCollector; } -void Switch::getDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) throw(Exception) +void Switch::getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) throw(Exception) { map::iterator iter=_outPortsCollector.find(finalTarget); if(iter==_outPortsCollector.end()) @@ -559,7 +595,7 @@ void Switch::getDelegateOf(std::pair& port, InPort *finalT port.first=(*iter).second; } -void Switch::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception) +void Switch::releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception) { set repr; portDwn->getAllRepresented(repr); @@ -605,23 +641,27 @@ string Switch::getRepresentationOfCase(int i) * \param node: the node which effective state is queried * \return the effective node state */ -YACS::StatesForNode Switch::getEffectiveState(Node* node) +YACS::StatesForNode Switch::getEffectiveState(const Node* node) const { YACS::StatesForNode effectiveState=Node::getEffectiveState(); - if(effectiveState==YACS::INITED) - return YACS::INITED; + if(effectiveState==YACS::READY) + return YACS::READY; if(effectiveState==YACS::TOACTIVATE) - return YACS::INITED; + return YACS::READY; if(effectiveState==YACS::DISABLED) return YACS::DISABLED; - map< int , Node * >::iterator iter=_mapOfNode.find(_condition.getIntValue()); + map< int , Node * >::const_iterator iter=_mapOfNode.find(_condition.getIntValue()); if(iter!=_mapOfNode.end() && (*iter).second==node) return node->getState(); else - return YACS::INITED; + return YACS::READY; +} +YACS::StatesForNode Switch::getEffectiveState() const +{ + return Node::getEffectiveState(); } -void Switch::writeDot(std::ostream &os) +void Switch::writeDot(std::ostream &os) const { os << " subgraph cluster_" << getId() << " {\n" ; for(map::const_iterator iter=_mapOfNode.begin();iter!=_mapOfNode.end();iter++) diff --git a/src/engine/Switch.hxx b/src/engine/Switch.hxx index c1fad1c1a..1996c22f4 100644 --- a/src/engine/Switch.hxx +++ b/src/engine/Switch.hxx @@ -23,13 +23,15 @@ namespace YACS bool isAlreadyLinkedWith(InPort *with) const; std::string getNameOfTypeOfCurrentInstance() const; void edRemoveAllLinksLinkedWithMe() throw(Exception); - bool isDifferentTypeOf(const DataPort *other) const; + TypeOfChannel getTypeOfChannel() const; void getAllRepresented(std::set& represented) const; bool addInPort(InPort *inPort) throw(Exception); int removeInPort(InPort *inPort, bool forward) throw(Exception); + public: + void getHumanReprOfIncompleteCases(std::ostream& stream) const; private://Specific part bool removePotentialProducerForMaster(); - void checkCompletenessOfCases() const throw(Exception); + void checkConsistency(LinkInfo& info) const; CollectorSwOutPort(Switch *master, InPort *port); CollectorSwOutPort(const CollectorSwOutPort& other, Switch *master); void addPotentialProducerForMaster(OutPort *port); @@ -79,37 +81,45 @@ namespace YACS ~Switch(); void exUpdateState(); void init(bool start=true); - Node *edSetDefaultNode(Node *node); + //Node* DISOWNnode is a SWIG notation to indicate that the ownership of the node is transfered to C++ + Node *edSetDefaultNode(Node *DISOWNnode); Node *edReleaseDefaultNode() throw(Exception); Node *edReleaseCase(int caseId) throw(Exception); - Node *edSetNode(int caseId, Node *node) throw(Exception); + Node *edSetNode(int caseId, Node *DISOWNnode) throw(Exception); void getReadyTasks(std::vector& tasks); void selectRunnableTasks(std::vector& tasks); - std::set edGetDirectDescendants() const; + std::list edGetDirectDescendants() const; InputPort *edGetConditionPort() { return &_condition; } - void writeDot(std::ostream &os); + void writeDot(std::ostream &os) const; int getNumberOfInputPorts() const; void edRemoveChild(Node *node) throw(Exception); std::list getSetOfInputPort() const; - YACS::StatesForNode getEffectiveState(Node* node); + std::list getLocalInputPorts() const; + YACS::StatesForNode getEffectiveState() const; + YACS::StatesForNode getEffectiveState(const Node* node) const; OutPort *getOutPort(const std::string& name) const throw(Exception); InputPort* getInputPort(const std::string& name) const throw(Exception); - void checkConsistency(ComposedNode *pointOfView=0) const throw(Exception); Node *getChildByShortName(const std::string& name) const throw(Exception); std::string getMyQualifiedName(const Node *directSon) const; std::string getCaseId(const Node *node) const throw(Exception); virtual void accept(Visitor *visitor); int getRankOfNode(Node *node) const; + virtual std::string typeName() {return "YACS__ENGINE__Switch";} protected: YACS::Event updateStateOnFinishedEventFrom(Node *node); Node *simpleClone(ComposedNode *father, bool editionOnly=true) const; std::set getAllInPortsComingFromOutsideOfCurrentScope() const; - std::vector< std::pair > getSetOfLinksComingInCurrentScope() const; - void checkLinkPossibility(OutPort *start, const std::set& pointsOfViewStart, - InPort *end, const std::set& pointsOfViewEnd) throw(Exception); - void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView); - void getDelegateOf(std::pair& port, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); - void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::set& pointsOfView) throw(Exception); + void checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) throw(Exception); + void buildDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView); + void getDelegateOf(std::pair& port, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); + void releaseDelegateOf(OutPort *portDwn, OutPort *portUp, InPort *finalTarget, const std::list& pointsOfView) throw(Exception); + void checkCFLinks(const std::list& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const; + void checkControlDependancy(OutPort *start, InPort *end, bool cross, + std::map < ComposedNode *, std::list < OutPort * > >& fw, + std::vector& fwCross, + std::map< ComposedNode *, std::list < OutPort *> >& bw, + LinkInfo& info) const; void checkNoCyclePassingThrough(Node *node) throw(Exception); private: int getNbOfCases() const; diff --git a/src/engine/Test/Makefile.am b/src/engine/Test/Makefile.am index 3e59783d2..2b00abcd1 100644 --- a/src/engine/Test/Makefile.am +++ b/src/engine/Test/Makefile.am @@ -9,7 +9,7 @@ TestEngine_SOURCES = \ engineTest.cxx TestEngine_LDADD = \ - ../libYACSEngine.la \ + ../libYACSlibEngine.la \ ../../bases/libYACSBases.la @@ -38,7 +38,7 @@ IntegrationTestEngine_SOURCES = \ RuntimeForEngineIntegrationTest.cxx IntegrationTestEngine_LDADD = \ - ../libYACSEngine.la \ + ../libYACSlibEngine.la \ ../../bases/libYACSBases.la IntegrationTestEngine_LDFLAGS = $(CPPUNIT_LIBS) -pthread -ldl @@ -53,4 +53,12 @@ IntegrationTestEngine_CXXFLAGS = \ TESTS = TestEngine IntegrationTestEngine +EXTRA_DIST = \ +ComponentInstanceTest.hxx ContainerTest.hxx engineIntegrationTest.hxx \ +engineTest.hxx PluginOptEvTest1.hxx RuntimeForEngineIntegrationTest.hxx \ +RuntimeForEngineTest.hxx ToyNode.hxx + +clean-local: + rm -f traceExec_* dumpState.xml + include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/engine/Test/RuntimeForEngineIntegrationTest.cxx b/src/engine/Test/RuntimeForEngineIntegrationTest.cxx index 5f08db5bd..8750ad668 100644 --- a/src/engine/Test/RuntimeForEngineIntegrationTest.cxx +++ b/src/engine/Test/RuntimeForEngineIntegrationTest.cxx @@ -1,6 +1,7 @@ #include "RuntimeForEngineIntegrationTest.hxx" #include "ComponentInstanceTest.hxx" #include "ToyNode.hxx" +#include "TypeCode.hxx" #include using namespace std; diff --git a/src/engine/Test/ToyNode.cxx b/src/engine/Test/ToyNode.cxx index c45350fa0..b29075e8f 100644 --- a/src/engine/Test/ToyNode.cxx +++ b/src/engine/Test/ToyNode.cxx @@ -1,4 +1,5 @@ #include "ToyNode.hxx" +#include "TypeCode.hxx" #include using namespace YACS::ENGINE; diff --git a/src/engine/Test/engineIntegrationTest.cxx b/src/engine/Test/engineIntegrationTest.cxx index 92cc1a16b..30c54f9b8 100644 --- a/src/engine/Test/engineIntegrationTest.cxx +++ b/src/engine/Test/engineIntegrationTest.cxx @@ -172,10 +172,26 @@ void EngineIntegrationTest::testBloc3() delete clonedGraph; } +/*! + * Test for cross hierarchy detection when defining a hierarchy. + */ +void EngineIntegrationTest::testBloc4() +{ + Bloc *graph=new Bloc("Graph"); + Bloc *g1=new Bloc("g1"); + Bloc *g2=new Bloc("g2"); + + graph->edAddChild(g1); + g1->edAddChild(g2); + CPPUNIT_ASSERT_THROW(g2->edAddChild(graph),YACS::Exception); + delete graph; +} + void EngineIntegrationTest::testForLoop1() { TypeCode *tc_double = Runtime::_tc_double; TypeCode *tc_int = Runtime::_tc_int; + LinkInfo info(LinkInfo::ALL_DONT_STOP); ToyNode *n1=new ToyNode("T1"); InputPort *i11=n1->edAddInputPort("i11",tc_double); i11->edInit(3.14); @@ -202,6 +218,8 @@ void EngineIntegrationTest::testForLoop1() graph->edAddLink(o1,i21); graph->edAddCFLink(n1,loop); graph->edAddLink(o21,i21); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)n2->getOutputPort("o1"))->get()->getDoubleValue(),19.397, DBL_PRECISION_COMPARE); @@ -216,6 +234,8 @@ void EngineIntegrationTest::testForLoop1() Bloc *clonedGraph=(Bloc *)graph->clone(0); delete graph; Executor exe2; + clonedGraph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe2.RunW(clonedGraph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)clonedGraph->getOutputPort("toto.titi.T2.o1"))->get()->getDoubleValue(),19.397, DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(((Loop *)clonedGraph->getChildByName("toto"))->getNbOfTurns(),3); @@ -228,6 +248,7 @@ void EngineIntegrationTest::testForLoop2() { TypeCode *tc_double = Runtime::_tc_double; TypeCode *tc_int = Runtime::_tc_int; + LinkInfo info(LinkInfo::ALL_DONT_STOP); ToyNode *n1=new ToyNode("T1"); InputPort *i11=n1->edAddInputPort("i11",tc_double); i11->edInit(3.14); @@ -252,12 +273,16 @@ void EngineIntegrationTest::testForLoop2() graph->edAddLink(o1,i21); graph->edAddCFLink(n1,loop); graph->edAddLink(o21,i21); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)n2->getOutputPort("o1"))->get()->getDoubleValue(),19.397, DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),3); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)n2->getOutputPort("o1"))->get()->getDoubleValue(),19.397, DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),3); @@ -271,6 +296,7 @@ void EngineIntegrationTest::testForLoop3() { TypeCode *tc_double = Runtime::_tc_double; TypeCode *tc_int = Runtime::_tc_int; + LinkInfo info(LinkInfo::ALL_DONT_STOP); ToyNode *n1=new ToyNode("T1"); InputPort *i11=n1->edAddInputPort("i11",tc_double); i11->edInit(3.14); @@ -298,6 +324,8 @@ void EngineIntegrationTest::testForLoop3() graph->edAddLink(o12,loop->edGetNbOfTimesInputPort()); graph->edAddLink(o21,i21); graph->edAddLink(o21,i31); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)graph->getOutputPort("T3.o1"))->get()->getDoubleValue(),10.12, DBL_PRECISION_COMPARE); @@ -306,6 +334,8 @@ void EngineIntegrationTest::testForLoop3() CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n1->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n3->getState(),YACS::DONE); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)graph->getOutputPort("T3.o1"))->get()->getDoubleValue(),10.12, DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),2); @@ -318,12 +348,16 @@ void EngineIntegrationTest::testForLoop3() n1->edRemovePort(i12); graph->edRemoveLink(o21,i31); graph->edAddLink(o11,i31); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),0); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n1->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n3->getState(),YACS::DONE); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),0); @@ -331,6 +365,8 @@ void EngineIntegrationTest::testForLoop3() CPPUNIT_ASSERT_EQUAL(n1->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n3->getState(),YACS::DONE); Bloc *clonedGraph=(Bloc *)graph->clone(0); + clonedGraph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe2; exe2.RunW(clonedGraph); CPPUNIT_ASSERT_EQUAL(((Loop *)clonedGraph->getChildByName("toto"))->getState(),YACS::DONE); @@ -348,6 +384,8 @@ void EngineIntegrationTest::testForLoop3() CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::FAILED); CPPUNIT_ASSERT_EQUAL(n1->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n3->getState(),YACS::FAILED); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::ERROR); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),0); @@ -355,6 +393,8 @@ void EngineIntegrationTest::testForLoop3() CPPUNIT_ASSERT_EQUAL(n1->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n3->getState(),YACS::FAILED); clonedGraph=(Bloc *)graph->clone(0); + clonedGraph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe2.RunW(clonedGraph); CPPUNIT_ASSERT_EQUAL(((Loop *)clonedGraph->getChildByName("toto"))->getState(),YACS::ERROR); CPPUNIT_ASSERT_EQUAL(((Loop *)clonedGraph->getChildByName("toto"))->getNbOfTurns(),0); @@ -366,12 +406,16 @@ void EngineIntegrationTest::testForLoop3() //retrieves back state and retest graph->edRemoveLink(o21,i31); graph->edAddLink(o11,i31); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),0); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n1->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n3->getState(),YACS::DONE); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),0); @@ -385,6 +429,8 @@ void EngineIntegrationTest::testForLoop3() i11->edInit(3.14); i12=n1->edAddInputPort("i12",tc_double); i12->edInit(2.78); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)graph->getOutputPort("T3.o1"))->get()->getDoubleValue(),10.12, DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),2); @@ -392,6 +438,8 @@ void EngineIntegrationTest::testForLoop3() CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n1->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(n3->getState(),YACS::DONE); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)graph->getOutputPort("T3.o1"))->get()->getDoubleValue(),10.12, DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(loop->getNbOfTurns(),2); @@ -404,6 +452,7 @@ void EngineIntegrationTest::testForLoop3() void EngineIntegrationTest::testForLoop4() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("Graph"); ToyNode *n1=new ToyNode("T1"); graph->edAddChild(n1); ForLoop *loop=new ForLoop("loop"); graph->edAddChild(loop); graph->edAddCFLink(n1,loop); @@ -420,6 +469,8 @@ void EngineIntegrationTest::testForLoop4() graph->edAddLink(n1->edGetNbOfInputsOutputPort(),loop->edGetNbOfTimesInputPort()); Bloc *graph2=(Bloc *)graph->clone(0); loop->edGetNbOfTimesInputPort()->edInit(0); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); @@ -438,6 +489,8 @@ void EngineIntegrationTest::testForLoop4() graph->edAddCFLink(n1,blocInt); graph->edAddLink(o11,i21); graph->edAddLink(n1->edGetNbOfInputsOutputPort(),loop->edGetNbOfTimesInputPort()); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); @@ -457,7 +510,8 @@ void EngineIntegrationTest::testForLoop4() CPPUNIT_ASSERT_EQUAL(loop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(0,loop->getNbOfTurns()); - + graph2->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph2); ForLoop *loop2=(ForLoop *)graph2->getChildByName("loop"); CPPUNIT_ASSERT_EQUAL(loop2->getState(),YACS::DONE); @@ -479,6 +533,11 @@ void EngineIntegrationTest::testForLoop4() i21=graph2->getInputPort("blocInt.loop.T2.i21"); graph2->edAddLink(o11,i21); graph2->edAddLink(n1->edGetNbOfInputsOutputPort(),loop2->edGetNbOfTimesInputPort()); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + exe.RunW(graph); + graph2->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph2); CPPUNIT_ASSERT_EQUAL(loop2->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph2->getState(),YACS::DONE); @@ -496,6 +555,7 @@ void EngineIntegrationTest::testForLoop4() //multi loop inclusion void EngineIntegrationTest::testForLoop5() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("Graph"); ToyNode *n1=new ToyNode("T1"); graph->edAddChild(n1); Bloc *b1=new Bloc("b1"); graph->edAddChild(b1); graph->edAddCFLink(n1,b1); @@ -516,6 +576,8 @@ void EngineIntegrationTest::testForLoop5() graph->edAddLink(o21,i21); graph->edAddLink(o11,i21); Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)loop2->getOutputPort("b3.loop4.b5.T2.o21"))->get()->getDoubleValue(),54., DBL_PRECISION_COMPARE); @@ -533,6 +595,7 @@ void EngineIntegrationTest::testWhileLoop1() { TypeCode *tc_double = Runtime::_tc_double; TypeCode *tc_int = Runtime::_tc_int; + LinkInfo info(LinkInfo::ALL_DONT_STOP); ToyNode *n1=new ToyNode("T1"); InputPort *i11=n1->edAddInputPort("i11",tc_double); i11->edInit(3.14); @@ -573,6 +636,14 @@ void EngineIntegrationTest::testWhileLoop1() graph->edAddLink(l2->getSwitchPort(),whileLoop->edGetConditionPort()); graph->edAddLink(o1,i21); graph->edAddLink(o1,l1->getEntry()); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + CPPUNIT_ASSERT(1==info.getNumberOfInfoLinks(I_CF_USELESS)); + graph->edRemoveCFLink(n1,whileLoop); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + CPPUNIT_ASSERT(0==info.getNumberOfInfoLinks(I_CF_USELESS)); + Executor exe; exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputLimitPort*)l2->getCounterPort())->get()->getDoubleValue(),207.0922, DBL_PRECISION_COMPARE); @@ -587,6 +658,7 @@ void EngineIntegrationTest::testSwitch() { RuntimeForEngineIntegrationTest::setRuntime(); Runtime *myRuntime = getRuntime(); + LinkInfo info(LinkInfo::ALL_DONT_STOP); TypeCode *tc_double = Runtime::_tc_double; TypeCode *tc_int = Runtime::_tc_int; Bloc *graph=new Bloc("Graph"); @@ -633,6 +705,8 @@ void EngineIntegrationTest::testSwitch() mySwitch->edSetNode(2,n4); graph->edAddLink(o1,i41); Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)o31)->get()->getDoubleValue(),19., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(((OutputToyPort*)o21)->get(),(Any *)0); @@ -641,6 +715,8 @@ void EngineIntegrationTest::testSwitch() CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); InputPort *i12=n1->edAddInputPort("i12",tc_double); i12->edInit(17.); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)o41)->get()->getDoubleValue(),37., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(((OutputToyPort*)o21)->get(),(Any *)0); @@ -654,6 +730,7 @@ void EngineIntegrationTest::testSwitch2() { TypeCode *tc_double = Runtime::_tc_double; TypeCode *tc_int = Runtime::_tc_int; + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("Graph"); ToyNode *n1=new ToyNode("T1"); @@ -718,30 +795,22 @@ void EngineIntegrationTest::testSwitch2() inLoop->edAddLink(l2->getCounterPort(),ii21); graph->edAddLink(l1->getSwitchPort(),whileLoop->edGetConditionPort()); graph->edAddLink(l2->getSwitchPort(),whileLoop->edGetConditionPort()); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); graph->edRemoveLink(o31,ii22); - try - { - mySwitch->checkConsistency(); - CPPUNIT_ASSERT(0); - } - catch(Exception& e) - { - CPPUNIT_ASSERT(std::string(e.what())=="CollectorSwOutPort::checkCompletenessOfCases : For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :1 "); - } + graph->checkConsistency(info); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_ALL) ); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_UNCOMPLETE_SW) ); + CPPUNIT_ASSERT(info.getErrRepr()=="For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :1 \n"); graph->edRemoveLink(o41,ii22); - try - { - mySwitch->checkConsistency(); - CPPUNIT_ASSERT(0); - } - catch(Exception& e) - { - CPPUNIT_ASSERT(std::string(e.what())=="CollectorSwOutPort::checkCompletenessOfCases : For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :1 2 "); - } + graph->checkConsistency(info); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_ALL) ); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_UNCOMPLETE_SW) ); + CPPUNIT_ASSERT(info.getErrRepr()=="For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :1 2 \n"); graph->edAddLink(o31,ii22); graph->edAddLink(o41,ii22); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; DEBTRACE("Run graph"); exe.RunW(graph); @@ -750,6 +819,8 @@ void EngineIntegrationTest::testSwitch2() CPPUNIT_ASSERT_EQUAL(whileLoop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),161., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,whileLoop->getNbOfTurns()); @@ -763,24 +834,22 @@ void EngineIntegrationTest::testSwitch2() i52->edInit(4.); mySwitch->edSetDefaultNode(n5); graph->edAddLink(o1,i51); - try - { - mySwitch->checkConsistency(); - CPPUNIT_ASSERT(0); - } - catch(Exception& e) - { - CPPUNIT_ASSERT(std::string(e.what())=="CollectorSwOutPort::checkCompletenessOfCases : For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :default "); - } + graph->checkConsistency(info); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_ALL) ); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_UNCOMPLETE_SW) ); + CPPUNIT_ASSERT(info.getErrRepr()=="For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :default \n"); graph->edAddLink(o51,ii22); - mySwitch->checkConsistency(); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),161., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,whileLoop->getNbOfTurns()); CPPUNIT_ASSERT_EQUAL(whileLoop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),161., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,whileLoop->getNbOfTurns()); @@ -796,14 +865,17 @@ void EngineIntegrationTest::testSwitch2() CPPUNIT_ASSERT(std::string(e.what())=="Switch::edReleaseCase : the case # 4 is not set yet."); } mySwitch->edReleaseCase(1); - mySwitch->checkConsistency(); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),175., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,whileLoop->getNbOfTurns()); CPPUNIT_ASSERT_EQUAL(whileLoop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),175., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,whileLoop->getNbOfTurns()); @@ -811,13 +883,16 @@ void EngineIntegrationTest::testSwitch2() CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); //now test when unexpected value is recieved and no default node specifies mySwitch->edReleaseDefaultNode(); - mySwitch->checkConsistency(); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(whileLoop->getState(),YACS::FAILED); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::FAILED); CPPUNIT_ASSERT_EQUAL(mySwitch->getState(),YACS::ERROR); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(whileLoop->getState(),YACS::FAILED); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::FAILED); @@ -825,17 +900,13 @@ void EngineIntegrationTest::testSwitch2() //retrieving back state mySwitch->edSetDefaultNode(n5); graph->edAddLink(o1,i51); - try - { - mySwitch->checkConsistency(); - CPPUNIT_ASSERT(0); - } - catch(Exception& e) - { - CPPUNIT_ASSERT(std::string(e.what())=="CollectorSwOutPort::checkCompletenessOfCases : For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :default "); - } + graph->checkConsistency(info); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_ALL) ); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_UNCOMPLETE_SW) ); + CPPUNIT_ASSERT(info.getErrRepr()=="For link to ii2 of node TT2 the cases of switch node named mySwitch do not define links for following cases ids :default \n"); graph->edAddLink(o51,ii22); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); DEBTRACE("Run graph"); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),175., DBL_PRECISION_COMPARE); @@ -853,12 +924,16 @@ void EngineIntegrationTest::testSwitch2() graph->edAddLink(o1,i31); graph->edAddLink(o31,ii22); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),161., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,whileLoop->getNbOfTurns()); CPPUNIT_ASSERT_EQUAL(whileLoop->getState(),YACS::DONE); CPPUNIT_ASSERT_EQUAL(graph->getState(),YACS::DONE); DEBTRACE("Run graph"); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)l2->getCounterPort())->get()->getDoubleValue(),161., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,whileLoop->getNbOfTurns()); @@ -867,6 +942,8 @@ void EngineIntegrationTest::testSwitch2() Bloc *clonedGraph=(Bloc *)graph->clone(0); delete graph; Executor exe2; + clonedGraph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe2.RunW(clonedGraph); CPPUNIT_ASSERT_DOUBLES_EQUAL(((OutputToyPort*)clonedGraph->getOutPort("MyWhile.inLoop.L2.SwitchPort2"))->get()->getDoubleValue(),161., DBL_PRECISION_COMPARE); CPPUNIT_ASSERT_EQUAL(3,((WhileLoop *)clonedGraph->getChildByName("MyWhile"))->getNbOfTurns()); @@ -880,6 +957,7 @@ void EngineIntegrationTest::testSwitch2() */ void EngineIntegrationTest::testSwitch3() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("Graph"); Switch *mySwitch1=new Switch("mySwitch1"); graph->edAddChild(mySwitch1); @@ -907,8 +985,10 @@ void EngineIntegrationTest::testSwitch3() graph->edAddLink(o31,i61); graph->edAddLink(o41,i61); graph->edAddLink(o51,i61); - mySwitch1->checkConsistency(); - mySwitch2->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,n6->getInGate()->getNumberOfBackLinks()); CPPUNIT_ASSERT_EQUAL(1,i61->edGetNumberOfLinks());// <-- important CPPUNIT_ASSERT_EQUAL(4,o11->edGetNumberOfOutLinks()); @@ -929,19 +1009,15 @@ void EngineIntegrationTest::testSwitch3() CPPUNIT_ASSERT_EQUAL(1,i61->edGetNumberOfLinks()); graph->edAddLink(o41,i61); CPPUNIT_ASSERT_EQUAL(1,i61->edGetNumberOfLinks()); - try - { - mySwitch2->checkConsistency(); - CPPUNIT_ASSERT(0); - } - catch(Exception& e) - { - CPPUNIT_ASSERT(std::string(e.what())=="CollectorSwOutPort::checkCompletenessOfCases : For link to i61 of node T6 the cases of switch node named mySwitch2 do not define links for following cases ids :2 8 "); - } + graph->checkConsistency(info); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_ALL) ); + CPPUNIT_ASSERT( 1==info.getNumberOfErrLinks(E_UNCOMPLETE_SW) ); + CPPUNIT_ASSERT(info.getErrRepr()=="For link to i61 of node T6 the cases of switch node named mySwitch2 do not define links for following cases ids :2 8 \n"); graph->edAddLink(o31,i61); graph->edAddLink(o51,i61); - mySwitch2->checkConsistency(); CPPUNIT_ASSERT_EQUAL(1,i61->edGetNumberOfLinks()); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL( ((OutputToyPort*)graph->getOutputPort("T6.o61"))->get()->getDoubleValue(),21., DBL_PRECISION_COMPARE); @@ -958,6 +1034,7 @@ void EngineIntegrationTest::testSwitch3() void EngineIntegrationTest::testWhileLoop2()//Test of 0 turn of loop { //first test without any link to condition port on start of loop that is to say WhileLoop is considered has while and NOT dowhile. + LinkInfo info(LinkInfo::ALL_DONT_STOP); TypeCode *tc_double = Runtime::_tc_double; TypeCode *tc_int = Runtime::_tc_int; ToyNode *n1=new ToyNode("T1"); @@ -994,6 +1071,8 @@ void EngineIntegrationTest::testWhileLoop2()//Test of 0 turn of loop graph->edAddLink(ol2s,loop->edGetConditionPort()); graph->edAddLink(o21,i21); graph->edAddLink(o21,i31); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; DEBTRACE("Run graph"); exe.RunW(graph); @@ -1179,7 +1258,7 @@ void EngineIntegrationTest::testEdInitOnLoops() void EngineIntegrationTest::testLinkUpdate1() { Bloc *graph=new Bloc("Graph"); - + LinkInfo info(LinkInfo::ALL_DONT_STOP); ToyNode *n1=new ToyNode("T1"); InputPort *i11=n1->edAddInputPort("i11",Runtime::_tc_double); i11->edInit(17.); @@ -1219,7 +1298,8 @@ void EngineIntegrationTest::testLinkUpdate1() graph->edAddCFLink(mySwitch,n4); graph->edAddLink(o21,i41); graph->edAddLink(o31,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks());// <-- important @@ -1247,7 +1327,8 @@ void EngineIntegrationTest::testLinkUpdate1() // graph->edAddLink(o21,i41); graph->edAddLink(o31,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks()); @@ -1264,7 +1345,8 @@ void EngineIntegrationTest::testLinkUpdate1() CPPUNIT_ASSERT_EQUAL(0,o51->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks()); graph->edAddLink(o51,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o51->edGetNumberOfOutLinks()); @@ -1275,11 +1357,13 @@ void EngineIntegrationTest::testLinkUpdate1() CPPUNIT_ASSERT_EQUAL(1,o51->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks()); graph->edAddLink(o31,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); graph->edAddLink(o22,i42); graph->edAddLink(o32,i42); graph->edAddLink(o52,i42); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o51->edGetNumberOfOutLinks()); @@ -1306,7 +1390,8 @@ void EngineIntegrationTest::testLinkUpdate1() CPPUNIT_ASSERT_EQUAL(1,i42->edGetNumberOfLinks()); CPPUNIT_ASSERT_EQUAL(1,i62->edGetNumberOfLinks()); graph->edRemoveChild(n6);//normally implies collector inputport deletion - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o22->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o32->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o52->edGetNumberOfOutLinks()); @@ -1365,7 +1450,7 @@ void EngineIntegrationTest::testLinkUpdate1() void EngineIntegrationTest::testLinkUpdate1DS() { Bloc *graph=new Bloc("Graph"); - + LinkInfo info(LinkInfo::ALL_DONT_STOP); ToyNode *n1=new ToyNode("T1"); InputDataStreamPort *i11=n1->edAddInputDataStreamPort("i11",Runtime::_tc_double); OutputDataStreamPort *o1=n1->edAddOutputDataStreamPort("o1",Runtime::_tc_double); @@ -1401,7 +1486,8 @@ void EngineIntegrationTest::testLinkUpdate1DS() graph->edAddCFLink(mySwitch,n4); graph->edAddLink(o21,i41); graph->edAddLink(o31,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks());// <-- important @@ -1429,7 +1515,8 @@ void EngineIntegrationTest::testLinkUpdate1DS() // graph->edAddLink(o21,i41); graph->edAddLink(o31,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks()); @@ -1445,7 +1532,8 @@ void EngineIntegrationTest::testLinkUpdate1DS() CPPUNIT_ASSERT_EQUAL(0,o51->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks()); graph->edAddLink(o51,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o51->edGetNumberOfOutLinks()); @@ -1456,11 +1544,13 @@ void EngineIntegrationTest::testLinkUpdate1DS() CPPUNIT_ASSERT_EQUAL(1,o51->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,i41->edGetNumberOfLinks()); graph->edAddLink(o31,i41); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); graph->edAddLink(o22,i42); graph->edAddLink(o32,i42); graph->edAddLink(o52,i42); - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o21->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o31->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o51->edGetNumberOfOutLinks()); @@ -1487,7 +1577,8 @@ void EngineIntegrationTest::testLinkUpdate1DS() CPPUNIT_ASSERT_EQUAL(1,i42->edGetNumberOfLinks()); CPPUNIT_ASSERT_EQUAL(1,i62->edGetNumberOfLinks()); graph->edRemoveChild(n6);//normally implies collector inputport deletion - mySwitch->checkConsistency(); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); CPPUNIT_ASSERT_EQUAL(1,o22->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o32->edGetNumberOfOutLinks()); CPPUNIT_ASSERT_EQUAL(1,o52->edGetNumberOfOutLinks()); @@ -1855,6 +1946,52 @@ void EngineIntegrationTest::testLinkUpdate2DS() delete graph; } +void EngineIntegrationTest::testLinkUpdate3() +{ + Bloc *graph=new Bloc("Graph"); + WhileLoop *loop2=new WhileLoop("loop2"); + graph->edAddChild(loop2); + LimitNode *n1=new LimitNode("T1"); graph->edAddChild(n1); + OutputPort *o1s=n1->getSwitchPort(); + graph->edAddCFLink(n1,loop2); + LimitNode *n2=new LimitNode("T2"); loop2->edSetNode(n2); + OutputPort *o2s=n2->getSwitchPort(); + graph->edAddLink(o1s,loop2->edGetConditionPort()); + graph->edAddLink(o2s,loop2->edGetConditionPort()); + graph->edRemoveLink(o2s,loop2->edGetConditionPort()); + graph->edRemoveLink(o1s,loop2->edGetConditionPort()); + delete graph; +} + +void EngineIntegrationTest::testLinkUpdate4() +{ + Bloc *graph1=new Bloc("graph1"); + Bloc *graph2=new Bloc("graph2"); + graph1->edAddChild(graph2); + ForEachLoop *forEach=new ForEachLoop("myFE",Runtime::_tc_double); + graph2->edAddChild(forEach); + ToyNode *n1=new ToyNode("T1"); + OutputPort *o11=n1->edAddOutputPort("o11",Runtime::_tc_double); + Seq2ToyNode *n2=new Seq2ToyNode("n2"); + graph2->edAddChild(n2); + graph2->edAddCFLink(forEach,n2); + forEach->edSetNode(n1); + Seq2ToyNode *n3=new Seq2ToyNode("n3"); + graph1->edAddChild(n3); + graph1->edAddCFLink(graph2,n3); + // + CPPUNIT_ASSERT(graph1->edAddLink(o11,n2->edGetInValue1())); + CPPUNIT_ASSERT(!graph1->edAddLink(o11,n2->edGetInValue1())); + CPPUNIT_ASSERT(graph1->edAddLink(o11,n3->edGetInValue1())); + CPPUNIT_ASSERT(!graph1->edAddLink(o11,n3->edGetInValue1())); + graph1->edRemoveLink(o11,n2->edGetInValue1()); + graph1->edRemoveLink(o11,n3->edGetInValue1()); + // + graph1->edRemoveChild(graph2); + delete graph2; + delete graph1; +} + /*! * test of links between 2 loops to simulate coupling. */ @@ -2004,6 +2141,7 @@ void EngineIntegrationTest::deathTestForLinks() void EngineIntegrationTest::testForEachLoop1() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("graph"); ForEachLoop *forEach=new ForEachLoop("myFE",Runtime::_tc_double); graph->edAddChild(forEach); @@ -2034,6 +2172,8 @@ void EngineIntegrationTest::testForEachLoop1() int tab[]={12,14,16,18,20}; vector tabv(tab,tab+5); SequenceAnyPtr tmp=SequenceAny::New(tabv);//expected sequence + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); Executor exe; exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(3,(int)forEach->getNumberOfBranchesCreatedDyn()); @@ -2052,6 +2192,8 @@ void EngineIntegrationTest::testForEachLoop1() CPPUNIT_ASSERT_EQUAL(2,(int)forEach->getNumberOfBranchesCreatedDyn()); Bloc *graph2=(Bloc *)graph->clone(0); delete graph; + graph2->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph2); CPPUNIT_ASSERT_EQUAL(2,(int)((ForEachLoop *)graph2->getChildByName("myFE"))->getNumberOfBranchesCreatedDyn()); exe.RunW(graph2); @@ -2064,6 +2206,7 @@ void EngineIntegrationTest::testForEachLoop1() void EngineIntegrationTest::testForEachLoop2() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("graph"); ForEachLoop *forEach=new ForEachLoop("myFE",Runtime::_tc_double); graph->edAddChild(forEach); @@ -2098,6 +2241,8 @@ void EngineIntegrationTest::testForEachLoop2() vector tabv(tab,tab+5); SequenceAnyPtr tmp=SequenceAny::New(tabv);//expected sequence Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(3,(int)forEach->getNumberOfBranchesCreatedDyn()); Any *val=n4->edGetSeqOut()->get(); @@ -2115,6 +2260,8 @@ void EngineIntegrationTest::testForEachLoop2() CPPUNIT_ASSERT_EQUAL(2,(int)forEach->getNumberOfBranchesCreatedDyn()); Bloc *graph2=(Bloc *)graph->clone(0); delete graph; + graph2->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph2); CPPUNIT_ASSERT_EQUAL(2,(int)((ForEachLoop *)graph2->getChildByName("myFE"))->getNumberOfBranchesCreatedDyn()); exe.RunW(graph2); @@ -2128,6 +2275,7 @@ void EngineIntegrationTest::testForEachLoop2() //Multi inclusion of ForEach void EngineIntegrationTest::testForEachLoop3() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("graph"); ForEachLoop *forEach1=new ForEachLoop("myFE1",Runtime::_tc_double); TypeCodeSeq *tc1=new TypeCodeSeq("","",Runtime::_tc_double); @@ -2183,6 +2331,8 @@ void EngineIntegrationTest::testForEachLoop3() tmp=SequenceAny::New(tabvI3); tmpO->setEltAtRank(2,tmp); Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(3,(int)forEach2->getNumberOfBranchesCreatedDyn()); Any *val=n2->edGetSeqOut()->get(); @@ -2203,6 +2353,10 @@ void EngineIntegrationTest::testForEachLoop3() } Bloc *graphCloned=(Bloc *)graph->clone(0); delete graph; + clone->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + graphCloned->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(clone); CPPUNIT_ASSERT_EQUAL(3,(int)clone->getNumberOfBranchesCreatedDyn()); exe.RunW(clone); @@ -2221,6 +2375,7 @@ void EngineIntegrationTest::testForEachLoop3() void EngineIntegrationTest::testForEachLoop4() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("graph"); ForEachLoop *forEach1=new ForEachLoop("myFE1",Runtime::_tc_int); Switch *sw=new Switch("Sw1"); @@ -2269,6 +2424,9 @@ void EngineIntegrationTest::testForEachLoop4() //graph->edAddLink(n0->edGetSeqOut(),forEach1->edGetSeqOfSamplesPort()); graph->edAddLink(n0->edGetSeqOut(),n2->edGetInValue2()); Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(1==info.getNumberOfErrLinks(E_NEVER_SET_INPUTPORT)); + try { exe.RunW(graph); @@ -2283,6 +2441,8 @@ void EngineIntegrationTest::testForEachLoop4() int tabI2[]={29,44,44,29,44,29,29,44}; vector tabvI2(tabI2,tabI2+8); SequenceAnyPtr tmp2=SequenceAny::New(tabvI2); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); Any *val=n2->edGetSeqOut()->get(); CPPUNIT_ASSERT( *val==*tmp2 ); @@ -2293,6 +2453,8 @@ void EngineIntegrationTest::testForEachLoop4() CPPUNIT_ASSERT_EQUAL(7,(int)forEach1->getNumberOfBranchesCreatedDyn()); Bloc *graphCloned=(Bloc *)graph->clone(0); delete graph; + graphCloned->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graphCloned); val=((Seq2ToyNode *)graphCloned->getChildByName("T2"))->edGetSeqOut()->get(); delete graphCloned; @@ -2303,6 +2465,7 @@ void EngineIntegrationTest::testForEachLoop4() */ void EngineIntegrationTest::testForEachLoop5() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("graph"); ForEachLoop *forEach=new ForEachLoop("myFE",Runtime::_tc_double); graph->edAddChild(forEach); @@ -2335,6 +2498,8 @@ void EngineIntegrationTest::testForEachLoop5() vector tabv(tab,tab+5); SequenceAnyPtr tmp=SequenceAny::New(tabv);//expected sequence Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_EQUAL(3,(int)forEach->getNumberOfBranchesCreatedDyn()); Any *val=n4->edGetSeqOut()->get(); @@ -2367,6 +2532,7 @@ void EngineIntegrationTest::testForEachLoop5() */ void EngineIntegrationTest::testForOptimizerLoop1() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("Global"); OptimizerLoop *opt=new OptimizerLoop("myOptWthAlgSync",".libs/libPluginOptEvTest1","PluginOptEvTest1Factory",true); graph->edAddChild(opt); @@ -2385,6 +2551,8 @@ void EngineIntegrationTest::testForOptimizerLoop1() opt->edGetNbOfBranchesPort()->edInit(2); opt->edGetPortForInitFile()->edInit("toto"); Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(45.6,((OutputToyPort*)o2_1)->get()->getDoubleValue(),DBL_PRECISION_COMPARE ); CPPUNIT_ASSERT(8==(int)opt->getNumberOfEltsConsumed() or 7==(int)opt->getNumberOfEltsConsumed()); @@ -2395,6 +2563,8 @@ void EngineIntegrationTest::testForOptimizerLoop1() CPPUNIT_ASSERT_EQUAL(2,(int)((DynParaLoop *)(opt))->getNumberOfBranchesCreatedDyn()); Bloc *clone=(Bloc *)graph->clone(0); delete graph; + clone->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(clone); CPPUNIT_ASSERT_DOUBLES_EQUAL(45.6,((OutputToyPort*)(clone->getOutPort("T2.o1")))->get()->getDoubleValue(),DBL_PRECISION_COMPARE ); CPPUNIT_ASSERT(8==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed() or 7==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed()); @@ -2412,6 +2582,7 @@ void EngineIntegrationTest::testForOptimizerLoop1() */ void EngineIntegrationTest::testForOptimizerLoop2() { + LinkInfo info(LinkInfo::ALL_DONT_STOP); Bloc *graph=new Bloc("Global"); OptimizerLoop *opt=new OptimizerLoop("myOptWthAlgSync",".libs/libPluginOptEvTest1","PluginOptEvTest1Factory",true); graph->edAddChild(opt); @@ -2432,6 +2603,8 @@ void EngineIntegrationTest::testForOptimizerLoop2() opt->edGetNbOfBranchesPort()->edInit(2); opt->edGetPortForInitFile()->edInit("toto"); Executor exe; + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(graph); CPPUNIT_ASSERT_DOUBLES_EQUAL(45.6,((OutputToyPort*)o2_1)->get()->getDoubleValue(),DBL_PRECISION_COMPARE ); CPPUNIT_ASSERT(8==(int)opt->getNumberOfEltsConsumed() or 7==(int)opt->getNumberOfEltsConsumed()); @@ -2442,13 +2615,15 @@ void EngineIntegrationTest::testForOptimizerLoop2() CPPUNIT_ASSERT_EQUAL(2,(int)((DynParaLoop *)(opt))->getNumberOfBranchesCreatedDyn()); Bloc *clone=(Bloc *)graph->clone(0); delete graph; + clone->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); exe.RunW(clone); CPPUNIT_ASSERT_DOUBLES_EQUAL(45.6,((OutputToyPort*)(clone->getOutPort("T2.o1")))->get()->getDoubleValue(),DBL_PRECISION_COMPARE ); - CPPUNIT_ASSERT(8==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed() or 7==(int)((OptimizerLoop *)(clone->getChildByName("Bloc.myOptWthAlgSync")))->getNumberOfEltsConsumed()); + CPPUNIT_ASSERT(8==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed() or 7==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed()); CPPUNIT_ASSERT_EQUAL(2,(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfBranchesCreatedDyn()); exe.RunW(clone); CPPUNIT_ASSERT_DOUBLES_EQUAL(45.6,((OutputToyPort*)(clone->getOutPort("T2.o1")))->get()->getDoubleValue(),DBL_PRECISION_COMPARE ); - CPPUNIT_ASSERT(8==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed() or 7==(int)((OptimizerLoop *)(clone->getChildByName("Bloc.myOptWthAlgSync")))->getNumberOfEltsConsumed()); + CPPUNIT_ASSERT(8==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed() or 7==(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfEltsConsumed()); CPPUNIT_ASSERT_EQUAL(2,(int)((OptimizerLoop *)(clone->getChildByName("myOptWthAlgSync")))->getNumberOfBranchesCreatedDyn()); delete clone; } @@ -2774,8 +2949,9 @@ void EngineIntegrationTest::testForCheckConsistency1() checkSetsEqual(setExpected,s3); s3.clear(); setExpected.clear(); list< vector > vec; graph->findAllPathsStartingFrom(n7, vec,accelStr); - graph->findAllNodesStartingFrom(n7,s3,accelStr,info); accelStr.clear();setExpected=graph->edGetDirectDescendants(); setExpected.erase(n8); setExpected.erase(n7); - checkSetsEqual(setExpected,s3); s3.clear(); setExpected.clear(); + graph->findAllNodesStartingFrom(n7,s3,accelStr,info); accelStr.clear();//setExpected=graph->edGetDirectDescendants(); setExpected.erase(n8); setExpected.erase(n7); + //checkSetsEqual(setExpected,s3); + s3.clear(); setExpected.clear(); //Testing good reinitialisation setExpected.insert(n2); setExpected.insert(n4); setExpected.insert(n3); setExpected.insert(n10); setExpected.insert(n11); setExpected.insert(n12); setExpected.insert(n5); setExpected.insert(n6); setExpected.insert(n7); setExpected.insert(n8); @@ -2840,7 +3016,7 @@ void EngineIntegrationTest::testForCheckConsistency1() OutputPort *o1_1=n1->edAddOutputPort("o1_1",Runtime::_tc_double); graph->edAddLink(o1_1,i11_1); graph->checkConsistency(info); - CPPUNIT_ASSERT_EQUAL(1,(int)info.getNumberOfInfoLinks(I_ALL)); CPPUNIT_ASSERT_EQUAL(2,(int)info.getNumberOfInfoLinks(I_USELESS)); CPPUNIT_ASSERT_EQUAL(0,(int)info.getNumberOfWarnLinksGrp(W_ALL)); + CPPUNIT_ASSERT_EQUAL(2,(int)info.getNumberOfInfoLinks(I_ALL)); CPPUNIT_ASSERT_EQUAL(2,(int)info.getNumberOfInfoLinks(I_USELESS)); CPPUNIT_ASSERT_EQUAL(0,(int)info.getNumberOfWarnLinksGrp(W_ALL)); CPPUNIT_ASSERT_EQUAL(0,(int)info.getNumberOfErrLinks(E_ALL)); // collapse and useless ; useless OutputPort *o3_1=n3->edAddOutputPort("o3_1",Runtime::_tc_double); @@ -2879,7 +3055,7 @@ void EngineIntegrationTest::testForCheckConsistency1() CPPUNIT_ASSERT( (pair(o12_1,i11_1)==info.getInfoLink(0,I_BACK_USELESS)) ); graph->edAddLink(o11_1,i11_1); graph->checkConsistency(info); - CPPUNIT_ASSERT_EQUAL(2,(int)info.getNumberOfInfoLinks(I_ALL)); CPPUNIT_ASSERT_EQUAL(0,(int)info.getNumberOfWarnLinksGrp(W_ALL)); CPPUNIT_ASSERT_EQUAL(0,(int)info.getNumberOfErrLinks(E_ALL)); + CPPUNIT_ASSERT_EQUAL(3,(int)info.getNumberOfInfoLinks(I_ALL)); CPPUNIT_ASSERT_EQUAL(0,(int)info.getNumberOfWarnLinksGrp(W_ALL)); CPPUNIT_ASSERT_EQUAL(0,(int)info.getNumberOfErrLinks(E_ALL)); CPPUNIT_ASSERT_EQUAL(1,(int)info.getNumberOfInfoLinks(I_BACK)); CPPUNIT_ASSERT_EQUAL(2,(int)info.getNumberOfInfoLinks(I_BACK_USELESS)); delete graph; } @@ -2903,3 +3079,110 @@ void EngineIntegrationTest::testForCheckConsistency2() graph->findAllNodesStartingFrom(n1,s3,accelStr,info); accelStr.clear(); delete graph; } + +/*! + * Testing forwarding of check consistency. + */ +void EngineIntegrationTest::testForCheckConsistency3() +{ + LinkInfo info(LinkInfo::ALL_DONT_STOP); + ToyNode *n1=new ToyNode("T1"); ToyNode *n2=new ToyNode("T2"); ToyNode *n3=new ToyNode("T3"); + Bloc *graph=new Bloc("Global"); + Bloc *g1=new Bloc("G1"); Bloc *g2=new Bloc("G2"); + graph->edAddChild(g1); + graph->edAddChild(g2); + g1->edAddChild(n1); + g2->edAddChild(n2); + g2->edAddChild(n3); + g2->edAddCFLink(n2,n3); + graph->edAddCFLink(g1,g2); + InputPort *i1_3=n3->edAddInputPort("i1_3",Runtime::_tc_double); + OutputPort *o1_1=n1->edAddOutputPort("o1_1",Runtime::_tc_double); + OutputPort *o2_1=n2->edAddOutputPort("o1_2",Runtime::_tc_double); + graph->edAddLink(o1_1,i1_3); + graph->edAddLink(o2_1,i1_3); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + CPPUNIT_ASSERT(1==info.getNumberOfInfoLinks(I_ALL)); CPPUNIT_ASSERT(1==info.getNumberOfInfoLinks(I_USELESS)); + pair p=info.getInfoLink(0,I_USELESS); + CPPUNIT_ASSERT(p.first==o1_1); CPPUNIT_ASSERT(p.second==i1_3); + //now substituting g2 and graph in superv graph (by keeping same address) + graph->edRemoveChild(g1); + graph->edRemoveChild(g2); + g2->edRemoveChild(n2); + g2->edRemoveChild(n3); + g2->edAddChild(g1); g2->edAddChild(graph); + graph->edAddChild(n2); graph->edAddChild(n3); + graph->edAddCFLink(n2,n3); + g2->edAddCFLink(g1,graph); + g2->edAddLink(o1_1,i1_3); + g2->edAddLink(o2_1,i1_3); + g2->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + CPPUNIT_ASSERT(1==info.getNumberOfInfoLinks(I_ALL)); CPPUNIT_ASSERT(1==info.getNumberOfInfoLinks(I_USELESS)); + p=info.getInfoLink(0,I_USELESS); + CPPUNIT_ASSERT(p.first==o1_1); CPPUNIT_ASSERT(p.second==i1_3); + g2->edRemoveLink(o1_1,i1_3); + g2->checkConsistency(info); + CPPUNIT_ASSERT(0==info.getNumberOfInfoLinks(I_ALL)); + //Now back-links + InputPort *i1_1=n1->edAddInputPort("i1_1",Runtime::_tc_double); + InputPort *i1_2=n2->edAddInputPort("i1_2",Runtime::_tc_double); + OutputPort *o1_3=n3->edAddOutputPort("o1_3",Runtime::_tc_double); + g2->edAddLink(o1_3,i1_1); + g2->edAddLink(o1_3,i1_2); + g2->checkConsistency(info); + CPPUNIT_ASSERT(2==info.getNumberOfErrLinks(E_ALL)); CPPUNIT_ASSERT(2==info.getNumberOfErrLinks(E_ONLY_BACKWARD_DEFINED)); + i1_1->edInit(0.); i1_2->edInit(0.); + g2->checkConsistency(info); + CPPUNIT_ASSERT(2==info.getNumberOfInfoLinks(I_ALL)); CPPUNIT_ASSERT(2==info.getNumberOfInfoLinks(I_BACK)); + delete g2; +} + +void EngineIntegrationTest::testForCheckConsistency4() +{ + LinkInfo info(LinkInfo::ALL_DONT_STOP); + ToyNode *n1=new ToyNode("T1"); ToyNode *n2=new ToyNode("T2"); ToyNode *n3=new ToyNode("T3"); ToyNode *n4=new ToyNode("T4"); + Bloc *graph=new Bloc("Global"); + InputPort *i1_4=n4->edAddInputPort("i1_4",Runtime::_tc_double); + OutputPort *o1_1=n1->edAddOutputPort("o1_1",Runtime::_tc_double); + OutputPort *o1_2=n2->edAddOutputPort("o1_2",Runtime::_tc_double); + OutputPort *o1_3=n3->edAddOutputPort("o1_3",Runtime::_tc_double); + Switch *mySwitch=new Switch("mySwitch"); + mySwitch->edSetNode(0,n1); + mySwitch->edSetNode(7,n2); + graph->edAddChild(n3); + graph->edAddChild(n4); + graph->edAddChild(mySwitch); + graph->edAddCFLink(mySwitch,n4); + graph->edAddCFLink(n3,n4); + graph->edAddLink(o1_1,i1_4); + graph->edAddLink(o1_2,i1_4); + mySwitch->edGetConditionPort()->edInit(7); + graph->checkConsistency(info); + CPPUNIT_ASSERT(!info.areWarningsOrErrors()); + graph->edAddLink(o1_3,i1_4); + graph->checkConsistency(info); + CPPUNIT_ASSERT(1==info.getNumberOfWarnLinksGrp(W_ALL)); + graph->edRemoveLink(o1_1,i1_4); + graph->checkConsistency(info); + CPPUNIT_ASSERT(1==info.getNumberOfWarnLinksGrp(W_ALL)); + CPPUNIT_ASSERT(1==info.getNumberOfErrLinks(E_ALL)); + CPPUNIT_ASSERT(1==info.getNumberOfErrLinks(E_UNCOMPLETE_SW)); + CPPUNIT_ASSERT(info.getErrRepr()=="For link to i1_4 of node T4 the cases of switch node named mySwitch do not define links for following cases ids :0 \n"); + graph->edRemoveChild(mySwitch); + Bloc *bloc4Fun=new Bloc("bloc4Fun"); + graph->edAddChild(bloc4Fun); + bloc4Fun->edAddChild(mySwitch); + graph->edAddCFLink(bloc4Fun,n4); + graph->edAddLink(o1_1,i1_4); + graph->edAddLink(o1_2,i1_4); + graph->checkConsistency(info); + CPPUNIT_ASSERT(1==info.getNumberOfWarnLinksGrp(W_ALL)); + graph->edRemoveLink(o1_1,i1_4); + graph->checkConsistency(info); + CPPUNIT_ASSERT(1==info.getNumberOfWarnLinksGrp(W_ALL)); + CPPUNIT_ASSERT(1==info.getNumberOfErrLinks(E_ALL)); + CPPUNIT_ASSERT(1==info.getNumberOfErrLinks(E_UNCOMPLETE_SW)); + delete graph; +} diff --git a/src/engine/Test/engineIntegrationTest.hxx b/src/engine/Test/engineIntegrationTest.hxx index edac72be8..60efc0260 100644 --- a/src/engine/Test/engineIntegrationTest.hxx +++ b/src/engine/Test/engineIntegrationTest.hxx @@ -2,6 +2,7 @@ #define __ENGINEINTEGRATIONTEST_HXX__ #include +#include namespace YACS { @@ -15,6 +16,7 @@ namespace YACS CPPUNIT_TEST( testBloc1 ); CPPUNIT_TEST( testBloc2 ); CPPUNIT_TEST( testBloc3 ); + CPPUNIT_TEST( testBloc4 ); CPPUNIT_TEST( testForLoop1 ); CPPUNIT_TEST( testForLoop2 ); CPPUNIT_TEST( testForLoop3 ); @@ -30,6 +32,8 @@ namespace YACS CPPUNIT_TEST( testLinkUpdate1DS ); CPPUNIT_TEST( testLinkUpdate2 ); CPPUNIT_TEST( testLinkUpdate2DS ); + CPPUNIT_TEST( testLinkUpdate3 ); + CPPUNIT_TEST( testLinkUpdate4 ); CPPUNIT_TEST( testInterLoopDFLink ); CPPUNIT_TEST( deathTestForLinks ); CPPUNIT_TEST( testForEachLoop1 ); @@ -43,6 +47,8 @@ namespace YACS CPPUNIT_TEST( testForDeployment2 ); CPPUNIT_TEST( testForCheckConsistency1 ); CPPUNIT_TEST( testForCheckConsistency2 ); + CPPUNIT_TEST( testForCheckConsistency3 ); + CPPUNIT_TEST( testForCheckConsistency4 ); CPPUNIT_TEST_SUITE_END(); public: void setUp(); @@ -50,6 +56,7 @@ namespace YACS void testBloc1(); void testBloc2(); void testBloc3(); + void testBloc4(); void testSwitch(); void testSwitch2(); void testSwitch3(); @@ -65,6 +72,8 @@ namespace YACS void testLinkUpdate1DS(); void testLinkUpdate2(); void testLinkUpdate2DS(); + void testLinkUpdate3(); + void testLinkUpdate4(); void testInterLoopDFLink(); void deathTestForLinks(); void testForEachLoop1(); @@ -78,13 +87,27 @@ namespace YACS void testForDeployment2(); void testForCheckConsistency1(); void testForCheckConsistency2(); + void testForCheckConsistency3(); + void testForCheckConsistency4(); protected: + template + static void checkListsEqual(const std::list& setToTest1, const std::list& setToTest2); template static void checkSetsEqual(const std::set& setToTest1, const std::set& setToTest2); template static void checkSetsNotEqual(const std::set& setToTest1, const std::set&setToTest2); }; + template + void EngineIntegrationTest::checkListsEqual(const std::list& setToTest1, const std::list& setToTest2) + { + typename std::list::iterator iter1=setToTest1.begin(); + typename std::list::iterator iter2=setToTest2.begin(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Lists can't be equal : size different", (int)setToTest1.size(), (int)setToTest2.size()); + for(;iter1!=setToTest1.end();iter1++,iter2++) + CPPUNIT_ASSERT_MESSAGE("Lists can't be equal : value different", *iter1==*iter2); + } + template void EngineIntegrationTest::checkSetsEqual(const std::set& setToTest1, const std::set& setToTest2) { diff --git a/src/engine/Test/engineTest.cxx b/src/engine/Test/engineTest.cxx index b7828bbc1..0b4ca9e4b 100644 --- a/src/engine/Test/engineTest.cxx +++ b/src/engine/Test/engineTest.cxx @@ -2,6 +2,8 @@ // --- include from engine first, to avoid redifinition warning _POSIX_C_SOURCE #include "Bloc.hxx" +#include "Proc.hxx" +#include "Logger.hxx" #include "ElementaryNode.hxx" #include "Loop.hxx" #include "Switch.hxx" @@ -85,7 +87,8 @@ void EngineTest::checkAny1() CPPUNIT_ASSERT( tmp->getStringValue() == "lkjlkj"); CPPUNIT_ASSERT( tmp->getStringValue() == "lkjlkj"); tmp->decrRef(); - tmp=AtomAny::New("coucou",0); + const char tmp2[]="coucou"; + tmp=AtomAny::New((char *)tmp2,0); CPPUNIT_ASSERT( tmp->getStringValue() == "coucou"); CPPUNIT_ASSERT( tmp->getStringValue() == "coucou"); tmp->decrRef(); @@ -375,7 +378,8 @@ void EngineTest::checkAny4() tmp->setEltAtRank(3,tmp2); CPPUNIT_ASSERT_EQUAL(107,(*tmp)[3]->getIntValue()); tmp=SequenceAny::New(Runtime::_tc_string,2); - tmp2=AtomAny::New("titi",0); + const char tmpSt[]="titi"; + tmp2=AtomAny::New((char*)tmpSt,0); tmp->setEltAtRank(1,tmp2); CPPUNIT_ASSERT((*tmp)[1]->getStringValue()=="titi"); vector vec4; @@ -424,6 +428,7 @@ void EngineTest::checkAny5() CPPUNIT_ASSERT((*tmp3)[2]->getStringValue()=="tutu"); AnyPtr tmp4=tmp3->clone(); CPPUNIT_ASSERT( (*tmp3==*tmp4) ); + CPPUNIT_ASSERT( (*tmp3==*tmp3) ); tmp3->popBack(); CPPUNIT_ASSERT( !(*tmp3==*tmp4) ); tmp1=AtomAny::New("tutu"); @@ -440,6 +445,203 @@ void EngineTest::checkAny5() CPPUNIT_ASSERT( !(*tmp3==*tmp4) ); } +/*! + * Test of ArrayAny. Only one level. + */ +void EngineTest::checkAny6() +{ + const int lgth=8; + const int tab[lgth]={0,1,1,9,2,7,2,3}; + const int tab2[lgth]={13,1,1,9,2,7,2,3}; + ArrayAnyPtr tmp1(ArrayAny::New(tab,lgth)); + ArrayAnyPtr tmp2(ArrayAny::New(tab,lgth)); + CPPUNIT_ASSERT((*tmp1)[3]->getIntValue()==9); + CPPUNIT_ASSERT( (*tmp1==*tmp2) ); + CPPUNIT_ASSERT( (*tmp1==*tmp1) ); + CPPUNIT_ASSERT( 8==tmp1->size() ); + CPPUNIT_ASSERT( 8==tmp2->size() ); + tmp2=ArrayAny::New(tab,lgth-1); + CPPUNIT_ASSERT( 7==tmp2->size() ); + CPPUNIT_ASSERT( !(*tmp1==*tmp2) ); + tmp2=ArrayAny::New(tab2,lgth); + CPPUNIT_ASSERT( !(*tmp1==*tmp2) ); + tmp2=ArrayAny::New(tab,lgth); + CPPUNIT_ASSERT( (*tmp1==*tmp2) ); + ArrayAnyPtr tmp3=(ArrayAny *)tmp1->clone(); + CPPUNIT_ASSERT( (*tmp1==*tmp3) ); + CPPUNIT_ASSERT((*tmp3)[3]->getIntValue()==9); CPPUNIT_ASSERT((*tmp3)[4]->getIntValue()==2); + // Ok let's test with double. + const double tab3[lgth]={0.1,1.1,1.1,9.1,2.1,7.1,2.1,3.1}; + const double tab4[lgth]={13.1,1.1,1.1,9.1,2.1,7.1,2.1,3.1}; + ArrayAnyPtr tmp4(ArrayAny::New(tab3,lgth)); + ArrayAnyPtr tmp5(ArrayAny::New(tab3,lgth)); + CPPUNIT_ASSERT_DOUBLES_EQUAL((*tmp4)[3]->getDoubleValue(),9.1,1e-12); + CPPUNIT_ASSERT( (*tmp4==*tmp5) ); + CPPUNIT_ASSERT( (*tmp4==*tmp4) ); + CPPUNIT_ASSERT( 8==tmp4->size() ); + CPPUNIT_ASSERT( 8==tmp5->size() ); + tmp5=ArrayAny::New(tab3,lgth-1); + CPPUNIT_ASSERT( 7==tmp5->size() ); + CPPUNIT_ASSERT( !(*tmp4==*tmp5) ); + tmp5=ArrayAny::New(tab4,lgth); + CPPUNIT_ASSERT( !(*tmp4==*tmp5) ); + tmp5=ArrayAny::New(tab3,lgth); + CPPUNIT_ASSERT( (*tmp4==*tmp5) ); + ArrayAnyPtr tmp6=(ArrayAny *)tmp4->clone(); + CPPUNIT_ASSERT( (*tmp4==*tmp6) ); + CPPUNIT_ASSERT_DOUBLES_EQUAL((*tmp6)[3]->getDoubleValue(),9.1,1e-12); + CPPUNIT_ASSERT_DOUBLES_EQUAL((*tmp6)[4]->getDoubleValue(),2.1,1e-12); + //Ok let's test with bool. + const bool tab5[lgth]={false,true,false,true,false,false,false,false}; + const bool tab6[lgth]={true ,true,false,true,false,false,false,false}; + ArrayAnyPtr tmp7(ArrayAny::New(tab5,lgth)); + ArrayAnyPtr tmp8(ArrayAny::New(tab5,lgth)); + CPPUNIT_ASSERT((*tmp7)[3]->getBoolValue()); + CPPUNIT_ASSERT( (*tmp7==*tmp8) ); + CPPUNIT_ASSERT( (*tmp7==*tmp7) ); + CPPUNIT_ASSERT( 8==tmp7->size() ); + CPPUNIT_ASSERT( 8==tmp8->size() ); + tmp8=ArrayAny::New(tab5,lgth-1); + CPPUNIT_ASSERT( 7==tmp8->size() ); + CPPUNIT_ASSERT( !(*tmp7==*tmp8) ); + tmp8=ArrayAny::New(tab6,lgth); + CPPUNIT_ASSERT( !(*tmp7==*tmp8) ); + tmp8=ArrayAny::New(tab5,lgth); + CPPUNIT_ASSERT( (*tmp7==*tmp8) ); + ArrayAnyPtr tmp9=(ArrayAny *)tmp7->clone(); + CPPUNIT_ASSERT( (*tmp9==*tmp7) ); + CPPUNIT_ASSERT((*tmp8)[3]->getBoolValue()); + CPPUNIT_ASSERT(!(*tmp8)[4]->getBoolValue()); + //Ok let's test with strings. + vector tab7(lgth); tab7[0]="abc"; tab7[1]="def"; tab7[2]="ghi"; tab7[3]="jkl"; tab7[4]="mno"; tab7[5]="pqr"; tab7[6]="stu"; tab7[7]="vwx"; + vector tab8(lgth); tab8[0]="zbc"; tab8[1]="def"; tab8[2]="ghi"; tab8[3]="jkl"; tab8[4]="mno"; tab8[5]="pqr"; tab8[6]="stu"; tab8[7]="vwx"; + ArrayAnyPtr tmp10(ArrayAny::New(tab7)); + ArrayAnyPtr tmp11(ArrayAny::New(tab7)); + CPPUNIT_ASSERT((*tmp10)[3]->getStringValue()=="jkl"); + CPPUNIT_ASSERT( (*tmp10==*tmp11) ); + CPPUNIT_ASSERT( (*tmp10==*tmp10) ); + CPPUNIT_ASSERT( 8==tmp10->size() ); + CPPUNIT_ASSERT( 8==tmp11->size() ); + vector tab9(tab7); tab9.pop_back(); + tmp11=ArrayAny::New(tab9); + CPPUNIT_ASSERT( 7==tmp11->size() ); + CPPUNIT_ASSERT( !(*tmp10==*tmp11) ); + tmp11=ArrayAny::New(tab8); + CPPUNIT_ASSERT( !(*tmp10==*tmp11) ); + tmp11=ArrayAny::New(tab7); + CPPUNIT_ASSERT( (*tmp10==*tmp11) ); + ArrayAnyPtr tmp12=(ArrayAny *)tmp10->clone(); + CPPUNIT_ASSERT( (*tmp12==*tmp10) ); + CPPUNIT_ASSERT((*tmp11)[3]->getStringValue()=="jkl"); + CPPUNIT_ASSERT((*tmp11)[4]->getStringValue()=="mno"); +} + +/*! + * Test of ArrayAny on multi-levels. To test recursion. + */ +void EngineTest::checkAny7() +{ + const int lgth=8; + const int tab1[lgth]={0,1,1,9,2,7,2,3}; + const int tab2[lgth]={7,8,8,16,9,14,9,10}; + //Testing Arrays of arrays + ArrayAnyPtr tmp11(ArrayAny::New(tab1,lgth)); + ArrayAnyPtr tmp12(ArrayAny::New(tab2,lgth)); + ArrayAnyPtr tmp12Throw(ArrayAny::New(tab2,lgth+1)); + ArrayAnyPtr tmp2(ArrayAny::New(tmp11->getType(),2)); + tmp2->setEltAtRank(0,tmp11); + CPPUNIT_ASSERT_THROW(tmp2->setEltAtRank(1,tmp12Throw),Exception); + tmp2->setEltAtRank(1,tmp12); + CPPUNIT_ASSERT_EQUAL(0,(*tmp2)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp2)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp2)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp2)[1][3]->getIntValue()); + // Show deep copy process of arrays + AnyPtr tmp=AtomAny::New(49); + tmp11->setEltAtRank(0,tmp); + CPPUNIT_ASSERT_EQUAL(0,(*tmp2)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp2)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp2)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp2)[1][3]->getIntValue()); + ArrayAnyPtr tmp2Cloned=(ArrayAny *)(tmp2->clone()); + CPPUNIT_ASSERT_EQUAL(0,(*tmp2Cloned)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp2Cloned)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp2Cloned)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp2Cloned)[1][3]->getIntValue()); + CPPUNIT_ASSERT( *tmp2==*tmp2Cloned ); + CPPUNIT_ASSERT( *tmp2==*tmp2 ); + //Testing Array of Sequences + SequenceAnyPtr tmp13(SequenceAny::New((int *)tab1,lgth,0)); + SequenceAnyPtr tmp14(SequenceAny::New((int *)tab2,lgth,0)); + tmp2=ArrayAny::New(tmp13->getType(),2); + tmp2->setEltAtRank(0,tmp13); + tmp2->setEltAtRank(1,tmp14); + CPPUNIT_ASSERT_EQUAL(0,(*tmp2)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp2)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp2)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp2)[1][3]->getIntValue()); + tmp13->setEltAtRank(0,tmp); + // No deep copy here contrary to 14 lines ahead. + CPPUNIT_ASSERT_EQUAL(49,(*tmp2)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp2)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp2)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp2)[1][3]->getIntValue()); + tmp2Cloned=(ArrayAny *)(tmp2->clone()); + CPPUNIT_ASSERT_EQUAL(49,(*tmp2Cloned)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp2Cloned)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp2Cloned)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp2Cloned)[1][3]->getIntValue()); + CPPUNIT_ASSERT( *tmp2==*tmp2Cloned ); + CPPUNIT_ASSERT( *tmp2==*tmp2 ); + //Testing Sequence of array + tmp13=SequenceAny::New(tmp11->getType(),2); + tmp13->setEltAtRank(0,tmp11); + tmp13->setEltAtRank(1,tmp12); + CPPUNIT_ASSERT_EQUAL(49,(*tmp13)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp13)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp13)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp13)[1][3]->getIntValue()); + tmp14=(SequenceAny *)tmp13->clone(); + CPPUNIT_ASSERT_EQUAL(49,(*tmp14)[0][0]->getIntValue()); CPPUNIT_ASSERT_EQUAL(7,(*tmp14)[1][0]->getIntValue()); + CPPUNIT_ASSERT_EQUAL(9,(*tmp14)[0][3]->getIntValue()); CPPUNIT_ASSERT_EQUAL(16,(*tmp14)[1][3]->getIntValue()); + CPPUNIT_ASSERT( *tmp13==*tmp14 ); + CPPUNIT_ASSERT( *tmp13==*tmp13 ); +} + +/*! + * First test of structs. + */ +void EngineTest::checkAny8() +{ + TypeCodeStruct *tc=new TypeCodeStruct("",""); + tc->addMember("MyInt",Runtime::_tc_int); + tc->addMember("MyDouble",Runtime::_tc_double); + tc->addMember("MyBool",Runtime::_tc_bool); + tc->addMember("MyStr",Runtime::_tc_string); + StructAnyPtr tmp1=StructAny::New(tc); + tmp1=StructAny::New(tc); + AnyPtr tmpAtom=AtomAny::New(3791); + tmp1->setEltAtRank("MyInt",tmpAtom); + CPPUNIT_ASSERT_THROW(tmp1->setEltAtRank(1,tmpAtom),Exception); + tmpAtom=AtomAny::New(3.14); + CPPUNIT_ASSERT_THROW(tmp1->setEltAtRank("MyDoubl",tmpAtom),Exception); + tmp1->setEltAtRank("MyDouble",tmpAtom); + tmpAtom=AtomAny::New(false); + tmp1->setEltAtRank("MyBool",tmpAtom); + tmpAtom=AtomAny::New("abcdef"); + tmp1->setEltAtRank("MyStr",tmpAtom); + CPPUNIT_ASSERT_EQUAL(3791,(*tmp1)["MyInt"]->getIntValue()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(3.14,(*tmp1)["MyDouble"]->getDoubleValue(),1e-12); + CPPUNIT_ASSERT_THROW((*tmp1)["MyIntT"],Exception); + CPPUNIT_ASSERT(!(*tmp1)["MyBool"]->getBoolValue()); + CPPUNIT_ASSERT_THROW((*tmp1)["MyBool"]->getStringValue(),Exception); + CPPUNIT_ASSERT((*tmp1)["MyStr"]->getStringValue()=="abcdef"); + tmpAtom=AtomAny::New("ghijklm"); + tmp1->setEltAtRank("MyStr",tmpAtom); + CPPUNIT_ASSERT((*tmp1)["MyStr"]->getStringValue()=="ghijklm"); + //Introduce some recursive structure. + SequenceAnyPtr tmp2=SequenceAny::New(tc,2); + tmp2->setEltAtRank(0,tmp1); + tmpAtom=AtomAny::New("opqrst"); + tmp1->setEltAtRank("MyStr",tmpAtom); + tmp2->setEltAtRank(1,tmp1); + CPPUNIT_ASSERT_EQUAL(3791,(*tmp2)[1]["MyInt"]->getIntValue()); + CPPUNIT_ASSERT((*tmp2)[0]["MyStr"]->getStringValue()=="ghijklm"); + CPPUNIT_ASSERT((*tmp2)[1]["MyStr"]->getStringValue()=="opqrst"); + CPPUNIT_ASSERT(*tmp2==*tmp2); + AnyPtr tmp3=tmp2->clone(); + CPPUNIT_ASSERT(*tmp2==*tmp3); + CPPUNIT_ASSERT((*tmp3)[0]["MyStr"]->getStringValue()=="ghijklm"); + CPPUNIT_ASSERT((*tmp3)[1]["MyStr"]->getStringValue()=="opqrst"); + tc->decrRef(); +} + void EngineTest::checkInGateOutGate() { string nodeName = "Node1"; @@ -569,7 +771,7 @@ void EngineTest::checkAddNodesToBloc() bloc1->edAddChild(_nodeMap["Node_1"]); bloc1->edAddChild(_nodeMap["Node_2"]); { - set setelem = bloc1->getRecursiveConstituents(); + list setelem = bloc1->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 2); } } @@ -609,9 +811,9 @@ void EngineTest::checkRecursiveBlocs_NumberOfNodes() bloc3->edAddChild((bloc2)); // 1 elementary node bloc3->edAddChild(_nodeMap["Node_4"]); // 1 elementary node { - set setelem = bloc3->getRecursiveConstituents(); + list setelem = bloc3->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 4); - for (set::iterator it=setelem.begin(); it!=setelem.end(); it++) + for (list::iterator it=setelem.begin(); it!=setelem.end(); it++) { DEBTRACE(" elem name = " << (*it)->getName()); } @@ -669,10 +871,10 @@ void EngineTest::checkRemoveNode() bloc->edAddChild(_nodeMap["Node_7"]); { - set setelem = _nodeMap["blocR"]->getRecursiveConstituents(); + list setelem = _nodeMap["blocR"]->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 3); - for (set::iterator it=setelem.begin(); it!=setelem.end(); it++) + for (list::iterator it=setelem.begin(); it!=setelem.end(); it++) { DEBTRACE(" elem name = " << (*it)->getName()); } @@ -681,9 +883,9 @@ void EngineTest::checkRemoveNode() ((Bloc *)_nodeMap["blocR"])->edRemoveChild(_nodeMap["Node_6"]); { - set setelem = _nodeMap["blocR"]->getRecursiveConstituents(); + list setelem = _nodeMap["blocR"]->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 2); - for (set::iterator it=setelem.begin(); it!=setelem.end(); it++) + for (list::iterator it=setelem.begin(); it!=setelem.end(); it++) { DEBTRACE(" elem name = " << (*it)->getName()); DEBTRACE(" elem name in Bloc = " << ((Bloc *)_nodeMap["blocR"])->getChildName(*it)); @@ -708,7 +910,7 @@ void EngineTest::checkRemoveNode() ((Bloc *)_nodeMap["blocR"])->edRemoveChild(_nodeMap["Node_5"]); ((Bloc *)_nodeMap["blocR"])->edRemoveChild(_nodeMap["Node_7"]); { - set setelem = _nodeMap["blocR"]->getRecursiveConstituents(); + list setelem = _nodeMap["blocR"]->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 0); } } @@ -756,9 +958,9 @@ void EngineTest::RecursiveBlocs_multipleRecursion() } { - set setelem = _nodeMap["graphe"]->getRecursiveConstituents(); + list setelem = _nodeMap["graphe"]->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 9); - for (set::iterator it=setelem.begin(); it!=setelem.end(); it++) + for (list::iterator it=setelem.begin(); it!=setelem.end(); it++) { DEBTRACE(" elem name = " << (*it)->getName()); } @@ -795,7 +997,7 @@ void EngineTest::RecursiveBlocs_removeNodes() // } { - set setNode = ((Bloc*)_nodeMap["graphe"])->getAllRecursiveConstituents(); + list setNode = ((Bloc*)_nodeMap["graphe"])->getAllRecursiveConstituents(); CPPUNIT_ASSERT(setNode.size() == 16); list inset = _nodeMap["bloc7"]->getSetOfInputPort(); list outset = _nodeMap["bloc7"]->getSetOfOutputPort(); @@ -808,9 +1010,9 @@ void EngineTest::RecursiveBlocs_removeNodes() ((Bloc *)_nodeMap["bloc7"])->edRemoveChild(_nodeMap["bloc6"]); { - set setNode = ((Bloc*)_nodeMap["graphe"])->getAllRecursiveConstituents(); + list setNode = ((Bloc*)_nodeMap["graphe"])->getAllRecursiveConstituents(); CPPUNIT_ASSERT(setNode.size() == 9); - for (set::iterator it=setNode.begin(); it!=setNode.end(); it++) + for (list::iterator it=setNode.begin(); it!=setNode.end(); it++) { DEBTRACE(" elem name = " << ((Bloc *)_nodeMap["graphe"])->getChildName(*it)); } @@ -823,3 +1025,31 @@ void EngineTest::RecursiveBlocs_removeNodes() } } + +void EngineTest::checkLogger() +{ + Proc* proc=new Proc("proc"); + Logger* logger=proc->getLogger("parser"); + logger->error("error1","file.cxx",324); + logger->error("error2","file.cxx",852); + CPPUNIT_ASSERT(logger->hasErrors()==true); + CPPUNIT_ASSERT(logger->isEmpty()==false); + const char* expected1="LogRecord: parser:ERROR:error1 (file.cxx:324)\n" + "LogRecord: parser:ERROR:error2 (file.cxx:852)\n"; + CPPUNIT_ASSERT(logger->getStr()==expected1); + + logger->reset(); + CPPUNIT_ASSERT(logger->hasErrors()==false); + CPPUNIT_ASSERT(logger->isEmpty()==true); + + logger->error("error1","file.cxx",324); + logger->error("error2","file.cxx",852); + logger->error("error3","file.cxx",978); + CPPUNIT_ASSERT(logger->hasErrors()==true); + CPPUNIT_ASSERT(logger->isEmpty()==false); + const char* expected2="LogRecord: parser:ERROR:error1 (file.cxx:324)\n" + "LogRecord: parser:ERROR:error2 (file.cxx:852)\n" + "LogRecord: parser:ERROR:error3 (file.cxx:978)\n"; + CPPUNIT_ASSERT(logger->getStr()==expected2); + delete proc; +} diff --git a/src/engine/Test/engineTest.hxx b/src/engine/Test/engineTest.hxx index b815dbef0..d9c90de51 100644 --- a/src/engine/Test/engineTest.hxx +++ b/src/engine/Test/engineTest.hxx @@ -21,6 +21,9 @@ namespace YACS CPPUNIT_TEST(checkAny3); CPPUNIT_TEST(checkAny4); CPPUNIT_TEST(checkAny5); + CPPUNIT_TEST(checkAny6); + CPPUNIT_TEST(checkAny7); + CPPUNIT_TEST(checkAny8); CPPUNIT_TEST(checkInGateOutGate ); CPPUNIT_TEST(checkNodePortNumber ); CPPUNIT_TEST(checkPortTypeName ); @@ -37,6 +40,7 @@ namespace YACS CPPUNIT_TEST(RecursiveBlocs_multipleRecursion ); CPPUNIT_TEST(RecursiveBlocs_removeNodes ); CPPUNIT_TEST(cleanUp); + CPPUNIT_TEST(checkLogger); CPPUNIT_TEST_SUITE_END(); public: @@ -52,6 +56,9 @@ namespace YACS void checkAny3(); void checkAny4(); void checkAny5(); + void checkAny6(); + void checkAny7(); + void checkAny8(); void checkInGateOutGate(); void checkNodePortNumber(); void checkPortTypeName(); @@ -67,6 +74,7 @@ namespace YACS void checkRemoveNode(); void RecursiveBlocs_multipleRecursion(); void RecursiveBlocs_removeNodes(); + void checkLogger(); protected: static std::map _nodeMap; diff --git a/src/engine/TypeCode.cxx b/src/engine/TypeCode.cxx index 9aeb6ba72..09331cfd2 100644 --- a/src/engine/TypeCode.cxx +++ b/src/engine/TypeCode.cxx @@ -120,6 +120,18 @@ int TypeCode::isAdaptable(const TypeCode* tc) const } } +//! Check if this TypeCode can be used in place of tc +/*! + * this TypeCode is equivalent to tc if they have the same kind + * + * \param tc : the TypeCode to compare + */ +int TypeCode::isEquivalent(const TypeCode* tc) const +{ + if(_kind == tc->kind()) return 1; + return 0; +} + unsigned TypeCode::getSizeInByteOfAnyReprInSeq() const { switch(_kind) @@ -213,18 +225,28 @@ TypeCode * TypeCode::structTc(const char* id, return new TypeCodeStruct(id, name); }; +TypeCodeComposed::TypeCodeComposed(const TypeCodeComposed& other):TypeCode(other), + _name(other._name),_repoId(other._repoId), + _shortName(other._shortName) +{ +} + +TypeCodeComposed::TypeCodeComposed(DynType kind, const char* repositoryId, const char* name):TypeCode(kind), + _repoId(repositoryId),_name(name) +{ + string::size_type debut =_name.find_last_of('/'); + if(debut == std::string::npos) + _shortName= name; + else + _shortName=_name.substr(debut+1); +} // --- TypeCodeObjref TypeCodeObjref::TypeCodeObjref(const char* repositoryId, - const char* name) : TypeCode(Objref) + const char* name) : TypeCodeComposed(Objref,repositoryId,name) { - _repoId = repositoryId; - _name = name; - string::size_type debut =_name.find_last_of('/'); - if(debut == std::string::npos)_shortName= name; - else _shortName=_name.substr(debut+1); } @@ -271,14 +293,9 @@ const char * TypeCodeObjref::shortName() const } TypeCodeObjref::TypeCodeObjref(const char* repositoryId, - const char* name, - const std::list& ltc) : TypeCode(Objref) + const char* name, + const std::list& ltc) : TypeCodeComposed(Objref,repositoryId,name) { - _repoId = repositoryId; - _name = name; - string::size_type debut =_name.find_last_of('/'); - if(debut == std::string::npos)_shortName= name; - else _shortName=_name.substr(debut+1); _listOfBases=ltc; list::const_iterator iter; for(iter=_listOfBases.begin();iter != _listOfBases.end(); iter++) @@ -322,9 +339,21 @@ int TypeCodeObjref::isAdaptable(const TypeCode* tc) const return 0; } -TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCode(other),_name(other._name), - _repoId(other._shortName), - _listOfBases(other._listOfBases) +//! Check if this TypeCode can be used in place of tc +/*! + * this TypeCode is equivalent to tc if they have the same kind + * + * \param tc : the TypeCode to compare + */ +int TypeCodeObjref::isEquivalent(const TypeCode* tc) const +{ + if(_kind != tc->kind())return 0; + if(_repoId == tc->id())return 1; + return 0; +} + +TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCodeComposed(other), + _listOfBases(other._listOfBases) { list::const_iterator iter; for(iter=other._listOfBases.begin();iter!=other._listOfBases.end();iter++) @@ -341,14 +370,9 @@ TypeCodeObjref::TypeCodeObjref(const TypeCodeObjref& other):TypeCode(other),_nam * \param content : the given contained TypeCode */ TypeCodeSeq::TypeCodeSeq(const char* repositoryId, - const char* name, - const TypeCode *content) : TypeCode(Sequence), _content(content) + const char* name, + const TypeCode *content) : TypeCodeComposed(Sequence,repositoryId,name), _content(content) { - _repoId = repositoryId; - _name = name; - string::size_type debut =_name.find_last_of('/'); - if(debut == std::string::npos)_shortName= name; - else _shortName=_name.substr(debut+1); _content->incrRef(); } @@ -372,6 +396,11 @@ void TypeCodeSeq::destroyZippedAny(char *data) const SequenceAny::destroyReprAtPlace(data,this); } +unsigned TypeCodeSeq::getSizeInByteOfAnyReprInSeq() const +{ + return sizeof(void*); +} + AnyPtr TypeCodeSeq::getOrBuildAnyFromZippedData(char *data) const { return SequenceAny::getOrBuildFromData(data,this); @@ -415,10 +444,21 @@ int TypeCodeSeq::isAdaptable(const TypeCode* tc) const return 0; } -TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCode(tc), - _name(tc._name),_shortName(tc._shortName), - _repoId(tc._repoId), - _content(tc._content) +//! Check if this TypeCode can be used in place of tc +/*! + * this TypeCode is equivalent to tc if they have the same kind + * + * \param tc : the TypeCode to compare + */ +int TypeCodeSeq::isEquivalent(const TypeCode* tc) const +{ + if(_kind == tc->kind()) + return _content->isEquivalent(tc->contentType()); + return 0; +} + +TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCodeComposed(tc), + _content(tc._content) { _content->incrRef(); } @@ -435,13 +475,8 @@ TypeCodeSeq::TypeCodeSeq(const TypeCodeSeq& tc):TypeCode(tc), TypeCodeArray::TypeCodeArray(const char* repositoryId, const char* name, const TypeCode *content, - unsigned staticLgth) : TypeCode(Array), _content(content),_staticLgth(staticLgth) + unsigned staticLgth) : TypeCodeComposed(Array,repositoryId,name), _content(content),_staticLgth(staticLgth) { - _repoId = repositoryId; - _name = name; - string::size_type debut =_name.find_last_of('/'); - if(debut == std::string::npos)_shortName= name; - else _shortName=_name.substr(debut+1); _content->incrRef(); } @@ -519,9 +554,20 @@ int TypeCodeArray::isAdaptable(const TypeCode* tc) const return 0; } -TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCode(tc), - _name(tc._name),_shortName(tc._shortName), - _repoId(tc._repoId), +//! Check if this TypeCode can be used in place of tc +/*! + * this TypeCode is equivalent to tc if they have the same kind + * + * \param tc : the TypeCode to compare + */ +int TypeCodeArray::isEquivalent(const TypeCode* tc) const +{ + if(_kind == tc->kind()) + return _content->isEquivalent(tc->contentType()); + return 0; +} + +TypeCodeArray::TypeCodeArray(const TypeCodeArray& tc):TypeCodeComposed(tc), _content(tc._content), _staticLgth(tc._staticLgth) { @@ -542,11 +588,8 @@ unsigned TypeCodeArray::getSizeInByteOfAnyReprInSeq() const * \param name : the given name */ TypeCodeStruct::TypeCodeStruct(const char* repositoryId, - const char* name) : TypeCode(Struct), _name(name),_repoId(repositoryId) + const char* name) : TypeCodeComposed(Struct,repositoryId,name) { - string::size_type debut =_name.find_last_of('/'); - if(debut == std::string::npos)_shortName= name; - else _shortName=_name.substr(debut+1); } TypeCodeStruct::~TypeCodeStruct() @@ -558,25 +601,25 @@ TypeCode *TypeCodeStruct::clone() const return new TypeCodeStruct(*this); } -TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCode(tc), - _name(tc._name),_shortName(tc._shortName), - _repoId(tc._repoId) +TypeCodeStruct::TypeCodeStruct(const TypeCodeStruct& tc):TypeCodeComposed(tc),_members(tc._members) { + for(vector< std::pair >::iterator iter=_members.begin();iter!=_members.end();iter++) + (*iter).second->incrRef(); } void TypeCodeStruct::putReprAtPlace(char *pt, const char *val, bool deepCpy) const { - throw Exception("Not implemented yet : YACS::Any for struct"); + StructAny::putReprAtPlace(pt,val,this,deepCpy); } void TypeCodeStruct::destroyZippedAny(char *data) const { - throw Exception("Not implemented yet : YACS::Any for struct"); + StructAny::destroyReprAtPlace(data,this); } AnyPtr TypeCodeStruct::getOrBuildAnyFromZippedData(char *data) const { - throw Exception("Not implemented yet : YACS::Any for struct"); + return StructAny::getOrBuildFromData(data,this); } const char * TypeCodeStruct::id() const throw(Exception) @@ -594,6 +637,20 @@ const char * TypeCodeStruct::shortName() const return _shortName.c_str(); } +unsigned TypeCodeStruct::getSizeInByteOfAnyReprInSeq() const +{ + unsigned ret=0; + for(vector< pair >::const_iterator iter=_members.begin();iter!=_members.end();iter++) + ret+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + return ret; +} + +const TypeCode *TypeCodeStruct::contentType() const throw(Exception) +{ + const char what[]="Content type is specified by giving a key."; + throw Exception(what); +} + //! Check if this TypeCode is derived from a TypeCode with a given id /*! * \param id : a given id @@ -601,7 +658,7 @@ const char * TypeCodeStruct::shortName() const */ int TypeCodeStruct::isA(const char* id) const throw(Exception) { - if(_repoId.c_str() == id)return 1; + if(_repoId == id)return 1; return 0; } @@ -612,7 +669,17 @@ int TypeCodeStruct::isA(const char* id) const throw(Exception) */ int TypeCodeStruct::isA(const TypeCode* tc) const { - return isA(tc->id()); + if(_kind != tc->kind()) return 0; + if(_repoId == tc->id())return 1; + int nMember=memberCount(); + if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0; + for(int i=0;imemberName(i)) != 0)return 0; + if(!memberType(i)->isA(((TypeCodeStruct*)tc)->memberType(i)))return 0; + } + return 1; } //! Check if this TypeCode is adaptable to a given TypeCode (tc) @@ -626,6 +693,26 @@ int TypeCodeStruct::isAdaptable(const TypeCode* tc) const return 0; } +//! Check if this TypeCode can be used in place of tc +/*! + * this TypeCode is equivalent to tc if they have the same kind + * + * \param tc : the TypeCode to compare + */ +int TypeCodeStruct::isEquivalent(const TypeCode* tc) const +{ + if(_kind != tc->kind()) return 0; + int nMember=memberCount(); + if(nMember != ((TypeCodeStruct*)tc)->memberCount())return 0; + for(int i=0;imemberName(i)) != 0)return 0; + if(!memberType(i)->isEquivalent(((TypeCodeStruct*)tc)->memberType(i)))return 0; + } + return 1; +} + void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc) { DEBTRACE(name << " " << tc->name()); @@ -638,6 +725,23 @@ void TypeCodeStruct::addMember(const std::string& name,TypeCode* tc) _members.push_back(std::pair(name,tc)); } +/*! + * If name is not an existing key, 0 is returned. + * \param offset : Out parameter, that specified the location of start of data discriminated by name key. + */ +const TypeCode *TypeCodeStruct::getMember(const std::string& name, unsigned& offset) const +{ + std::vector< std::pair >::const_iterator iter; + offset=0; + for(iter=_members.begin();iter != _members.end(); iter++) + { + if((*iter).first==name) + return (*iter).second; + offset+=(*iter).second->getSizeInByteOfAnyReprInSeq(); + } + return 0; +} + int TypeCodeStruct::memberCount() const { return _members.size(); diff --git a/src/engine/TypeCode.hxx b/src/engine/TypeCode.hxx index 222f865c6..1cdd434e7 100644 --- a/src/engine/TypeCode.hxx +++ b/src/engine/TypeCode.hxx @@ -16,7 +16,7 @@ namespace YACS typedef enum { - None = 0, + NONE = 0, Double = 1, Int = 2, String = 3, @@ -63,6 +63,7 @@ namespace YACS virtual int isA(const char* repositoryId) const throw(Exception); virtual int isA(const TypeCode* tc) const ; virtual int isAdaptable(const TypeCode* tc) const; + virtual int isEquivalent(const TypeCode* tc) const; virtual unsigned getSizeInByteOfAnyReprInSeq() const; static const char *getKindRepr(DynType kind); @@ -77,17 +78,28 @@ namespace YACS TypeCode& operator=(const TypeCode& tc); virtual ~TypeCode(); protected: - DynType _kind; + const DynType _kind; static const char *KIND_STR_REPR []; }; + class TypeCodeComposed : public TypeCode + { + protected: + TypeCodeComposed(const TypeCodeComposed& other); + TypeCodeComposed(DynType kind, const char* repositoryId, const char* name); + protected: + const std::string _name; + const std::string _repoId; + std::string _shortName; + }; + /*! \brief Class for reference objects. * * \ingroup TypeCodes * */ - class TypeCodeObjref: public TypeCode + class TypeCodeObjref : public TypeCodeComposed { friend class Visitor; public: @@ -105,13 +117,11 @@ namespace YACS int isA(const char* repositoryId) const throw(Exception); virtual int isA(const TypeCode* tc) const ; virtual int isAdaptable(const TypeCode* tc) const; + virtual int isEquivalent(const TypeCode* tc) const; protected: ~TypeCodeObjref(); TypeCodeObjref(const TypeCodeObjref& other); private: - std::string _name; - std::string _shortName; - std::string _repoId; std::list _listOfBases; }; @@ -121,7 +131,7 @@ namespace YACS * \ingroup TypeCodes * */ - class TypeCodeSeq: public TypeCode + class TypeCodeSeq: public TypeCodeComposed { public: TypeCodeSeq(const char* repositoryId, const char* name, const TypeCode *content); @@ -129,6 +139,7 @@ namespace YACS TypeCode *clone() const; void putReprAtPlace(char *pt, const char *val, bool deepCpy) const; void destroyZippedAny(char *data) const; + virtual unsigned getSizeInByteOfAnyReprInSeq() const; AnyPtr getOrBuildAnyFromZippedData(char *data) const; const char * id() const throw(Exception); const char * name() const throw(Exception); @@ -137,13 +148,11 @@ namespace YACS virtual const TypeCode * contentType() const throw(Exception); virtual int isA(const TypeCode* tc) const ; virtual int isAdaptable(const TypeCode* tc) const; + virtual int isEquivalent(const TypeCode* tc) const; protected: ~TypeCodeSeq(); TypeCodeSeq(const TypeCodeSeq& tc); private: - std::string _name; - std::string _shortName; - std::string _repoId; const TypeCode *_content; }; @@ -152,7 +161,7 @@ namespace YACS * \ingroup TypeCodes * */ - class TypeCodeArray : public TypeCode + class TypeCodeArray : public TypeCodeComposed { public: TypeCodeArray(const char* repositoryId, const char* name, const TypeCode *content, unsigned staticLgth); @@ -168,25 +177,26 @@ namespace YACS virtual const TypeCode * contentType() const throw(Exception); virtual int isA(const TypeCode* tc) const ; virtual int isAdaptable(const TypeCode* tc) const; + virtual int isEquivalent(const TypeCode* tc) const; unsigned getSizeInByteOfAnyReprInSeq() const; protected: ~TypeCodeArray(); TypeCodeArray(const TypeCodeArray& tc); private: - std::string _name; - std::string _shortName; - std::string _repoId; - unsigned _staticLgth; const TypeCode *_content; + const unsigned _staticLgth; }; + class StructAny; + /*! \brief Class for struct type. * * \ingroup TypeCodes * */ - class TypeCodeStruct : public TypeCode + class TypeCodeStruct : public TypeCodeComposed { + friend class StructAny;//Access to _members attribute. public: TypeCodeStruct(const char* repositoryId, const char* name); TypeCode *clone() const; @@ -196,10 +206,15 @@ namespace YACS const char * id() const throw(Exception); const char * name() const throw(Exception); const char * shortName() const; + virtual unsigned getSizeInByteOfAnyReprInSeq() const; + const TypeCode * contentType() const throw(Exception); virtual int isA(const char* repositoryId) const throw(Exception); virtual int isA(const TypeCode* tc) const ; virtual int isAdaptable(const TypeCode* tc) const; + virtual int isEquivalent(const TypeCode* tc) const; + //! The only non const method. virtual void addMember(const std::string& name,TypeCode* tc); + const TypeCode *getMember(const std::string& name, unsigned& offset) const; int memberCount() const; const char* memberName(int index) const; TypeCode* memberType(int index) const; @@ -207,9 +222,6 @@ namespace YACS ~TypeCodeStruct(); TypeCodeStruct(const TypeCodeStruct& tc); private: - std::string _name; - std::string _shortName; - std::string _repoId; std::vector< std::pair > _members; }; diff --git a/src/engine/Visitor.cxx b/src/engine/Visitor.cxx index ca7b01954..ff23faf60 100644 --- a/src/engine/Visitor.cxx +++ b/src/engine/Visitor.cxx @@ -2,6 +2,7 @@ #include "Visitor.hxx" #include "Node.hxx" #include "Proc.hxx" +#include "TypeCode.hxx" using namespace YACS::ENGINE; using namespace std; diff --git a/src/engine/Visitor.hxx b/src/engine/Visitor.hxx index 22c566765..2a16faac5 100644 --- a/src/engine/Visitor.hxx +++ b/src/engine/Visitor.hxx @@ -21,6 +21,7 @@ namespace YACS class Proc; class ServiceNode; class ServiceInlineNode; + class DataNode; class Switch; class WhileLoop; class TypeCode; @@ -43,6 +44,10 @@ namespace YACS virtual void visitServiceInlineNode(ServiceInlineNode *node) = 0; virtual void visitSwitch(Switch *node) = 0; virtual void visitWhileLoop(WhileLoop *node) = 0; + virtual void visitPresetNode(DataNode *node) = 0; + virtual void visitOutNode(DataNode *node) = 0; + virtual void visitStudyInNode(DataNode *node) = 0; + virtual void visitStudyOutNode(DataNode *node) = 0; protected: std::map getNodeProperties(Node *node); diff --git a/src/engine/VisitorSaveSchema.cxx b/src/engine/VisitorSaveSchema.cxx index fd905b3ff..42e8b1035 100644 --- a/src/engine/VisitorSaveSchema.cxx +++ b/src/engine/VisitorSaveSchema.cxx @@ -18,6 +18,7 @@ #include "InputDataStreamPort.hxx" #include "OutputDataStreamPort.hxx" #include "Container.hxx" +#include "DataNode.hxx" #include #include @@ -72,6 +73,7 @@ void VisitorSaveSchema::visitBloc(Bloc *node) _out << " state=\"disabled\">" << endl; else _out << ">" << endl; + writeProperties(node); node->ComposedNode::accept(this); writeControls(node); writeSimpleDataLinks(node); @@ -85,6 +87,7 @@ void VisitorSaveSchema::visitElementaryNode(ElementaryNode *node) { DEBTRACE("START visitElementaryNode " << _root->getChildName(node)); beginCase(node); + writeProperties(node); writeInputPorts(node); writeInputDataStreamPorts(node); writeOutputPorts(node); @@ -109,6 +112,7 @@ void VisitorSaveSchema::visitForEachLoop(ForEachLoop *node) _out << " type=\"" << node->edGetSamplePort()->edGetType()->name() << "\""; _out << ">" << endl; + writeProperties(node); node->ComposedNode::accept(this); writeSimpleDataLinks(node); writeSimpleStreamLinks(node); @@ -130,6 +134,7 @@ void VisitorSaveSchema::visitForLoop(ForLoop *node) _out << ">" << endl; else _out << " nsteps=\"" << nsteps->getIntValue() << "\">" << endl; + writeProperties(node); node->ComposedNode::accept(this); writeSimpleDataLinks(node); writeSimpleStreamLinks(node); @@ -148,6 +153,7 @@ void VisitorSaveSchema::visitInlineNode(InlineNode *node) _out << " state=\"disabled\">" << endl; else _out << ">" << endl; + writeProperties(node); _out << indent(depth+1) << "" << endl; @@ -170,6 +176,7 @@ void VisitorSaveSchema::visitInlineFuncNode(InlineFuncNode *node) _out << " state=\"disabled\">" << endl; else _out << ">" << endl; + writeProperties(node); _out << indent(depth+1) << "getFname() << "\">" << endl; _out << indent(depth+2) << "getScript(); @@ -189,6 +196,7 @@ void VisitorSaveSchema::visitLoop(Loop *node) DEBTRACE("START visitLoop " << _root->getChildName(node)); beginCase(node); int depth = depthNode(node); + writeProperties(node); node->ComposedNode::accept(this); writeControls(node); writeSimpleDataLinks(node); @@ -223,6 +231,7 @@ void VisitorSaveSchema::visitServiceNode(ServiceNode *node) _out << " state=\"disabled\">" << endl; else _out << ">" << endl; + writeProperties(node); if (node->getKind() == "XML") { _out << indent(depth+1) << "xmlsh" << endl; @@ -231,7 +240,7 @@ void VisitorSaveSchema::visitServiceNode(ServiceNode *node) else { ComponentInstance *compo = node->getComponent(); - if (_componentInstanceMap.find(compo) == _componentInstanceMap.end()) + if (compo && (_componentInstanceMap.find(compo) == _componentInstanceMap.end())) { _out << indent(depth+1) << compo->getFileRepr() << endl; _componentInstanceMap[compo] = _root->getChildName(node); @@ -273,7 +282,12 @@ void VisitorSaveSchema::visitServiceInlineNode(ServiceInlineNode *node) _out << " state=\"disabled\">" << endl; else _out << ">" << endl; - _out << indent(depth+1) << node->getComponent()->getFileRepr() << endl; + + writeProperties(node); + ComponentInstance *compo = node->getComponent(); + if (compo) + _out << indent(depth+1) << compo->getFileRepr() << endl; + _out << indent(depth+1) << "getMethod() << "\">" << endl; _out << indent(depth+2) << "getScript(); @@ -286,6 +300,30 @@ void VisitorSaveSchema::visitServiceInlineNode(ServiceInlineNode *node) DEBTRACE("END visitServiceInlineNode " << _root->getChildName(node)); } +void VisitorSaveSchema::visitPresetNode(DataNode *node) +{ + DEBTRACE("START visitPresetNode " << _root->getChildName(node)); + DEBTRACE("END visitPresetNode " << _root->getChildName(node)); +} + +void VisitorSaveSchema::visitOutNode(DataNode *node) +{ + DEBTRACE("START visitOutNode " << _root->getChildName(node)); + DEBTRACE("END visitOutNode " << _root->getChildName(node)); +} + +void VisitorSaveSchema::visitStudyInNode(DataNode *node) +{ + DEBTRACE("START visitStudyInNode " << _root->getChildName(node)); + DEBTRACE("END visitStudyInNode " << _root->getChildName(node)); +} + +void VisitorSaveSchema::visitStudyOutNode(DataNode *node) +{ + DEBTRACE("START visitStudyOutNode " << _root->getChildName(node)); + DEBTRACE("END visitStudyOutNode " << _root->getChildName(node)); +} + void VisitorSaveSchema::visitSwitch(Switch *node) { @@ -300,6 +338,7 @@ void VisitorSaveSchema::visitSwitch(Switch *node) _out << ">" << endl; else _out << " select=\"" << condition->getIntValue() << "\">" << endl; + writeProperties(node); node->ComposedNode::accept(this); writeControls(node); writeSimpleDataLinks(node); @@ -319,6 +358,7 @@ void VisitorSaveSchema::visitWhileLoop(WhileLoop *node) _out << " state=\"disabled\">" << endl; else _out << ">" << endl; + writeProperties(node); node->ComposedNode::accept(this); writeSimpleDataLinks(node); writeSimpleStreamLinks(node); @@ -340,6 +380,124 @@ void VisitorSaveSchema::writeProperties(Node *node) } } +void VisitorSaveSchema::dumpTypeCode(TypeCode* type, set& typeNames,map& typeMap,int depth) +{ + DynType kind = type->kind(); + string typeName = type->name(); + if (typeNames.find(typeName) != typeNames.end()) + return; + switch(kind) + { + case YACS::ENGINE::Double: + { + typeNames.insert(typeName); + _out << indent(depth) << "" << endl; + break; + } + case YACS::ENGINE::Int: + { + typeNames.insert(typeName); + _out << indent(depth) << "" << endl; + break; + } + case YACS::ENGINE::String: + { + typeNames.insert(typeName); + _out << indent(depth) << "" << endl; + break; + } + case YACS::ENGINE::Bool: + { + typeNames.insert(typeName); + _out << indent(depth) << "" << endl; + break; + } + case YACS::ENGINE::Objref: + { + TypeCodeObjref *objref = dynamic_cast(type); + std::list listOfBases = getListOfBases(objref); + //try to dump base classes + for(std::list::iterator il=listOfBases.begin(); il != listOfBases.end(); ++il) + { + if (typeNames.find((*il)->name()) == typeNames.end()) + dumpTypeCode((*il),typeNames,typeMap,depth); + } + //effective dump + typeNames.insert(typeName); + _out << indent(depth) << "id() << "\""; + if (listOfBases.empty()) + _out << "/>" << endl; + else + { + _out << ">" << endl; + for(std::list::iterator il=listOfBases.begin(); il != listOfBases.end(); ++il) + { + _out << indent(depth+1) << ""; + _out << (*il)->name(); + _out << "" << endl; + } + _out << indent(depth) << "" << endl; + } + break; + } + case YACS::ENGINE::Sequence: + { + TypeCode* content = (TypeCode*)type->contentType(); + if (typeNames.find(content->name()) == typeNames.end()) + { + //content type not dumped + dumpTypeCode(content,typeNames,typeMap,depth); + } + typeNames.insert(typeName); + _out << indent(depth) << "name() << "\"/>" << endl; + break; + } + case YACS::ENGINE::Array: + { + TypeCode* content = (TypeCode*)type->contentType(); + if (typeNames.find(content->name()) == typeNames.end()) + { + //content type not dumped + dumpTypeCode(content,typeNames,typeMap,depth); + } + typeNames.insert(typeName); + _out << indent(depth) << "name() << "\"/>" << endl; + break; + } + case YACS::ENGINE::Struct: + { + TypeCodeStruct* tcStruct = dynamic_cast(type); + assert(tcStruct); + int mbCnt = tcStruct->memberCount(); + for (int i=0; imemberType(i); + if (typeNames.find(member->name()) == typeNames.end()) + { + //content type not dumped + dumpTypeCode(member,typeNames,typeMap,depth); + } + } + _out << indent(depth) << "" << endl; + for (int i=0; imemberType(i); + _out << indent(depth+1) << "memberName(i) << "\" type=\"" << member->name() << "\"/>" << endl; + } + _out << indent(depth) << "" << endl; + break; + } + default: + { + string what = "wrong TypeCode: "; + throw Exception(what); + } + } +} + void VisitorSaveSchema::writeTypeCodes(Proc *proc) { int depth = depthNode(proc)+1; @@ -360,82 +518,7 @@ void VisitorSaveSchema::writeTypeCodes(Proc *proc) for (it = typeMap.begin(); it != typeMap.end(); it++) { - DynType kind = (it->second)->kind(); - string typeId = (it->second)->id(); - switch(kind) - { - case YACS::ENGINE::Double: - { - if (typeNames.find(typeId) == typeNames.end()) - { - typeNames.insert(typeId); - _out << indent(depth) << "" << endl; - } - break; - } - case YACS::ENGINE::Int: - { - if (typeNames.find(typeId) == typeNames.end()) - { - typeNames.insert(typeId); - _out << indent(depth) << "" << endl; - } - break; - } - case YACS::ENGINE::String: - { - if (typeNames.find(typeId) == typeNames.end()) - { - typeNames.insert(typeId); - _out << indent(depth) << "" << endl; - } - break; - } - case YACS::ENGINE::Bool: - { - if (typeNames.find(typeId) == typeNames.end()) - { - typeNames.insert(typeId); - _out << indent(depth) << "" << endl; - } - break; - } - case YACS::ENGINE::Objref: - { - TypeCodeObjref *objref = dynamic_cast(it->second); - assert(objref); - std::list listOfBases = getListOfBases(objref); - _out << indent(depth) << "first << "\" id=\"" - << objref->id() << "\""; - if (listOfBases.empty()) - _out << "/>" << endl; - else - { - _out << ">" << endl; - for(std::list::iterator il=listOfBases.begin(); il != listOfBases.end(); ++il) - { - _out << indent(depth+1) << ""; - _out << (*il)->name(); - _out << "" << endl; - } - _out << indent(depth) << "" << endl; - } - break; - } - case YACS::ENGINE::Sequence: - { - const TypeCode* content = (it->second)->contentType(); - - _out << indent(depth) << "first << "\" content=\"" - << content->name() << "\"/>" << endl; - break; - } - default: - { - string what = "wrong TypeCode: "; - throw Exception(what); - } - } + dumpTypeCode(it->second,typeNames,typeMap,depth); } } @@ -448,6 +531,11 @@ void VisitorSaveSchema::writeContainers(Proc *proc) { string name = it->first; _out << indent(depth) << "" << endl; + map properties = (it->second)->getProperties(); + map::iterator itm; + for(itm = properties.begin(); itm != properties.end(); ++itm) + _out << indent(depth+1) << "" << endl; _out << indent(depth) << "" << endl; } } @@ -522,8 +610,8 @@ void VisitorSaveSchema::writeOutputDataStreamPorts(Node *node) void VisitorSaveSchema::writeControls(ComposedNode *node) { int depth = depthNode(node)+1; - set setOfChildren = node->edGetDirectDescendants(); - for (set::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic) + list setOfChildren = node->edGetDirectDescendants(); + for (list::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic) { // --- Control links from direct descendant to nodes inside the bloc set setOfInGates = (*ic)->getOutGate()->edSetInGate(); @@ -563,18 +651,22 @@ void VisitorSaveSchema::writeControls(ComposedNode *node) void VisitorSaveSchema::writeSimpleDataLinks(ComposedNode *node) { int depth = depthNode(node)+1; - set setOfChildren = node->edGetDirectDescendants(); + list setOfChildren = node->edGetDirectDescendants(); - set setOfChildrenPlusSplitters = setOfChildren; + list setOfChildrenPlusSplitters = setOfChildren; - for (set::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic) + for (list::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic) // add "splitter" node of ForEachLoop nodes to the set of children if ( dynamic_cast( *ic ) ) - setOfChildrenPlusSplitters.insert( (*ic)->getChildByName(ForEachLoop::NAME_OF_SPLITTERNODE) ); + { + Node *nodeToInsert=(*ic)->getChildByName(ForEachLoop::NAME_OF_SPLITTERNODE); + if(find(setOfChildrenPlusSplitters.begin(),setOfChildrenPlusSplitters.end(),nodeToInsert)==setOfChildrenPlusSplitters.end()) + setOfChildrenPlusSplitters.push_back(nodeToInsert); + } // --- first pass, write links where the input port is inside the node scope. Keep in memory others. - for (set::iterator ic = setOfChildrenPlusSplitters.begin(); ic != setOfChildrenPlusSplitters.end(); ++ic) + for (list::iterator ic = setOfChildrenPlusSplitters.begin(); ic != setOfChildrenPlusSplitters.end(); ++ic) { Node* from = *ic; list listOP = from->getLocalOutputPorts(); @@ -586,13 +678,13 @@ void VisitorSaveSchema::writeSimpleDataLinks(ComposedNode *node) { InPort *anIP = *iip; Node* to = anIP->getNode(); - cerr << "from " << from->getName() << " outputPort " << anOP->getName() - << " to " << to->getName() << " inputPort " << anIP->getName() << endl; + DEBTRACE("from " << from->getName() << " outputPort " << anOP->getName() + << " to " << to->getName() << " inputPort " << anIP->getName() ); Node* child = node->isInMyDescendance(to); if (child && (child->getNumId() != node->getNumId()) && (from->getNumId() != to->getNumId())) { - cerr << "BINGO!" << endl; + DEBTRACE( "BINGO!" ); string fromName; if ( dynamic_cast(from) && dynamic_cast(from->getFather()) ) @@ -614,7 +706,7 @@ void VisitorSaveSchema::writeSimpleDataLinks(ComposedNode *node) } else { // --- store info to create the link later, given the input port - cerr << "For later" << endl; + DEBTRACE( "For later" ); struct DataLinkInfo aLink = { from, to, anOP, anIP, false }; _mapOfDLtoCreate.insert(make_pair(anIP->getNumId(), aLink)); } @@ -668,11 +760,11 @@ void VisitorSaveSchema::writeSimpleDataLinks(ComposedNode *node) void VisitorSaveSchema::writeSimpleStreamLinks(ComposedNode *node) { int depth = depthNode(node)+1; - set setOfChildren = node->edGetDirectDescendants(); + list setOfChildren = node->edGetDirectDescendants(); // --- first pass, write links where the input port is inside the node scope. Keep in memory others. - for (set::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic) + for (list::iterator ic = setOfChildren.begin(); ic != setOfChildren.end(); ++ic) { Node* from = *ic; if ( dynamic_cast(from) ) continue; @@ -685,13 +777,13 @@ void VisitorSaveSchema::writeSimpleStreamLinks(ComposedNode *node) { InPort *anIP = *iip; Node* to = anIP->getNode(); - cerr << "from " << from->getName() << " outputPort " << anOP->getName() - << " to " << to->getName() << " inputPort " << anIP->getName() << endl; + DEBTRACE("from " << from->getName() << " outputPort " << anOP->getName() + << " to " << to->getName() << " inputPort " << anIP->getName() ); Node* child = node->isInMyDescendance(to); if (child && (child->getNumId() != node->getNumId()) && (from->getNumId() != to->getNumId())) { - cerr << "BINGO!" << endl; + DEBTRACE( "BINGO!" ); string childName = node->getChildName(to); _out << indent(depth) << "" << endl; _out << indent(depth+1) << "" << node->getChildName(from) << " "; @@ -708,7 +800,7 @@ void VisitorSaveSchema::writeSimpleStreamLinks(ComposedNode *node) } else { // --- store info to create the link later, given the input port - cerr << "For later" << endl; + DEBTRACE("For later" ); struct StreamLinkInfo aLink = { from, to, anOP, anIP, false }; _mapOfSLtoCreate.insert(make_pair(anIP->getNumId(), aLink)); } @@ -768,8 +860,8 @@ void VisitorSaveSchema::writeSimpleStreamLinks(ComposedNode *node) std::set VisitorSaveSchema::getAllNodes(ComposedNode *node) { set ret; - set setOfNode = node->edGetDirectDescendants(); - for(set::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + list< Node *> setOfNode = node->edGetDirectDescendants(); + for(list::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) { if ( dynamic_cast (*iter) ) { @@ -779,12 +871,12 @@ std::set VisitorSaveSchema::getAllNodes(ComposedNode *node) } else { - set myCurrentSet=(*iter)->getRecursiveConstituents(); + list myCurrentSet=(*iter)->getRecursiveConstituents(); ret.insert(myCurrentSet.begin(),myCurrentSet.end()); ret.insert(*iter); } } - return ret; + return ret; } void VisitorSaveSchema::writeParameters(Proc *proc) @@ -793,9 +885,9 @@ void VisitorSaveSchema::writeParameters(Proc *proc) set nodeSet = getAllNodes(proc); for (set::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter) { -// ElementaryNode *node = dynamic_cast(*iter); -// if (node) -// writeParametersNode(proc,node); + // ElementaryNode *node = dynamic_cast(*iter); + // if (node) + // writeParametersNode(proc,node); writeParametersNode(proc,(*iter)); } } diff --git a/src/engine/VisitorSaveSchema.hxx b/src/engine/VisitorSaveSchema.hxx index d8673a668..2af507771 100644 --- a/src/engine/VisitorSaveSchema.hxx +++ b/src/engine/VisitorSaveSchema.hxx @@ -55,9 +55,14 @@ namespace YACS virtual void visitServiceInlineNode(ServiceInlineNode *node); virtual void visitSwitch(Switch *node); virtual void visitWhileLoop(WhileLoop *node); + virtual void visitPresetNode(DataNode *node); + virtual void visitOutNode(DataNode *node); + virtual void visitStudyInNode(DataNode *node); + virtual void visitStudyOutNode(DataNode *node); protected: virtual void writeProperties(Node *node); + virtual void dumpTypeCode(TypeCode* type, std::set& typeNames,std::map& typeMap,int depth); virtual void writeTypeCodes(Proc *proc); virtual void writeContainers(Proc *proc); virtual void writeInputPorts(Node *node); diff --git a/src/engine/VisitorSaveState.cxx b/src/engine/VisitorSaveState.cxx index 088c102ec..5489ebab9 100644 --- a/src/engine/VisitorSaveState.cxx +++ b/src/engine/VisitorSaveState.cxx @@ -11,6 +11,7 @@ #include "InlineNode.hxx" #include "ServiceNode.hxx" #include "ServiceInlineNode.hxx" +#include "DataNode.hxx" #include "VisitorSaveState.hxx" @@ -25,7 +26,7 @@ using namespace std; VisitorSaveState::VisitorSaveState(ComposedNode *root): Visitor(root) { - _nodeStateName[YACS::INITED] ="INITED"; + _nodeStateName[YACS::READY] ="READY"; _nodeStateName[YACS::TOLOAD] ="TOLOAD"; _nodeStateName[YACS::LOADED] ="LOADED"; _nodeStateName[YACS::TOACTIVATE] ="TOACTIVATE"; @@ -193,9 +194,11 @@ void VisitorSaveState::visitWhileLoop(WhileLoop *node) InputPort * ip = node->edGetConditionPort(); if (ip->isEmpty()) throw Exception("condition in WhileLoop empty, case not handled yet..."); - Any *val = static_cast(ip->get()); - bool condition = val->getBoolValue(); - _out << " " << condition << "" << endl; + if ( ConditionInputPort* cip = dynamic_cast(ip) ) + { + bool condition = cip->getValue(); + _out << " " << condition << "" << endl; + } _out << " " << endl; } @@ -240,3 +243,23 @@ void VisitorSaveState::visitServiceInlineNode(ServiceInlineNode *node) { visitElementaryNode(node); } + +void VisitorSaveState::visitPresetNode(DataNode *node) +{ + visitElementaryNode(node); +} + +void VisitorSaveState::visitOutNode(DataNode *node) +{ + visitElementaryNode(node); +} + +void VisitorSaveState::visitStudyInNode(DataNode *node) +{ + visitElementaryNode(node); +} + +void VisitorSaveState::visitStudyOutNode(DataNode *node) +{ + visitElementaryNode(node); +} diff --git a/src/engine/VisitorSaveState.hxx b/src/engine/VisitorSaveState.hxx index 279fadd3f..d4ded7439 100644 --- a/src/engine/VisitorSaveState.hxx +++ b/src/engine/VisitorSaveState.hxx @@ -31,6 +31,10 @@ namespace YACS virtual void visitServiceInlineNode(ServiceInlineNode *node); virtual void visitSwitch(Switch *node); virtual void visitWhileLoop(WhileLoop *node); + virtual void visitPresetNode(DataNode *node); + virtual void visitOutNode(DataNode *node); + virtual void visitStudyInNode(DataNode *node); + virtual void visitStudyOutNode(DataNode *node); protected: std::ofstream _out; diff --git a/src/engine/WhileLoop.cxx b/src/engine/WhileLoop.cxx index d20e2f30c..90ce94ddf 100644 --- a/src/engine/WhileLoop.cxx +++ b/src/engine/WhileLoop.cxx @@ -56,23 +56,11 @@ void WhileLoop::exUpdateState() } } -int WhileLoop::getNumberOfInputPorts() const -{ - return StaticDefinedComposedNode::getNumberOfInputPorts()+1; -} - Node *WhileLoop::simpleClone(ComposedNode *father, bool editionOnly) const { return new WhileLoop(*this,father,editionOnly); } -std::list WhileLoop::getSetOfInputPort() const -{ - list ret=StaticDefinedComposedNode::getSetOfInputPort(); - ret.push_back((InputPort *)&_conditionPort); - return ret; -} - InputPort *WhileLoop::getInputPort(const std::string& name) const throw(Exception) { if(name==NAME_OF_INPUT_CONDITION) @@ -104,9 +92,9 @@ YACS::Event WhileLoop::updateStateOnFinishedEventFrom(Node *node) } void WhileLoop::checkLinkPossibility(OutPort *start, - const std::set& pointsOfViewStart, + const std::list& pointsOfViewStart, InPort *end, - const std::set& pointsOfViewEnd) throw(Exception) + const std::list& pointsOfViewEnd) throw(Exception) { DEBTRACE("WhileLoop::checkLinkPossibility"); } diff --git a/src/engine/WhileLoop.hxx b/src/engine/WhileLoop.hxx index 3fa085129..35c518dc9 100644 --- a/src/engine/WhileLoop.hxx +++ b/src/engine/WhileLoop.hxx @@ -26,15 +26,15 @@ namespace YACS void exUpdateState(); void init(bool start=true); InputPort *edGetConditionPort() { return &_conditionPort; } - int getNumberOfInputPorts() const; - std::list getSetOfInputPort() const; InputPort* getInputPort(const std::string& name) const throw(Exception); std::list getLocalInputPorts() const; virtual void accept(Visitor *visitor); + InputPort *getDecisionPort() const { return (InputPort *)&_conditionPort; } + virtual std::string typeName() {return "YACS__ENGINE__WhileLoop";} protected: Node *simpleClone(ComposedNode *father, bool editionOnly=true) const; - void checkLinkPossibility(OutPort *start, const std::set& pointsOfViewStart, - InPort *end, const std::set& pointsOfViewEnd) throw(Exception); + void checkLinkPossibility(OutPort *start, const std::list& pointsOfViewStart, + InPort *end, const std::list& pointsOfViewEnd) throw(Exception); YACS::Event updateStateOnFinishedEventFrom(Node *node); }; } diff --git a/src/engine/engtypemaps.i b/src/engine/engtypemaps.i new file mode 100644 index 000000000..6e3f80667 --- /dev/null +++ b/src/engine/engtypemaps.i @@ -0,0 +1,553 @@ +%include std_except.i +%include std_string.i +%include std_map.i +%include std_list.i +%include std_vector.i +%include std_set.i + +// ---------------------------------------------------------------------------- + +%{ +#include "yacsconfig.h" + +#ifdef OMNIORB +#include + +//--- from omniORBpy.h (not present on Debian Sarge packages) +struct omniORBPYAPI +{ + PyObject* (*cxxObjRefToPyObjRef)(const CORBA::Object_ptr cxx_obj, + CORBA::Boolean hold_lock); + // Convert a C++ object reference to a Python object reference. + // If is true, caller holds the Python interpreter lock. + + CORBA::Object_ptr (*pyObjRefToCxxObjRef)(PyObject* py_obj, + CORBA::Boolean hold_lock); + // Convert a Python object reference to a C++ object reference. + // Raises BAD_PARAM if the Python object is not an object reference. + // If is true, caller holds the Python interpreter lock. + + PyObject* (*handleCxxSystemException)(const CORBA::SystemException& ex); + // Sets the Python exception state to reflect the given C++ system + // exception. Always returns NULL. The caller must hold the Python + // interpreter lock. +}; + +omniORBPYAPI* api; + +#define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS \ +catch (const CORBA::SystemException& ex) { \ + return api->handleCxxSystemException(ex); \ +} +#else +#define OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS +#endif + +#include "Node.hxx" +#include "InlineNode.hxx" +#include "ComposedNode.hxx" +#include "ServiceNode.hxx" +#include "ServiceInlineNode.hxx" +#include "Proc.hxx" +#include "Bloc.hxx" +#include "ForLoop.hxx" +#include "WhileLoop.hxx" +#include "ForEachLoop.hxx" +#include "Switch.hxx" +#include "InputPort.hxx" +#include "OutputPort.hxx" +#include "InputDataStreamPort.hxx" +#include "OutputDataStreamPort.hxx" +#include "OptimizerLoop.hxx" + +class InterpreterUnlocker +{ +public: + InterpreterUnlocker() + { + _save = PyEval_SaveThread(); // allow Python threads to run + } + ~InterpreterUnlocker() + { + PyEval_RestoreThread(_save); // restore the thread state + } +private: + PyThreadState *_save; +}; + +static PyObject* convertNode(YACS::ENGINE::Node* node,int owner=0) +{ + if (!node) + return SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Node,owner); + PyObject * ob; + //should use $descriptor(YACS::ENGINE::Bloc *) and so on but $descriptor is not defined here + // It is better to define a helper function to avoid code bloat + // First try to find a swig type info by its mangled name + std::string swigtypename="_p_"+node->typeName(); + swig_type_info *ret = SWIG_MangledTypeQuery(swigtypename.c_str()); + if (ret) + ob=SWIG_NewPointerObj((void*)node,ret,owner); + else + { + //typeName not known by swig. Try dynamic_cast on known classes + //You must respect inheritance order in casting : Bloc before ComposedNode and so on + if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Proc,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Bloc,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ForLoop,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__WhileLoop,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ForEachLoop,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Switch,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ComposedNode,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__InlineFuncNode,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__InlineNode,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServiceInlineNode,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ServiceNode,owner); + else if(dynamic_cast(node)) + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__ElementaryNode,owner); + else + ob=SWIG_NewPointerObj((void*)node,SWIGTYPE_p_YACS__ENGINE__Node,owner); + } + return ob; +} + +static PyObject* convertPort(YACS::ENGINE::Port* port,int owner=0) +{ + if(!port) + return SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__Port, owner); + PyObject * ob; + std::string swigtypename="_p_"+port->typeName(); + swig_type_info *ret = SWIG_MangledTypeQuery(swigtypename.c_str()); + if (ret) + { + YACS::ENGINE::InputPort *inport = dynamic_cast(port); + if(inport) + return SWIG_NewPointerObj((void*)inport,ret,owner); + + YACS::ENGINE::OutputPort *outport = dynamic_cast(port); + if(outport) + return SWIG_NewPointerObj((void*)outport,ret,owner); + + YACS::ENGINE::InputDataStreamPort *indsport = dynamic_cast(port); + if(indsport) + return SWIG_NewPointerObj((void*)indsport,ret,owner); + + YACS::ENGINE::OutputDataStreamPort *outdsport = dynamic_cast(port); + if(outdsport) + return SWIG_NewPointerObj((void*)outdsport,ret,owner); + + return SWIG_NewPointerObj((void*)port,ret,owner); + } + else + { + if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InputPort,owner); + else if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutputPort,owner); + else if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InputDataStreamPort, owner); + else if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutputDataStreamPort, owner); + else if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InPort, owner); + else if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutPort, owner); + else if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__InGate, owner); + else if(dynamic_cast(port)) + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__OutGate, owner); + else + ob=SWIG_NewPointerObj((void*)port,SWIGTYPE_p_YACS__ENGINE__Port, owner); + } + return ob; +} + +%} + +#if SWIG_VERSION >= 0x010329 +%template() std::list; +%template() std::list; +#else + +#ifdef SWIGPYTHON +%typemap(out) std::list +{ + int i; + std::list::iterator iL; + + $result = PyList_New($1.size()); + for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) + PyList_SetItem($result,i,PyLong_FromLong((*iL))); +} + +%typemap(out) std::list +{ + int i; + std::list::iterator iL; + + $result = PyList_New($1.size()); + for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) + PyList_SetItem($result,i,PyString_FromString((*iL).c_str())); +} + +%typemap(in) std::list +{ + /* Check if input is a list */ + if (PyList_Check($input)) + { + int size = PyList_Size($input); + int i = 0; + std::list myList; + $1 = myList; + for (i = 0; i < size; i++) + { + PyObject *o = PyList_GetItem($input,i); + if (PyString_Check(o)) + $1.push_back(std::string(PyString_AsString(PyList_GetItem($input,i)))); + else + { + PyErr_SetString(PyExc_TypeError,"list must contain strings"); + return NULL; + } + } + } + else + { + PyErr_SetString(PyExc_TypeError,"not a list"); + return NULL; + } +} +#endif +#endif + +#ifdef SWIGPYTHON +%typemap(in) std::list +{ + // Check if input is a list + if (PyList_Check($input)) + { + int size = PyList_Size($input); + int i = 0; + std::list myList; + $1 = myList; + for (i = 0; i < size; i++) + { + PyObject *o = PyList_GetItem($input,i); + YACS::ENGINE::TypeCode* temp; + if ((SWIG_ConvertPtr(o, (void **) &temp, $descriptor(YACS::ENGINE::TypeCode*),0)) == -1) + { + PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCode*"); + return NULL; + } + else + { + if(temp->kind() == YACS::ENGINE::Objref) + $1.push_back((YACS::ENGINE::TypeCodeObjref*)temp); + else + { + PyErr_SetString(PyExc_TypeError,"not a YACS::ENGINE::TypeCodeObjref*"); + return NULL; + } + } + } + } + else + { + PyErr_SetString(PyExc_TypeError,"not a list"); + return NULL; + } +} + +%typemap(out) YACS::ENGINE::Node* +{ + $result=convertNode($1,$owner); +} + +%typemap(out) YACS::ENGINE::ServiceNode* +{ + $result=convertNode($1,$owner); +} + +%typemap(out) YACS::ENGINE::InlineNode* +{ + $result=convertNode($1,$owner); +} + +%typemap(out) YACS::ENGINE::ComposedNode* +{ + $result=convertNode($1,$owner); +} + +%typemap(out) YACS::ENGINE::Proc* +{ + $result=convertNode($1,$owner); +} + +%typemap(out) std::set +{ + int i; + std::set::iterator iL; + + $result = PyList_New($1.size()); + PyObject * ob; + for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) + { + ob=convertNode(*iL); + PyList_SetItem($result,i,ob); + } +} + +%typemap(out) std::list +{ + int i; + std::list::iterator iL; + + $result = PyList_New($1.size()); + PyObject * ob; + for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) + { + ob=convertNode(*iL); + PyList_SetItem($result,i,ob); + } +} + +%typemap(out) std::set +{ + int i; + std::set::iterator iL; + $result = PyList_New($1.size()); + PyObject * ob; + for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) + { + ob=convertPort(*iL); + PyList_SetItem($result,i,ob); + } +} + +%typemap(out) std::set +{ + int i; + std::set::iterator iL; + $result = PyList_New($1.size()); + PyObject * ob; + for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) + { + ob=convertPort(*iL); + PyList_SetItem($result,i,ob); + } +} + +%typemap(out) std::set +{ + std::set::iterator iL; + $result = PyList_New(0); + PyObject * ob; + int status; + for (iL=$1.begin(); iL!=$1.end(); iL++) + { + ob=convertPort(*iL); + status=PyList_Append($result,ob); + Py_DECREF(ob); + if (status < 0) + { + PyErr_SetString(PyExc_TypeError,"cannot build the inport list"); + return NULL; + } + } +} + +%typemap(out) std::set +{ + std::set::iterator iL; + $result = PyList_New(0); + PyObject * ob; + int status; + for (iL=$1.begin(); iL!=$1.end(); iL++) + { + ob=convertPort(*iL); + status=PyList_Append($result,ob); + Py_DECREF(ob); + if (status < 0) + { + PyErr_SetString(PyExc_TypeError,"cannot build the outport list"); + return NULL; + } + } +} + +%typemap(out) std::list +{ + std::list::const_iterator it; + $result = PyTuple_New($1.size()); + int i = 0; + for (it = $1.begin(); it != $1.end(); ++it, ++i) { + PyTuple_SetItem($result,i,convertPort(*it)); + } +} +%typemap(out) std::list +{ + std::list::const_iterator it; + $result = PyTuple_New($1.size()); + int i = 0; + for (it = $1.begin(); it != $1.end(); ++it, ++i) { + PyTuple_SetItem($result,i,convertPort(*it)); + } +} +%typemap(out) std::list +{ + std::list::const_iterator it; + $result = PyTuple_New($1.size()); + int i = 0; + for (it = $1.begin(); it != $1.end(); ++it, ++i) { + PyTuple_SetItem($result,i,convertPort(*it)); + } +} +%typemap(out) std::list +{ + std::list::const_iterator it; + $result = PyTuple_New($1.size()); + int i = 0; + for (it = $1.begin(); it != $1.end(); ++it, ++i) { + PyTuple_SetItem($result,i,convertPort(*it)); + } +} + +#endif + +/* + * Exception section + */ +// a general exception handler +%exception { + try + { + $action + } + catch(YACS::Exception& _e) + { + PyErr_SetString(PyExc_ValueError,_e.what()); + return NULL; + } + catch(std::invalid_argument& _e) + { + PyErr_SetString(PyExc_IOError ,_e.what()); + return NULL; + } + OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS + catch(...) + { + SWIG_exception(SWIG_UnknownError, "Unknown exception"); + } +} + +// a specific exception handler = generic + release lock +%define PYEXCEPTION(name) +%exception name { + try + { + InterpreterUnlocker _l; + $action + } + catch(YACS::Exception& _e) + { + PyErr_SetString(PyExc_ValueError,_e.what()); + return NULL; + } + catch(std::invalid_argument& _e) + { + PyErr_SetString(PyExc_IOError ,_e.what()); + return NULL; + } + OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS + catch(...) + { + SWIG_exception(SWIG_UnknownError, "Unknown exception"); + } +} +%enddef + +%define EXCEPTION(name) +%exception name { + try + { + $action + } + catch(YACS::Exception& _e) + { + PyErr_SetString(PyExc_ValueError,_e.what()); + return NULL; + } + catch(std::invalid_argument& _e) + { + PyErr_SetString(PyExc_IOError ,_e.what()); + return NULL; + } + OMNIPY_CATCH_AND_HANDLE_SYSTEM_EXCEPTIONS + catch(...) + { + SWIG_exception(SWIG_UnknownError, "Unknown exception"); + } +} +%enddef +/* + * End of Exception section + */ + +/* + * Ownership section + */ +//Release ownership : transfer it to C++ +%apply SWIGTYPE *DISOWN { YACS::ENGINE::CatalogLoader* factory}; +%apply SWIGTYPE *DISOWN { YACS::ENGINE::Node *DISOWNnode }; +%apply SWIGTYPE *DISOWN { Node *DISOWNnode }; +/* + * End of ownership section + */ + +/* + * Reference counting section + */ +//not well understood +//%feature("ref") YACS::ENGINE::RefCounter "$this->incrRef();" +//%feature("unref") YACS::ENGINE::RefCounter "$this->decrRef();" +/* + * End of Reference counting section + */ + +/* +%wrapper %{ + namespace swig { + template <> struct traits_from { + static PyObject *from(YACS::ENGINE::InPort* val){ + return convertPort(val); + } + }; + template <> struct traits_from { + static PyObject *from(YACS::ENGINE::OutPort* val) { + return convertPort(val); + } + }; + template <> struct traits_from { + static PyObject *from(YACS::ENGINE::InPort* val){ + return convertPort(val); + } + }; + template <> struct traits_from { + static PyObject *from(YACS::ENGINE::OutPort* val) { + return convertPort(val); + } + }; + } +%} +*/ + diff --git a/src/engine/pilot.i b/src/engine/pilot.i index aec9934ec..6c22dd670 100644 --- a/src/engine/pilot.i +++ b/src/engine/pilot.i @@ -1,406 +1,104 @@ -// ---------------------------------------------------------------------------- %define DOCSTRING -"Pilot docstring -All is needed to create and execute a calculation schema." +"All is needed to create and execute a calculation schema." %enddef -%module(directors="1",docstring=DOCSTRING) pilot +%module(docstring=DOCSTRING) pilot -%feature("autodoc", "0"); +#ifndef SWIGIMPORTED +//work around SWIG bug #1863647 +#define PySwigIterator pilot_PySwigIterator +#endif -%include std_except.i -%include std_string.i -%include std_map.i -%include std_list.i -%include std_vector.i -%include std_set.i +%feature("autodoc", "1"); -// ---------------------------------------------------------------------------- +%include "engtypemaps.i" %{ -#include "Runtime.hxx" -#include "Loop.hxx" -#include "WhileLoop.hxx" -#include "ForLoop.hxx" -#include "ForEachLoop.hxx" -#include "OptimizerLoop.hxx" -#include "Switch.hxx" -#include "Bloc.hxx" -#include "Proc.hxx" -#include "ElementaryNode.hxx" -#include "InlineNode.hxx" -#include "ServiceNode.hxx" -#include "ComponentInstance.hxx" -#include "Dispatcher.hxx" -#include "ServiceInlineNode.hxx" - +#include "Any.hxx" #include "TypeCode.hxx" - -#include "OutPort.hxx" -#include "InputPort.hxx" -#include "OutputPort.hxx" -#include "InputDataStreamPort.hxx" -#include "OutputDataStreamPort.hxx" - -#include "ExecutorSwig.hxx" -#include "Executor.hxx" -#include "Task.hxx" -#include "Scheduler.hxx" +#include "ComponentDefinition.hxx" +#include "Visitor.hxx" #include "VisitorSaveSchema.hxx" +#include "VisitorSaveState.hxx" +#include "LinkInfo.hxx" +#include "Catalog.hxx" +#include "Executor.hxx" +#include "ExecutorSwig.hxx" +#include "Dispatcher.hxx" #include "Container.hxx" - -#include -#include -#include -#include -#include -#include +#include "Logger.hxx" +#include "DeploymentTree.hxx" +#include "ComponentInstance.hxx" using namespace YACS::ENGINE; -using namespace std; -class InterpreterUnlocker -{ -public: - InterpreterUnlocker() - { - _save = PyEval_SaveThread(); // allow Python threads to run - } - ~InterpreterUnlocker() - { - PyEval_RestoreThread(_save); // restore the thread state - } -private: - PyThreadState *_save; -}; - -#define POINTER_OWN 1 +%} -namespace YACS -{ - namespace ENGINE +%init +%{ + // init section +#ifdef OMNIORB + PyObject* omnipy = PyImport_ImportModule((char*)"_omnipy"); + if (!omnipy) { - class PyObserver:public Observer - { - public: - virtual void notifyObserver(Node* object,const std::string& event) - { - //YACS engine processing is pure C++ : need to take the GIL - PyGILState_STATE gstate = PyGILState_Ensure(); - - try - { - pynotify(object,event); - if (PyErr_Occurred()) - { - // print the exception and clear it - PyErr_Print(); - //do not propagate the python exception (ignore it) - } - } - catch (...) - { - //ignore this exception:probably Swig::DirectorException - if (PyErr_Occurred()) - PyErr_Print(); - } - PyGILState_Release(gstate); - } - virtual void pynotify(Node* object,const std::string& event) - { - //To inherit (Python class) - std::cerr << "pynotify " << event << object << std::endl; - } - }; + PyErr_SetString(PyExc_ImportError,(char*)"Cannot import _omnipy"); + return; } -} - + PyObject* pyapi = PyObject_GetAttrString(omnipy, (char*)"API"); + api = (omniORBPYAPI*)PyCObject_AsVoidPtr(pyapi); + Py_DECREF(pyapi); +#endif %} -%typemap(python,out) std::list -{ - int i; - std::list::iterator iL; - - $result = PyList_New($1.size()); - for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) - PyList_SetItem($result,i,PyLong_FromLong((*iL))); -} - -%typemap(python,out) std::list -{ - int i; - std::list::iterator iL; - - $result = PyList_New($1.size()); - for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) - PyList_SetItem($result,i,PyString_FromString((*iL).c_str())); -} - -%typemap(python,in) std::list -{ - /* Check if input is a list */ - if (PyList_Check($input)) - { - int size = PyList_Size($input); - int i = 0; - std::list myList; - $1 = myList; - for (i = 0; i < size; i++) - { - PyObject *o = PyList_GetItem($input,i); - if (PyString_Check(o)) - $1.push_back(std::string(PyString_AsString(PyList_GetItem($input,i)))); - else - { - PyErr_SetString(PyExc_TypeError,"list must contain strings"); - return NULL; - } - } - } - else - { - PyErr_SetString(PyExc_TypeError,"not a list"); - return NULL; - } -} - -%typemap(python,out) std::set -{ - int i; - std::set::iterator iL; - - $result = PyList_New($1.size()); - PyObject * ob; - for (i=0, iL=$1.begin(); iL!=$1.end(); i++, iL++) - { - if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::Bloc *),0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::ForLoop *),0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::WhileLoop *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::ForEachLoop *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::Switch *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::ComposedNode *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::InlineFuncNode *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::InlineNode *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::ServiceNode *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::ServiceInlineNode *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::ElementaryNode *), 0); - else - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::Node *), 0); - - PyList_SetItem($result,i,ob); - } -} - -%typemap(python,out) std::set -{ - std::set::iterator iL; - $result = PyList_New(0); - PyObject * ob; - int status; - for (iL=$1.begin(); iL!=$1.end(); iL++) - { - if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::InputPort *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::InputDataStreamPort *), 0); - else - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::InPort *), 0); - - //ob=swig::from((YACS::ENGINE::InPort *)(*iL)); - - status=PyList_Append($result,ob); - Py_DECREF(ob); - if (status < 0) - { - PyErr_SetString(PyExc_TypeError,"cannot build the inport list"); - return NULL; - } - } -} - -%typemap(python,out) std::set -{ - std::set::iterator iL; - $result = PyList_New(0); - PyObject * ob; - int status; - for (iL=$1.begin(); iL!=$1.end(); iL++) - { - if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::OutputPort *), 0); - else if(dynamic_cast(*iL)) - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::OutputDataStreamPort *), 0); - else - ob=SWIG_NewPointerObj((void*)(*iL),$descriptor(YACS::ENGINE::OutPort *), 0); - - //ob=swig::from((YACS::ENGINE::OutPort *)(*iL)); - - status=PyList_Append($result,ob); - Py_DECREF(ob); - if (status < 0) - { - PyErr_SetString(PyExc_TypeError,"cannot build the outport list"); - return NULL; - } - } -} - -/* - * Exception section - */ -// a general exception handler -%exception { - try - { - $action - } - catch(YACS::Exception& _e) - { - PyErr_SetString(PyExc_ValueError,_e.what()); - return NULL; - } - catch (Swig::DirectorException &e) - { - SWIG_fail; - } -} - -// a specific exception handler = generic + release lock -%exception RunW { - try { - InterpreterUnlocker _l; - $action - } catch(YACS::Exception& _e) { - PyErr_SetString(PyExc_ValueError,_e.what()); - return NULL; - } -} -%exception RunB { - try { - InterpreterUnlocker _l; - $action - } catch(YACS::Exception& _e) { - PyErr_SetString(PyExc_ValueError,_e.what()); - return NULL; - } -} - -%exception setExecMode { - try { - InterpreterUnlocker _l; - $action - } catch(YACS::Exception& _e) { - PyErr_SetString(PyExc_ValueError,_e.what()); - return NULL; - } -} - -%exception resumeCurrentBreakPoint { - try { - InterpreterUnlocker _l; - $action - } catch(YACS::Exception& _e) { - PyErr_SetString(PyExc_ValueError,_e.what()); - return NULL; - } -} - -%exception stopExecution { - try { - InterpreterUnlocker _l; - $action - } catch(YACS::Exception& _e) { - PyErr_SetString(PyExc_ValueError,_e.what()); - return NULL; - } -} - -/* - * End of Exception section - */ +%ignore YACS::ENGINE::TypeCode::operator=; +%ignore YACS::ENGINE::DeploymentTree::operator=; +%ignore operator<<; +%ignore YACS::ENGINE::Runtime::_tc_double; +%ignore YACS::ENGINE::Runtime::_tc_int; +%ignore YACS::ENGINE::Runtime::_tc_bool; +%ignore YACS::ENGINE::Runtime::_tc_string; +%ignore YACS::ENGINE::Runtime::_tc_file; +%rename(StateLoader) YACS::ENGINE::StateLoader; // to suppress a 503 warning +%rename(NbDoneLoader) YACS::ENGINE::NbDoneLoader; // to suppress a 503 warning +%rename(getRuntime) YACS::ENGINE::getRuntime; // to suppress a 503 warning +%rename(_from) YACS::ENGINE::DataLinkInfo::from ; // to suppress a 314 warning +%rename(_from) YACS::ENGINE::StreamLinkInfo::from ; // to suppress a 314 warning /* * Template section */ - - -%wrapper %{ - /* Modification de la mecanique swig pour caster les objets dans les containers STL - * Probablement trop dependant de swig (desactive) - namespace swig { - template <> struct traits_from { - static PyObject *from(YACS::ENGINE::InPort* val) { - //std::cerr << "typeid: " << typeid(*val).name() << std::endl; - if(dynamic_cast(val)) - return traits_from_ptr::from((YACS::ENGINE::InputPort*)val, 0); - else if(dynamic_cast(val)) - return traits_from_ptr::from((YACS::ENGINE::InputDataStreamPort*)val, 0); - else - return traits_from_ptr::from(val, 0); - } - }; - template <> struct traits_from { - static PyObject *from(YACS::ENGINE::OutPort* val) { - std::cerr << "from:YACS::ENGINE::OutPort*" << std::endl; - std::cerr << "typeid: " << typeid(val).name() << std::endl; - std::cerr << "typeid: " << typeid(*val).name() << std::endl; - std::cerr << val->getNameOfTypeOfCurrentInstance() << std::endl; - std::cerr << dynamic_cast(val) << std::endl; - if(dynamic_cast(val)) - return traits_from_ptr::from((YACS::ENGINE::OutputPort*)val, 0); - else if(dynamic_cast(val)) - return traits_from_ptr::from((YACS::ENGINE::OutputDataStreamPort*)val, 0); - else - return traits_from_ptr::from(val, 0); - } - }; - } - */ -%} - - %template() std::pair; %template() std::pair; %template() std::pair; %template() std::pair; +%template() std::pair; %template() std::pair; %template() std::pair; -%template(TypeList) std::list; %template(TCmap) std::map; %template(NODEmap) std::map; %template(INODEmap) std::map; %template(SNODEmap) std::map; +%template(CONTAINmap) std::map; %template(strvec) std::vector; %template(linksvec) std::vector< std::pair >; %template(linkvec) std::vector< std::pair >; -%template(inlist) std::list; -%template(outlist) std::list; -%template(inputlist) std::list; -%template(outputlist) std::list; %template(instreamlist) std::list; %template(outstreamlist) std::list; -//Pb : cannot iterate with SWIG 1.3.24 -//%template(NODEset) std::set; -//%template(InPortset) std::set; -//%template(OutPortset) std::set; +%template() std::pair; +%template(loadermap) std::map; +%template() std::pair; +%template(composedmap) std::map; +%template() std::pair; +%template(compomap) std::map; +%template() std::pair; +%template(propmap) std::map; /* * End of Template section */ + /* * Ownership section */ @@ -411,22 +109,29 @@ namespace YACS %newobject YACS::ENGINE::Runtime::createRefNode; %newobject YACS::ENGINE::Runtime::createCompoNode; %newobject YACS::ENGINE::Runtime::createSInlineNode; +%newobject YACS::ENGINE::Runtime::createInDataNode; +%newobject YACS::ENGINE::Runtime::createOutDataNode; %newobject YACS::ENGINE::Runtime::createBloc; %newobject YACS::ENGINE::Runtime::createForLoop; %newobject YACS::ENGINE::Runtime::createForEachLoop; %newobject YACS::ENGINE::Runtime::createWhileLoop; %newobject YACS::ENGINE::Runtime::createSwitch; - -//Release ownership : transfer it to C++ -%apply SWIGTYPE *DISOWN { YACS::ENGINE::Node *DISOWNnode }; - -//Take ownership : transfer it from C++ (to complete) +%newobject YACS::ENGINE::Runtime::loadCatalog; +%newobject YACS::ENGINE::Runtime::createComponentInstance; +%newobject YACS::ENGINE::Runtime::createContainer; +%newobject YACS::ENGINE::Runtime::createInputPort; +%newobject YACS::ENGINE::Runtime::createOutputPort; +%newobject YACS::ENGINE::Runtime::createInputDataStreamPort; +%newobject YACS::ENGINE::Runtime::createOutputDataStreamPort; +%newobject YACS::ENGINE::Node::clone; + +//Take ownership : transfer it from C++ (has to be completed) %newobject YACS::ENGINE::Loop::edRemoveNode; %newobject YACS::ENGINE::Switch::edReleaseDefaultNode; %newobject YACS::ENGINE::Switch::edReleaseCase; %newobject YACS::ENGINE::DynParaLoop::edRemoveNode; %newobject YACS::ENGINE::DynParaLoop::edRemoveInitNode; -//No other way to do +//No other way to do ?? %feature("pythonappend") YACS::ENGINE::Bloc::edRemoveChild(Node *node)%{ args[1].thisown=1 %} @@ -434,524 +139,117 @@ namespace YACS * End of ownership section */ -/* - * Reference counting section - */ -//not well understood -//%feature("ref") YACS::ENGINE::RefCounter "$this->incrRef();" -//%feature("unref") YACS::ENGINE::RefCounter "$this->decrRef();" -/* - * End of Reference counting section - */ - -%feature("director") YACS::ENGINE::PyObserver; -%feature("nodirector") YACS::ENGINE::PyObserver::notifyObserver; -/* -%feature("director:except") { - if ($error != NULL) { - // print the exception and clear it - PyErr_Print(); - //do not propagate the python exception (ignore it) - //throw Swig::DirectorMethodException(); - } -} -*/ - %include %include %include %include + +PYEXCEPTION(YACS::ENGINE::Executor::RunW) +PYEXCEPTION(YACS::ENGINE::Executor::RunB) +PYEXCEPTION(YACS::ENGINE::Executor::setExecMode) +PYEXCEPTION(YACS::ENGINE::Executor::resumeCurrentBreakPoint) +PYEXCEPTION(YACS::ENGINE::Executor::stopExecution) +PYEXCEPTION(YACS::ENGINE::Executor::waitPause) %include + +EXCEPTION(YACS::ENGINE::ExecutorSwig::RunPy) +EXCEPTION(YACS::ENGINE::ExecutorSwig::waitPause) %include -%include -%import -%import +%include +%ignore YACS::ENGINE::TypeCode::getOrBuildAnyFromZippedData; +%include -namespace YACS +%include +%include +%include +%include +%include +%extend YACS::ENGINE::Port { - namespace ENGINE - { - typedef enum - { - //Problem with None (same name as python) - // None = 0, - Double = 1, - Int = 2, - String = 3, - Bool = 4, - Objref = 5, - Sequence = 6, - Array = 7 - } DynType; - - class TypeCode : public RefCounter - { - public: - TypeCode(DynType kind); - DynType kind() const; - virtual TypeCode *clone() const; - virtual const char * name() ; - virtual const char * shortName() ; - virtual const char * id() ; - virtual const TypeCode * contentType() ; - virtual int isA(const char* repositoryId) ; - virtual int isA(const TypeCode* tc) const; - virtual int isAdaptable(const TypeCode* tc) const; - protected: - TypeCode(const TypeCode& tc); - virtual ~TypeCode(); - }; - - class TypeCodeObjref: public TypeCode - { - public: - TypeCodeObjref(const char* repositoryId, const char* name); - TypeCodeObjref(const char* repositoryId, const char* name, - const std::list& ltc); - protected: - virtual ~TypeCodeObjref(); - }; - - class DeploymentTree - { - public: - DeploymentTree(); - ~DeploymentTree(); - unsigned char appendTask(Task *task, Scheduler *cloner); - // - unsigned getNumberOfCTDefContainer() const; - unsigned getNumberOfRTODefContainer() const; - unsigned getNumberOfCTDefComponentInstances() const; - unsigned getNumberOfRTODefComponentInstances() const; - // - bool presenceOfDefaultContainer() const; - }; - - class Node; - - class Observer - { - public: - virtual void notifyObserver(Node* object,const std::string& event); - virtual ~Observer(); - }; - - class PyObserver:public Observer + int __cmp__(Port* other) { - public: - //virtual void notifyObserver(Node* object,const std::string& event); - virtual void pynotify(Node* object,const std::string& event); - }; - - class Dispatcher - { - public: - static Dispatcher* getDispatcher(); - virtual void dispatch(Node* object,const std::string& event); - virtual void addObserver(Observer* observer,Node* object,const std::string& event); - virtual void removeObserver(Observer* observer,Node* object,const std::string& event); - virtual void printObservers(); - }; - - class Port - { - public: - virtual ~Port(); - Node *getNode() const ; - virtual std::string getNameOfTypeOfCurrentInstance() const; - %extend{ - int __cmp__(Port* other) - { - if(self==other)return 0; - else return 1; - } - long ptr() - { - return (long)self; - } - } - protected: - Port(Node *node); - Port(const Port& other, Node *newHelder); - }; - - class DataPort : public virtual Port - { - public: - static const char NAME[]; - TypeCode* edGetType() const ; - void edSetType(TypeCode* type); - std::string getName() const ; - std::string getNameOfTypeOfCurrentInstance() const; - virtual void edRemoveAllLinksLinkedWithMe() = 0; - protected: - virtual ~DataPort(); - DataPort(const DataPort& other, Node *newHelder); - DataPort(const std::string& name, Node *node, TypeCode* type); - }; - - class InPort; - class OutPort : virtual public DataPort - { - protected: - OutPort(const OutPort& other, Node *newHelder); - OutPort(const std::string& name, Node *node, TypeCode* type); - public: - virtual int edGetNumberOfOutLinks() const; - virtual std::set edSetInPort() const = 0; - virtual bool isAlreadyLinkedWith(InPort *with) const = 0; - virtual void getAllRepresented(std::set& represented) const; - virtual bool addInPort(InPort *inPort) throw(Exception) = 0; - virtual int removeInPort(InPort *inPort, bool forward) throw(Exception) = 0; - virtual ~OutPort(); - std::vector calculateHistoryOfLinkWith(InPort *end); - }; - - class InPort : virtual public DataPort + if(self==other) + return 0; + else + return 1; + } + long ptr() { - public: - virtual int edGetNumberOfLinks() const; - virtual std::set edSetOutPort() const; - virtual ~InPort(); - protected: - InPort(const InPort& other, Node *newHelder); - InPort(const std::string& name, Node *node, TypeCode* type); - void edRemoveAllLinksLinkedWithMe() throw(Exception); - virtual void edNotifyReferencedBy(OutPort *fromPort); - virtual void edNotifyDereferencedBy(OutPort *fromPort); - virtual void getAllRepresentants(std::set& repr) const; - }; - } + return (long)self; + } } - +%include +%include +%include %include %include %include %include -namespace YACS +%include +%include + +%include +%include +%include +%extend YACS::ENGINE::InputPort { - namespace ENGINE - { - class InputPort : public DataFlowPort, public InPort + void edInitXML(const char * s) { - public: - std::string getNameOfTypeOfCurrentInstance() const; - template - void edInit(T value); - %template(edInitInt) edInit; - %template(edInitBool) edInit; - %template(edInitString) edInit; - %template(edInitDbl) edInit; - void edInit(const std::string& impl,char* value); - virtual InputPort *clone(Node *newHelder) const = 0; - bool isEmpty(); - virtual void put(const void *data) throw(ConversionException) = 0; - virtual std::string dump(); - protected: - InputPort(const std::string& name, Node *node, TypeCode* type); - }; - - class OutputPort : public DataFlowPort, public OutPort + self->edInit("XML",s); + } + void edInitPy(PyObject* ob) { - public: - virtual ~OutputPort(); - std::set edSetInPort() const; - bool isAlreadyLinkedWith(InPort *with) const; - bool isAlreadyInSet(InputPort *inputPort) const; - std::string getNameOfTypeOfCurrentInstance() const; - int removeInPort(InPort *inPort, bool forward) throw(Exception); - virtual bool edAddInputPort(InputPort *phyPort) throw(Exception); - virtual int edRemoveInputPort(InputPort *inputPort, bool forward) throw(Exception); - bool addInPort(InPort *inPort) throw(Exception); - void edRemoveAllLinksLinkedWithMe() throw(Exception);//entry point for forward port deletion - virtual void exInit(); - virtual OutputPort *clone(Node *newHelder) const = 0; - virtual void put(const void *data) throw(ConversionException); - virtual std::string dump(); - protected: - OutputPort(const OutputPort& other, Node *newHelder); - OutputPort(const std::string& name, Node *node, TypeCode* type); - }; + self->edInit("Python",ob); + } +} +%template(edInitInt) YACS::ENGINE::InputPort::edInit; +%template(edInitBool) YACS::ENGINE::InputPort::edInit; +%template(edInitString) YACS::ENGINE::InputPort::edInit; +%template(edInitDbl) YACS::ENGINE::InputPort::edInit; - class InputDataStreamPort : public DataStreamPort, public InPort - { - public: - InputDataStreamPort(const std::string& name, Node *node, TypeCode* type); - std::string getNameOfTypeOfCurrentInstance() const; - InputDataStreamPort *clone(Node *newHelder) const; - }; +%include +%include +%include +%include - class OutputDataStreamPort : public DataStreamPort, public OutPort +%include +%extend YACS::ENGINE::Node +{ + int __cmp__(Node* other) { - public: - OutputDataStreamPort(const OutputDataStreamPort& other, Node *newHelder); - OutputDataStreamPort(const std::string& name, Node *node, TypeCode* type); - virtual ~OutputDataStreamPort(); - virtual OutputDataStreamPort *clone(Node *newHelder) const; - std::set edSetInPort() const; - virtual int edGetNumberOfOutLinks() const; - bool isAlreadyLinkedWith(InPort *with) const; - virtual std::string getNameOfTypeOfCurrentInstance() const; - virtual bool addInPort(InPort *inPort) throw(Exception); - virtual bool edAddInputDataStreamPort(InputDataStreamPort *port) throw(ConversionException); - int edRemoveInputDataStreamPort(InputDataStreamPort *inPort, bool forward) throw(Exception); - void edRemoveAllLinksLinkedWithMe() throw(Exception); - int removeInPort(InPort *inPort, bool forward) throw(Exception); - }; - - class ComposedNode; - class ElementaryNode; - - class Node + if(self==other) + return 0; + else + return 1; + } + long ptr() { - protected: - Node(const std::string& name); - public: - virtual ~Node(); - YACS::StatesForNode getState() ; - virtual YACS::StatesForNode getEffectiveState() ; - std::string getColorState(YACS::StatesForNode state); - InGate *getInGate() ; - OutGate *getOutGate(); - const std::string& getName(); - ComposedNode * getFather() ; - std::set getOutNodes() const; - virtual std::set getRecursiveConstituents() const = 0; - virtual int getNumberOfInputPorts() const = 0; - virtual int getNumberOfOutputPorts() const = 0; - std::list getSetOfInPort() const; - std::list getSetOfOutPort() const; - virtual std::list getSetOfInputPort() const = 0; - virtual std::list getSetOfOutputPort() const = 0; - virtual std::string getInPortName(const InPort *) const = 0; - virtual std::string getOutPortName(const OutPort *) const = 0; - virtual std::list getSetOfInputDataStreamPort() const = 0; - virtual std::list getSetOfOutputDataStreamPort() const = 0; - InPort *getInPort(const std::string& name) const ; - virtual OutPort *getOutPort(const std::string& name) const ; - virtual std::set getAllOutPortsLeavingCurrentScope() const = 0; - virtual std::set getAllInPortsComingFromOutsideOfCurrentScope() const = 0; - virtual InputPort *getInputPort(const std::string& name) const = 0; - virtual OutputPort *getOutputPort(const std::string& name) const = 0; - virtual InputDataStreamPort *getInputDataStreamPort(const std::string& name) const = 0; - virtual OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) const = 0; - std::set getAllAscendanceOf(ComposedNode *levelToStop = 0); - std::string getImplementation(); - virtual ComposedNode *getRootNode() ; - virtual void setProperty(const std::string& name,const std::string& value); - virtual Node *getChildByName(const std::string& name) const = 0; - virtual void sendEvent(const std::string& event); - - %extend{ - int __cmp__(Node* other) - { - if(self==other)return 0; - else return 1; - } - long ptr() - { return (long)self; - } - } - }; - - class Container - { - public: - virtual bool isAlreadyStarted() const; - virtual std::string getPlacementId() const = 0; - virtual void attachOnCloning() const; - virtual void dettachOnCloning() const; - bool isAttachedOnCloning() const; - protected: - ~Container(); - }; - - class ElementaryNode: public Node, public Task - { - public: - virtual InputPort *edAddInputPort(const std::string& inputPortName, TypeCode* type) ; - virtual OutputPort *edAddOutputPort(const std::string& outputPortName, TypeCode* type) ; - InputPort *getInputPort(const std::string& name) ; - OutputPort *getOutputPort(const std::string& name) ; - InputDataStreamPort *getInputDataStreamPort(const std::string& name) ; - OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) ; - virtual InputDataStreamPort *edAddInputDataStreamPort(const std::string& inputPortDSName, TypeCode* type) ; - virtual OutputDataStreamPort *edAddOutputDataStreamPort(const std::string& outputPortDSName, TypeCode* type) ; - protected: - ElementaryNode(const std::string& name); - }; - - class ComposedNode: public Node, public Scheduler - { - protected: - ComposedNode(const std::string& name); - ComposedNode(const ComposedNode& other, ComposedNode *father); - public: - virtual ~ComposedNode(); - bool isFinished(); - DeploymentTree getDeploymentTree() const; - std::vector getNextTasks(bool& isMore); - void notifyFrom(const Task *sender, YACS::Event event); - bool edAddLink(OutPort *start, InPort *end) throw(Exception); - virtual bool edAddDFLink(OutPort *start, InPort *end) throw(Exception); - bool edAddLink(OutGate *start, InGate *end) throw(Exception); - bool edAddCFLink(Node *nodeS, Node *nodeE) throw(Exception); - void edRemoveLink(OutPort *start, InPort *end) throw(Exception); - void edRemoveLink(OutGate *start, InGate *end) throw(Exception); - virtual bool isRepeatedUnpredictablySeveralTimes() const { return false; } - virtual std::set edGetDirectDescendants() const = 0; - std::set getRecursiveConstituents() const; - std::string getInPortName(const InPort *) const throw (Exception); - std::string getOutPortName(const OutPort *) const throw (Exception); - - int getNumberOfInputPorts() const; - int getNumberOfOutputPorts() const; - std::list getSetOfInputPort() const; - std::list getSetOfOutputPort() const; - std::set getAllOutPortsLeavingCurrentScope() const; - std::set getAllInPortsComingFromOutsideOfCurrentScope() const; - std::list getSetOfInputDataStreamPort() const; - std::list getSetOfOutputDataStreamPort() const; - OutPort *getOutPort(const std::string& name) const throw(Exception); - InputPort *getInputPort(const std::string& name) const throw(Exception); - OutputPort *getOutputPort(const std::string& name) const throw(Exception); - InputDataStreamPort *getInputDataStreamPort(const std::string& name) const throw(Exception); - OutputDataStreamPort *getOutputDataStreamPort(const std::string& name) const throw(Exception); - std::vector< std::pair > getSetOfInternalLinks() const; - std::vector< std::pair > getSetOfLinksLeavingCurrentScope() const; - virtual std::vector< std::pair > getSetOfLinksComingInCurrentScope() const; - // - ComposedNode *getRootNode() throw(Exception); - bool isNodeAlreadyAggregated(Node *node) const; - Node *isInMyDescendance(Node *nodeToTest) const; - std::string getChildName(Node* node) const throw(Exception); - Node *getChildByName(const std::string& name) const throw(Exception); - static ComposedNode *getLowestCommonAncestor(Node *node1, Node *node2) throw(Exception); - void loaded(); - }; - - class Bloc: public ComposedNode - { - public: - Bloc(const std::string& name); - bool edAddChild(Node *DISOWNnode) ; - void edRemoveChild(Node *node) ; - std::set getChildren(); - std::set edGetDirectDescendants() const; - bool isFinished(); - }; - - class Loop : public ComposedNode - { - public: - Loop(const std::string& name); - int getNbOfTurns() ; - void edSetNode(Node *DISOWNnode); - std::set edGetDirectDescendants() const; - Node *edRemoveNode(); - }; - - class ForLoop : public Loop - { - public: - ForLoop(const std::string& name); - InputPort *edGetNbOfTimesInputPort(); - }; - - class WhileLoop : public Loop - { - public: - WhileLoop(const std::string& name); - InputPort *edGetConditionPort(); - }; - - class DynParaLoop : public ComposedNode - { - public: - Node *edRemoveNode(); - Node *edRemoveInitNode(); - Node *edSetNode(Node *DISOWNnode); - Node *edSetInitNode(Node *DISOWNnode); - InputPort *edGetNbOfBranchesPort(); - OutputPort *edGetSamplePort(); - unsigned getNumberOfBranchesCreatedDyn() const throw(Exception); - Node *getChildByNameExec(const std::string& name, unsigned id) const throw(Exception); - protected: - ~DynParaLoop(); - }; - - class ForEachLoop : public DynParaLoop - { - public: - ForEachLoop(const std::string& name, TypeCode *typeOfDataSplitted); - std::set edGetDirectDescendants() const; - InputPort *edGetSeqOfSamplesPort(); - }; - - class Switch : public ComposedNode - { - public: - Switch(const std::string& name); - Node *clone(ComposedNode *father) const; - Node *edSetDefaultNode(Node *DISOWNnode); - Node *edReleaseDefaultNode() ; - Node *edReleaseCase(int caseId) ; - Node *edSetNode(int caseId, Node *DISOWNnode) ; - InputPort *edGetConditionPort(); - std::set edGetDirectDescendants() const; - void checkConsistency(); - }; - - class Proc: public Bloc - { - public: - Proc(const std::string& name); - bool isFinished(); - virtual TypeCode *createType(const std::string& name, const std::string& kind); - virtual TypeCodeObjref *createInterfaceTc(const std::string& id, const std::string& name, - std::list ltc); - virtual TypeCode *createSequenceTc(const std::string& id, const std::string& name, - TypeCode *content); - virtual TypeCode *createStructTc(const std::string& id, const std::string& name); - - virtual TypeCode* getTypeCode(const std::string& name); - virtual void setTypeCode(const std::string& name,TypeCode *t); - - YACS::StatesForNode getNodeState(int numId); - std::string getXMLState(int numId); - std::list getNumIds(); - std::list getIds(); - - std::map typeMap; - std::map nodeMap; - std::map serviceMap; - std::map inlineMap; - std::vector names; - void setName(const std::string& name); - }; - } + } } +%include %include %include -%include %include + +%include +%include +%include +%include + +%include +%include +%include +%include +%include %include %include - -namespace YACS -{ - namespace ENGINE - { - class SchemaSave - { - public: - SchemaSave(Proc* proc); - virtual void save(std::string xmlSchemaFile); - }; - } -} +%include +%include +%include +%include +%include diff --git a/src/engine/pypilot.i b/src/engine/pypilot.i new file mode 100644 index 000000000..5e97ea653 --- /dev/null +++ b/src/engine/pypilot.i @@ -0,0 +1,123 @@ +%define PYPILOTDOCSTRING +"This module provides 2 classes PyObserver and PyCatalogLoader that can be subclassed in Python (uses director feature)" +%enddef + +%module(directors="1",docstring=PYPILOTDOCSTRING) pypilot + +%feature("autodoc", "1"); + +%include "engtypemaps.i" + +%{ +#include "Dispatcher.hxx" +#include "Catalog.hxx" +#include "TypeCode.hxx" + +namespace YACS +{ + namespace ENGINE + { + class PyObserver:public Observer + { + public: + virtual void notifyObserver(Node* object,const std::string& event) + { + //YACS engine processing is pure C++ : need to take the GIL + PyGILState_STATE gstate = PyGILState_Ensure(); + + try + { + pynotify(object,event); + if (PyErr_Occurred()) + { + // print the exception and clear it + PyErr_Print(); + //do not propagate the python exception (ignore it) + } + } + catch (...) + { + //ignore this exception:probably Swig::DirectorException + if (PyErr_Occurred()) + PyErr_Print(); + } + PyGILState_Release(gstate); + } + virtual void pynotify(Node* object,const std::string& event) + { + //To inherit (Python class) + std::cerr << "pynotify " << event << object << std::endl; + } + }; + + class PyCatalogLoader:public CatalogLoader + { + protected: + virtual CatalogLoader* newLoader(const std::string& path) {return 0;} + }; + } +} + +%} + +%init +%{ + // init section +#ifdef OMNIORB + PyObject* omnipy = PyImport_ImportModule((char*)"_omnipy"); + if (!omnipy) + { + PyErr_SetString(PyExc_ImportError,(char*)"Cannot import _omnipy"); + return; + } + PyObject* pyapi = PyObject_GetAttrString(omnipy, (char*)"API"); + api = (omniORBPYAPI*)PyCObject_AsVoidPtr(pyapi); + Py_DECREF(pyapi); +#endif +%} + +/* + * Director section : classes that can be subclassed in python + */ +%feature("director") YACS::ENGINE::PyObserver; +%feature("nodirector") YACS::ENGINE::PyObserver::notifyObserver; +%feature("director") YACS::ENGINE::PyCatalogLoader; +%feature("nodirector") YACS::ENGINE::PyCatalogLoader::newLoader; + +/* +%feature("director:except") { + if ($error != NULL) { + // print the exception and clear it + PyErr_Print(); + //do not propagate the python exception (ignore it) + //throw Swig::DirectorMethodException(); + } +} +*/ +/* + * End of Director section + */ + +%types(YACS::ENGINE::InputPort *,YACS::ENGINE::OutputPort *,YACS::ENGINE::InputDataStreamPort *,YACS::ENGINE::OutputDataStreamPort *); +%types(YACS::ENGINE::InGate *,YACS::ENGINE::OutGate *,YACS::ENGINE::InPort *,YACS::ENGINE::OutPort *,YACS::ENGINE::Port *); + +%import "pilot.i" + +namespace YACS +{ + namespace ENGINE + { + class PyObserver:public Observer + { + public: + virtual void pynotify(Node* object,const std::string& event); + }; + + class PyCatalogLoader:public CatalogLoader + { + protected: + virtual CatalogLoader* newLoader(const std::string& path); + }; + } +} + diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 5826b30a9..c4a61d9d2 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1,20 +1,44 @@ include $(top_srcdir)/adm/unix/make_begin.am -lib_LTLIBRARIES = libYACSGui.la +lib_LTLIBRARIES = libYACS.la # Implementation files LIBSOURCES = \ YACSGui_Node.cxx \ YACSGui_Graph.cxx \ + YACSGui_Graph_1.cxx \ YACSGui_Module.cxx \ YACSGui_DataModel.cxx \ YACSGui_DataObject.cxx \ + YACSGui_TreeView.cxx \ + YACSGui_TreeViewItem.cxx \ YACSGui_Executor.cxx \ YACSGui_Observer.cxx \ YACSGui_XMLDriver.cxx \ YACSGui_Swig.cxx \ - YACSGui_RunMode.cxx + YACSGui_RunMode.cxx \ + YACSGui_InputPanel.cxx \ + YACSGui_ContainerPage.cxx \ + YACSGui_ComponentPage.cxx \ + YACSGui_SchemaPage.cxx \ + YACSGui_BlockNodePage.cxx \ + YACSGui_NodePage.cxx \ + YACSGui_InlineNodePage.cxx \ + YACSGui_ServiceNodePage.cxx \ + YACSGui_ForLoopNodePage.cxx \ + YACSGui_ForEachLoopNodePage.cxx \ + YACSGui_WhileLoopNodePage.cxx \ + YACSGui_SwitchNodePage.cxx \ + YACSGui_PropertyPage.cxx \ + YACSGui_LinkPage.cxx \ + YACSGui_DataTypePage.cxx \ + YACSGui_DataNodePage.cxx \ + YACSGui_YACSORBContainerDialog.cxx \ + YACSGui_Selection.cxx \ + YACSGui_PlusMinusGrp.cxx \ + YACSGui_Table.cxx + # Headers LIBHEADERS = \ @@ -23,36 +47,75 @@ LIBHEADERS = \ YACSGui_Module.h \ YACSGui_DataModel.h \ YACSGui_DataObject.h \ + YACSGui_TreeView.h \ + YACSGui_TreeViewItem.h \ YACSGui_Executor.h \ YACSGui_Observer.h \ YACSGui_XMLDriver.h \ - YACSGui_Swig.h + YACSGui_Swig.h \ + YACSGui_Selection.h \ + YACSGui_PlusMinusGrp.h \ + YACSGui_Table.h \ + YACSGui_DataObject.h YACSGui_InputPanel.h YACSGui_LogViewer.h YACSGui_RunMode.h # MOC-generated files MOCSOURCES = \ YACSGui_Module_moc.cxx \ YACSGui_Executor_moc.cxx \ runmode_moc.cxx \ - YACSGui_RunMode_moc.cxx + YACSGui_RunMode_moc.cxx \ + YACSGui_InputPanel_moc.cxx \ + YACSGui_TreeView_moc.cxx \ + YACSGui_PlusMinusGrp_moc.cxx \ + YACSGui_Table_moc.cxx \ + schemapage_moc.cxx \ + containerpage_moc.cxx \ + componentpage_moc.cxx \ + inlinenodepage_moc.cxx \ + servicenodepage_moc.cxx \ + forloopnodepage_moc.cxx \ + foreachloopnodepage_moc.cxx \ + whileloopnodepage_moc.cxx \ + switchnodepage_moc.cxx \ + blocknodepage_moc.cxx \ + datatypepage_moc.cxx \ + datanodepage_moc.cxx # UIC-generated files runmode.cxx : runmode.h -UISOURCES = runmode.cxx +schemapage.cxx : schemapage.h +containerpage.cxx : containerpage.h +componentpage.cxx : componentpage.h +inlinenodepage.cxx : inlinenodepage.h +servicenodepage.cxx : servicenodepage.h +forloopnodepage.cxx : forloopnodepage.h +foreachloopnodepage.cxx : foreachloopnodepage.h +whileloopnodepage.cxx : whileloopnodepage.h +switchnodepage.cxx : switchnodepage.h +blocknodepage.cxx : blocknodepage.h +datatypepage.cxx : datatypepage.h +datanodepage.cxx : datanodepage.h + +UISOURCES = runmode.cxx schemapage.cxx containerpage.cxx componentpage.cxx inlinenodepage.cxx servicenodepage.cxx \ + forloopnodepage.cxx foreachloopnodepage.cxx whileloopnodepage.cxx switchnodepage.cxx blocknodepage.cxx \ + datatypepage.cxx datanodepage.cxx # Resources LIBPOFILES = \ - YACSGui_msg_en.po \ - YACSGui_images.po + YACS_msg_en.po \ + YACS_images.po LIBICONS = \ sample.png \ ModuleYacs.png \ SalomeApp.xml \ - YACSGuiCatalog.xml \ + YACSCatalog.xml \ add_in_study.png \ add_node.png \ change_informations.png \ control_view.png \ + dataflow_view.png \ + datastream_view.png \ export_dataflow.png \ filter_next_steps.png \ filter_notification.png \ @@ -61,38 +124,89 @@ LIBICONS = \ import_superv_dataflow.png \ insert_file.png \ kill.png \ - mode_breakpoint.png \ + breakpoints.png \ + breakpoints_active.png \ mode_continue.png \ modify_dataflow.png \ modify_superv_dataflow.png \ new_dataflow.png \ rebuild_links.png \ + arrange_nodes.png \ reload.png \ remote_run.png \ run.png \ + run_active.png \ save_dataflow_state.png \ step_by_step.png \ + step_by_step_active.png \ suspend_resume.png \ table_view.png \ - toggle_stop_on_error.png + toggle_stop_on_error.png \ + schema.png \ + block_node.png \ + loop_node.png \ + switch_node.png \ + node.png \ + out_port.png \ + in_port.png \ + control_link.png \ + data_link.png \ + stream_link.png \ + container.png \ + component.png \ + run_object.png \ + new_salome_component.png \ + new_salomepy_component.png \ + new_corba_component.png \ + new_salome_service_node.png \ + new_corba_service_node.png \ + new_nodenode_service_node.png \ + new_cpp_node.png \ + new_service_inline_node.png \ + new_xml_node.png \ + new_inline_script_node.png \ + new_inline_function_node.png \ + new_block_node.png \ + new_for_loop_node.png \ + new_foreach_loop_node.png \ + new_while_loop_node.png \ + new_switch_loop_node.png \ + new_from_library_node.png \ + new_link.png \ + icon_select.png \ + icon_up.png \ + icon_down.png \ + icon_insert.png \ + icon_select.png \ + icon_plus.png \ + icon_minus.png \ + new_execution.png \ + new_edition.png \ + new_batch_execution.png \ + load_execution_state.png \ + execute_in_batch.png \ + pause.png \ + resume.png \ + reset.png \ + connect_to_batch_session.png \ + icon_text.png # Add "resources" subdirectory to resource file names -POFILES = $(LIBPOFILES:%=resources/%) -ICONS = $(LIBICONS:%=resources/%) +POFILES += $(LIBPOFILES:%=resources/%) +ICONS += $(LIBICONS:%=resources/%) -libYACSGui_la_SOURCES = $(LIBSOURCES) $(LIBHEADERS) -nodist_libYACSGui_la_SOURCES = $(UISOURCES) $(MOCSOURCES) +libYACS_la_SOURCES = $(LIBSOURCES) $(LIBHEADERS) $(UISOURCES) $(MOCSOURCES) # List all generated files here BUILT_SOURCES = $(UISOURCES) $(MOCSOURCES) YACSGui_SwigWRAP.cxx MYSWIG_FLAGS = -noexcept -I$(srcdir)/../bases -pkgpython_PYTHON = YACSGui_Swig.py \ +salomepython_PYTHON = YACSGui_Swig.py \ yacsguiloader.py -pkgpyexec_LTLIBRARIES = _YACSGui_Swig.la +salomepyexec_LTLIBRARIES = _YACSGui_Swig.la -YACSGui_SwigWRAP.cxx:YACSGui_Swig.i YACSGui_Swig.h +YACSGui_SwigWRAP.cxx: YACSGui_Swig.i YACSGui_Swig.h $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) $(MYSWIG_FLAGS) -o $@ $< _YACSGui_Swig_la_SOURCES = \ @@ -105,20 +219,29 @@ _YACSGui_Swig_la_CXXFLAGS = \ _YACSGui_Swig_la_LDFLAGS = -module -_YACSGui_Swig_la_LIBADD = libYACSGui.la +_YACSGui_Swig_la_LIBADD = libYACS.la -libYACSGui_la_LIBADD = \ +libYACS_la_LDFLAGS = \ + @GRAPHVIZ_LDFLAGS@ \ + @GUI_LDFLAGS@ \ + @QT_MT_LDFLAGS@ + +libYACS_la_LIBADD = \ ../runtime/libYACSRuntimeSALOME.la \ ../yacsloader/libYACSloader.la \ ../prs/libYACSPrs.la \ ../lineconn2d/libLineConn2d.la \ - ../yacsorb/libYACSorb.la \ - @QT_MT_LIBS@ @GUI_LDFLAGS@ \ - -lQxGraph -lCAM -lsuit -lLightApp -lexpat -lxml2 + ../hmi/libHMI.la \ + @GRAPHVIZ_LIBADD@ @QSCINTILLA_LIBADD@ \ + @QT_MT_LIBADD@\ + -lQxGraph -lCAM -lsuit -lLightApp $(EXPAT_LIBS) $(LIBXML_LIBS) -libYACSGui_la_CXXFLAGS = \ +libYACS_la_CXXFLAGS = \ $(THREAD_DEF) \ $(PYTHON_CPPFLAGS) \ + $(OMNIORB_INCLUDES) \ + $(LIBXML_INCLUDES) \ + $(BOOST_CPPFLAGS) \ -I$(KERNEL_ROOT_DIR)/include/salome \ -I$(srcdir)/../bases \ -I$(srcdir)/../engine \ @@ -126,8 +249,14 @@ libYACSGui_la_CXXFLAGS = \ -I$(srcdir)/../yacsloader \ -I$(srcdir)/../prs \ -I$(srcdir)/../lineconn2d \ + -I$(srcdir)/../hmi \ -I../../idl \ -I../yacsorb \ - @QT_INCLUDES@ @GUI_CXXFLAGS@ @CAS_CPPFLAGS@ + @QT_INCLUDES@ @GUI_CXXFLAGS@ @CAS_CPPFLAGS@ @GRAPHVIZ_CPPFLAGS@ @QSCINTILLA_CCPFLAGS@ + +EXTRA_DIST = YACSGui_Swig.i \ + runmode.h schemapage.h containerpage.h componentpage.h inlinenodepage.h \ + servicenodepage.h forloopnodepage.h foreachloopnodepage.h whileloopnodepage.h \ + switchnodepage.h blocknodepage.h datatypepage.h datanodepage.h include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/gui/YACSGui_BlockNodePage.cxx b/src/gui/YACSGui_BlockNodePage.cxx new file mode 100644 index 000000000..166c6fe7d --- /dev/null +++ b/src/gui/YACSGui_BlockNodePage.cxx @@ -0,0 +1,698 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + +/* + Class : YACSGui_BlockNodePage + Description : Page for block node properties +*/ + +YACSGui_BlockNodePage::YACSGui_BlockNodePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : BlockNodePage( theParent, theName, theFlags ), + YACSGui_NodePage(), + myIsSelectChild(false) +{ + if ( myDirectChildrenGroupBox ) + { + myDirectChildrenGroupBox->setTitle( tr("Direct Children") ); + myDirectChildrenGroupBox->HideBtn( YACSGui_PlusMinusGrp::InsertBtn | + YACSGui_PlusMinusGrp::UpBtn | + YACSGui_PlusMinusGrp::DownBtn ); + myDirectChildrenGroupBox->EnableBtn( YACSGui_PlusMinusGrp::SelectBtn, false ); + YACSGui_Table* aTable = myDirectChildrenGroupBox->Table(); + aTable->setFixedHeight( 100 ); + aTable->setNumCols( 1 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Node name" ) ); + aTable->setCellType( -1, 0, YACSGui_Table::String ); + + myDirectChildrenGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + myDirectChildrenGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + myDirectChildrenGroupBox->Btn(YACSGui_PlusMinusGrp::SelectBtn)->setTextLabel(tr("SELECT_BTN_TOOLTIP"),true); + myDirectChildrenGroupBox->Btn(YACSGui_PlusMinusGrp::PlusBtn)->setTextLabel(tr("PLUS_BTN_TOOLTIP"),true); + myDirectChildrenGroupBox->Btn(YACSGui_PlusMinusGrp::MinusBtn)->setTextLabel(tr("MINUS_BTN_TOOLTIP"),true); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); + connect( myDirectChildrenGroupBox, SIGNAL(initSelection( const int, const int )), + this, SLOT(onInitSelection( const int, const int )) ); + connect( myDirectChildrenGroupBox->Table(), SIGNAL(itemCreated( const int, const int )), + this, SLOT(onNewItem( const int, const int )) ); + + connect( myDirectChildrenGroupBox, SIGNAL(Added( const int )), this, SLOT(onAdded( const int )) ); + connect( myDirectChildrenGroupBox, SIGNAL(Inserted( const int )), this, SLOT(onInserted( const int )) ); + connect( myDirectChildrenGroupBox, SIGNAL(MovedUp( const int )), this, SLOT(onMovedUp( const int )) ); + connect( myDirectChildrenGroupBox, SIGNAL(MovedDown( const int )), this, SLOT(onMovedDown( const int )) ); + connect( myDirectChildrenGroupBox, SIGNAL(Removed( const int )), this, SLOT(onRemoved( const int )) ); + } + + // TODO: implement presentation of the block node in collapsed mode + // temporary solution : + myCollapsedRadioButton->setEnabled(false ); +} + +YACSGui_BlockNodePage::~YACSGui_BlockNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); + + myRow2ChildMap.clear(); + myRowsOfSelectedChildren.clear(); +} + +void YACSGui_BlockNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( dynamic_cast( theSNode->getNode() ) ) + YACSGui_NodePage::setSNode( theSNode ); +} + +void YACSGui_BlockNodePage::setChild( YACS::HMI::SubjectNode* theChildNode ) +{ + if ( !theChildNode ) return; + + if ( !myDirectChildrenGroupBox ) return; + YACSGui_Table* aTable = myDirectChildrenGroupBox->Table(); + + myIsSelectChild = false; + myDirectChildrenGroupBox->setOffSelect(); + myDirectChildrenGroupBox->EnableBtn( YACSGui_PlusMinusGrp::SelectBtn, false ); + + // sets the child node name into tables cell + QStringList aChildNames; + aTable->strings( 0, aChildNames ); + aChildNames[aTable->currentRow()] = theChildNode->getNode()->getName(); + aTable->setStrings( 0, aChildNames ); + + // add theChildNode into the map of children of this block node + if ( myRow2ChildMap.find(aTable->currentRow()) == myRow2ChildMap.end() ) + myRow2ChildMap.insert( std::make_pair( aTable->currentRow(), theChildNode ) ); + else + myRow2ChildMap[aTable->currentRow()] = theChildNode; + + bool anExist = false; + std::list::iterator it = myRowsOfSelectedChildren.begin(); + for ( ; it != myRowsOfSelectedChildren.end(); it++ ) + if ( *it == aTable->currentRow() ) + { + anExist = true; + break; + } + if ( !anExist ) + myRowsOfSelectedChildren.push_back( aTable->currentRow() ); +} + +bool YACSGui_BlockNodePage::isSelectChild() const +{ + return myIsSelectChild; +} + +void YACSGui_BlockNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + myNodeName->setReadOnly(false); + + myDirectChildrenGroupBox->ShowBtn( YACSGui_PlusMinusGrp::SelectBtn | + YACSGui_PlusMinusGrp::PlusBtn | + YACSGui_PlusMinusGrp::MinusBtn ); + YACSGui_Table* aTable = myDirectChildrenGroupBox->Table(); + aTable->setReadOnly( -1, 0, false ); + + ViewModeButtonGroup->show(); + + ExecutionGroupBox->hide(); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + myNodeName->setReadOnly(true); + + myDirectChildrenGroupBox->HideBtn(); + YACSGui_Table* aTable = myDirectChildrenGroupBox->Table(); + aTable->setReadOnly( -1, 0, true ); + + ViewModeButtonGroup->hide(); + + ExecutionGroupBox->show(); + } +} + +void YACSGui_BlockNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_BlockNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_BlockNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + DEBTRACE("==> BlockNodePage : Size of theInPortName2Value : " << theInPortName2Value.size()); +} + +void YACSGui_BlockNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + DEBTRACE("==> BlockNodePage : Size of theOutPortName2Value : " << theOutPortName2Value.size()); +} + +void YACSGui_BlockNodePage::notifyNodeCreateNode( YACS::HMI::Subject* theSubject ) +{ + updateState(); +} + +void YACSGui_BlockNodePage::checkModifications() +{ + if ( !getNode() ) return; + + Bloc* aBloc = dynamic_cast(getNode()); + if ( !aBloc ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + + if ( myNodeName->text().compare(getNodeName()) != 0 ) isModified = true; + else + { + // check child nodes + YACSGui_Table* aTable = myDirectChildrenGroupBox->Table(); + if ( !aTable ) return; + + QStringList aChildNames; + aTable->strings( 0, aChildNames ); + + list aChildren = aBloc->edGetDirectDescendants(); + + if ( aChildNames.count() != aChildren.size() ) isModified = true; + else + { + int aRowId = 0; + for ( QStringList::Iterator it = aChildNames.begin(); it != aChildNames.end(); ++it ) + { + Node* aChild = 0; + if ( SubjectNode* aSChild = myRow2ChildMap[aRowId] ) + aChild = aSChild->getNode(); + + bool isContains = false; + for (list::iterator itn = aChildren.begin(); itn != aChildren.end(); ++itn) + if (aChild == (*itn)) + { + isContains = true; + break; + } + if (!isContains) + { + isModified = true; + break; + } + + aRowId++; + } + } + } + + //if ( !isModified ) + // TODO: compare view mode: expanded or collapsed (not yet in use) + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::InlineNodeId); + } +} + +void YACSGui_BlockNodePage::onApply() +{ + // Rename a node + if ( myNodeName && getNode() ) + getNode()->setName( myNodeName->text().latin1() ); + + // To remove a new child nodes from its old places in the tree view + std::list::iterator it = myRowsOfSelectedChildren.begin(); + for ( ; it != myRowsOfSelectedChildren.end(); it++ ) + { + SubjectNode* aNewSelectedChild = myRow2ChildMap[*it]; + if( !aNewSelectedChild ) + continue; + Node* aNode = aNewSelectedChild->getNode(); + try { + getNode()->getChildByName( aNode->getName() ); + } + catch (YACS::Exception& ex) { + // block is not contain nodes with the same name as aNode + // get schema engine object + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( !aProc ) return; + // get gui graph + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + aNewSelectedChild->getParent()->detach(aGraph); // to remove only a node view item in the tree, node presentation is still alive + + aNewSelectedChild->getParent()->update( REMOVE, + ProcInvoc::getTypeOfNode( aNewSelectedChild->getNode() ), + aNewSelectedChild ); + + aNewSelectedChild->getParent()->attach(aGraph); // to remove only a node view item in the tree, node presentation is still alive + } + } + + // Reset the list of direct children + setDirectChildren(); + + // Reset the view mode + // ... + + mySNode->update( EDIT, 0, mySNode ); + + // clear for next selections + myRowsOfSelectedChildren.clear(); + + updateBlocSize(); +} + +void YACSGui_BlockNodePage::updateState() +{ + myRow2ChildMap.clear(); + myRowsOfSelectedChildren.clear(); + + // Clear input ports table and output ports tables, if they are not empty + if ( myDirectChildrenGroupBox ) { + myDirectChildrenGroupBox->Table()->setNumRows( 0 ); + myDirectChildrenGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Fill the table of child nodes of the block + SubjectBloc* aSNode = dynamic_cast(mySNode); + if ( aSNode && dynamic_cast(getNode()) && myDirectChildrenGroupBox ) + { + QStringList aChildNames; + + list aChildren = dynamic_cast(getNode())->edGetDirectDescendants(); + list::iterator aChildIt = aChildren.begin(); + int aRow = 0; + for( ;aChildIt!=aChildren.end();aChildIt++) + { + // Collect child names in the list + aChildNames.append( (*aChildIt)->getName() ); + if ( myRow2ChildMap.find(aRow) == myRow2ChildMap.end() ) + myRow2ChildMap.insert( std::make_pair( aRow, aSNode->getChild(*aChildIt) ) ); + else + myRow2ChildMap[aRow] = aSNode->getChild(*aChildIt); + aRow++; + } + + // Fill "Node name" column + myDirectChildrenGroupBox->Table()->setStrings( 0, aChildNames, true ); + + if ( !aChildNames.empty() ) myDirectChildrenGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + + // Set view mode of the given block node + // the following method can be used if its needed: + // YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( myProc ); + // ... +} + +void YACSGui_BlockNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + +void YACSGui_BlockNodePage::onInitSelection( const int theRow, const int theCol ) +{ + myIsSelectChild = true; +} + +void YACSGui_BlockNodePage::onNewItem( const int theRow, const int theCol ) +{ + if ( myDirectChildrenGroupBox ) + myDirectChildrenGroupBox->Table()->setReadOnly( theRow, theCol, true ); +} + +void YACSGui_BlockNodePage::onAdded( const int theRow ) +{ + SubjectNode* aNode = 0; + myRow2ChildMap.insert( std::make_pair( theRow, aNode ) ); +} + +void YACSGui_BlockNodePage::onInserted( const int theRow ) +{ + SubjectNode* aNode = 0; + + if ( myRow2ChildMap.find(theRow) == myRow2ChildMap.end() ) + myRow2ChildMap.insert( std::make_pair( theRow, aNode ) ); + else + { + SubjectNode* aStartNodeToMoveDown = myRow2ChildMap[theRow]; + myRow2ChildMap[theRow] = aNode; + + for ( int aRow = myRow2ChildMap.size()-1; aRow > theRow+1; aRow-- ) + myRow2ChildMap[aRow] = myRow2ChildMap[aRow-1]; + + myRow2ChildMap[theRow+1] = aStartNodeToMoveDown; + } +} + +void YACSGui_BlockNodePage::onMovedUp( const int theUpRow ) +{ + SubjectNode* aNodeToMoveDown = myRow2ChildMap[theUpRow]; + SubjectNode* aNodeToMoveUp = myRow2ChildMap[theUpRow+1]; + + myRow2ChildMap[theUpRow] = aNodeToMoveUp; + myRow2ChildMap[theUpRow+1] = aNodeToMoveDown; + +} + +void YACSGui_BlockNodePage::onMovedDown( const int theDownRow ) +{ + SubjectNode* aNodeToMoveUp = myRow2ChildMap[theDownRow]; + SubjectNode* aNodeToMoveDown = myRow2ChildMap[theDownRow-1]; + + myRow2ChildMap[theDownRow] = aNodeToMoveDown; + myRow2ChildMap[theDownRow-1] = aNodeToMoveUp; +} + +void YACSGui_BlockNodePage::onRemoved( const int theRow ) +{ + /* + SubjectNode* aSNodeToRaise = myRow2ChildMap[theRow]; + Node* aNodeToRaise = aSNodeToRaise->getNode(); + + Bloc* aBloc = dynamic_cast( getNode() ); + if ( !aBloc ) return; + + // remove aNodeToRaise node from the children list (if it is present in it) + set aChildren = aBloc->edGetDirectDescendants(); + set::iterator aChildIter = aChildren.begin(); + for( ;aChildIter!=aChildren.end();aChildIter++) + { + if ( *aChildIter == aNodeToRaise ) + { + // get schema engine object + Proc* aProc = dynamic_cast(aBloc->getRootNode()); + if ( !aProc ) return; + + // get schema subject + //YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + //if ( !aGraph ) return; + //SubjectProc* aSProc = aGraph->getContext()->getSubjectProc(); + SubjectProc* aSProc = GuiContext::getCurrent()->getSubjectProc() + if ( !aSProc ) return; + + aBloc->edRemoveChild(aNodeToRaise); + + try { + aProc->edAddChild(aNodeToRaise); // raise the removed child to the Proc level + aSNodeToRaise->reparent(aSProc); + } + catch (YACS::Exception& ex) { + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString(ex.what())+QString("\nThe child node will be deleted. Do you want to continue?"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 1) == 0 ) + { + // delete the old child node + if ( YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ) ) + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(aNodeToRaise) ) + { + anItem->hide(); + aGraph->removeItem(anItem); + delete anItem; + } + //aNodeToRaise = 0; + delete aNodeToRaise; + } + else + { + aBloc->edAddChild(aNodeToRaise); + return; + } + } + break; + } + } + */ + + if ( theRow == myRow2ChildMap.size()-1 ) + myRow2ChildMap.erase(theRow); + else + { + for ( int aRow = theRow; aRow < myRow2ChildMap.size()-1; aRow++ ) + myRow2ChildMap[aRow] = myRow2ChildMap[aRow+1]; + myRow2ChildMap.erase(myRow2ChildMap.size()-1); + } +} + +void YACSGui_BlockNodePage::setDirectChildren() +{ + if ( !myDirectChildrenGroupBox ) return; + + SubjectBloc* aSNode = dynamic_cast(mySNode); + if ( !aSNode ) return; + + Bloc* aBloc = dynamic_cast( getNode() ); + if ( !aBloc ) return; + + // get schema engine object + Proc* aProc = dynamic_cast(aBloc->getRootNode()); + if ( !aProc ) return; + + // get schema subject + SubjectProc* aSProc = GuiContext::getCurrent()->getSubjectProc(); + if ( !aSProc ) return; + + // get gui graph + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + // remove old children + Node* aRemovedOldChild; + list aChildren = aBloc->edGetDirectDescendants(); + list::iterator aChildIter = aChildren.begin(); + for( ;aChildIter!=aChildren.end();aChildIter++) + { + bool isNeedToRemove = true; + map::iterator aChildIt = myRow2ChildMap.begin(); + for( ;aChildIt!=myRow2ChildMap.end();aChildIt++) + if ( (*aChildIt).second->getNode() == (*aChildIter) ) + { + isNeedToRemove = false; + break; + } + if ( !isNeedToRemove ) continue; + + aBloc->edRemoveChild(*aChildIter); // the _father of the removed node will be 0 + aRemovedOldChild = *aChildIter; + SubjectNode* aSChild = aSNode->getChild(*aChildIter); + + try { + aProc->edAddChild(*aChildIter); // raise the removed child to the Proc level + aSChild->reparent(aSProc); + } + catch (YACS::Exception& ex) + { + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString(ex.what())+QString("\nThe child node will be deleted. Do you want to continue?"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 1) == 0 ) + { + // delete the old child node + // 1) delete corresponding tree view item + aSNode->update(REMOVE, ProcInvoc::getTypeOfNode( aSChild->getNode() ), aSChild); + // 2) delete 2D presentation + aGraph->removeNode( aSChild->getNode() ); + // 3) delete corresponding subject + aSNode->destroy(aSChild); + } + else + { + aBloc->edAddChild(aRemovedOldChild); + updateState(); + return; + } + } + } + + // read new children nodes from the table + YACSGui_Table* aTable = myDirectChildrenGroupBox->Table(); + + QStringList aChildNames; + aTable->strings( 0, aChildNames ); + + bool isNeedToUpdate = false; + map::iterator aChildIt = myRow2ChildMap.begin(); + for( ;aChildIt!=myRow2ChildMap.end();aChildIt++) + { + SubjectNode* aSChild = (*aChildIt).second; + if( !aSChild ) + continue; + Node* aChild = aSChild->getNode(); + if ( aChildNames.find( QString(aChild->getName()) ) != aChildNames.end() ) + { + if ( Bloc* aFather = dynamic_cast(aChild->getFather()) ) + { + aFather->edRemoveChild(aChild); + + try { + aBloc->edAddChild(aChild); + aSChild->reparent(mySNode); + } + catch (YACS::Exception& ex) + { + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString(ex.what())+QString("\nRename, please, a new child node and try to add it into the block once more."), + tr("BUT_OK")); + + aFather->edAddChild(aChild); + isNeedToUpdate = true; + } + } + } + } + + if ( isNeedToUpdate ) updateState(); + + // update the block node presentation + aGraph->update( aBloc, dynamic_cast( getSNode()->getParent() ) ); +} diff --git a/src/gui/YACSGui_ComponentPage.cxx b/src/gui/YACSGui_ComponentPage.cxx new file mode 100644 index 000000000..51663ae91 --- /dev/null +++ b/src/gui/YACSGui_ComponentPage.cxx @@ -0,0 +1,394 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_ComponentPage + Description : Page for component properties +*/ + +YACSGui_ComponentPage::YACSGui_ComponentPage( QWidget* theParent, const char* theName, WFlags theFlags ) + : ComponentPage( theParent, theName, theFlags ), + GuiObserver(), + mySComponent( 0 ), + myType( SALOME ), + myEditComp(true) +{ + connect( myContainerName, SIGNAL( activated( const QString& ) ), + this, SLOT( onContainerChanged( const QString& ) ) ); +} + +YACSGui_ComponentPage::~YACSGui_ComponentPage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); + + if ( mySComponent ) mySComponent->detach(this); +} + +void YACSGui_ComponentPage::select( bool isSelected ) +{ + DEBTRACE(">> YACSGui_ComponentPage::select"); +} + +void YACSGui_ComponentPage::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSGui_ComponentPage::update"); + switch (event) + { + case REMOVE: + { + if ( !type && !son && mySComponent ) + { + mySComponent->detach(this); + mySComponent = 0; + } + } + break; + default: + GuiObserver::update(event, type, son); + } +} + +YACSGui_InputPanel* YACSGui_ComponentPage::getInputPanel() const +{ + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( !anApp ) + return 0; + + YACSGui_Module* aModule = dynamic_cast( anApp->activeModule() ); + if( !aModule ) + return 0; + + return aModule->getInputPanel(); +} + +void YACSGui_ComponentPage::setSComponent( YACS::HMI::SubjectComponent* theSComponent, bool isEdit ) +{ + if( mySComponent != theSComponent) + { + if ( mySComponent ) mySComponent->detach(this); // detach from old component + mySComponent = theSComponent; + if ( mySComponent ) + { + mySComponent->attach(this); // attach to new component + + if ( getComponent() && getComponent()->getKind() != CORBAComponent::KIND ) + { + YACSGui_ContainerPage* aContPage = + dynamic_cast( getInputPanel()->getPage( YACSGui_InputPanel::ContainerId ) ); + if ( aContPage ) + aContPage->setSContainer( GuiContext::getCurrent()->_mapOfSubjectContainer[getComponent()->getContainer()] ); + } + } + } + myEditComp = isEdit; + updateState(); +} + +YACS::ENGINE::ComponentInstance* YACSGui_ComponentPage::getComponent() const +{ + return ( mySComponent ? mySComponent->getComponent() : 0 ); +} + +QString YACSGui_ComponentPage::getComponentName() const +{ + return ( mySComponent ? QString( mySComponent->getComponent()->getCompoName() ) : QString("") ); +} + +QString YACSGui_ComponentPage::getInstanceName() const +{ + return ( mySComponent ? QString( mySComponent->getComponent()->getInstanceName() ) : QString("") ); +} + +void YACSGui_ComponentPage::setComponentType() +{ + if ( !getComponent() || !myComponentType ) return; + + if ( getComponent()->getKind() == SalomeComponent::KIND ) + { + myComponentType->setText("SALOME"); + myType = SALOME; + } + else if ( getComponent()->getKind() == SalomePythonComponent::KIND ) + { + myComponentType->setText("SALOME Python"); + myType = SALOMEPython; + } + else if ( getComponent()->getKind() == CppComponent::KIND ) + { + myComponentType->setText("CPP"); + myType = CPP; + } + else if ( getComponent()->getKind() == CORBAComponent::KIND ) + { + myComponentType->setText("CORBA"); + myType = CORBA; + } +} + +YACSGui_ComponentPage::ComponentType YACSGui_ComponentPage::getComponentType() const +{ + return myType; +} + +QString YACSGui_ComponentPage::getContainerName() const +{ + QString aName; + + if ( !getComponent() ) return aName; + + if ( Container* aCont = getComponent()->getContainer() ) + aName = QString(aCont->getName()); + + return aName; +} + +void YACSGui_ComponentPage::setContainer() +{ + if ( !getComponent() ) return; + + QString aText = myContainerName->currentText(); + if ( aText.isEmpty() ) return; + + string aContName( aText.latin1() ); + + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( !aProc ) return; + + if ( aProc->containerMap.count(aContName) ) + if ( Container* aCont = aProc->containerMap[aContName] ) + getComponent()->setContainer(aCont); +} + +void YACSGui_ComponentPage::checkModifications( bool& theWarnToShow, bool& theToApply ) +{ + if ( !getComponent() || !theWarnToShow && !theToApply ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + if (myContainerName->currentText().compare(getContainerName()) != 0 ) isModified = true; + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( theWarnToShow ) + { + theWarnToShow = false; + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + theToApply = true; + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ComponentId); + } + else + theToApply = false; + } + else if ( theToApply ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ComponentId); + } +} + +void YACSGui_ComponentPage::onApply() +{ + setContainer(); + + if ( mySComponent ) { + mySComponent->update( EDIT, 0, mySComponent ); + YACSGui_EditionTreeView * aETV = + dynamic_cast(getInputPanel()->getModule()->activeTreeView()); + if(!aETV) return; + if(aETV->getSelected().empty()) return; + if ( YACSGui_ComponentViewItem* aComp = dynamic_cast(aETV->getSelected().front()) ) { + if ( aComp->getSComponent() == mySComponent ) { + QListViewItem* aChild = aComp->firstChild(); + while( aChild ){ + if(YACSGui_ReferenceViewItem* aRef = dynamic_cast(aChild)) { + SubjectServiceNode* aSSNode = dynamic_cast(aRef->getSReference()->getParent()); + ServiceNode* sNode = dynamic_cast(aSSNode->getNode()); + if(aSSNode && sNode) { + YACSGui_InputPanel* anIP = getInputPanel(); + YACSGui_ServiceNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ServiceNodeId ) ); + if( aSNPage ) { + if ( !dynamic_cast(sNode) ) { + YACSGui_ContainerPage* aContPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ContainerId ) ); + if ( aContPage ) { + SubjectContainer* aCont = 0; + if ( mySComponent->getComponent()->getContainer() ) + aCont = GuiContext::getCurrent()->_mapOfSubjectContainer[mySComponent->getComponent()->getContainer()]; + aContPage->setSContainer(aCont); + anIP->setOn( false, YACSGui_InputPanel::ContainerId ); + } + } + + aSNPage->setSNode( aSSNode ); + anIP->setOn( true, YACSGui_InputPanel::ServiceNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::ServiceNodeId ); + aSNPage->setComponent(mySComponent->getComponent()); + aSNPage->onApply(); + } + } + } + aChild = aChild->nextSibling(); + } + } + } + } +} + +void YACSGui_ComponentPage::fillContainerNames() +{ + myContainerName->clear(); + + if ( myType == CORBA ) + myContainerName->setEnabled(false); + else + myContainerName->setEnabled(true); + + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( !aProc ) return; + + for ( map::iterator it = aProc->containerMap.begin(); it != aProc->containerMap.end(); it++ ) + myContainerName->insertItem( (*it).first ); +} + +void YACSGui_ComponentPage::updateState() +{ + myComponentName->setText( getComponentName() ); + myComponentName->setReadOnly(true); + + myInstanceName->setText( getInstanceName() ); + myInstanceName->setReadOnly(true); + + // Set component type + setComponentType(); + + // Set container + fillContainerNames(); + myContainerName->setCurrentText( getContainerName() ); +} + +void YACSGui_ComponentPage::onContainerChanged( const QString& theContainerName ) +{ + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( !aProc ) return; + + std::string aName = theContainerName.latin1(); + Container* aContainer = aProc->containerMap[ aName ]; + + if ( getComponent() && getComponent()->getKind() != CORBAComponent::KIND ) + { + YACSGui_ContainerPage* aContPage = + dynamic_cast( getInputPanel()->getPage( YACSGui_InputPanel::ContainerId ) ); + if ( aContPage && aContPage->isVisible() ) + aContPage->setSContainer( GuiContext::getCurrent()->_mapOfSubjectContainer[aContainer] ); + } +} diff --git a/src/gui/YACSGui_ContainerPage.cxx b/src/gui/YACSGui_ContainerPage.cxx new file mode 100644 index 000000000..9e8bbb8cd --- /dev/null +++ b/src/gui/YACSGui_ContainerPage.cxx @@ -0,0 +1,559 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_ContainerPage + Description : Page for container properties +*/ + +YACSGui_ContainerPage::YACSGui_ContainerPage( QWidget* theParent, const char* theName, WFlags theFlags ) + : ContainerPage( theParent, theName, theFlags ), + GuiObserver(), + mySContainer( 0 ) +{ + showAdvanced->setChecked(false); + onShowAdvanced(); + connect(showAdvanced, SIGNAL(clicked()), this, SLOT(onShowAdvanced())); +} + +YACSGui_ContainerPage::~YACSGui_ContainerPage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); + + if ( mySContainer ) mySContainer->detach(this); +} + +void YACSGui_ContainerPage::select( bool isSelected ) +{ + DEBTRACE(">> YACSGui_ContainerPage::select"); +} + +void YACSGui_ContainerPage::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSGui_ContainerPage::update"); + switch (event) + { + case REMOVE: + { + if ( !type && !son && mySContainer ) + { + mySContainer->detach(this); + mySContainer = 0; + } + } + break; + default: + GuiObserver::update(event, type, son); + } +} + +void YACSGui_ContainerPage::setSContainer(YACS::HMI::SubjectContainer* theSContainer ) +{ + if ( mySContainer != theSContainer ) + { + if ( mySContainer ) mySContainer->detach(this); //detach from old container + mySContainer = theSContainer; + if ( mySContainer ) mySContainer->attach(this); // attach to new container + + fillHostNames(); + updateState(); + } + + if ( theSContainer ) + { + // set "Container Name" fields to read only if the user is editing a service node + ServiceNode* aService = 0; + if ( YACSGui_EditionTreeView * aETV = + dynamic_cast(getInputPanel()->getModule()->activeTreeView()) ) + { + std::list aList = aETV->getSelected(); + if (!aList.empty()) + if ( YACSGui_NodeViewItem* aNode = dynamic_cast(aList.front()) ) + aService = dynamic_cast(aNode->getNode()); + } + + if ( aService ) + { + myDefinitionName->setReadOnly(true); + myExecutionName->setReadOnly(true); + } + else + { + myDefinitionName->setReadOnly(false); + myExecutionName->setReadOnly(false); + } + } +} + +YACS::ENGINE::Container* YACSGui_ContainerPage::getContainer() const +{ + return ( mySContainer ? mySContainer->getContainer() : 0 ); +} + +YACS::ENGINE::SalomeContainer* YACSGui_ContainerPage::getSalomeContainer() const +{ + return ( mySContainer ? dynamic_cast(mySContainer->getContainer()) : 0 ); +} + +QString YACSGui_ContainerPage::getDefinitionName() const +{ + return ( mySContainer ? QString( mySContainer->getName() ) : QString("") ); +} + +bool YACSGui_ContainerPage::setDefinitionName( const QString& theName ) +{ + DEBTRACE("YACSGui_ContainerPage::setDefinitionName " << theName.latin1()); + // --- TODO: create a command in hmi for container rename. + bool ret = false; + bool alreadyExists = false; + GuiContext* aContext = GuiContext::getCurrent(); + if ( getContainer() ) + { + map::const_iterator it; + for(it = aContext->_mapOfSubjectContainer.begin(); it !=aContext->_mapOfSubjectContainer.end(); ++it) + { + if ( QString::compare(theName, (*it).first->getName().c_str()) == 0) + { + alreadyExists =true; + break; + } + } + } + if (!alreadyExists) + { + DEBTRACE("set name " << theName.latin1()); + string oldName = getContainer()->getName(); + getContainer()->setName( theName.latin1() ); + aContext->getProc()->containerMap.erase(oldName); + aContext->getProc()->containerMap[theName.latin1()] = getContainer(); + + mySContainer->update( RENAME, 0, mySContainer ); + ret = true; + } + return ret; +} + +QString YACSGui_ContainerPage::getExecutionName() const +{ + QString name = ""; + if (getSalomeContainer()) + { + string nc = getSalomeContainer()->getProperty("container_name"); + name = nc.c_str(); + } + return name; +} + +void YACSGui_ContainerPage::setExecutionName( const QString& theName ) +{ + if ( getSalomeContainer() ) + { + getSalomeContainer()->setProperty( "container_name", theName.latin1() ); + mySContainer->update( RENAME, 0, mySContainer ); + } +} + +YACSGui_InputPanel* YACSGui_ContainerPage::getInputPanel() const +{ + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( !anApp ) + return 0; + + YACSGui_Module* aModule = dynamic_cast( anApp->activeModule() ); + if( !aModule ) + return 0; + + return aModule->getInputPanel(); +} + +void YACSGui_ContainerPage::fillHostNames() const +{ + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + SALOME_NamingService* namingService = anApp->namingService(); + + CORBA::Object_var obj = namingService->Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS); + if ( !CORBA::is_nil(obj) ) + if ( Engines::ResourcesManager_var aResManager=Engines::ResourcesManager::_narrow(obj) ) + { + Engines::CompoList aCompoList ; + Engines::MachineParameters params; + anApp->lcc()->preSet(params); + + Engines::MachineList* aMachineList = aResManager->GetFittingResources( params, aCompoList ); + + myHostName->clear(); + myHostName->insertItem( QString("localhost") ); + for ( unsigned int i = 0; i < aMachineList->length(); i++ ) + { + const char* aMachine = (*aMachineList)[i]; + myHostName->insertItem( QString(aMachine) ); + } + } +} + +QString YACSGui_ContainerPage::getHostName() const +{ + if ( getSalomeContainer() ) + { + QString aHN(getSalomeContainer()->_params.hostname); + return aHN; + } + else + return QString(""); +} + +void YACSGui_ContainerPage::setHostName( const QString& theHostName ) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "hostname", theHostName.latin1() ); +} + +int YACSGui_ContainerPage::getMemMb() const +{ + return ( getSalomeContainer() ? getSalomeContainer()->_params.mem_mb : 0 ); +} + +void YACSGui_ContainerPage::setMemMb(const int theMem) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "mem_mb", QString("%1").arg(theMem).latin1() ); +} + +int YACSGui_ContainerPage::getCpuClock() const +{ + return ( getSalomeContainer() ? getSalomeContainer()->_params.cpu_clock : 0 ); +} + +void YACSGui_ContainerPage::setCpuClock(const int theClock) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "cpu_clock", QString("%1").arg(theClock).latin1() ); +} + +int YACSGui_ContainerPage::getNbProcPerNode() const +{ + return ( getSalomeContainer() ? getSalomeContainer()->_params.nb_proc_per_node : 0 ); +} + +void YACSGui_ContainerPage::setNbProcPerNode(const int theNbProc) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "nb_proc_per_node", QString("%1").arg(theNbProc).latin1() ); +} + +int YACSGui_ContainerPage::getNbNode() const +{ + return ( getSalomeContainer() ? getSalomeContainer()->_params.nb_node : 0 ); +} + +void YACSGui_ContainerPage::setNbNode(const int theNbNode) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "nb_node", QString("%1").arg(theNbNode).latin1() ); +} + +bool YACSGui_ContainerPage::getMpiUsage() const +{ + return ( getSalomeContainer() ? getSalomeContainer()->_params.isMPI : false ); +} + +void YACSGui_ContainerPage::setMpiUsage(const bool on) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "isMPI", on ? "true" : "false" ); +} + +QString YACSGui_ContainerPage::getParallelLib() const +{ + return ( getSalomeContainer() ? QString(getSalomeContainer()->_params.parallelLib) : QString("") ); +} + +void YACSGui_ContainerPage::setParallelLib( const QString& theLib) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "parallelLib", theLib.latin1() ); +} + +int YACSGui_ContainerPage::getNbComponentNodes() const +{ + return ( getSalomeContainer() ? getSalomeContainer()->_params.nb_component_nodes : 0 ); +} + +void YACSGui_ContainerPage::setNbComponentNodes(const int theNbComponentNodes) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "nb_component_nodes", QString("%1").arg(theNbComponentNodes).latin1() ); +} + +QString YACSGui_ContainerPage::getWorkingDir() const +{ + return ( getSalomeContainer() ? QString(getSalomeContainer()->_params.workingdir) : QString("") ); +} + +void YACSGui_ContainerPage::setWorkingDir( const QString& theWD) +{ + if ( getSalomeContainer() ) + getSalomeContainer()->setProperty( "workingdir", theWD.latin1() ); +} + +void YACSGui_ContainerPage::checkModifications( bool& theWarnToShow, bool& theToApply ) +{ + if ( !getContainer() || !theWarnToShow && !theToApply ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + if ( myDefinitionName->text().compare(getDefinitionName()) != 0 + || + myExecutionName->text().compare(getExecutionName()) != 0 + || + myHostName->currentText().compare(getHostName()) != 0 + || + myMemMb->value() != getMemMb() + || + myCpuClock->value() != getCpuClock() + || + myNbProcPerNode->value() != getNbProcPerNode() + || + myNbNode->value() != getNbNode() + || + ( myMpiUsage->currentItem() ? false : true ) != getMpiUsage() + || + myParallelLib->text().compare(getParallelLib()) != 0 + || + myNbComponentNodes->value() != getNbComponentNodes() + || + myWorkingDir->text().compare(getWorkingDir()) != 0 + ) isModified = true; + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( theWarnToShow ) + { + theWarnToShow = false; + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + theToApply = true; + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ContainerId); + } + else + theToApply = false; + } + else if ( theToApply ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ContainerId); + } +} + +void YACSGui_ContainerPage::onShowAdvanced() +{ + if(showAdvanced->isChecked()) { + groupBoxAdv->show(); + } else { + groupBoxAdv->hide(); + } +} + +void YACSGui_ContainerPage::updateState() +{ + // Set container name + + if ( myDefinitionName ) + { + QString defName = getDefinitionName(); + if (QString::compare(defName, "DefaultContainer") == 0) + myDefinitionName->setReadOnly(true); + else + myDefinitionName->setReadOnly(false); + myDefinitionName->setText(defName); + + } + + if ( myExecutionName ) + myExecutionName->setText(getExecutionName()); + + // Set host name + if ( myHostName ) + myHostName->setCurrentText(getHostName()); + + // Set mem_mb + if ( myMemMb ) + myMemMb->setValue(getMemMb()); + + // Set cpu_clock + if ( myCpuClock ) + myCpuClock->setValue(getCpuClock()); + + // Set nb_proc_per_node + if ( myNbProcPerNode ) + myNbProcPerNode->setValue(getNbProcPerNode()); + + // Set nb_node + if ( myNbNode ) + myNbNode->setValue(getNbNode()); + + // Set MPI usage + if ( myMpiUsage ) + myMpiUsage->setCurrentItem( getMpiUsage() ? 0 : 1 ); + + // Set parallel library + if ( myParallelLib ) + myParallelLib->setText(getParallelLib()); + + // Set nb_component_nodes + if ( myNbComponentNodes ) + myNbComponentNodes->setValue(getNbComponentNodes()); + + // Set working directory + if ( myWorkingDir ) + myWorkingDir->setText(getWorkingDir()); + +} + +void YACSGui_ContainerPage::onApply() +{ + if ( myDefinitionName ) + if (! setDefinitionName(myDefinitionName->text().latin1())) + if (getContainer()) myDefinitionName->setText(getContainer()->getName()); + + if ( myExecutionName ) + setExecutionName(myExecutionName->text().latin1()); + + if ( myHostName ) + setHostName(myHostName->currentText().latin1()); + + if ( myMemMb ) + setMemMb(myMemMb->value()); + + if ( myCpuClock ) + setCpuClock(myCpuClock->value()); + + if ( myNbProcPerNode ) + setNbProcPerNode(myNbProcPerNode->value()); + + if ( myNbNode ) + setNbNode(myNbNode->value()); + + if ( myMpiUsage ) + setMpiUsage( myMpiUsage->currentItem() ? false : true ); + + if ( myParallelLib ) + setParallelLib(myParallelLib->text().latin1()); + + if ( myNbComponentNodes ) + setNbComponentNodes(myNbComponentNodes->value()); + + if ( myWorkingDir ) + setWorkingDir(myWorkingDir->text().latin1()); + + //mySContainer->update( EDIT, 0, mySContainer ); +} + diff --git a/src/gui/YACSGui_DataModel.cxx b/src/gui/YACSGui_DataModel.cxx index 1b62b494d..9fd061321 100644 --- a/src/gui/YACSGui_DataModel.cxx +++ b/src/gui/YACSGui_DataModel.cxx @@ -20,19 +20,73 @@ #include #include +#include +#include #include #include +#include #include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" using namespace YACS::ENGINE; +using namespace YACS::HMI; + +/*! + Method for conversion enum value to string value +*/ +QString YACSGui_DataModel::Type2Str( YACSGui_DataModel::ObjectType type ) +{ + switch( type ) + { + case SchemaObject: + return "SchemaObject"; + case RunObject: + return "RunObject"; + } + return "UnknownObject"; +} + +YACSGui_DataModel::ObjectType YACSGui_DataModel::Str2Type( const QString& name) +{ + if ( name == "SchemaObject") + return SchemaObject; + else if ( name == "RunObject") + return RunObject; + + return UnknownObject; +} /*! Constructor */ YACSGui_DataModel::YACSGui_DataModel( CAM_Module* theModule ) : - LightApp_DataModel(theModule) + SalomeApp_DataModel(theModule) { } @@ -43,57 +97,300 @@ YACSGui_DataModel::~YACSGui_DataModel() { } +bool YACSGui_DataModel::open( const QString& theFileName, CAM_Study* theStudy, QStringList theListOfFiles) +{ + SalomeApp_DataModel::open( theFileName, theStudy, theListOfFiles ); -/*! - Add item to the map of procs -*/ -void YACSGui_DataModel::add(Proc* theProc, bool isEditable) + // create Proc* objects for all schema (and schema run), published in the Object Browser + YACSGui_Module* aModule = dynamic_cast( module() ); + if ( aModule ) + { + // get a list of all schemas + DataObjectList objlist = root()->children( true ); + + for ( DataObjectListIterator it( objlist ); it.current(); ++it ) + { + SalomeApp_DataObject* obj = dynamic_cast( it.current() ); + + if ( obj && aModule && aModule->getApp()->checkDataObject(obj) && + ( objectType( obj->entry() ) == YACSGui_DataModel::SchemaObject /*|| + objectType( obj->entry() ) == YACSGui_DataModel::RunObject*/ ) ) + { + _PTR(SObject) sobj = obj->object(); + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + _PTR(AttributeParameter) aType; + if ( sobj->FindAttribute( anAttr, "AttributeParameter" ) ) + { + aType = _PTR(AttributeParameter) ( anAttr ); + QString aSchemaFileName( aType->GetString("FilePath") ); + DEBTRACE(">> DataModel : open : FilePath = " << aSchemaFileName.latin1()); + + YACSGui_Loader aLoader; + GuiContext* aCProc = 0; + + try + { + Proc* aProc = 0; + + if (!aSchemaFileName.isEmpty()) + aProc = aLoader.load(aSchemaFileName); + + if (!aProc) + { + SUIT_MessageBox::error1(aModule->getApp()->desktop(), + tr("ERROR"), + tr("MSG_OPEN_STUDY_ERROR").arg(aSchemaFileName.latin1()), + tr("BUT_OK")); + return 0; + } + + aProc->setName( QFileInfo(aSchemaFileName).baseName() ); + myObjectProcMap.insert( std::make_pair( sobj->GetID(), aProc ) ); + + // create GuiContext for Proc* + aCProc = new GuiContext(); + GuiContext::setCurrent( aCProc ); + aCProc->setProc( aProc ); + aCProc->setXMLSchema( aSchemaFileName.latin1() ); + } + catch (YACS::Exception& ex) + { + DEBTRACE("YACSGui_DataModel::open: " <NewChildIterator(theParent); + it->InitEx(true); + while( it->More() ) + { + _PTR(SObject) child = it->Value(); + if ( child->FindAttribute(anAttr, "AttributeName") ) + { + aName = _PTR(AttributeName) ( anAttr ); + QString name ( aName->Value() ); + if (name.length() > thePattern.length()) + { + if ( name.left( thePattern.length() ) == thePattern ) + { + bool ok = true; + int loc_index = name.right( name.length()- thePattern.length() ).toInt( &ok ); + if ( ok && index < loc_index) + index = loc_index; + } + } + } + it->Next(); + } + index++; + result = thePattern + QString().setNum(index); + } + + return result; } -/*! - Builds tree. -*/ -void YACSGui_DataModel::build() +void YACSGui_DataModel::createNewSchema( QString& theName, YACS::ENGINE::Proc* proc) +{ + SalomeApp_ModuleObject* aRoot = dynamic_cast( root() ); + if ( aRoot ) + { + _PTR(SComponent) aSComp( aRoot->object() ); + + + _PTR(Study) aStudy = getStudy()->studyDS(); + _PTR(StudyBuilder) aBuilder ( aStudy->NewBuilder() ); + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + _PTR(AttributePixMap) aPixmap; + _PTR(AttributeParameter) aType; + + _PTR(SObject) aSObj; + // create a new schema SObject + aSObj = aBuilder->NewObject(aSComp); + + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + + if ( !theName.isEmpty() ) + aName->SetValue( QFileInfo(theName).baseName() ); + else + { + theName = generateSchemeName(aStudy, aSComp, "Schema"); + aName->SetValue( theName ); + } + + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributePixMap"); + aPixmap = _PTR(AttributePixMap)( anAttr ); + aPixmap->SetPixMap( "ICON_SCHEMA_OBJECT" ); + + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributeParameter"); + aType = _PTR(AttributeParameter)( anAttr ); + aType->SetInt( "ObjectType", SchemaObject ); + QString theFilePath = GuiContext::getCurrent()->getXMLSchema(); + aType->SetString( "FilePath", theFilePath ); + DEBTRACE(">> DataModel : FilePath = " << theFilePath.latin1()); + + myObjectProcMap.insert( std::make_pair( aSObj->GetID(), proc ) ); + } +} + +void YACSGui_DataModel::createNewRun( _PTR(SObject) parent, QString& theName, YACS::ENGINE::Proc* proc) +{ + SalomeApp_ModuleObject* aRoot = dynamic_cast( root() ); + if ( aRoot ) + { + _PTR(Study) aStudy = getStudy()->studyDS(); + _PTR(StudyBuilder) aBuilder ( aStudy->NewBuilder() ); + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + _PTR(AttributePixMap) aPixmap; + _PTR(AttributeParameter) aType; + + _PTR(SObject) aSObj; + // create a new schema SObject + + QDateTime curTime = QDateTime::currentDateTime(); + + QString name = curTime.toString( "yyyyMMdd_hhmmss" );//"24/10/2007-12:00";// test time + if (parent->FindAttribute( anAttr, "AttributeName" )) + { + aName = _PTR(AttributeName) ( anAttr ); + name = aName->Value() + QString("-") + name; + } + + aSObj = aBuilder->NewObject(parent); + + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + + aName->SetValue(name); + + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributePixMap"); + aPixmap = _PTR(AttributePixMap)( anAttr ); + aPixmap->SetPixMap( "ICON_RUN_OBJECT" ); + + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributeParameter"); + aType = _PTR(AttributeParameter)( anAttr ); + aType->SetInt( "ObjectType", RunObject ); + + aType->SetString( "FilePath", theName ); + + myObjectProcMap.insert( std::make_pair( aSObj->GetID(), proc ) ); + } +} + +YACSGui_DataModel::ObjectType YACSGui_DataModel::objectType( const QString& entry ) const { - YACSGui_ModuleObject* aRoot = dynamic_cast( root() ); - if( !aRoot ) { - aRoot = new YACSGui_ModuleObject( this, 0 ); - setRoot( aRoot ); + _PTR(Study) aStudy = getStudy()->studyDS(); + if ( aStudy ) + { + _PTR(SObject) sobj = aStudy->FindObjectID( entry ); + if ( sobj ) + { + _PTR(GenericAttribute) anAttr; + _PTR(AttributeInteger) anType; + if ( sobj->FindAttribute( anAttr, "AttributeParameter" ) ) + return (ObjectType) (_PTR(AttributeParameter)(anAttr))->GetInt("ObjectType"); + } } - std::list::iterator it = myProcData.begin(); - for(; it != myProcData.end(); it++) { - Proc* aProc = *it; - YACSGui_DataObject* aDataObj = new YACSGui_DataObject( aRoot, aProc ); + return UnknownObject; +} + +YACS::ENGINE::Proc* YACSGui_DataModel::getProc( _PTR(SObject) theObject ) const +{ + Proc* aProc = 0; + + std::map::const_iterator aPIt = myObjectProcMap.find( theObject->GetID() ); + if ( aPIt != myObjectProcMap.end() ) aProc = (*aPIt).second; + + return aProc; +} + +SUIT_DataObject* YACSGui_DataModel::getDataObject( YACS::ENGINE::Proc* theProc ) const +{ + SUIT_DataObject* aRetObj = 0; + + YACSGui_Module* aModule = dynamic_cast( module() ); + + if ( theProc && aModule ) + { + // get a list of all schemas + DataObjectList objlist = root()->children( true ); + + for ( DataObjectListIterator it( objlist ); it.current(); ++it ) + { + SalomeApp_DataObject* obj = dynamic_cast( it.current() ); + + if ( obj && aModule && aModule->getApp()->checkDataObject(obj) ) + if ( getProc( obj->object() ) == theProc ) + { + aRetObj = obj; + break; + } + } } + + return aRetObj; } - void YACSGui_DataModel::addData(Proc* theProc) +void YACSGui_DataModel::updateItem( YACS::ENGINE::Proc* theProc, bool theIsRecursive ) { - if(myProcData.size() > 0) { - std::list::iterator result = std::find(myProcData.begin(), myProcData.end(), theProc); - if (result != myProcData.end()) - return; + if ( SalomeApp_DataObject* anObj = dynamic_cast( getDataObject(theProc) ) ) + { + _PTR(Study) aStudy = getStudy()->studyDS(); + _PTR(StudyBuilder) aBuilder ( aStudy->NewBuilder() ); + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + + _PTR(SObject) aSObj = anObj->object(); + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + aName->SetValue( theProc->getName() ); + + if ( theIsRecursive ) + { + _PTR(SObject) aResult; + _PTR(ChildIterator) anIterator ( aStudy->NewChildIterator(aSObj) ); + for (; anIterator->More(); anIterator->Next()) { + if (anIterator->Value()->FindAttribute(anAttr, "AttributeName")) { + aName = _PTR(AttributeName) ( anAttr ); + + QString aRunName = aName->Value(); + int aRLength = QDateTime::currentDateTime().toString( "yyyyMMdd_hhmmss" ).length()+1; + aRunName = QString( theProc->getName() ) + aRunName.right( aRLength ); + + aName->SetValue( aRunName ); + if ( Proc* aRunProc = getProc(anIterator->Value()) ) + aRunProc->setName( aRunName ); + } + } + } + } - - myProcData.push_back(theProc); - update(); } diff --git a/src/gui/YACSGui_DataModel.h b/src/gui/YACSGui_DataModel.h index ae5f949ce..ee6271a03 100644 --- a/src/gui/YACSGui_DataModel.h +++ b/src/gui/YACSGui_DataModel.h @@ -19,34 +19,48 @@ #ifndef YACSGui_DataModel_HeaderFile #define YACSGui_DataModel_HeaderFile +#include #include +#include -#include +#include #include -class YACSGui_DataModel : public LightApp_DataModel +class YACSGui_DataModel : public SalomeApp_DataModel { + public: + enum ObjectType + { + SchemaObject, + RunObject, + UnknownObject + }; -public: + static QString Type2Str( ObjectType type ); + static ObjectType Str2Type( const QString& ); + + public: YACSGui_DataModel(CAM_Module* theModule); virtual ~YACSGui_DataModel(); - void add(YACS::ENGINE::Proc*, bool); - void remove(YACS::ENGINE::Proc*); + virtual bool open( const QString&, CAM_Study*, QStringList ); + virtual bool save( QStringList& ); + virtual bool saveAs( const QString&, CAM_Study*, QStringList& ); - void addData(YACS::ENGINE::Proc*); + void createNewSchema( QString&, YACS::ENGINE::Proc* ); + void createNewRun( _PTR(SObject), QString& theName, YACS::ENGINE::Proc* ); - bool isEditable(YACS::ENGINE::Proc*); + ObjectType objectType( const QString& ) const; -protected: - virtual void build(); + YACS::ENGINE::Proc* getProc( _PTR(SObject) ) const; + SUIT_DataObject* getDataObject( YACS::ENGINE::Proc* ) const; -private: - typedef std::map ProcMap; - ProcMap myProcs; + void updateItem( YACS::ENGINE::Proc*, bool theIsRecursive = false ); - std::list myProcData; + private: + typedef std::map ObjectProcMap; + ObjectProcMap myObjectProcMap; }; #endif diff --git a/src/gui/YACSGui_DataNodePage.cxx b/src/gui/YACSGui_DataNodePage.cxx new file mode 100644 index 000000000..44fb15d1e --- /dev/null +++ b/src/gui/YACSGui_DataNodePage.cxx @@ -0,0 +1,2416 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +// #define SPACING 5 +// #define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + +YACSGui_DataNodePage::YACSGui_DataNodePage( int pageId, + QWidget* theParent, + const char* theName, + WFlags theFlags) + : DataNodePage( theParent, theName, theFlags ), + YACSGui_NodePage(), + myIsNeedToReorder(false), + myPageId(pageId) +{ + if ( !myInputPortsGroupBox || !myOutputPortsGroupBox ) return; + + _isInput = true; + _isStudy = false; + _fileName = ""; + _studyName = ""; + _studyId = 0; + switch (myPageId) + { + case YACSGui_InputPanel::InDataNodeId: + { + _isInput = true; + _isStudy = false; + myNodeType->setText("input data node"); + break; + } + case YACSGui_InputPanel::OutDataNodeId: + { + _isInput = false; + _isStudy = false; + myNodeType->setText("output data node"); + break; + } + case YACSGui_InputPanel::InStudyNodeId: + { + _isInput = true; + _isStudy = true; + myNodeType->setText("input study node"); + break; + } + case YACSGui_InputPanel::OutStudyNodeId: + { + _isInput = false; + _isStudy = true; + myNodeType->setText("output study node"); + break; + } + default: + return; + } + + QString aPortTypes = QString("Data Flow"); //";Data Stream (BASIC);Data Stream (CALCIUM);Data Stream (PALM)"); + QString aValueTypes = QString("Double;Int;String;Bool"); + + // Input Ports table + myInputPortsGroupBox->setTitle( tr("Input Ports") ); + myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + //aTable->setFixedHeight( 100 ); + aTable->setNumCols( 4 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) ); + aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) ); + aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) ); + aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) ); + aTable->setColumnWidth(0,58); + aTable->setColumnWidth(1,84); + aTable->setColumnWidth(2,80); + aTable->setCellType( -1, 0, YACSGui_Table::String ); + aTable->setCellType( -1, 1, YACSGui_Table::Combo ); + aTable->setCellType( -1, 2, YACSGui_Table::ComboSelect ); + //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column + + aTable->setParams( 0, 1, aPortTypes ); + aTable->setParams( 0, 2, aValueTypes ); + + aTable->setDefValue( 0, 1, "Data Flow"); + aTable->setDefValue( 0, 2, "Double"); + + aTable->setEditorSync(true); + + connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) ); + + connect( aTable, SIGNAL(selectButtonClicked( const int, const int )), this, SLOT(onSelectDataType( const int, const int )) ); + + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + myInputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + connect( myInputPortsGroupBox, SIGNAL(Inserted( const int )), this, SLOT(onInserted( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(MovedUp( const int )), this, SLOT(onMovedUp( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(MovedDown( const int )), this, SLOT(onMovedDown( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(Added( const int )), this, SLOT(onAdded( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(Removed( const int )), this, SLOT(onRemoved( const int )) ); + + // Output Ports table + myOutputPortsGroupBox->setTitle( tr("Output Ports") ); + myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + aTable = myOutputPortsGroupBox->Table(); + //aTable->setFixedHeight( 100 ); + aTable->setNumCols( 5 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) ); + aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) ); + aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) ); + aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) ); + aTable->horizontalHeader()->setLabel( 4, tr( "Is in study" ) ); + aTable->setColumnWidth(0,58); + aTable->setColumnWidth(1,84); + aTable->setColumnWidth(2,80); + aTable->setCellType( -1, 0, YACSGui_Table::String ); + aTable->setCellType( -1, 1, YACSGui_Table::Combo ); + aTable->setCellType( -1, 2, YACSGui_Table::ComboSelect ); + //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column + aTable->setCellType( -1, 4, YACSGui_Table::Combo ); + + aTable->setParams( 0, 1, aPortTypes ); + aTable->setParams( 0, 2, aValueTypes ); + aTable->setParams( 0, 4, QString("Yes;No") ); + + aTable->setDefValue( 0, 1, "Data Flow"); + aTable->setDefValue( 0, 2, "Double"); + aTable->setDefValue( 0, 4, QString("Yes") ); + + aTable->setEditorSync(true); + + myPara = 0; + myIndex = 0; + + connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) ); + + connect( aTable, SIGNAL(selectButtonClicked( const int, const int )), this, SLOT(onSelectDataType( const int, const int )) ); + + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + myOutputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + connect( myOutputPortsGroupBox, SIGNAL(Inserted( const int )), this, SLOT(onInserted( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(MovedUp( const int )), this, SLOT(onMovedUp( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(MovedDown( const int )), this, SLOT(onMovedDown( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(Added( const int )), this, SLOT(onAdded( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(Removed( const int )), this, SLOT(onRemoved( const int )) ); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); + + if (_isInput) + { + ports->removePage(tab); + } + else + { + ports->removePage(tab_2); + } + if (_isStudy) + { + DataNodeFrameLayout->remove(FileGroupBox); + FileGroupBox->hide(); + } + else + { + DataNodeFrameLayout->remove(StudyGroupBox); + StudyGroupBox->hide(); + } +} + +YACSGui_DataNodePage::~YACSGui_DataNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); +} + +void YACSGui_DataNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( dynamic_cast( theSNode->getNode() ) ) + { + YACSGui_NodePage::setSNode( theSNode ); + myIPList.clear(); + myOPList.clear(); + } +} + +void YACSGui_DataNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + myNodeName->setReadOnly(false); + + ExecutionGroupBox->hide(); + + EditPortsGroupBox->setTitle( tr( "Edit Ports" ) ); + + YACSGui_Table* aTable; + + myInputPortsGroupBox->ShowBtn(); + myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + aTable = myInputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, false ); + aTable->setReadOnly( -1, 1, false ); + aTable->setReadOnly( -1, 2, false ); +// aTable->setReadOnly( -1, 3, true ); + + myOutputPortsGroupBox->ShowBtn(); + myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + aTable = myOutputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, false ); + aTable->setReadOnly( -1, 1, false ); + aTable->setReadOnly( -1, 2, false ); +// aTable->setReadOnly( -1, 3, false ); + +// InPythonEditorGroupBox->show(); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + myNodeName->setReadOnly(true); + + ExecutionGroupBox->show(); + + EditPortsGroupBox->setTitle( tr( "Port List" ) ); + + YACSGui_Table* aTable; + + myInputPortsGroupBox->HideBtn(); + aTable = myInputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, true ); + aTable->setReadOnly( -1, 1, true ); + aTable->setReadOnly( -1, 2, true ); + + myOutputPortsGroupBox->HideBtn(); + aTable = myOutputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, true ); + aTable->setReadOnly( -1, 1, true ); + aTable->setReadOnly( -1, 2, true ); + +// InPythonEditorGroupBox->hide(); + } +} + +void YACSGui_DataNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_DataNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_DataNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + DEBTRACE("YACSGui_DataNodePage::notifyInPortValues" ); + QStringList aValues; + + QStringList aPortNames; + myInputPortsGroupBox->Table()->strings( 0, aPortNames ); + + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + map::iterator it1 = theInPortName2Value.find( (*it).latin1() ); + if ( it1 != theInPortName2Value.end() ) + aValues.append( QString((*it1).second.c_str()) ); + } + + if ( aPortNames.count() == aValues.count() ) + myInputPortsGroupBox->Table()->setStrings( 3, aValues ); +} + +void YACSGui_DataNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + DEBTRACE("YACSGui_DataNodePage::notifyOutPortValues" ); + QStringList aValues; + + QStringList aPortNames; + myOutputPortsGroupBox->Table()->strings( 0, aPortNames ); + + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + map::iterator it1 = theOutPortName2Value.find( (*it).latin1() ); + if ( it1 != theOutPortName2Value.end() ) + aValues.append( QString((*it1).second.c_str()) ); + } + + if ( aPortNames.count() == aValues.count() ) + myOutputPortsGroupBox->Table()->setStrings( 3, aValues ); +} + +void YACSGui_DataNodePage::setDataType( YACS::ENGINE::TypeCode* theDataType ) +{ + DEBTRACE("YACSGui_DataNodePage::setDataType: " << theDataType->name()); + if ( mySelectDataTypeFor.myRow < 0 ) return; + + YACSGui_Table* aTable = 0; + if ( mySelectDataTypeFor.myIn ) + { + aTable = myInputPortsGroupBox->Table(); + + if ( myRow2DataTypeIn.find(mySelectDataTypeFor.myRow) != myRow2DataTypeIn.end() ) + myRow2DataTypeIn[mySelectDataTypeFor.myRow] = theDataType; + else + myRow2DataTypeIn.insert(make_pair(mySelectDataTypeFor.myRow,theDataType)); + DEBTRACE(theDataType->name()); + } + else + { + aTable = myOutputPortsGroupBox->Table(); + + if ( myRow2DataTypeOut.find(mySelectDataTypeFor.myRow) != myRow2DataTypeOut.end() ) + myRow2DataTypeOut[mySelectDataTypeFor.myRow] = theDataType; + else + myRow2DataTypeOut.insert(make_pair(mySelectDataTypeFor.myRow,theDataType)); + DEBTRACE(theDataType->name()); + } + + if ( aTable ) + { + // update the content of the cell according to the selected data type + if ( YACSGui_TableComboSelectItem* aCSItem = + dynamic_cast(aTable->item( mySelectDataTypeFor.myRow, 2 )) ) + { + if( aCSItem->selectButton() && aCSItem->selectButton()->isOn() ) + aCSItem->selectButton()->setOn( false ); + + QString aTypeName(theDataType->name()); + aCSItem->showText(aTypeName); + aTable->setDefValue( mySelectDataTypeFor.myRow, 2, aTypeName ); + } + + mySelectDataTypeFor.myRow = -1; + } +} + +void YACSGui_DataNodePage::checkModifications() +{ + DEBTRACE("YACSGui_DataNodePage::checkModifications"); + if ( !getNode() ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + if ( myNodeName->text().compare(getNodeName()) != 0 ) isModified = true; + DEBTRACE(isModified); + + if ( !isModified ) isModified = isPortsModified(); + DEBTRACE(isModified); + if ( !isModified ) isModified = isPortsModified(false); + DEBTRACE(isModified); + + if ( !isModified ) + { + if (_isStudy) + { + if (QString::compare(_studyName, myStudyName->text()) != 0) isModified = true; + else if (_studyId != myStudyId->value()) isModified = true; + } + else + { + if (QString::compare(_fileName,myFileName->text()) != 0) isModified = true; + } + } + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::DataNodeId); + } +} + +void YACSGui_DataNodePage::onApply() +{ + DEBTRACE("YACSGui_DataNodePage::onApply"); + // Rename a node + if ( myNodeName ) + setNodeName( myNodeName->text() ); + + bool withFilling = ( myIPList.isEmpty() || myOPList.isEmpty() ); + + // Reset the list of input ports + setInputPorts(); + + // Reset the list of output ports + setOutputPorts(); + + if ( myIsNeedToReorder ) + { + orderPorts(withFilling); + myIsNeedToReorder = false; + } + + // set file or study + if (_isStudy) + { + _studyName = myStudyName->text(); + _studyId = myStudyId->value(); + } + else + { + _fileName = myFileName->text(); + } + setProperties(); + + resetStoredPortsMaps(); + resetDataTypeMaps(); + resetPLists(); + + updateBlocSize(); +} + +//! Update widget state from node state +/*! + * + */ +void YACSGui_DataNodePage::updateState() +{ + DEBTRACE("YACSGui_DataNodePage::updateState()"); + // Clear input ports table and output ports tables, if they are not empty + if ( myInputPortsGroupBox ) + { + myInputPortsGroupBox->Table()->setNumRows( 0 ); + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + if ( myOutputPortsGroupBox ) + { + myOutputPortsGroupBox->Table()->setNumRows( 0 ); + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Set node type: inline function or inline script + if ( dynamic_cast( getNode() ) ) + myNodeType->setText( tr( "INLINE_FUNCTION_NODE" ) ); // inline function node + else if ( dynamic_cast( getNode() ) ) + myNodeType->setText( tr( "INLINE_SCRIPT_NODE" ) ); // inline script node + + // Fill the table of input ports of the node + fillInputPortsTable(); + + // Fill the table of output ports of the node + fillOutputPortsTable(); + + // Show the body (script/function) of inline node +// if ( DataNode* anIN = dynamic_cast( getNode() ) ) +// setScriptText( QString(anIN->getScript()) ); +} + +void YACSGui_DataNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + +void YACSGui_DataNodePage::onValueChanged( int theRow, int theCol ) +{ + DEBTRACE("YACSGui_DataNodePage::onValueChanged "<< theRow << " " << theCol); + if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() ) + { + if ( theCol == 1 ) // the port type was changed + { + if( aTable == myInputPortsGroupBox->Table() ) + aTable->setReadOnly( theRow, 3, true ); + } + + if ( theCol == 2 ) // the value type of the port was changed + { + setValueCellValidator( aTable, theRow ); + + if( aTable == myOutputPortsGroupBox->Table() ) + aTable->setReadOnly( theRow, 3, false ); + } + + if ( theCol == 1 || theCol == 2 ) // port type or value type was changed + { + if ( myInputPortsGroupBox->Table() == aTable ) + if ( myRow2StoredInPorts.find(theRow) != myRow2StoredInPorts.end() ) + myRow2StoredInPorts.erase(theRow); + + if ( myOutputPortsGroupBox->Table() == aTable ) + if ( myRow2StoredOutPorts.find(theRow) != myRow2StoredOutPorts.end() ) + myRow2StoredOutPorts.erase(theRow); + } + } +} + +void YACSGui_DataNodePage::hideEvent( QHideEvent*) +{ + myPara = 0; + myIndex = 0; +} + +void YACSGui_DataNodePage::onInserted( const int theRow ) +{ + DEBTRACE("YACSGui_DataNodePage::onInserted: " << theRow); + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredInPorts + if ( myRow2StoredInPorts.size() == 0 ) + return; + + if ( myRow2StoredInPorts.size() == 1 ) + { + if ( theRow == 0 ) + { + InPort* aPort = myRow2StoredInPorts[0]; + myRow2StoredInPorts.insert( std::make_pair(1,aPort) ); + myRow2StoredInPorts.erase(0); + } + } + else + { + map::iterator it = myRow2StoredInPorts.end(); + map::iterator itBeforeBegin = myRow2StoredInPorts.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + InPort* aPort = (*it).second; + + if ( aRow >= theRow ) + { + myRow2StoredInPorts.insert( std::make_pair(aRow+1,aPort) ); + myRow2StoredInPorts.erase(aRow); + } + } + } + + // change the content of myRow2DataTypeIn + if ( myRow2DataTypeIn.size() == 0 ) + return; + + if ( myRow2DataTypeIn.size() == 1 ) + { + if ( theRow == 0 ) + { + TypeCode* aTC = myRow2DataTypeIn[0]; + myRow2DataTypeIn.insert( std::make_pair(1,aTC) ); + myRow2DataTypeIn.erase(0); + } + } + else + { + map::iterator it = myRow2DataTypeIn.end(); + map::iterator itBeforeBegin = myRow2DataTypeIn.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + TypeCode* aTC = (*it).second; + + if ( aRow >= theRow ) + { + myRow2DataTypeIn.insert( std::make_pair(aRow+1,aTC) ); + myRow2DataTypeIn.erase(aRow); + } + } + } + + myIsNeedToReorder = true; + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredOutPorts + if ( myRow2StoredOutPorts.size() == 0 ) + return; + + if ( myRow2StoredOutPorts.size() == 1 ) + { + if ( theRow == 0 ) + { + OutPort* aPort = myRow2StoredOutPorts[0]; + myRow2StoredOutPorts.insert( std::make_pair(1,aPort) ); + myRow2StoredOutPorts.erase(0); + } + } + else + { + map::iterator it = myRow2StoredOutPorts.end(); + map::iterator itBeforeBegin = myRow2StoredOutPorts.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + OutPort* aPort = (*it).second; + + if ( aRow >= theRow ) + { + myRow2StoredOutPorts.insert( std::make_pair(aRow+1,aPort) ); + myRow2StoredOutPorts.erase(aRow); + } + } + } + + // change the content of myRow2DataTypeOut + if ( myRow2DataTypeOut.size() == 0 ) + return; + + if ( myRow2DataTypeOut.size() == 1 ) + { + if ( theRow == 0 ) + { + TypeCode* aTC = myRow2DataTypeOut[0]; + myRow2DataTypeOut.insert( std::make_pair(1,aTC) ); + myRow2DataTypeOut.erase(0); + DEBTRACE(aTC->name()); + } + } + else + { + map::iterator it = myRow2DataTypeOut.end(); + map::iterator itBeforeBegin = myRow2DataTypeOut.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + TypeCode* aTC = (*it).second; + + if ( aRow >= theRow ) + { + myRow2DataTypeOut.insert( std::make_pair(aRow+1,aTC) ); + myRow2DataTypeOut.erase(aRow); + DEBTRACE(aTC->name()); + } + } + } + + myIsNeedToReorder = true; + } +} + +void YACSGui_DataNodePage::onMovedUp( const int theUpRow ) +{ + DEBTRACE("YACSGui_DataNodePage::onMovedUp: " << theUpRow); + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredInPorts + InPort* aPortToMoveDown = 0; + if ( myRow2StoredInPorts.find(theUpRow) != myRow2StoredInPorts.end() ) + { + aPortToMoveDown = myRow2StoredInPorts[theUpRow]; + myRow2StoredInPorts.erase(theUpRow); + } + + InPort* aPortToMoveUp = 0; + if ( myRow2StoredInPorts.find(theUpRow+1) != myRow2StoredInPorts.end() ) + { + aPortToMoveUp = myRow2StoredInPorts[theUpRow+1]; + myRow2StoredInPorts.erase(theUpRow+1); + } + + if ( aPortToMoveUp ) myRow2StoredInPorts.insert( std::make_pair(theUpRow,aPortToMoveUp)); + if ( aPortToMoveDown ) myRow2StoredInPorts.insert( std::make_pair(theUpRow+1,aPortToMoveDown)); + + // change the content of myRow2DataTypeIn + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeIn.find(theUpRow) != myRow2DataTypeIn.end() ) + { + aTCToMoveDown = myRow2DataTypeIn[theUpRow]; + myRow2DataTypeIn.erase(theUpRow); + } + + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeIn.find(theUpRow+1) != myRow2DataTypeIn.end() ) + { + aTCToMoveUp = myRow2DataTypeIn[theUpRow+1]; + myRow2DataTypeIn.erase(theUpRow+1); + } + + if ( aTCToMoveUp ) myRow2DataTypeIn.insert( std::make_pair(theUpRow,aTCToMoveUp)); + if ( aTCToMoveDown ) myRow2DataTypeIn.insert( std::make_pair(theUpRow+1,aTCToMoveDown)); + + myIsNeedToReorder = true; + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredOutPorts + OutPort* aPortToMoveDown = 0; + if ( myRow2StoredOutPorts.find(theUpRow) != myRow2StoredOutPorts.end() ) + { + aPortToMoveDown = myRow2StoredOutPorts[theUpRow]; + myRow2StoredOutPorts.erase(theUpRow); + } + + OutPort* aPortToMoveUp = 0; + if ( myRow2StoredOutPorts.find(theUpRow+1) != myRow2StoredOutPorts.end() ) + { + aPortToMoveUp = myRow2StoredOutPorts[theUpRow+1]; + myRow2StoredOutPorts.erase(theUpRow+1); + } + + if ( aPortToMoveUp ) myRow2StoredOutPorts.insert( std::make_pair(theUpRow,aPortToMoveUp)); + if ( aPortToMoveDown ) myRow2StoredOutPorts.insert( std::make_pair(theUpRow+1,aPortToMoveDown)); + + // change the content of myRow2DataTypeOut + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeOut.find(theUpRow) != myRow2DataTypeOut.end() ) + { + aTCToMoveDown = myRow2DataTypeOut[theUpRow]; + myRow2DataTypeOut.erase(theUpRow); + } + + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeOut.find(theUpRow+1) != myRow2DataTypeOut.end() ) + { + aTCToMoveUp = myRow2DataTypeOut[theUpRow+1]; + myRow2DataTypeOut.erase(theUpRow+1); + } + + if ( aTCToMoveUp ) myRow2DataTypeOut.insert( std::make_pair(theUpRow,aTCToMoveUp)); + if ( aTCToMoveDown ) myRow2DataTypeOut.insert( std::make_pair(theUpRow+1,aTCToMoveDown)); + + myIsNeedToReorder = true; + } +} + +void YACSGui_DataNodePage::onMovedDown( const int theDownRow ) +{ + DEBTRACE("YACSGui_DataNodePage::onMovedDown: " << theDownRow); + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredInPorts + InPort* aPortToMoveUp = 0; + if ( myRow2StoredInPorts.find(theDownRow) != myRow2StoredInPorts.end() ) + { + aPortToMoveUp = myRow2StoredInPorts[theDownRow]; + myRow2StoredInPorts.erase(theDownRow); + } + + InPort* aPortToMoveDown = 0; + if ( myRow2StoredInPorts.find(theDownRow-1) != myRow2StoredInPorts.end() ) + { + aPortToMoveDown = myRow2StoredInPorts[theDownRow-1]; + myRow2StoredInPorts.erase(theDownRow-1); + } + + if ( aPortToMoveDown ) myRow2StoredInPorts.insert( std::make_pair(theDownRow,aPortToMoveDown)); + if ( aPortToMoveUp ) myRow2StoredInPorts.insert( std::make_pair(theDownRow-1,aPortToMoveUp)); + + // change the content of myRow2DataTypeIn + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeIn.find(theDownRow) != myRow2DataTypeIn.end() ) + { + aTCToMoveUp = myRow2DataTypeIn[theDownRow]; + myRow2DataTypeIn.erase(theDownRow); + } + + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeIn.find(theDownRow-1) != myRow2DataTypeIn.end() ) + { + aTCToMoveDown = myRow2DataTypeIn[theDownRow-1]; + myRow2DataTypeIn.erase(theDownRow-1); + } + + if ( aTCToMoveDown ) myRow2DataTypeIn.insert( std::make_pair(theDownRow,aTCToMoveDown)); + if ( aTCToMoveUp ) myRow2DataTypeIn.insert( std::make_pair(theDownRow-1,aTCToMoveUp)); + + myIsNeedToReorder = true; + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredOutPorts + OutPort* aPortToMoveUp = 0; + if ( myRow2StoredOutPorts.find(theDownRow) != myRow2StoredOutPorts.end() ) + { + aPortToMoveUp = myRow2StoredOutPorts[theDownRow]; + myRow2StoredOutPorts.erase(theDownRow); + } + + OutPort* aPortToMoveDown = 0; + if ( myRow2StoredOutPorts.find(theDownRow-1) != myRow2StoredOutPorts.end() ) + { + aPortToMoveDown = myRow2StoredOutPorts[theDownRow-1]; + myRow2StoredOutPorts.erase(theDownRow-1); + } + + if ( aPortToMoveDown ) myRow2StoredOutPorts.insert( std::make_pair(theDownRow,aPortToMoveDown)); + if ( aPortToMoveUp ) myRow2StoredOutPorts.insert( std::make_pair(theDownRow-1,aPortToMoveUp)); + + // change the content of myRow2DataTypeOut + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeOut.find(theDownRow) != myRow2DataTypeOut.end() ) + { + aTCToMoveUp = myRow2DataTypeOut[theDownRow]; + myRow2DataTypeOut.erase(theDownRow); + } + + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeOut.find(theDownRow-1) != myRow2DataTypeOut.end() ) + { + aTCToMoveDown = myRow2DataTypeOut[theDownRow-1]; + myRow2DataTypeOut.erase(theDownRow-1); + } + + if ( aTCToMoveDown ) myRow2DataTypeOut.insert( std::make_pair(theDownRow,aTCToMoveDown)); + if ( aTCToMoveUp ) myRow2DataTypeOut.insert( std::make_pair(theDownRow-1,aTCToMoveUp)); + + myIsNeedToReorder = true; + } +} + +void YACSGui_DataNodePage::onRemoved( const int theRow ) +{ + DEBTRACE("YACSGui_DataNodePage::onRemoved " << theRow); + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + DEBTRACE("Change input ports"); + // change the content of myRow2StoredInPorts + int aRow; + DEBTRACE(myRow2StoredInPorts.size()); + for(aRow=theRow;aRowTable()->setDefValue( theRow, 2, "" ); + myInputPortsGroupBox->Table()->item( theRow, 2 )->setText("Double"); + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + myOutputPortsGroupBox->Table()->setDefValue( theRow, 2, "" ); + myOutputPortsGroupBox->Table()->item( theRow, 2 )->setText("Double"); + } +} + +void YACSGui_DataNodePage::onSelectDataType( const int theRow, const int theCol ) +{ + DEBTRACE("YACSGui_DataNodePage::onSelectDataType: " << theRow << " " << theCol); + if ( theCol == 2 && theRow >= 0 ) // the value type selection + { + if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() ) + { + YACSGui_TableComboSelectItem* aCSItem = dynamic_cast(aTable->item( theRow, theCol )); + if ( aCSItem && aCSItem->selectButton() && !aCSItem->selectButton()->isOn() ) + { + mySelectDataTypeFor.myRow = -1; + return; + } + + if ( aTable == myInputPortsGroupBox->Table() ) + { + if ( !mySelectDataTypeFor.myIn && mySelectDataTypeFor.myRow >= 0 ) + if ( YACSGui_TableComboSelectItem* aCSPrevItem = + dynamic_cast(aTable->item( mySelectDataTypeFor.myRow, theCol )) ) + if ( aCSPrevItem->selectButton() ) aCSPrevItem->selectButton()->setOn(false); + + mySelectDataTypeFor.myIn = true; + mySelectDataTypeFor.myRow = theRow; + } + else if ( aTable == myOutputPortsGroupBox->Table() ) + { + if ( mySelectDataTypeFor.myIn && mySelectDataTypeFor.myRow >= 0 ) + if ( YACSGui_TableComboSelectItem* aCSPrevItem = + dynamic_cast(aTable->item( mySelectDataTypeFor.myRow, theCol )) ) + if ( aCSPrevItem->selectButton() ) aCSPrevItem->selectButton()->setOn(false); + + mySelectDataTypeFor.myIn = false; + mySelectDataTypeFor.myRow = theRow; + } + } + } +} + +//! Update input port table state from node state +/*! + * + */ +void YACSGui_DataNodePage::fillInputPortsTable() +{ + DEBTRACE("YACSGui_DataNodePage::fillInputPortsTable()"); + if ( !getNode() ) return; + + myRow2StoredInPorts.clear(); + myRow2DataTypeIn.clear(); + + QStringList aPortNames; + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + + QValueList aReadOnlyFlags; + + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + QStringList aPTCB = aTable->Params( 0, 1 ); + + bool isStudyNode=false; + int aRowId = 0; + list anInPortsEngine = getNode()->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + { + InPort* anInPort = *anInPortsIter; + + myRow2StoredInPorts.insert( std::make_pair(aRowId,anInPort) ); + myRow2DataTypeIn[aRowId]=anInPort->edGetType(); + + // Collect port names in the list + aPortNames.append( anInPort->getName() ); + + // Port type + if ( InputStudyPort* anInputP = dynamic_cast(anInPort) ) + { + isStudyNode=true; + aPortTypes.append( aPTCB[0] ); + aReadOnlyFlags.append( false ); + } + else if ( InputPort* anInputP = dynamic_cast(anInPort) ) + { + aPortTypes.append( aPTCB[0] ); + + int nbLinks = anInPort->edGetNumberOfLinks(); + aReadOnlyFlags.append( nbLinks > 0 ); + } + //else if ( InputBasicStreamPort* aBasicStreamP = dynamic_cast(anInPort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[1] ); + //} + else if ( InputCalStreamPort* aCalStreamP = dynamic_cast(anInPort) ) + { + aPortTypes.append( aPTCB[2] ); + aReadOnlyFlags.append( true ); + } + //else if ( InputPalmStreamPort* aPalmStreamP = dynamic_cast(anInPort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[3] ); + //} + else + { // take default value from combo box + aPortTypes.append( aPTCB[0] ); + aReadOnlyFlags.append( true ); + } + + // Value type + aValueTypes.append( getPortType( anInPort ) ); + + // Value + aValues.append( getPortValue( anInPort ) ); + + aRowId++; + } + + // Fill "Port name" column + aTable->setStrings( 0, aPortNames, true ); + + // Fill "Port type" column + aTable->setStrings( 1, aPortTypes, true ); + + // Fill "Value type" column + aTable->setStrings( 2, aValueTypes, true ); + + //Do not set validators for study as all values are strings whatever is the type + if(isStudyNode) + for (int irow=0; irow < aTable->numRows(); irow++) + aTable->setCellType( irow, 3, YACSGui_Table::String ); + + // Fill "Value" column + aTable->setStrings( 3, aValues, true ); + + // Set "Value" column read only (for linked ports) + // no read only for study node only for data node + for ( int i = 0, n = aTable->numRows(); i < n; i++ ) + { + aTable->setDefValue( i, 2, aValueTypes[i] ); + aTable->setReadOnly( i, 3, aReadOnlyFlags[i] ); + } + + if ( !aPortNames.empty() ) myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); +} + +//! Update output port table state from node state +/*! + * + */ +void YACSGui_DataNodePage::fillOutputPortsTable() +{ + DEBTRACE("YACSGui_DataNodePage::fillOutputPortsTable()" ); + if ( !getNode() ) return; + + myRow2StoredOutPorts.clear(); + myRow2DataTypeOut.clear(); + + QStringList aPortNames; + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + QStringList anIsInStudy; + + YACSGui_Table* aTable = myOutputPortsGroupBox->Table(); + QStringList aPTCB = aTable->Params( 0, 1 ); + + bool isStudyNode=false; + int aRowId = 0; + list anOutPortsEngine = getNode()->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + { + OutPort* anOutPort = *anOutPortsIter; + + myRow2StoredOutPorts.insert( std::make_pair(aRowId,anOutPort) ); + myRow2DataTypeOut[aRowId]=anOutPort->edGetType(); + + // Collect port names in the list + aPortNames.append( anOutPort->getName() ); + + // Port type + if ( OutputStudyPort* anOutputP = dynamic_cast(anOutPort) ) + { + //Output study port + aPortTypes.append( aPTCB[0] ); + isStudyNode=true; + } + else if ( OutputPort* anOutputP = dynamic_cast(anOutPort) ) + { + aPortTypes.append( aPTCB[0] ); + } + //else if ( OutputBasicStreamPort* aBasicStreamP = dynamic_cast(anOutPort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[1] ); + //} + else if ( OutputCalStreamPort* aCalStreamP = dynamic_cast(anOutPort) ) + { + aPortTypes.append( aPTCB[2] ); + } + //else if ( OutputPalmStreamPort* aPalmStreamP = dynamic_cast(anOutPort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[3] ); + //} + else + { // take default value from combo box + aPortTypes.append( aPTCB[0] ); + } + + // Value type + aValueTypes.append( getPortType( anOutPort ) ); + + // Value + aValues.append( getPortValue( anOutPort ) ); + + // Is in study + // There is no a such parameter either in engine or GUI at the current moment. + // TODO: we need to implement it at GUI side. + // As a temporary solution we set the default value + anIsInStudy.append( aTable->defValue( 0, 4 ) ); + + aRowId++; + } + + // Fill "Port name" column + aTable->setStrings( 0, aPortNames, true ); + + // Fill "Port type" column + aTable->setStrings( 1, aPortTypes, true ); + + // Fill "Value type" column + aTable->setStrings( 2, aValueTypes, true ); + + //Do not set validators for study as all values are strings whatever is the type + for (int irow=0; irow < aTable->numRows(); irow++) + if(isStudyNode == false) + setValueCellValidator( aTable, irow); + else + aTable->setCellType( irow, 3, YACSGui_Table::String ); + + // Fill "Value" column + aTable->setStrings( 3, aValues, true ); + + // Fill "Is in study" column + aTable->setStrings( 4, anIsInStudy, true ); + + // Set "Value" column read write + DEBTRACE("ReadOnly"); + for ( int i = 0, n = aTable->numRows(); i < n; i++ ) + { + aTable->setDefValue( i, 2, aValueTypes[i] ); + aTable->setReadOnly( i, 3, false ); + } + + if ( !aPortNames.empty() ) myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + DEBTRACE("End of fillOutputPorts"); +} + +QString YACSGui_DataNodePage::getPortType( YACS::ENGINE::Port* thePort ) const +{ + DEBTRACE("YACSGui_DataNodePage::getPortType"); + QString aType; + + YACSGui_Table* aTable = 0; + if ( dynamic_cast(thePort) ) + aTable = myInputPortsGroupBox->Table(); + else if ( dynamic_cast(thePort) ) + aTable = myOutputPortsGroupBox->Table(); + + if ( !aTable ) return aType; + + QStringList aVTCB = aTable->Params( 0, 2 ); + + if ( DataPort* aDataPort = dynamic_cast(thePort) ) + { + DynType aDType = aDataPort->edGetType()->kind(); + if ( aDType > NONE && aDType < Objref ) + aType = aVTCB[aDType-1]; + else + aType = QString(aDataPort->edGetType()->name()); + } + + return aType; +} + +bool YACSGui_DataNodePage::isStored( YACS::ENGINE::Port* thePort ) +{ + DEBTRACE("YACSGui_DataNodePage::isStored: " << thePort); + if ( InPort* anIP = dynamic_cast(thePort) ) + { + map::iterator it = myRow2StoredInPorts.begin(); + for ( ; it != myRow2StoredInPorts.end(); it++ ) + { + DEBTRACE("isStored ? " << thePort << " " << (*it).second); + if ( (*it).second == thePort ) return true; + } + return false; + } + else if ( OutPort* anOP = dynamic_cast(thePort) ) + { + map::iterator it = myRow2StoredOutPorts.begin(); + for ( ; it != myRow2StoredOutPorts.end(); it++ ) + { + DEBTRACE("isStored ? " << thePort << " " << (*it).second); + if ( (*it).second == thePort ) return true; + } + return false; + } + return true; // the gate ports are kept (not re-create) +} + +void YACSGui_DataNodePage::resetStoredPortsMaps() +{ + DEBTRACE("YACSGui_DataNodePage::resetStoredPortsMaps"); + myRow2StoredInPorts.clear(); + myRow2DataTypeIn.clear(); + + QStringList aIPortNames; + myInputPortsGroupBox->Table()->strings( 0, aIPortNames ); + + int aRowId = 0; + for ( QStringList::Iterator it = aIPortNames.begin(); it != aIPortNames.end(); ++it ) + { + DEBTRACE((*it).latin1()); + if ( (*it).isEmpty() ) continue; + + try { + if ( InputPort* aIDP = getNode()->getInputPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aIDP); + myRow2StoredInPorts.insert( std::make_pair(aRowId,aIDP) ); + myRow2DataTypeIn[aRowId]=aIDP->edGetType(); + } + } + catch (YACS::Exception& ex) { + try { + if ( InputDataStreamPort* aIDSP = getNode()->getInputDataStreamPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aIDSP); + myRow2StoredInPorts.insert( std::make_pair(aRowId,aIDSP) ); + myRow2DataTypeIn[aRowId]=aIDSP->edGetType(); + } + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + aRowId++; + } + + myRow2StoredOutPorts.clear(); + myRow2DataTypeOut.clear(); + + QStringList aOPortNames; + myOutputPortsGroupBox->Table()->strings( 0, aOPortNames ); + + aRowId = 0; + for ( QStringList::Iterator it = aOPortNames.begin(); it != aOPortNames.end(); ++it ) + { + DEBTRACE((*it).latin1()); + if ( (*it).isEmpty() ) continue; + + try { + if ( OutputPort* aODP = getNode()->getOutputPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aODP); + myRow2StoredOutPorts.insert( std::make_pair(aRowId,aODP) ); + myRow2DataTypeOut[aRowId]=aODP->edGetType(); + } + } + catch (YACS::Exception& ex) { + try { + if ( OutputDataStreamPort* aODSP = getNode()->getOutputDataStreamPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aODSP); + myRow2StoredOutPorts.insert( std::make_pair(aRowId,aODSP) ); + myRow2DataTypeOut[aRowId]=aODSP->edGetType(); + } + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + aRowId++; + } +} + +void YACSGui_DataNodePage::resetDataTypeMaps() +{ + DEBTRACE("YACSGui_DataNodePage::resetDataTypeMaps"); + //myRow2DataTypeIn.clear(); + //myRow2DataTypeOut.clear(); +} + +void YACSGui_DataNodePage::resetPLists() +{ + DEBTRACE("YACSGui_DataNodePage::resetPLists"); + resetIPLists(); + resetOPLists(); +} + +void YACSGui_DataNodePage::resetIPLists() +{ + DEBTRACE("YACSGui_DataNodePage::resetIPLists"); + myIPList.clear(); + + QStringList aIPortNames; + myInputPortsGroupBox->Table()->strings( 0, aIPortNames ); + + for ( QStringList::Iterator it = aIPortNames.begin(); it != aIPortNames.end(); ++it ) + { + DEBTRACE((*it).latin1()); + if ( (*it).isEmpty() ) continue; + + try { + if ( InPort* aIDP = getNode()->getInputPort((*it).latin1()) ) + myIPList.append(aIDP); + } + catch (YACS::Exception& ex) { + try { + if ( InPort* aIDSP = getNode()->getInputDataStreamPort((*it).latin1()) ) + myIPList.append(aIDSP); + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + } +} + +void YACSGui_DataNodePage::resetOPLists() +{ + DEBTRACE("YACSGui_DataNodePage::resetOPLists"); + myOPList.clear(); + + QStringList aOPortNames; + myOutputPortsGroupBox->Table()->strings( 0, aOPortNames ); + + for ( QStringList::Iterator it = aOPortNames.begin(); it != aOPortNames.end(); ++it ) + { + DEBTRACE((*it).latin1()); + if ( (*it).isEmpty() ) continue; + + try { + if ( OutPort* aODP = getNode()->getOutputPort((*it).latin1()) ) + myOPList.append(aODP); + } + catch (YACS::Exception& ex) { + try { + if ( OutPort* aODSP = getNode()->getOutputDataStreamPort((*it).latin1()) ) + myOPList.append(aODSP); + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + } +} + +void YACSGui_DataNodePage::orderPorts( bool withFilling ) +{ + DEBTRACE("YACSGui_DataNodePage::orderPorts: " << withFilling); + ElementaryNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + + QStringList aPortNames; + int aRowId; + + // order input ports according to the list of ports names in the table + myInputPortsGroupBox->Table()->strings( 0, aPortNames ); + + if ( withFilling || myIPList.isEmpty() ) + { // copy the list of engine ports into the ptr list + myIPList.clear(); + list anInPortsEngine = aNode->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + myIPList.append(*anInPortsIter); + } + + aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + InPort* anIP = myIPList.at(aRowId); + if ( !anIP ) return; + + if ( (*it).compare( QString(anIP->getName()) ) ) // diff. order + { + bool isDataStream = false; + InPort* anIPToMove = 0; + if ( dynamic_cast(anIP) ) + anIPToMove = aNode->getInputPort((*it).latin1()); + else if ( dynamic_cast(anIP) ) + { + anIPToMove = aNode->getInputDataStreamPort((*it).latin1()); + isDataStream = true; + } + + int engineId = -1; + if ( anIPToMove ) + engineId = myIPList.find( anIPToMove ); + + if ( engineId > -1 ) + { + if ( aRowId < engineId ) // it is needed to move up engine port + for ( int i=aRowId; iupdate( UP, + ( !isDataStream ? INPUTPORT : INPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anIPToMove] ); + + if ( aRowId > engineId ) // it is needed to move down engine port + for ( int i=engineId; iupdate( DOWN, + ( !isDataStream ? INPUTPORT : INPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anIPToMove] ); + } + } + + aRowId++; + } + + aPortNames.clear(); + + // order output ports according to the list of ports names in the table + myOutputPortsGroupBox->Table()->strings( 0, aPortNames ); + + if ( withFilling || myOPList.isEmpty() ) + { // copy the list of engine ports into the ptr list + myOPList.clear(); + list anOutPortsEngine = aNode->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + myOPList.append(*anOutPortsIter); + } + + aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + OutPort* anOP = myOPList.at(aRowId); + if ( !anOP ) return; + + if ( (*it).compare( QString(anOP->getName()) ) ) // diff. order + { + bool isDataStream = false; + OutPort* anOPToMove = 0; + if ( dynamic_cast(anOP) ) + anOPToMove = aNode->getOutputPort((*it).latin1()); + else if ( dynamic_cast(anOP) ) + { + anOPToMove = aNode->getOutputDataStreamPort((*it).latin1()); + isDataStream = true; + } + + int engineId = -1; + if ( anOPToMove ) + engineId = myOPList.find( anOPToMove ); + + if ( engineId > -1 ) + { + if ( aRowId < engineId ) // it is needed to move up engine port + for ( int i=aRowId; iupdate( UP, + ( !isDataStream ? OUTPUTPORT : OUTPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anOPToMove] ); + + if ( aRowId > engineId ) // it is needed to move down engine port + for ( int i=engineId; iupdate( DOWN, + ( !isDataStream ? OUTPUTPORT : OUTPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anOPToMove] ); + } + } + + aRowId++; + } + + mySNode->update( UPDATE, 0, mySNode ); +} + +void YACSGui_DataNodePage::setProperties() +{ + DEBTRACE("YACSGui_DataNodePage::setProperties"); + ElementaryNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + DataNode* aDataNode = dynamic_cast( getNode() ); + if ( !aDataNode ) return; + if (_isStudy) + { + string aStudyName(_studyName.latin1()); + if (! _studyName.isEmpty()) aDataNode->setRef(aStudyName); + if (_studyId) + { + std::stringstream theStudyId; + theStudyId << _studyId; + aDataNode->setProperty("StudyID", theStudyId.str()); + } + } + else + { + string aFileName(_fileName.latin1()); + if (! _fileName.isEmpty()) aDataNode->setRef(aFileName); + } +} + +void YACSGui_DataNodePage::setInputPorts() +{ + DEBTRACE("YACSGui_DataNodePage::setInputPorts"); + if ( !myInputPortsGroupBox ) return; + + ElementaryNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + DataNode* aDataNode = dynamic_cast( getNode() ); + if ( !aDataNode ) return; + + myInputPortsGroupBox->Table()->stopEdit(true); + + // remove old ports + DEBTRACE("Remove old ports"); + list anInPortsEngine = aNode->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + if ( !isStored(*anInPortsIter) ) + { + DEBTRACE("Port not stored: " << *anInPortsIter); + mySNode->update( REMOVE, + ( dynamic_cast(*anInPortsIter) ? INPUTPORT : INPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] ); + myIPList.take(myIPList.find(*anInPortsIter)); + + //aNode->edRemovePort(*anInPortsIter); + // remove port subject (and all subject links connected to this port) + mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] ); + } + + // read input data and input data stream ports from the table + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + + QStringList aPortNames; + QStringList aValues; + + aTable->strings( 0, aPortNames ); + aTable->strings( 3, aValues ); + + YACS::ENGINE::Catalog* aCatalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it,++aRowId ) + { + if ( (*it).isEmpty() ) continue; + + if ( aPortNames.contains(*it) > 1 ) + { + std::string what("The node "); + what += mySNode->getName(); + what += " contains two or more "; + what+=(*it).latin1(); + what+=" input ports"; + INFOS("=========="<getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + what, + tr("BUT_OK")); + continue; + } + + // retrieve a type name of the input port as a string + std::string aType = ""; + + if (QTableItem* anItem = aTable->item( aRowId, 2 ) ) + { + if ( QComboBox* aCB = dynamic_cast(aTable->cellWidget( aRowId, 2 )) ) + { + if ( aCB->lineEdit() ) + aType = aCB->lineEdit()->text().latin1(); + } + else + aType = anItem->text().latin1(); + } + + TypeCode* aTC = 0; + bool toSwitch = true; + if ( !aType.empty() ) + { + QStringList aL = aTable->Params( aRowId, 2 ); + if ( aL.findIndex( QString(aType) ) == -1 ) toSwitch = false; + } + + if ( toSwitch ) + { + switch ( DynType(aTable->intValueCombo( 2, aRowId ) + 1) ) + { + case Double: + aType = "double"; + break; + case Int: + aType = "int"; + break; + case String: + aType = "string"; + break; + case Bool: + aType = "bool"; + break; + case Objref: + //aType = "objref"; + break; + case Sequence: + //aType = "sequence"; + break; + case Array: + //aType = "array"; + break; + case Struct: + //aType = "struct"; + break; + default: + break; + } + } + else + { + if ( myRow2DataTypeIn.find(aRowId) != myRow2DataTypeIn.end() ) + aTC = myRow2DataTypeIn[aRowId]->clone(); + if ( !aTC ) + { + std::cerr << "Problem with data types initialization" << std::endl; + continue; + } + } + + GuiEvent anEvent = EDIT; + if ( aTable->intValueCombo( 1, aRowId ) == 0 ) // Data Flow port + { + InputPort* aIDP = 0; + if ( myRow2StoredInPorts.find(aRowId) != myRow2StoredInPorts.end() ) + { // ---- update port ---- + if ( aIDP = dynamic_cast(myRow2StoredInPorts[aRowId]) ) + { + aIDP->setName(*it); + aTC = aIDP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + if ( !toSwitch ) + { + aIDP = aNode->edAddInputPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectInputPort(..) to public method + mySNode->addSubjectInputPort( aIDP, *it ); + } + else + { + aIDP = dynamic_cast( dynamic_cast(mySNode)->addInputPort( aCatalog, aType, *it )->getPort() ); + aTC = aIDP->edGetType(); + } + + // ADD event will be emitted from hmi after subject creation => re-create port prs + anEvent = ADD; + + myIPList.append(aIDP); + } + + if ( aIDP ) + { + // initialize new input data port + if(aValues[aRowId].isNull() || aValues[aRowId] == "< ? >") + continue; + + string val; + switch ( aTC->kind() ) + { + case Double: + { + if(_isStudy) + val=aValues[aRowId].latin1(); + else + { + stringstream sval; + double vald = aValues[aRowId].toDouble(); + sval << vald; + val = sval.str(); + } + aDataNode->setData(aIDP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + case Int: + { + if(_isStudy) + val=aValues[aRowId].latin1(); + else + { + stringstream sval; + int vali = aValues[aRowId].toInt(); + sval << vali; + val = sval.str(); + } + aDataNode->setData(aIDP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + case String: + { + val = ""; + if (! aValues[aRowId].isNull()) + val = aValues[aRowId].latin1(); + aDataNode->setData(aIDP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + case Bool: + { + if(_isStudy) + val=aValues[aRowId].latin1(); + else + val = (aValues[aRowId].compare( aTable->Params(aRowId,3)[0] ) ? "0" : "1" ); + aDataNode->setData(aIDP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + //case Objref: + //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + //anEvent = EDIT; + //break; + //case Sequence: + //aIDP->edInit( "" ); // TODO : create an Any* (i.e. SequenceAny*) with corresponding type and initialize with it + //anEvent = EDIT; + //break; + //case Array: + //aIDP->edInit( "" ); // TODO : create an Any* (i.e. ArrayAny*) with corresponding type and initialize with it + //anEvent = EDIT; + //break; + //case Struct: + //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + //anEvent = EDIT; + //break; + default: + { + //DEBTRACE("Problem, default type -------------------------------------------------"); + if(_isStudy) + { + string val = aValues[aRowId].latin1(); + aDataNode->setData(aIDP, val ); + anEvent = EDIT; + DEBTRACE(val); + } + // When Apply clicked directly after edition, abort on following line +// string val = aValues[aRowId].latin1(); +// aDataNode->setData(aIDP, val ); +// anEvent = EDIT; + break; + } + } + + if ( anEvent == EDIT ) + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDP]); + //else if ( anEvent == ADD ) + // mySNode->update( ADD, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDP]); + } + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 1 ) // Data Stream (BASIC) port + // aNode->edAddInputDataStreamPort( *it, aTC ); + // // TODO : initialize new created input data stream port + + else if ( aTable->intValueCombo( 1, aRowId ) == 2 ) // Data Stream (CALCIUM) port + { + InputDataStreamPort* aIDSP = 0; + if ( myRow2StoredInPorts.find(aRowId) != myRow2StoredInPorts.end() ) + { // ---- update port ---- + DEBTRACE("---- update port ---- " << *it); + if ( aIDSP = dynamic_cast(myRow2StoredInPorts[aRowId]) ) + { + aIDSP->setName(*it); + aTC = aIDSP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + DEBTRACE("---- create port ---- " << *it); + if ( aType.empty() ) + { + aIDSP = aNode->edAddInputDataStreamPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectIDSPort(..) to public method + mySNode->addSubjectIDSPort( aIDSP, *it ); + } + else + { + aIDSP = dynamic_cast( dynamic_cast(mySNode)->addIDSPort( aCatalog, aType, *it )->getPort() ); + aTC = aIDSP->edGetType(); + } + + // ADD event will be emitted => re-create port prs + anEvent = ADD; + + myIPList.append(aIDSP); + } + + // TODO : initialize new created input data stream port + + if ( aIDSP && anEvent == EDIT ) + mySNode->update( EDIT, INPUTDATASTREAMPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDSP]); + //else if ( anEvent == ADD ) + // mySNode->update( ADD, INPUTDATASTREAMPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDSP]); + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 3 ) // Data Stream (PALM) port + // aNode->edAddInputDataStreamPort( *it, aTC ); + // // TODO : initialize new created input data stream port + + } + + //resetIPLists(); +} + +void YACSGui_DataNodePage::setOutputPorts() +{ + DEBTRACE("YACSGui_DataNodePage::setOutputPorts"); + if ( !myOutputPortsGroupBox ) return; + + ElementaryNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + DataNode* aDataNode = dynamic_cast( getNode() ); + if ( !aDataNode ) return; + + myOutputPortsGroupBox->Table()->stopEdit(true); + + // remove old ports + list anOutPortsEngine = aNode->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + if ( !isStored(*anOutPortsIter) ) + { + DEBTRACE("Port not stored: " << *anOutPortsIter); + mySNode->update( REMOVE, + ( dynamic_cast(*anOutPortsIter) ? OUTPUTPORT : OUTPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] ); + myOPList.take(myOPList.find(*anOutPortsIter)); + + //aNode->edRemovePort(*anOutPortsIter); + // remove port subject (and all subject links connected to this port) + mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] ); + } + + DEBTRACE("YACSGui_DataNodePage::setOutputPorts"); + // read output data and output data stream ports from the table + YACSGui_Table* aTable = myOutputPortsGroupBox->Table(); + + QStringList aPortNames; + QStringList aValues; + + aTable->strings( 0, aPortNames ); + aTable->strings( 3, aValues ); + + YACS::ENGINE::Catalog* aCatalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + DEBTRACE("YACSGui_DataNodePage::setOutputPorts"); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it,++aRowId ) + { + DEBTRACE(aRowId << " " << *it); + if ( (*it).isEmpty() ) continue; + + if ( aPortNames.contains(*it) > 1 ) + { + std::string what("The node "); + what += mySNode->getName(); + what += " contains two or more "; + what+=(*it).latin1(); + what+=" output ports"; + INFOS("=========="<getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + what, + tr("BUT_OK")); + continue; + } + + // retrieve a type name of the input port as a string + std::string aType = ""; + + if (QTableItem* anItem = aTable->item( aRowId, 2 ) ) + { + if ( QComboBox* aCB = dynamic_cast(aTable->cellWidget( aRowId, 2 )) ) + { + if ( aCB->lineEdit() ) + aType = aCB->lineEdit()->text().latin1(); + } + else + aType = anItem->text().latin1(); + } + DEBTRACE(aType); + + TypeCode* aTC = 0; + bool toSwitch = true; + if ( !aType.empty() ) + { + QStringList aL = aTable->Params( aRowId, 2 ); + if ( aL.findIndex( QString(aType) ) == -1 ) toSwitch = false; + } + DEBTRACE(toSwitch); + if ( toSwitch ) + { + DEBTRACE("switch branch " << DynType(aTable->intValueCombo( 2, aRowId ) + 1)); + switch ( DynType(aTable->intValueCombo( 2, aRowId ) + 1) ) + { + case Double: + aType = "double"; + break; + case Int: + aType = "int"; + break; + case String: + aType = "string"; + break; + case Bool: + aType = "bool"; + break; + case Objref: + //aType = "objref"; + break; + case Sequence: + //aType = "sequence"; + break; + case Array: + //aType = "array"; + break; + case Struct: + //aType = "struct"; + break; + default: + break; + } + DEBTRACE(aType); + } + else + { + DEBTRACE("no switch branch " << myRow2DataTypeOut.size()); + if ( myRow2DataTypeOut.find(aRowId) != myRow2DataTypeOut.end() ) + { + DEBTRACE(myRow2DataTypeOut[aRowId]); + aTC = myRow2DataTypeOut[aRowId]->clone(); + } + if ( !aTC ) + { + std::cerr << "Problem with initialization of data types" << std::endl; + continue; + } + DEBTRACE(aTC); + } + + DEBTRACE("YACSGui_DataNodePage::setOutputPorts " << aTable->intValueCombo( 1, aRowId )); + + GuiEvent anEvent = EDIT; + if ( aTable->intValueCombo( 1, aRowId ) == 0 ) // Data Flow port + { + DEBTRACE("Data Flow"); + OutputPort* aODP = 0; + if ( myRow2StoredOutPorts.find(aRowId) != myRow2StoredOutPorts.end() ) + { // ---- update port ---- + DEBTRACE("---- update port ---- " << *it); + if ( aODP = dynamic_cast(myRow2StoredOutPorts[aRowId]) ) + { + aODP->setName(*it); + aTC = aODP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + DEBTRACE("---- create port ---- " << *it); + if ( !toSwitch ) + { + aODP = aNode->edAddOutputPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectOutputPort(..) to public method + mySNode->addSubjectOutputPort( aODP, *it ); + } + else + { + DEBTRACE("from catalog"); + aODP = dynamic_cast( dynamic_cast(mySNode)->addOutputPort( aCatalog, aType, *it )->getPort() ); + aTC = aODP->edGetType(); + } + + // ADD event will be emitted from hmi after subject creation => re-create port prs + anEvent = ADD; + + myOPList.append(aODP); + } + + if ( aODP ) + { + DEBTRACE("initialize ODP") + + // initialize new created input data port + string val; + switch ( aTC->kind() ) + { + case Double: + { + if (aValues[aRowId].isNull()) + break; + if(_isStudy) + val=aValues[aRowId].latin1(); + else + { + stringstream sval; + double vald = aValues[aRowId].toDouble(); + sval << vald; + val = sval.str(); + } + aDataNode->setData(aODP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + case Int: + { + if (aValues[aRowId].isNull()) + break; + if(_isStudy) + val=aValues[aRowId].latin1(); + else + { + stringstream sval; + int vali = aValues[aRowId].toInt(); + sval << vali; + val = sval.str(); + } + aDataNode->setData(aODP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + case String: + { + if (aValues[aRowId].isNull()) + break; + val = ""; + if (! aValues[aRowId].isNull()) + val = aValues[aRowId].latin1(); + aDataNode->setData(aODP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + case Bool: + { + if (aValues[aRowId].isNull()) + break; + if(_isStudy) + val=aValues[aRowId].latin1(); + else + val = (aValues[aRowId].compare( aTable->Params(aRowId,3)[0] ) ? "0" : "1" ); + aDataNode->setData(aODP, val ); + anEvent = EDIT; + DEBTRACE(val); + break; + } + //case Objref: + //aODP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + //anEvent = EDIT; + //break; + //case Sequence: + //aODP->edInit( "" ); // TODO : create an Any* (i.e. SequenceAny*) with corresponding type and initialize with it + //anEvent = EDIT; + //break; + //case Array: + //aODP->edInit( "" ); // TODO : create an Any* (i.e. ArrayAny*) with corresponding type and initialize with it + //anEvent = EDIT; + //break; + //case Struct: + //aODP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + //anEvent = EDIT; + //break; + default: + { + //DEBTRACE("Problem, default type -------------------------------------------------" ); + if (aValues[aRowId].isNull()) + break; + if(_isStudy) + { + val = aValues[aRowId].latin1(); + aDataNode->setData(aODP, val ); + anEvent = EDIT; + DEBTRACE(val); + } +// string val = aValues[aRowId].latin1(); +// aDataNode->setData(aODP, val ); +// anEvent = EDIT; +// break; + } + } + + if ( anEvent == EDIT ) + mySNode->update( EDIT, OUTPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aODP]); + } + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 1 ) // Data Stream (BASIC) port + // aNode->edAddOutputDataStreamPort( *it, aTC ); + + else if ( aTable->intValueCombo( 1, aRowId ) == 2 ) // Data Stream (CALCIUM) port + { + DEBTRACE("datastream ports"); + OutputDataStreamPort* aODSP = 0; + if ( myRow2StoredOutPorts.find(aRowId) != myRow2StoredOutPorts.end() ) + { // ---- update port ---- + DEBTRACE("---- update port ---- " << *it); + if ( aODSP = dynamic_cast(myRow2StoredOutPorts[aRowId]) ) + { + aODSP->setName(*it); + aTC = aODSP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + DEBTRACE("---- create port ---- " << *it); + if ( aType.empty() ) + { + aODSP = aNode->edAddOutputDataStreamPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectODSPort(..) to public method + mySNode->addSubjectODSPort( aODSP, *it ); + } + else + { + aODSP = dynamic_cast( dynamic_cast(mySNode)->addODSPort( aCatalog, aType, *it )->getPort() ); + aTC = aODSP->edGetType(); + } + + // ADD event will be emitted => re-create port prs + anEvent = ADD; + + myOPList.append(aODSP); + } + + if ( aODSP && anEvent == EDIT ) + mySNode->update( EDIT, OUTPUTDATASTREAMPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aODSP]); + + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 3 ) // Data Stream (PALM) port + // aNode->edAddOutputDataStreamPort( *it, aTC ); + + // TODO : Remember "Is in study" flag for output pirt + // ... + + } + + //resetOPLists(); +} + +YACS::ENGINE::TypeCode* YACSGui_DataNodePage::createTypeCode( YACS::ENGINE::DynType theType, + YACSGui_Table* theTable, + int theRowId ) +{ + TypeCode* aTC = 0; + + switch (theType) + { + case Double: + case Int: + case String: + case Bool: + aTC = new TypeCode(theType); + break; + case Objref: + { + if ( theTable->intValueCombo( 1, theRowId ) == 2 ) // Data Stream (CALCIUM) port + aTC = new TypeCodeObjref("CALCIUM","CALCIUM"); + else if ( theTable->intValueCombo( 1, theRowId ) == 1 ) // Data Stream (BASIC) port + aTC = new TypeCodeObjref("BASIC","BASIC"); + else if ( theTable->intValueCombo( 1, theRowId ) == 3 ) // Data Stream (PALM) port + aTC = new TypeCodeObjref("PALM","PALM"); + else + aTC = new TypeCodeObjref("",""); + } + break; + case Sequence: + aTC = new TypeCodeSeq("","",(new TypeCode(Double))); + break; + case Array: + aTC = new TypeCodeArray("","",(new TypeCode(Double)),0); + break; + case Struct: + aTC = new TypeCodeStruct("",""); + break; + default: + break; + } + + return aTC; +} + +bool YACSGui_DataNodePage::isPortsModified( bool theInput ) +{ + DEBTRACE("YACSGui_DataNodePage::isPortsModified: " << theInput); + bool isModified = false; + + if ( !getNode() ) return isModified; + // read data and data stream ports from the table + YACSGui_Table* aTable = 0; + if ( theInput ) aTable = myInputPortsGroupBox->Table(); + else aTable = myOutputPortsGroupBox->Table(); + if ( !aTable ) return isModified; + aTable->stopEdit(true); + + QStringList aPortNames; + aTable->strings( 0, aPortNames ); + + if ( ( theInput ? aPortNames.count() != getNode()->getNumberOfInputPorts() : + aPortNames.count() != getNode()->getNumberOfOutputPorts() ) ) isModified = true; + else + { + DEBTRACE("YACSGui_DataNodePage::isPortsModified: " << isModified); + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + + aTable->strings( 1, aPortTypes ); + aTable->strings( 2, aValueTypes ); + aTable->strings( 3, aValues ); + + QStringList aPTCB = aTable->Params( 0, 1 ); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + DEBTRACE(*it); + Port* aPort = 0; + try { + aPort = ( theInput ? (Port*)(getNode()->getInPort(*it)) : (Port*)(getNode()->getOutPort(*it)) ); + } + catch (...) {} + + if ( aPort ) + { + // check value type and value of the port + DEBTRACE("YACSGui_DataNodePage::isPortsModified: " << getPortValue( aPort ) << " " << getPortType( aPort ) ); + QString value=aValues[aRowId]; + QString valtype=aValueTypes[aRowId]; + if(value.isNull()) + value=""; + if(valtype.isNull()) + valtype=""; + DEBTRACE(value<<","<(aPort) ) + aPortType = aPTCB[2]; + + if ( aPortType.compare(aPortTypes[aRowId]) != 0 ) + { + isModified = true; + DEBTRACE("YACSGui_DataNodePage::isPortsModified: " << isModified); + break; + } + + //if ( !theInput ) + // TODO: compare "Is in study" fields (not yet in use) + } + else // this case means that we renamed any port or added a new one (i.e. check port name) + { + isModified = true; + DEBTRACE("YACSGui_DataNodePage::isPortsModified: " << isModified); + break; + } + aRowId++; + } + } + return isModified; +} + diff --git a/src/gui/YACSGui_DataObject.cxx b/src/gui/YACSGui_DataObject.cxx index d4c078edd..dcf947631 100644 --- a/src/gui/YACSGui_DataObject.cxx +++ b/src/gui/YACSGui_DataObject.cxx @@ -23,101 +23,43 @@ #include #include -using namespace YACS::ENGINE; +#include +#include -/*! - * Constructor - */ -YACSGui_DataObject::YACSGui_DataObject( SUIT_DataObject* theParent, Proc* theProc ) - : LightApp_DataObject( theParent ), - CAM_DataObject( theParent ), - myObject( theProc ) -{ -} +#include +#include +#include -/*! - * Destructor - */ -YACSGui_DataObject::~YACSGui_DataObject() -{ -} - -/*! - * Returns the data object icon - */ -QPixmap YACSGui_DataObject::icon() const -{ - return QPixmap(); -} +#include +#include +#include +#include +#include +#include +#include +#include -/*! - * Returns the data object name - */ -QString YACSGui_DataObject::name() const -{ - QString aName; - - if (myObject) - aName = myObject->getName(); - - return aName; -} - -/*! - * Returns the data object entry - */ -QString YACSGui_DataObject::entry() const -{ - return QString(""); -} +using namespace YACS::ENGINE; +// YACSGui_DataObject class: /*! * Constructor */ -YACSGui_ModuleObject::YACSGui_ModuleObject ( CAM_DataModel* theDataModel, - SUIT_DataObject* theParent ) - : YACSGui_DataObject(theParent), - LightApp_ModuleObject( theDataModel, theParent ), - CAM_DataObject( theParent ) -{ -} - -/*! - * Gets name of the root - */ -QString YACSGui_ModuleObject::name() const +YACSGui_DataObject::YACSGui_DataObject( const _PTR(SObject)& sobj, SUIT_DataObject* parent, Proc* proc ) + : SalomeApp_DataObject( sobj, parent ) { - return CAM_RootObject::name(); -} - - -/*! - * Gets an icon for the root - */ -QPixmap YACSGui_ModuleObject::icon() const -{ - QPixmap aRes; - if ( dataModel() ) { - QString anIconName = dataModel()->module()->iconName(); - if ( !anIconName.isEmpty() ) - aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACSGui", anIconName, false); - } - return aRes; + myProc = proc; } /*! - * Gets a tootip for the root + * Destructor */ -QString YACSGui_ModuleObject::toolTip() const +YACSGui_DataObject::~YACSGui_DataObject() { - return QObject::tr( "YACS_ROOT_TOOLTIP" ); } -/*! - * Inherited method, redefined - */ -QString YACSGui_ModuleObject::entry() const +Proc* YACSGui_DataObject::proc() const { - return "YACS_ModuleObject"; + return myProc; } diff --git a/src/gui/YACSGui_DataObject.h b/src/gui/YACSGui_DataObject.h index f01bb5763..569e503a1 100644 --- a/src/gui/YACSGui_DataObject.h +++ b/src/gui/YACSGui_DataObject.h @@ -19,43 +19,32 @@ #ifndef YACSGui_DataObject_HeaderFile #define YACSGui_DataObject_HeaderFile +#include +#include +#include #include +#include +#include -#include +//#include +#include +#include "SALOMEDSClient.hxx" /*! * YACS module data object */ -class YACSGui_DataObject : public virtual LightApp_DataObject +class YACSGui_DataObject : public SalomeApp_DataObject { public: - YACSGui_DataObject( SUIT_DataObject*, YACS::ENGINE::Proc* = 0 ); + //enum ObjectType { SchemaObject, RunObject, NodeObject }; + YACSGui_DataObject( const _PTR(SObject)&, SUIT_DataObject* = 0, YACS::ENGINE::Proc* = 0 ); virtual ~YACSGui_DataObject(); - - virtual QString entry() const; - - QString name() const; - QPixmap icon() const; - -private: - YACS::ENGINE::Proc* myObject; -}; - -/*! - * YACS module root object - */ -class YACSGui_ModuleObject : public virtual YACSGui_DataObject, - public virtual LightApp_ModuleObject -{ -public: - YACSGui_ModuleObject ( CAM_DataModel*, SUIT_DataObject* = 0 ); + YACS::ENGINE::Proc* proc() const; - virtual QString name() const; - virtual QString entry() const; - - QPixmap icon() const; - QString toolTip() const; +protected: + //ObjectType myType; + YACS::ENGINE::Proc* myProc; }; #endif diff --git a/src/gui/YACSGui_DataTypePage.cxx b/src/gui/YACSGui_DataTypePage.cxx new file mode 100644 index 000000000..9698aeaf1 --- /dev/null +++ b/src/gui/YACSGui_DataTypePage.cxx @@ -0,0 +1,388 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_DataTypePage + Description : Page for data type import +*/ + +YACSGui_DataTypePage::YACSGui_DataTypePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : DataTypePage( theParent, theName, theFlags ), + GuiObserver(), + mySDataType( 0 ) +{ + myProcName = ""; + myProcRadioButton->setEnabled(false); + + connect( myBrowseButton, SIGNAL(clicked( )), this, SLOT(onBrowse( )) ); + connect( this, SIGNAL( enableApply( bool ) ), getInputPanel(), SLOT( onApplyEnabled( bool ) ) ); + connect( CatalogTree, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( onCatalogDataTypeClicked( QListViewItem* ) ) ); + connect( mySessionRadioButton, SIGNAL( stateChanged( int ) ), this, SLOT( onCatalogChanged( int ) ) ); + connect( myProcRadioButton, SIGNAL( stateChanged( int ) ), this, SLOT( onCatalogChanged( int ) ) ); +} + +YACSGui_DataTypePage::~YACSGui_DataTypePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); + + if ( mySDataType ) mySDataType->detach(this); +} + +void YACSGui_DataTypePage::select( bool isSelected ) +{ + DEBTRACE(">> YACSGui_DataTypePage::select"); +} + +void YACSGui_DataTypePage::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSGui_DataTypePage::update"); +} + +void YACSGui_DataTypePage::setSDataType( YACS::HMI::SubjectDataType* theSDataType ) +{ + if ( theSDataType && mySDataType != theSDataType ) + { + if ( mySDataType ) mySDataType->detach(this); //detach from old schema + mySDataType = theSDataType; + mySDataType->attach(this); // attach to new schema + } + updateState(); +} + +YACS::ENGINE::TypeCode* YACSGui_DataTypePage::getTypeCode() const +{ + return ( mySDataType ? dynamic_cast(mySDataType->getTypeCode()) : 0 ); +} + +QString YACSGui_DataTypePage::getDataTypeName() const +{ + return ( mySDataType ? QString( mySDataType->getName() ) : QString("") ); +} + +YACSGui_InputPanel* YACSGui_DataTypePage::getInputPanel() const +{ + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( !anApp ) + return 0; + + YACSGui_Module* aModule = dynamic_cast( anApp->activeModule() ); + if( !aModule ) + return 0; + + return aModule->getInputPanel(); +} + +void YACSGui_DataTypePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + myMode = theMode; + + if ( myMode == YACSGui_InputPanel::NewMode ) + { + CatalogGroupBox->show(); + getInputPanel()->onApplyEnabled(false); + updateState(); + } + else if ( myMode == YACSGui_InputPanel::EditMode ) + { + CatalogGroupBox->hide(); + getInputPanel()->onApplyEnabled(true); + } +} + +void YACSGui_DataTypePage::onApply() +{ + if ( myMode == YACSGui_InputPanel::NewMode ) + { + GuiContext* aContext = GuiContext::getCurrent(); + if ( !aContext ) return; + + YACSGui_Module* aModule = getInputPanel()->getModule(); + if ( !aModule ) return; + + YACSGui_EditionTreeView * aETV = dynamic_cast(aModule->activeTreeView()); + if ( !aETV ) return; + + SubjectProc* aSchema = aContext->getSubjectProc(); + + YACS::ENGINE::Catalog* aCatalog = 0; + if ( myProcRadioButton->isChecked() ) + { + aCatalog = YACS::ENGINE::getSALOMERuntime()->loadCatalog( "proc", myProcName.c_str() ); + std::string errors=aCatalog->getErrors(); + if ( errors != "" ) + { + std::string msg="The imported file "; + msg=msg+myProcName+" has errors. Some nodes can be uncompletely built\n"; + LogViewer* log=new LogViewer(msg+errors,getInputPanel()->getModule()->getApp()->desktop(),"dialog",WDestructiveClose); + log->show(); + getInputPanel()->getModule()->getApp()->logWindow()->putMessage(msg+errors ); + } + } + else + aCatalog = aModule->getCatalog(); + + QListViewItem* anItem = CatalogTree->selectedItem(); + + if ( aSchema && aCatalog && anItem ) + { + string data_type; + if ( !myProcRadioButton->isChecked() ) + { + if ( myDataTypeMap.find( anItem ) == myDataTypeMap.end() ) + return; + + data_type = myDataTypeMap[anItem]; + } + else + { + if ( anItem->text( 0 ).isNull() ) + return; + + if ( !myProcDataTypesMap.count( anItem ) ) + return; + + data_type = anItem->text( 0 ).latin1(); + YACS::ENGINE::TypeCode* aTC = myProcDataTypesMap[ anItem ]; + + // Add data type in catalog map if necessary. In the other case it will not be + // found in CommandAddDataTypeFromCatalog method + if ( aCatalog->_typeMap.find(data_type) == aCatalog->_typeMap.end() ) + aCatalog->_typeMap[ data_type ] = aTC; + } + + // data type ( engine - subject ) creation + SubjectDataType* aCreatedDT = aSchema->addDataType( aCatalog, data_type ); + if ( !aCreatedDT ) + { + SUIT_MessageBox::warn1(aModule->getApp()->desktop(), + tr("WARNING"), + GuiContext::getCurrent()->_lastErrorMessage, + tr("BUT_OK")); + } + else aModule->temporaryExport(); + } + + //aModule->setGuiMode(YACSGui_Module::EditMode); + setMode(YACSGui_InputPanel::EditMode); + + if ( aModule->activeTreeView() ) + aModule->activeTreeView()->syncPageTypeWithSelection(); + + return; + } + +} + +void YACSGui_DataTypePage::onBrowse( ) +{ + QString fn = QFileDialog::getOpenFileName( QString::null, + tr( "XML-Files (*.xml);;All Files (*)" ), + this, + "load YACS scheme file dialog as catalog", + "Choose a filename to load" ); + if ( fn.isEmpty() ) + return; + + myProcName = fn.latin1(); + + myProcRadioButton->setEnabled(true); + myProcRadioButton->setChecked(true); + + getInputPanel()->onApplyEnabled(false); + updateState(); +} + +void YACSGui_DataTypePage::onCatalogDataTypeClicked( QListViewItem* it ) +{ + if ( it ) + if ( !myProcRadioButton->isChecked() ) + { + // session catalog is used + std::string aDT = myDataTypeMap[it]; + getInputPanel()->onApplyEnabled(!aDT.empty()); + } + else + { + // proc catalog is used. Apply button should be enabled if selected item is a data type. + QListViewItem* aParent = it->parent(); + getInputPanel()->onApplyEnabled( aParent != 0 ); + } +} + +void YACSGui_DataTypePage::onCatalogChanged( int ) +{ + getInputPanel()->onApplyEnabled(false); + updateState(); +} + +void YACSGui_DataTypePage::updateState() +{ + if ( myMode == YACSGui_InputPanel::NewMode ) + { + CatalogTree->clear(); + CatalogTree->setRootIsDecorated( TRUE ); + QListViewItem* aDTRoot = new QListViewItem( CatalogTree, tr( "DATA_TYPES" ) ); + + YACS::ENGINE::Catalog *_currentCatalog; + if ( myProcRadioButton->isChecked() ) + { + _currentCatalog = YACS::ENGINE::getSALOMERuntime()->loadCatalog( "proc", myProcName.c_str() ); + std::string errors=_currentCatalog->getErrors(); + if(errors != "") + { + std::string msg="The imported file "; + msg=msg+myProcName+" has errors. Some nodes can be uncompletely built\n"; + LogViewer* log=new LogViewer(msg+errors,getInputPanel()->getModule()->getApp()->desktop(),"dialog",WDestructiveClose); + log->show(); + getInputPanel()->getModule()->getApp()->logWindow()->putMessage(msg+errors ); + } + + if ( _currentCatalog ) + { + myProcDataTypesMap.clear(); + buildTree( _currentCatalog, aDTRoot ); + } + } + else + { + _currentCatalog = getInputPanel()->getModule()->getCatalog(); + if (_currentCatalog) buildTree( _currentCatalog, aDTRoot ); + } + + return; + } +} + +void YACSGui_DataTypePage::buildTree( YACS::ENGINE::Catalog* theCatalog, QListViewItem* theParent ) +{ + if ( !theCatalog ) return; + + map shortList; + + std::map::iterator anIter; + for ( anIter = theCatalog->_typeMap.begin(); anIter != theCatalog->_typeMap.end(); ++anIter ) + { + TypeCode* aTC = anIter->second; + if ( !aTC ) continue; + string aName( aTC->name() ); + if ( aName.empty()) continue; + shortList[aName] = aTC; + } + + for ( anIter = shortList.begin(); anIter != shortList.end(); ++anIter ) + { + TypeCode* aTC = anIter->second; + + // Create item corresponding to the data type + QString aName( aTC->name() ); + QListViewItem* anItem = new QListViewItem( theParent, aName ); + anItem->setPixmap( 0, YACSGui_DataTypeItem::icon() ); + + if ( myProcRadioButton->isChecked() ) myProcDataTypesMap[ anItem ] = aTC; + else myDataTypeMap[ anItem ] = aTC->name(); + } +} diff --git a/src/gui/YACSGui_Executor.cxx b/src/gui/YACSGui_Executor.cxx index 398bedaf3..1f2c01333 100644 --- a/src/gui/YACSGui_Executor.cxx +++ b/src/gui/YACSGui_Executor.cxx @@ -30,6 +30,11 @@ #include +#include //for debug only + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; using namespace YACS; using namespace std; @@ -43,13 +48,15 @@ YACSGui_Executor::YACSGui_Executor(YACSGui_Module* guiMod, Proc* theProc) : _proc(theProc) { _localEngine = 0; - _engineRef = YACSGui_ORB::YACSGui_Gen::_nil(); - _procRef = YACSGui_ORB::ProcExec::_nil(); - _observerRef = YACSGui_ORB::Observer::_nil(); + _engineRef = YACS_ORB::YACS_Gen::_nil(); + _procRef = YACS_ORB::ProcExec::_nil(); + _observerRef = YACS_ORB::Observer::_nil(); _serv = 0; _isRunning = false; _isSuspended = false; + _isStopOnError = false; _execMode = YACS::CONTINUE; + _loadStateFile = ""; } //! Destructor @@ -76,7 +83,7 @@ void YACSGui_Executor::run() */ void YACSGui_Executor::runDataflow(const bool isRemoteRun) { - MESSAGE("YACSGui_Executor::runDataflow"); + DEBTRACE("YACSGui_Executor::runDataflow"); _isRemoteRun = isRemoteRun; if (!isRemoteRun) // --- wanted local run { @@ -91,7 +98,10 @@ void YACSGui_Executor::runDataflow(const bool isRemoteRun) else // --- wanted run in a SALOME Container { if (CORBA::is_nil(_engineRef)) + { + DEBTRACE(">> Create YACS ORB engine!"); _engineRef = YACSGui_Module::InitYACSGuiGen(_guiMod->getApp()); + } if (_isRunning) if (! checkEndOfDataFlow()) return; @@ -101,18 +111,38 @@ void YACSGui_Executor::runDataflow(const bool isRemoteRun) if (CORBA::is_nil(_procRef)) { - MESSAGE("init _procRef"); - VisitorSaveSchema aWriter( _proc ); + DEBTRACE("init _procRef"); + VisitorSaveSalomeSchema aWriter( _proc ); aWriter.openFileSchema( aFileName ); aWriter.visitProc( _proc ); aWriter.closeFileSchema(); _procRef = _engineRef->LoadProc(aFileName.latin1()); registerStatusObservers(); - MESSAGE("_procRef _init"); + DEBTRACE("_procRef _init"); } _procRef->setExecMode(getCurrentExecMode()); _setBPList(); - _procRef->Run(); + if ( _loadStateFile.empty() ) + { + DEBTRACE(">> Run!"); + cout<<">> this = "<Run(); + } + else + { + DEBTRACE(">> Run from STATE!"); + try { + _procRef->RunFromState(_loadStateFile.c_str()); + } + catch (...) { + SUIT_MessageBox::error1(_guiMod->getApp()->desktop(), + tr("ERROR"), + tr("Runtime error: execution from the loaded state failed"), + tr("BUT_OK")); + return; + } + cout<<">> this = "<resumeCurrentBreakPoint(); } else - _procRef->setExecMode(YACSGui_ORB::STEPBYSTEP); + _procRef->setExecMode(YACS_ORB::STEPBYSTEP); } _isSuspended = !_isSuspended; } void YACSGui_Executor::suspendDataflow() { - MESSAGE("YACSGui_Executor::suspendDataflow"); + DEBTRACE("YACSGui_Executor::suspendDataflow"); if (running()) // --- local run { _localEngine->setExecMode(YACS::STEPBYSTEP); } else if (_isRunning) // --- remote run { - _procRef->setExecMode(YACSGui_ORB::STEPBYSTEP); + _procRef->setExecMode(YACS_ORB::STEPBYSTEP); } } void YACSGui_Executor::resumeDataflow() { - MESSAGE("YACSGui_Executor::ResumeDataflow"); + DEBTRACE("YACSGui_Executor::ResumeDataflow"); if (running()) // --- local run { _localEngine->setExecMode(_execMode); @@ -236,9 +266,12 @@ void YACSGui_Executor::resumeDataflow() } } +//! Stop dataflow. +/*! + */ void YACSGui_Executor::stopDataflow() { - MESSAGE("YACSGui_Executor::stopDataflow"); + DEBTRACE("YACSGui_Executor::stopDataflow"); if (running()) // --- local run { _localEngine->stopExecution(); @@ -252,21 +285,17 @@ void YACSGui_Executor::stopDataflow() void YACSGui_Executor::setStepByStepMode() { - MESSAGE("YACSGui_Executor::setStepByStepMode"); + DEBTRACE("YACSGui_Executor::setStepByStepMode"); _execMode = YACS::STEPBYSTEP; if (running()) // --- local run - { - _localEngine->setExecMode(YACS::STEPBYSTEP); - } + _localEngine->setExecMode(YACS::STEPBYSTEP); else if (_isRunning) // --- remote run - { - _procRef->setExecMode(YACSGui_ORB::STEPBYSTEP); - } + _procRef->setExecMode(YACS_ORB::STEPBYSTEP); } void YACSGui_Executor::setContinueMode() { - MESSAGE("YACSGui_Executor::setContinueMode"); + DEBTRACE("YACSGui_Executor::setContinueMode"); _execMode = YACS::CONTINUE; if (running()) // --- local run { @@ -274,13 +303,13 @@ void YACSGui_Executor::setContinueMode() } else if (_isRunning) // --- remote run { - _procRef->setExecMode(YACSGui_ORB::CONTINUE); + _procRef->setExecMode(YACS_ORB::CONTINUE); } } void YACSGui_Executor::setBreakpointMode() { - MESSAGE("YACSGui_Executor::setBreakpointMode"); + DEBTRACE("YACSGui_Executor::setBreakpointMode"); _execMode = YACS::STOPBEFORENODES; if (running()) // --- local run { @@ -288,33 +317,70 @@ void YACSGui_Executor::setBreakpointMode() } else if (_isRunning) // --- remote run { - _procRef->setExecMode(YACSGui_ORB::STOPBEFORENODES); + _procRef->setExecMode(YACS_ORB::STOPBEFORENODES); } } void YACSGui_Executor::setStopOnError(bool aMode) { - MESSAGE("YACSGui_Executor::setStopOnError"); + DEBTRACE("YACSGui_Executor::setStopOnError"); if (running()) // --- local run { _localEngine->setStopOnError(aMode, "/tmp/dumpStateOnError.xml"); + _isStopOnError = true; } else if (_isRunning) // --- remote run { _procRef->setStopOnError(aMode, "/tmp/dumpStateOnError.xml"); + _isStopOnError = true; + } +} + +void YACSGui_Executor::unsetStopOnError() +{ + DEBTRACE("YACSGui_Executor::unsetStopOnError"); + if (running()) // --- local run + { + _localEngine->unsetStopOnError(); + _isStopOnError = false; + } + else if (_isRunning) // --- remote run + { + _procRef->unsetStopOnError(); + _isStopOnError = false; } } +void YACSGui_Executor::saveState(const std::string& xmlFile) +{ + DEBTRACE("YACSGui_Executor::saveState"); + bool StartFinish = (getExecutorState() == YACS::NOTYETINITIALIZED || getExecutorState() == YACS::FINISHED ); + + if ( running() + || + _localEngine && (CORBA::is_nil(_procRef)) && StartFinish ) // --- local run + _localEngine->saveState(xmlFile); + else if ( _isRunning + || + !_localEngine && !(CORBA::is_nil(_procRef)) && StartFinish ) // --- remote run + _procRef->saveState(xmlFile.c_str()); +} + +void YACSGui_Executor::setLoadStateFile(std::string xmlFile) +{ + _loadStateFile = xmlFile; +} + void YACSGui_Executor::setNextStepList(std::list nextStepList) { - MESSAGE("YACSGui_Executor::setNextStepList"); + DEBTRACE("YACSGui_Executor::setNextStepList"); if (running()) // --- local run { _localEngine->setStepsToExecute(nextStepList); } else if (_isRunning) // --- remote run { - YACSGui_ORB::stringArray listOfNextStep; + YACS_ORB::stringArray listOfNextStep; listOfNextStep.length(nextStepList.size()); int i=0; for (list::iterator it = nextStepList.begin(); it != nextStepList.end(); ++it) @@ -325,7 +391,7 @@ void YACSGui_Executor::setNextStepList(std::list nextStepList) void YACSGui_Executor::setBreakpointList(std::list breakpointList) { - MESSAGE("YACSGui_Executor::setBreakpointList"); + DEBTRACE("YACSGui_Executor::setBreakpointList"); _breakpointList.clear(); _breakpointList = breakpointList; _setBPList(); @@ -340,7 +406,7 @@ void YACSGui_Executor::_setBPList() } else if (_isRunning) // --- remote run { - YACSGui_ORB::stringArray listOfBreakPoints; + YACS_ORB::stringArray listOfBreakPoints; listOfBreakPoints.length(_breakpointList.size()); int i=0; for (list::iterator it = _breakpointList.begin(); it != _breakpointList.end(); ++it) @@ -351,7 +417,7 @@ void YACSGui_Executor::_setBPList() void YACSGui_Executor::registerStatusObservers() { - MESSAGE("YACSGui_Executor::registerStatusObservers"); + DEBTRACE("YACSGui_Executor::registerStatusObservers"); if (CORBA::is_nil(_procRef)) { SUIT_MessageBox::error1(_guiMod->getApp()->desktop(), @@ -366,25 +432,99 @@ void YACSGui_Executor::registerStatusObservers() _observerRef = _serv->_this(); _serv->SetImpl(_graph->getStatusObserver()); } - MESSAGE("---"); + DEBTRACE("---"); _serv->SetRemoteProc(_procRef); _serv->setConversion(); - MESSAGE("---"); - std::set aNodeSet = _proc->getAllRecursiveConstituents(); - for ( std::set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + DEBTRACE("---"); + std::list aNodeSet = _proc->getAllRecursiveConstituents(); + for ( std::list::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) { _procRef->addObserver(_observerRef, _serv->getEngineId((*it)->getNumId()) , "status"); } _procRef->addObserver(_observerRef, _serv->getEngineId(_proc->getNumId()) , "executor"); } -YACSGui_ORB::executionMode YACSGui_Executor::getCurrentExecMode() +YACS_ORB::executionMode YACSGui_Executor::getCurrentExecMode() { switch (_execMode) { - case YACS::CONTINUE: return YACSGui_ORB::CONTINUE; - case YACS::STEPBYSTEP: return YACSGui_ORB::STEPBYSTEP; - case YACS::STOPBEFORENODES: return YACSGui_ORB::STOPBEFORENODES; - default: return YACSGui_ORB::CONTINUE; + case YACS::CONTINUE: return YACS_ORB::CONTINUE; + case YACS::STEPBYSTEP: return YACS_ORB::STEPBYSTEP; + case YACS::STOPBEFORENODES: return YACS_ORB::STOPBEFORENODES; + default: return YACS_ORB::CONTINUE; + } +} + +int YACSGui_Executor::getExecutorState() +{ + if ( running() + || + _localEngine && (CORBA::is_nil(_procRef)) ) // --- local run + return _localEngine->getExecutorState(); + else if ( _isRunning + || + !_localEngine && !(CORBA::is_nil(_procRef)) ) // --- remote run + return _procRef->getExecutorState(); + else if ( !_localEngine && (CORBA::is_nil(_procRef)) ) + return YACS::NOTYETINITIALIZED; + else if ( _localEngine && !(CORBA::is_nil(_procRef)) ) + return YACS::FINISHED; +} + +void YACSGui_Executor::setEngineRef(YACS_ORB::YACS_Gen_ptr theRef) +{ + _engineRef = theRef; +} + +std::string YACSGui_Executor::getErrorDetails(YACS::ENGINE::Node* node) +{ + if (_serv) + { + //get the node engine id + int engineId=_serv->getEngineId(node->getNumId()); + return _procRef->getErrorDetails(engineId); + } + return "---"; +} + +std::string YACSGui_Executor::getErrorReport(YACS::ENGINE::Node* node) +{ + if (_serv) + { + //get the node engine id + int engineId=_serv->getEngineId(node->getNumId()); + return _procRef->getErrorReport(engineId); + } + return "---"; +} + +std::string YACSGui_Executor::getContainerLog() +{ + DEBTRACE("YACSGui_Executor::getContainerLog"); + std::string msg=""; + if (!CORBA::is_nil(_engineRef)) + { + Engines::Container_var cont= _engineRef->GetContainerRef(); + CORBA::String_var logname = cont->logfilename(); + DEBTRACE(logname); + msg=logname; + std::string::size_type pos = msg.find(":"); + msg=msg.substr(pos+1); + } + return msg; +} + +std::string YACSGui_Executor::getContainerLog(YACS::ENGINE::Node* node) +{ + std::string msg; + if (_serv) + { + //get the node engine id + int engineId=_serv->getEngineId(node->getNumId()); + CORBA::String_var logname = _procRef->getContainerLog(engineId); + msg=logname; + std::string::size_type pos = msg.find(":"); + msg=msg.substr(pos+1); } + return msg; } diff --git a/src/gui/YACSGui_Executor.h b/src/gui/YACSGui_Executor.h index d143e28c0..cab47793b 100644 --- a/src/gui/YACSGui_Executor.h +++ b/src/gui/YACSGui_Executor.h @@ -20,8 +20,6 @@ #ifndef YACSGui_Executor_HeaderFile #define YACSGui_Executor_HeaderFile -#define YACS_PTHREAD //@ - #include #include @@ -52,29 +50,46 @@ class YACSGui_Executor : public QObject, public QThread void suspendDataflow(); void resumeDataflow(); void stopDataflow(); + void setStepByStepMode(); void setContinueMode(); void setBreakpointMode(); void setStopOnError(bool aMode); + void unsetStopOnError(); + void saveState(const std::string& xmlFile); + + void setLoadStateFile(std::string xmlFile); + + YACS_ORB::executionMode getCurrentExecMode(); + int getExecutorState(); + void setBreakpointList(std::list breakpointList); void setNextStepList(std::list nextStepList); void setGraph(YACSGui_Graph* theGraph) { _graph = theGraph; } + YACSGui_Graph* getGraph() const { return _graph; } void registerStatusObservers(); - bool isRunning() { return _isRunning; }; + bool isRunning() const { return _isRunning; }; + bool isStopOnError() const { return _isStopOnError; } + + void setEngineRef(YACS_ORB::YACS_Gen_ptr theRef); + //YACS::ENGINE::Executor* getLocalEngine() { return _localEngine; }; YACS::ENGINE::Proc* getProc() { return _proc; }; + std::string getErrorDetails(YACS::ENGINE::Node* node); + std::string getErrorReport(YACS::ENGINE::Node* node); + std::string getContainerLog(); + std::string getContainerLog(YACS::ENGINE::Node* node); protected: virtual void run(); - YACSGui_ORB::executionMode getCurrentExecMode(); void _setBPList(); private: YACS::ENGINE::Executor* _localEngine; YACS::ENGINE::Proc* _proc; - YACSGui_ORB::YACSGui_Gen_var _engineRef; - YACSGui_ORB::ProcExec_var _procRef; - YACSGui_ORB::Observer_var _observerRef; + YACS_ORB::YACS_Gen_var _engineRef; + YACS_ORB::ProcExec_var _procRef; + YACS_ORB::Observer_var _observerRef; YACS::ExecutionMode _execMode; Observer_i* _serv; YACSGui_Graph* _graph; @@ -82,7 +97,9 @@ class YACSGui_Executor : public QObject, public QThread bool _isRemoteRun; bool _isRunning; bool _isSuspended; + bool _isStopOnError; std::list _breakpointList; + std::string _loadStateFile; }; #endif diff --git a/src/gui/YACSGui_ForEachLoopNodePage.cxx b/src/gui/YACSGui_ForEachLoopNodePage.cxx new file mode 100644 index 000000000..f8d8078ef --- /dev/null +++ b/src/gui/YACSGui_ForEachLoopNodePage.cxx @@ -0,0 +1,373 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_ForEachLoopNodePage + Description : Page for FOREACH node properties +*/ + +YACSGui_ForEachLoopNodePage::YACSGui_ForEachLoopNodePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : ForEachLoopNodePage( theParent, theName, theFlags ), + YACSGui_NodePage() +{ + connect( myDataPortToDispatchValue, SIGNAL( textChanged( const QString& ) ), + this, SLOT( onSeqOfSamplesChanged( const QString& ) ) ); + + // TODO: implement presentation of the FOR node in collapsed mode + // temporary solution : + myCollapsedRadioButton->setEnabled(false ); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); +} + +YACSGui_ForEachLoopNodePage::~YACSGui_ForEachLoopNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); +} + +void YACSGui_ForEachLoopNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( dynamic_cast( theSNode->getNode() ) ) + YACSGui_NodePage::setSNode( theSNode ); +} + +void YACSGui_ForEachLoopNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + myNodeName->setReadOnly(false); + ViewModeButtonGroup->show(); + + ExecutionGroupBox->hide(); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + myNodeName->setReadOnly(true); + ViewModeButtonGroup->hide(); + + ExecutionGroupBox->show(); + } +} + +void YACSGui_ForEachLoopNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_ForEachLoopNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_ForEachLoopNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + //printf("==> ForEachLoopNodePage : Size of theInPortName2Value : %d\n",theInPortName2Value.size()); + + ForEachLoop* aForEachLoopNode = dynamic_cast( getNode() ); + if ( !aForEachLoopNode ) return; + + if ( theInPortName2Value.size() == 2 ) + { + QString aName1 = QString(aForEachLoopNode->edGetNbOfBranchesPort()->getName()); + QString aName2 = QString(aForEachLoopNode->edGetSeqOfSamplesPort()->getName()); + QString aGivenName, aValue; + + map::iterator it = theInPortName2Value.begin(); + for ( ; it!=theInPortName2Value.end(); it++ ) + { + aGivenName = QString( (*it).first ); + aValue = QString( (*it).second ); + + if ( !aGivenName.compare(aName1) && myNbBranchesInputPortValue ) + { // nbBranches port + if ( !aValue.compare(QString("< ? >")) ) + myNbBranchesInputPortValue->setValue( myNbBranchesInputPortValue->minValue() ); + else + myNbBranchesInputPortValue->setValue( aValue.toInt() ); + } + + if ( !aGivenName.compare(aName2) && myDataPortToDispatchValue ) + { // SmplsCollection port + myDataPortToDispatchValue->setText( aValue ); + } + } + } +} + +void YACSGui_ForEachLoopNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + //printf("==> ForEachLoopNodePage : Size of theOutPortName2Value : %d\n",theOutPortName2Value.size()); + // SmplPrt port (no gui control for it in the property page!) + //... +} + +void YACSGui_ForEachLoopNodePage::notifyNodeCreateBody( YACS::HMI::Subject* theSubject ) +{ + if( myLoopBodyNodeName ) + { + QString aBodyName = theSubject->getName(); + myLoopBodyNodeName->setText( aBodyName ); + } +} + +void YACSGui_ForEachLoopNodePage::checkModifications() +{ + if ( !getNode() ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + + if ( myNodeName->text().compare(getNodeName()) != 0 ) isModified = true; + else if ( YACS::ENGINE::ForEachLoop* aForEachLoopNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aBranchesPort = aForEachLoopNode->edGetNbOfBranchesPort() ) + { + bool ok; + int aValue = getPortValue( aBranchesPort ).toInt( &ok ); + if( ok && myNbBranchesInputPortValue->value() != aValue ) isModified = true; + } + if( YACS::ENGINE::InputPort* aSamplesPort = aForEachLoopNode->edGetSeqOfSamplesPort() ) + if ( myDataPortToDispatchValue->text().compare(getPortValue(aSamplesPort)) ) isModified = true; + } + + //if ( !isModified ) + // TODO: compare view mode: expanded or collapsed (not yet in use) + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::InlineNodeId); + } +} + +void YACSGui_ForEachLoopNodePage::onApply() +{ + // Rename a node + if ( myNodeName ) setNodeName( myNodeName->text() ); + + // Reset number of brances input port value and data port to dispatch value + if ( YACS::ENGINE::ForEachLoop* aForEachLoopNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aBranchesPort = aForEachLoopNode->edGetNbOfBranchesPort() ) + { + int aValue = myNbBranchesInputPortValue->value(); + aBranchesPort->edInit( aValue ); + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aBranchesPort] ); + } + + if( YACS::ENGINE::InputPort* aSamplesPort = aForEachLoopNode->edGetSeqOfSamplesPort() ) + { + QString aValue = myDataPortToDispatchValue->text(); + aSamplesPort->edInit( aValue.latin1() ); + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aSamplesPort] ); + } + } + + // Reset the view mode + // ... + + updateBlocSize(); +} + +void YACSGui_ForEachLoopNodePage::updateState() +{ + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Set number of brances input port value, data port to dispatch value and loop body node name + if ( YACS::ENGINE::ForEachLoop* aForEachLoopNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aBranchesPort = aForEachLoopNode->edGetNbOfBranchesPort() ) + { + bool ok; + int aValue = getPortValue( aBranchesPort ).toInt( &ok ); + if( ok && aValue > 1 ) + myNbBranchesInputPortValue->setValue( aValue ); + } + + if( YACS::ENGINE::InputPort* aSamplesPort = aForEachLoopNode->edGetSeqOfSamplesPort() ) + { + QString aValue = getPortValue( aSamplesPort ); + myDataPortToDispatchValue->setText( aValue ); + } + + if( myLoopBodyNodeName ) + { + std::list aNodes = aForEachLoopNode->edGetDirectDescendants(); + if ( !aNodes.empty() ) + { + QString aBodyName; + + std::list::iterator aNodesIt = aNodes.begin(); + Node* aNode = *aNodesIt; + if( aNode ) + aBodyName = aNode->getName(); + + myLoopBodyNodeName->setText( aBodyName ); + } + } + } + + // Set view mode of the given FOREACH node + // the following method can be used if its needed: + // YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( myProc ); + // ... +} + +void YACSGui_ForEachLoopNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + +void YACSGui_ForEachLoopNodePage::onSeqOfSamplesChanged( const QString& theText ) +{ + /* + QString aText = theText; + if( aText.left( 1 ) != "[" ) + aText.prepend( "[" ); + + if( aText.right( 1 ) != "]" ) + aText.append( "]" ); + + if( aText != theText ) + myDataPortToDispatchValue->setText( aText ); + */ +} + diff --git a/src/gui/YACSGui_ForLoopNodePage.cxx b/src/gui/YACSGui_ForLoopNodePage.cxx new file mode 100644 index 000000000..7d59d585c --- /dev/null +++ b/src/gui/YACSGui_ForLoopNodePage.cxx @@ -0,0 +1,331 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_ForLoopNodePage + Description : Page for FOR node properties +*/ + +YACSGui_ForLoopNodePage::YACSGui_ForLoopNodePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : ForLoopNodePage( theParent, theName, theFlags ), + YACSGui_NodePage() +{ + // TODO: implement presentation of the FOR node in collapsed mode + // temporary solution : + myCollapsedRadioButton->setEnabled(false ); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); +} + +YACSGui_ForLoopNodePage::~YACSGui_ForLoopNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); +} + +void YACSGui_ForLoopNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( dynamic_cast( theSNode->getNode() ) ) + YACSGui_NodePage::setSNode( theSNode ); +} + +void YACSGui_ForLoopNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + myNodeName->setReadOnly(false); + ViewModeButtonGroup->show(); + + ExecutionGroupBox->hide(); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + myNodeName->setReadOnly(true); + ViewModeButtonGroup->hide(); + + ExecutionGroupBox->show(); + } +} + +void YACSGui_ForLoopNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_ForLoopNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_ForLoopNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + DEBTRACE("==> ForLoopNodePage : Size of theInPortName2Value : " << theInPortName2Value.size()); + + ForLoop* aForLoopNode = dynamic_cast( getNode() ); + if ( !aForLoopNode ) return; + + if ( theInPortName2Value.size() == 1 ) + { + // nsteps port + QString aName(aForLoopNode->edGetNbOfTimesInputPort()->getName()); + map::iterator it = theInPortName2Value.begin(); + QString aGivenName( (*it).first ); + if ( !aGivenName.compare(aName) && myNbTimesInputPortValue ) + { + QString aValue( (*it).second ); + if ( !aValue.compare(QString("< ? >")) ) + myNbTimesInputPortValue->setValue( myNbTimesInputPortValue->minValue() ); + else + myNbTimesInputPortValue->setValue( aValue.toInt() ); + } + } +} + +void YACSGui_ForLoopNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + DEBTRACE("==> ForLoopNodePage : " << theOutPortName2Value.size()); +} + +void YACSGui_ForLoopNodePage::notifyNodeCreateBody( YACS::HMI::Subject* theSubject ) +{ + DEBTRACE("YACSGui_ForLoopNodePage::notifyNodeCreateBody"); + if( myLoopBodyNodeName ) + { + QString aBodyName = theSubject->getName(); + myLoopBodyNodeName->setText( aBodyName ); + } +} + +void YACSGui_ForLoopNodePage::checkModifications() +{ + if ( !getNode() ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + + if ( myNodeName->text().compare(getNodeName()) != 0 ) isModified = true; + else if ( YACS::ENGINE::ForLoop* aForLoopNode = dynamic_cast( getNode() ) ) + if( YACS::ENGINE::InputPort* aPort = aForLoopNode->edGetNbOfTimesInputPort() ) + { + bool ok; + int aValue = getPortValue( aPort ).toInt( &ok ); + if( ok && myNbTimesInputPortValue->value() != aValue ) isModified = true; + } + + //if ( !isModified ) + // TODO: compare view mode: expanded or collapsed (not yet in use) + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::InlineNodeId); + } +} + +void YACSGui_ForLoopNodePage::onApply() +{ + DEBTRACE("YACSGui_ForLoopNodePage::onApply"); + // Rename a node + if ( myNodeName ) setNodeName( myNodeName->text() ); + + // Reset number of times input port value + if ( YACS::ENGINE::ForLoop* aForLoopNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aPort = aForLoopNode->edGetNbOfTimesInputPort() ) + { + int aValue = myNbTimesInputPortValue->value(); + aPort->edInit( aValue ); + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aPort] ); + } + } + + // Reset the view mode + // ... + + updateBlocSize(); +} + +void YACSGui_ForLoopNodePage::updateState() +{ + DEBTRACE("YACSGui_ForLoopNodePage::updateState"); + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Set number of times input port value and loop body node name + if ( YACS::ENGINE::ForLoop* aForLoopNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aPort = aForLoopNode->edGetNbOfTimesInputPort() ) + { + bool ok; + int aValue = getPortValue( aPort ).toInt( &ok ); + if( ok && aValue > 1 ) + myNbTimesInputPortValue->setValue( aValue ); + } + + if( myLoopBodyNodeName ) + { + std::list aNodes = aForLoopNode->edGetDirectDescendants(); + if ( !aNodes.empty() ) + { + QString aBodyName; + + std::list::iterator aNodesIt = aNodes.begin(); + Node* aNode = *aNodesIt; + if( aNode ) + aBodyName = aNode->getName(); + + myLoopBodyNodeName->setText( aBodyName ); + } + } + } + + // Set view mode of the given FOR node + // the following method can be used if its needed: + // YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( myProc ); + // ... +} + +void YACSGui_ForLoopNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + diff --git a/src/gui/YACSGui_Graph.cxx b/src/gui/YACSGui_Graph.cxx index 42d1bf49d..4939ec741 100644 --- a/src/gui/YACSGui_Graph.cxx +++ b/src/gui/YACSGui_Graph.cxx @@ -18,6 +18,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +#include "yacsconfig.h" #include "YACSGui_Graph.h" #include "YACSGui_Node.h" #include "YACSGui_Module.h" @@ -25,6 +26,9 @@ #include "YACSPrs_ElementaryNode.h" #include "YACSPrs_BlocNode.h" +#include "YACSPrs_LoopNode.h" +#include "YACSPrs_ForEachLoopNode.h" +#include "YACSPrs_SwitchNode.h" #include "YACSPrs_Link.h" #include "YACSPrs_Def.h" @@ -36,11 +40,13 @@ #include "QxGraph_CanvasView.h" #include "SUIT_Session.h" +#include "SUIT_MessageBox.h" #include #include #include #include +#include #include #include #include @@ -56,18 +62,30 @@ #include #include "utilities.h" +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; +using namespace YACS::HMI; + +using namespace std; /*! Constructor */ YACSGui_Graph::YACSGui_Graph(YACSGui_Module* theModule, QxGraph_Canvas* theCanvas, - Proc* theProc) : + YACS::HMI::GuiContext* theCProc) : QxGraph_Prs(theCanvas), + GuiObserver(), myModule(theModule), - myProc(theProc) + myCProc(theCProc) { + _mainGraph = 0; + setDMode(YACSGui_Graph::FullId); + + if ( myCProc->getSubjectProc() ) myCProc->getSubjectProc()->attach(this); + // Create node status observer instance myNodeStatusObserver = new YACSGui_Observer(this); } @@ -77,6 +95,8 @@ YACSGui_Graph::YACSGui_Graph(YACSGui_Module* theModule, */ YACSGui_Graph::~YACSGui_Graph() { + if ( myCProc->getSubjectProc() ) myCProc->getSubjectProc()->detach(this); + Dispatcher* aDispatcher = Dispatcher::getDispatcher(); DMode2ItemList aDM = getDisplayMap(); @@ -84,86 +104,160 @@ YACSGui_Graph::~YACSGui_Graph() it1 != aDM.end(); it1++ ) { - for ( std::list::iterator it2 = (*it1).second.begin(); + for ( list::iterator it2 = (*it1).second.begin(); it2 != (*it1).second.end(); it2++ ) { QCanvasItem* anItem = *it2; YACSPrs_ElementaryNode* aEN = 0; aEN = dynamic_cast( *it2 ); - if ( aEN && aEN->isInBloc() ) - // remove item from the map of displayed items, because it is forbidden - // to destroy such items in QxGraph_Prs destructor: they will be deleted - // in the destructor of corresponding YACSPrs_BlocNode - removeItem( anItem ); + if ( aEN ) + { + if ( aEN->isInBloc() ) + // remove item from the map of displayed items, because it is forbidden + // to destroy such items in QxGraph_Prs destructor: they will be deleted + // in the destructor of corresponding YACSPrs_BlocNode + removeItem( anItem ); - // Remove status observer from dispatcher - aDispatcher->removeObserver(myNodeStatusObserver, aEN->getEngine(), "status"); + // Remove status observer from dispatcher + aDispatcher->removeObserver(myNodeStatusObserver, aEN->getEngine(), "status"); + } } } } +void YACSGui_Graph::select(bool isSelected) +{ + DEBTRACE(">> YACSGui_Graph::select"); +} + +void YACSGui_Graph::update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSGui_Graph::update"); + switch (event) + { + case ADD: + switch (type) + { + case BLOC: + case FOREACHLOOP: + case OPTIMIZERLOOP: + case FORLOOP: + case WHILELOOP: + case SWITCH: + case PYTHONNODE: + case PYFUNCNODE: + case CORBANODE: + case SALOMENODE: + case CPPNODE: + case SALOMEPYTHONNODE: + case PRESETNODE: + case OUTNODE: + case STUDYINNODE: + case STUDYOUTNODE: + case XMLNODE: + { + // add a node item (this = schema item) + DEBTRACE("Graph: ADD node"); + createPrs( son ); + } + break; + default: + break; + } + break; + case REMOVE: + switch (type) + { + case BLOC: + case FOREACHLOOP: + case OPTIMIZERLOOP: + case FORLOOP: + case WHILELOOP: + case SWITCH: + case PYTHONNODE: + case PYFUNCNODE: + case CORBANODE: + case SALOMENODE: + case CPPNODE: + case SALOMEPYTHONNODE: + case PRESETNODE: + case OUTNODE: + case STUDYINNODE: + case STUDYOUTNODE: + case XMLNODE: + { + // remove a node item (this = schema item) + DEBTRACE("Graph: REMOVE node"); + if ( SubjectNode* aNode = dynamic_cast(son) ) + deletePrs( aNode ); + } + break; + default: + break; + } + break; + case ADDLINK: + case ADDCONTROLLINK: + { + // add link item (this = composed schema item) + DEBTRACE("Graph: ADDLINK"); + createPrs(son); + } + break; + /* + case EDIT: + switch (type) + { + case DATALINK: + case CONTROLLINK: + { + if ( myModule ) myModule->temporaryExport(); + } + break; + default: + break; + } + break; + */ + default: + GuiObserver::update(event, type, son); + } +} + +//! Returns the subject's Proc +/*! + */ +YACS::ENGINE::Proc* YACSGui_Graph::getProc() const +{ + return ( myCProc ? myCProc->getProc() : 0 ); +} + //! Re-builds all the elements of the graph's presentation /*! */ void YACSGui_Graph::update() { - MESSAGE("YACSGui_Graph::update 1"); + DEBTRACE("YACSGui_Graph::update 1"); if ( !isToUpdate() ) return; - MESSAGE("YACSGui_Graph::update 2"); + DEBTRACE("YACSGui_Graph::update 2"); // TODO - clean exisiting items first // ... - // maximum width and height of nodes presentation (for table arrangement first level nodes) - int aMaxNodeWidth=0, aMaxNodeHeight=0; - bool aNeedToArrange = false; - - // Iterate through myProc's nodes and create presentation items for them - /// comment set for testing, uncomment this code when myProc'll be really not null graph - if (myProc) + // Iterate through Proc's nodes and create presentation items for them + Proc* aProc = getProc(); + if (aProc) { - std::set aNodeSet = myProc->getAllRecursiveConstituents(); //myProc->getChildren(); - - if ( !getItem( *(aNodeSet.begin()) ) ) aNeedToArrange = true; - - for ( std::set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) - { - // create presentations for all nodes except Bloc itself - // (for its internal not Bloc nodes presentations created too) - if ( !dynamic_cast( *it ) ) { - update( *it ); - - YACSPrs_ElementaryNode* aNodePrs = getItem( *it ); - if ( aNodePrs ) { - if ( aMaxNodeWidth < aNodePrs->maxWidth() ) aMaxNodeWidth = aNodePrs->maxWidth(); - if ( aMaxNodeHeight < aNodePrs->maxHeight() ) aMaxNodeHeight = aNodePrs->maxHeight(); - } - } - } + list aNodeSet = aProc->getAllRecursiveConstituents(); - // create presentations for Bloc nodes (for all other nodes, including internal - // nodes of Bloc's, presentations already created) - for ( std::set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) - { - // create presentations for all nodes except Bloc itself - // (for its internal not Bloc nodes presentations created too) - if ( dynamic_cast( *it ) ) { - update( *it ); - - YACSPrs_ElementaryNode* aNodePrs = getItem( *it ); - if ( aNodePrs ) { - if ( aMaxNodeWidth < aNodePrs->maxWidth() ) aMaxNodeWidth = aNodePrs->maxWidth(); - if ( aMaxNodeHeight < aNodePrs->maxHeight() ) aMaxNodeHeight = aNodePrs->maxHeight(); - } - } - } + createChildNodesPresentations( ( myCProc ? myCProc->getSubjectProc() : 0 ) ); - // TODO - Create links - for ( std::set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + // Create links + for ( list::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) { YACSPrs_ElementaryNode* aNodePrs = getItem( *it ); if ( aNodePrs ) @@ -174,47 +268,88 @@ void YACSGui_Graph::update() // data and control links YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); if ( anIOPort ) { - update( anIOPort ); + if ( getDMode() == YACSGui_Graph::FullId + || + getDMode() == YACSGui_Graph::ControlId && anIOPort->isGate() ) + update( anIOPort ); continue; } - // label links - YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ); - if ( aLabelPort ) update( aLabelPort ); + + if ( getDMode() == YACSGui_Graph::FullId ) + { + // label links + YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ); + if ( aLabelPort ) update( aLabelPort ); + } } } } + } + + QxGraph_Prs::update(); +} - if ( aNeedToArrange ) +//! Arrange nodes of the graph's presentation +/*! + */ +void YACSGui_Graph::show( bool theWithArrange ) +{ + DEBTRACE("YACSGui_Graph::show " << theWithArrange); + QxGraph_Prs::show(); + + if ( myModule && theWithArrange ) myModule->onArrangeNodes(); +} + +//! Corresponds the nodes positions : Full view <-> Control view. +/*! + */ +void YACSGui_Graph::viewModesConsistency( int theDModeFrom, int theDModeTo ) +{ + if ( myItems.find(theDModeFrom) != myItems.end() + && + myItems.find(theDModeTo) != myItems.end() ) + { + map aMapFrom = myItems[theDModeFrom]; + map::iterator it = aMapFrom.begin(); + for ( ; it!=aMapFrom.end(); it++ ) { - // table arrangement of the first level nodes - aNodeSet = myProc->edGetDirectDescendants(); - int aColNum, aRowNum; aColNum = aRowNum = (int)sqrt((double)aNodeSet.size()); - if ( aNodeSet.size() - aColNum*aRowNum > 0 ) aRowNum++; - int i=0,j=0; - int aMargin = 50; - for ( std::set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + YACSPrs_ElementaryNode* aFrom = (*it).second; + YACSPrs_ElementaryNode* aTo = 0; + + if ( myItems[theDModeTo].find((*it).first) != myItems[theDModeTo].end() ) + aTo = myItems[theDModeTo][(*it).first]; + + if ( aFrom && aTo ) { - YACSPrs_ElementaryNode* aNodePrs = getItem( *it ); - if ( aNodePrs ) - { - if ( j == aColNum) { j = 0; i++; } - aNodePrs->move( aNodePrs->x() + i*(aMaxNodeWidth+aMargin), aNodePrs->y() + j*(aMaxNodeHeight+aMargin) ); - j++; - } + aTo->hide(); + + if ( theDModeTo == YACSGui_Graph::ControlId ) aTo->setIsCheckAreaNeeded(false); + + YACSPrs_BlocNode* aBloc = dynamic_cast(aTo); + if ( aBloc + && + ( theDModeTo == YACSGui_Graph::ControlId + || + aBloc->width() <= aFrom->width() && aBloc->height() <= aFrom->height() ) ) + aBloc->resize( aFrom->width(), aFrom->height() ); + + aTo->move( (int)(aFrom->x()), (int)(aFrom->y()) ); + + if ( theDModeTo == YACSGui_Graph::ControlId ) aTo->setIsCheckAreaNeeded(true); + + aTo->show(); } } - } - - QxGraph_Prs::update(); } //! Updates the presentation items related to given graph node. /*! */ -void YACSGui_Graph::update(Node* theEngine) +void YACSGui_Graph::update(Node* theEngine, SubjectComposedNode* theParent) { - MESSAGE("YACSGui_Graph::update " << theEngine->getQualifiedName()); + DEBTRACE("YACSGui_Graph::update " << theEngine->getQualifiedName()); + DEBTRACE(theParent); /// comment set for testing, uncomment this code when theEngine'll be really not null node if ( !theEngine ) return; @@ -224,18 +359,21 @@ void YACSGui_Graph::update(Node* theEngine) return; YACSPrs_ElementaryNode* anItem = getItem( theEngine ); + DEBTRACE(anItem); bool needToAddItem = false; if ( !anItem ) // we need to add items, which will be created in update(...) by a driver, needToAddItem = true; // into display map for the current display mode // If is empty, it is filled by a driver, if not empty - only update by a driver - aDriver->update( theEngine, anItem ); + aDriver->update( theEngine, theParent, anItem ); - if (needToAddItem) - { - addItem( anItem ); // add item for the current display mode - myItems[theEngine] = anItem; - } + DEBTRACE(anItem); + if (needToAddItem && anItem) + { + addItem( anItem ); // add item for the current display mode + int aDMode = getDMode(); + myItems[aDMode][theEngine]=anItem; + } } //! Updates the data and control links presentations related to given node port. @@ -245,7 +383,7 @@ void YACSGui_Graph::update( YACSPrs_InOutPort* thePort ) { if ( thePort->getLinks().empty() ) { - std::string aClassName = thePort->getEngine()->getNameOfTypeOfCurrentInstance(); + string aClassName = thePort->getEngine()->getNameOfTypeOfCurrentInstance(); if ( !aClassName.compare(OutputPort::NAME) ) { // this is an output data port => create all links going from it OutputPort* anOutputDFPort = dynamic_cast( thePort->getEngine() ); @@ -263,8 +401,8 @@ void YACSGui_Graph::update( YACSPrs_InOutPort* thePort ) OutGate* anOutPort = dynamic_cast( thePort->getEngine() ); if ( anOutPort ) { - std::set anInPorts = anOutPort->edSetInGate(); - for(std::set::iterator iter=anInPorts.begin(); iter!=anInPorts.end(); iter++) + set anInPorts = anOutPort->edSetInGate(); + for(set::iterator iter=anInPorts.begin(); iter!=anInPorts.end(); iter++) { // the pair <(*iter),anOutPort> is a link YACSPrs_ElementaryNode* aToNodePrs = getItem((*iter)->getNode()); if ( aToNodePrs ) @@ -281,12 +419,16 @@ void YACSGui_Graph::update( YACSPrs_InOutPort* thePort ) } else { // update already existing port links + list aLinks = thePort->getLinks(); + list::iterator it = aLinks.begin(); + for(; it != aLinks.end(); it++) + ( *it )->show(); } } void YACSGui_Graph::createLinksFromGivenOutPortPrs( YACSPrs_InOutPort* theOutPortPrs, std::set theInPorts ) { - for(std::set::iterator iter=theInPorts.begin(); iter!=theInPorts.end(); iter++) + for(set::iterator iter=theInPorts.begin(); iter!=theInPorts.end(); iter++) { // the pair <(*iter),OutPort> is a link YACSPrs_ElementaryNode* aToNodePrs = 0; if ( dynamic_cast( (*iter)->getNode() ) ) @@ -309,6 +451,7 @@ void YACSGui_Graph::createLinksFromGivenOutPortPrs( YACSPrs_InOutPort* theOutPor */ void YACSGui_Graph::update( YACSPrs_LabelPort* thePort ) { + DEBTRACE("YACSGui_Graph::update"); if ( thePort->getLinks().empty() ) { if ( thePort->getSlaveNode() ) @@ -326,6 +469,60 @@ void YACSGui_Graph::update( YACSPrs_LabelPort* thePort ) } else { // update already existing label links + list aLinks = thePort->getLinks(); + list::iterator it = aLinks.begin(); + for(; it != aLinks.end(); it++) + ( *it )->show(); + } +} + +//! Creates presentations (and at first subjects), i.e. observers of the given composed node. +/*! + */ +void YACSGui_Graph::createChildNodesPresentations( YACS::HMI::SubjectComposedNode* theParent ) +{ + DEBTRACE("YACSGui_Graph::createChildNodesPresentations " << theParent); + if ( !theParent ) return; + + if ( ComposedNode* theNode = dynamic_cast( theParent->getNode() ) ) + { + list aNodeSet = theNode->edGetDirectDescendants(); + for ( list::iterator itN = aNodeSet.begin(); itN != aNodeSet.end(); itN++ ) + update( *itN, theParent ); + } +} + +void YACSGui_Graph::updateNodePrs( int theNodeId, std::string thePortName, std::string thePortValue ) +{ + if ( Node::idMap.count(theNodeId) == 0 ) return; + Node* aNode= Node::idMap[theNodeId]; + + if ( getDMode() == YACSGui_Graph::FullId ) + { + YACSPrs_ElementaryNode* aNodePrs = getItem(aNode); + if ( aNodePrs ) + { + Port* aPort = 0; + try { + aPort = aNode->getInPort(thePortName); + } + catch (YACS::Exception& ex) { + try { + aPort = aNode->getOutPort(thePortName); + } + catch (YACS::Exception& ex) { + SUIT_MessageBox::warn1(myModule->getApp()->desktop(), + QObject::tr("ERROR"), + QString("Update %1 node presentation : ").arg(aNode->getName().c_str()) + QString(ex.what()), + QObject::tr("BUT_OK")); + return; + } + } + if ( !aPort ) return; + + if ( YACSPrs_InOutPort* aPortPrs = aNodePrs->getPortPrs(aPort) ) + aPortPrs->updateValue(QString(thePortValue)); + } } } @@ -338,17 +535,18 @@ void YACSGui_Graph::rebuildLinks() aLineModel->SetSearchDepth( 2 ); // Bloc II : iteration on nodes -> output ports -> links => fill LineConn2d_Model object with datas - std::map aConnId2Link; - if (myProc) + map aConnId2Link; + Proc* aProc = getProc(); + if (aProc) { - std::map aNodePrs2ObjId; - std::map aPortPrs2PortId; + map aNodePrs2ObjId; + map aPortPrs2PortId; // 1 1 // commented because LabelPort <----> MasterPoint - //std::map aHookPrs2PortId; + //map aHookPrs2PortId; - std::set aNodeSet = myProc->getAllRecursiveConstituents(); - for ( std::set::iterator itN = aNodeSet.begin(); itN != aNodeSet.end(); itN++ ) + list aNodeSet = aProc->getAllRecursiveConstituents(); + for ( list::iterator itN = aNodeSet.begin(); itN != aNodeSet.end(); itN++ ) { YACSPrs_ElementaryNode* aNodePrs = getItem( *itN ); if ( aNodePrs ) @@ -362,8 +560,8 @@ void YACSGui_Graph::rebuildLinks() YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); if ( anIOPort && !anIOPort->isInput() ) { // anIOPort is a "from" port of the link - std::list aLinks = anIOPort->getLinks(); - for(std::list::iterator itL = aLinks.begin(); itL != aLinks.end(); itL++) + list aLinks = anIOPort->getLinks(); + for(list::iterator itL = aLinks.begin(); itL != aLinks.end(); itL++) { int PortId1 = addPortToLine2dModel(anIOPort, aNodePrs, *itL, aLineModel, aNodePrs2ObjId, aPortPrs2PortId); @@ -373,7 +571,7 @@ void YACSGui_Graph::rebuildLinks() int PortId2 = addPortToLine2dModel(anIPort, 0, *itL, aLineModel, aNodePrs2ObjId, aPortPrs2PortId); int ConnId = aLineModel->AddConnection( PortId1, PortId2 ); - aConnId2Link.insert(std::make_pair(ConnId,aPortLink)); + aConnId2Link.insert(make_pair(ConnId,aPortLink)); } } } @@ -383,8 +581,8 @@ void YACSGui_Graph::rebuildLinks() if ( aLabelPort ) { // aLabelPort is a "from" port of the link, //the master point of the slave node can be considered as a "to" port of the link - std::list aLinks = aLabelPort->getLinks(); - for(std::list::iterator itL = aLinks.begin(); itL != aLinks.end(); itL++) + list aLinks = aLabelPort->getLinks(); + for(list::iterator itL = aLinks.begin(); itL != aLinks.end(); itL++) { int PortId1 = addPortToLine2dModel(aLabelPort, aNodePrs, *itL, aLineModel, aNodePrs2ObjId, aPortPrs2PortId); @@ -393,7 +591,7 @@ void YACSGui_Graph::rebuildLinks() YACSPrs_Hook* aMPoint = aLabelLink->getSlaveNode()->getMasterPoint(); int PortId2 = addPortToLine2dModel(aMPoint, aLabelLink->getSlaveNode(), aLabelLink, aLineModel, aNodePrs2ObjId); int ConnId = aLineModel->AddConnection( PortId1, PortId2 ); - aConnId2Link.insert(std::make_pair(ConnId,aLabelLink)); + aConnId2Link.insert(make_pair(ConnId,aLabelLink)); } } } @@ -426,7 +624,7 @@ void YACSGui_Graph::rebuildLinks() if ( portId1 == -1 || portId2 == -1 ) continue; // should not be - std::list aList; + list aList; if ( !isSimpleLine ) { int nbSeg = curConn.NbSegments(); @@ -476,7 +674,7 @@ int YACSGui_Graph::addObjectToLine2dModel(YACSPrs_ElementaryNode* theNode, if ( aBNode && aBNode->getDisplayMode() == YACSPrs_BlocNode::Expanded ) break; } - theNodePrs2ObjId.insert( std::make_pair(theNode, ObjId) ); + theNodePrs2ObjId.insert( make_pair(theNode, ObjId) ); // <-- } @@ -496,9 +694,13 @@ int YACSGui_Graph::addPortToLine2dModel(YACSPrs_Port* thePort, int PortId = -1; YACSPrs_InOutPort* anIOPort = dynamic_cast( thePort ); - if ( anIOPort && !theNode) + if ( anIOPort && !theNode) { // take from anIOPort its node presentation - theNode = getItem( anIOPort->getEngine()->getNode() ); + Node* aNodeEngine = anIOPort->getEngine()->getNode(); + if ( SplitterNode* aSplitter = dynamic_cast(aNodeEngine) ) + aNodeEngine = aSplitter->getFather(); // take ForEach loop node if we added SmplsCollection port + theNode = getItem( aNodeEngine ); + } if ( theNode ) { @@ -509,7 +711,7 @@ int YACSGui_Graph::addPortToLine2dModel(YACSPrs_Port* thePort, gp_Dir2d aDir2d( 1, 0 ); if ( anIOPort && anIOPort->isInput() ) aDir2d.SetX( -1 ); PortId = theLineModel->AddPoort( ObjId, aP2d, aDir2d ); - thePortPrs2PortId.insert( std::make_pair(thePort, PortId) ); + thePortPrs2PortId.insert( make_pair(thePort, PortId) ); // <-- } @@ -544,8 +746,9 @@ int YACSGui_Graph::addPortToLine2dModel(YACSPrs_Hook* theHook, */ YACSGui_Node* YACSGui_Graph::driver(Node* theEngine) { + DEBTRACE("YACSGui_Graph::driver"); const char* aTypeName = typeid( *theEngine ).name(); - printf("== aTypeName = %s\n",aTypeName); + DEBTRACE("== aTypeName = " << aTypeName); if ( myDrivers.find( aTypeName ) == myDrivers.end() ) { YACSGui_Node* aDriver = 0; @@ -560,6 +763,8 @@ YACSGui_Node* YACSGui_Graph::driver(Node* theEngine) } else if ( dynamic_cast( theEngine ) ) aDriver = new YACSGui_InlineNode(this); + else if ( dynamic_cast< DataNode*>( theEngine ) ) + aDriver = new YACSGui_InlineNode(this); else if ( dynamic_cast( theEngine ) ) // but getNbOfCases() is a private method of Switch node => how to recognize If node type in engine? //if ( dynamic_cast( theEngine )->getNbOfCases() == 1 ) @@ -582,18 +787,47 @@ YACSGui_Node* YACSGui_Graph::driver(Node* theEngine) YACSPrs_ElementaryNode* YACSGui_Graph::getItem( YACS::ENGINE::Node* theEngine ) { + DEBTRACE("YACSGui_Graph::getItem " << theEngine); YACSPrs_ElementaryNode* aNode = 0; - if ( myItems.find( theEngine ) == myItems.end() ) - myItems[theEngine] = aNode; - return myItems[theEngine]; + int aDMode = getDMode(); + + if ( myItems.find(aDMode) == myItems.end() ) return aNode; + + if ( myItems[aDMode].find(theEngine) == myItems[aDMode].end() ) return aNode; + + //if ( myItems[getDMode()].find( theEngine ) == myItems[getDMode()].end() ) + // myItems[getDMode()][theEngine] = aNode; + //return myItems[getDMode()][theEngine]; + + DEBTRACE(myItems[aDMode][theEngine]); + return myItems[aDMode][theEngine]; +} + +void YACSGui_Graph::removeNode( YACS::ENGINE::Node* theNode ) +{ + if ( !theNode ) return; + + map >::iterator it = myItems.begin(); + for ( ; it!=myItems.end(); it++ ) + { + if ( (*it).second.find(theNode) != (*it).second.end() ) + { + if ( (*it).first != getDMode() ) + // not current view mode => remove the canvas item associated with theNode from display mode map + removeItem( (*it).second[theNode], (*it).first ); + + (*it).second.erase(theNode); + } + } } void YACSGui_Graph::getAllBlocChildren(Bloc* theNode, std::set& theSet) { + DEBTRACE("YACSGui_Graph::getAllBlocChildren " << theNode->getName()); if ( theNode ) { - std::set aChildren = theNode->getChildren(); - for ( std::set::iterator it = aChildren.begin(); it != aChildren.end(); it++ ) + list aChildren = theNode->getChildren(); + for ( list::iterator it = aChildren.begin(); it != aChildren.end(); it++ ) { if ( dynamic_cast( *it ) || @@ -614,8 +848,8 @@ void YACSGui_Graph::getAllComposedNodeChildren(ComposedNode* theNode, std::set aDescendants = theNode->edGetDirectDescendants(); - for ( std::set::iterator it = aDescendants.begin(); it != aDescendants.end(); it++ ) + list aDescendants = theNode->edGetDirectDescendants(); + for ( list::iterator it = aDescendants.begin(); it != aDescendants.end(); it++ ) { if ( dynamic_cast( *it ) || @@ -623,7 +857,10 @@ void YACSGui_Graph::getAllComposedNodeChildren(ComposedNode* theNode, std::set( *it ); - if ( aCNode ) getAllComposedNodeChildren( aCNode, theSet ); + if ( aCNode ) { + getAllComposedNodeChildren( aCNode, theSet ); + theSet.insert( *it ); + } } } } @@ -635,7 +872,7 @@ void YACSGui_Graph::getAllComposedNodeChildren(ComposedNode* theNode, std::setgetQualifiedName()); + DEBTRACE("YACSGui_Graph::registerStatusObserverWithNode " << theNode->getQualifiedName()); Dispatcher* aDispatcher = Dispatcher::getDispatcher(); aDispatcher->addObserver(myNodeStatusObserver, theNode, "status"); } @@ -663,3 +900,281 @@ YACS::ENGINE::Node* YACSGui_Graph::getNodeByName( const std::string theName ) co return getProc()->getChildByName(theName); } + +//! Create prs for the defined subject in graph +/*! + */ +void YACSGui_Graph::createPrs(YACS::HMI::Subject* theSubject) +{ + DEBTRACE("YACSGui_Graph::createPrs: " << theSubject); + if( SubjectNode* aSubject = dynamic_cast(theSubject) ) + { + update( aSubject->getNode(), dynamic_cast(aSubject->getParent()) ); + show( false ); + + if( SubjectComposedNode* aComposedNode = dynamic_cast( aSubject->getParent() ) ) + { + //The parent is a composed node + if( YACSPrs_LoopNode* aNodePrs = dynamic_cast( getItem( aComposedNode->getNode() ) ) ) + { + // If the parent node is a loop make what needs to be done + aNodePrs->updatePorts( true ); + QPtrList aPorts = aNodePrs->getPortList(); + for (YACSPrs_Port* aPort = aPorts.first(); aPort; aPort = aPorts.next()) + { + if( YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ) ) + update( aLabelPort ); + else if( YACSPrs_InOutPort* anInOutPort = dynamic_cast( aPort ) ) + { + if( anInOutPort->isInput() ) + { + if( InPort* anInPort = dynamic_cast( anInOutPort->getEngine() ) ) + { + std::set aSetOfOutPort = anInPort->edSetOutPort(); + for( set::iterator iter = aSetOfOutPort.begin(); iter != aSetOfOutPort.end(); iter++ ) + { + OutPort* anOutPort = *iter; + Node* anOutNode = anOutPort->getNode(); + + if( YACSPrs_ElementaryNode* anOutPrs = dynamic_cast( getItem( anOutNode ) ) ) + { + YACSPrs_InOutPort* aPortPrs = anOutPrs->getPortPrs( anOutPort ); + if( aPortPrs ) + update( aPortPrs ); + } + } + } + else if( InGate* anInGate = dynamic_cast( anInOutPort->getEngine() ) ) + { + std::map aSetOfOutGate = anInGate->edMapOutGate(); + for( map::iterator iter = aSetOfOutGate.begin(); iter != aSetOfOutGate.end(); iter++ ) + { + OutGate* anOutGate = (*iter).first; + Node* anOutNode = anOutGate->getNode(); + + if( YACSPrs_ElementaryNode* anOutPrs = dynamic_cast( getItem( anOutNode ) ) ) + { + YACSPrs_InOutPort* aPortPrs = anOutPrs->getPortPrs( anOutGate ); + if( aPortPrs ) + update( aPortPrs ); + } + } + } + } + else + update( anInOutPort ); + } + } + } + else + { + //Not a loop : just update the composed node + if(SubjectComposedNode* aParentBloc = dynamic_cast( aComposedNode->getParent() ) ) + { + update(aComposedNode->getNode(),aParentBloc); + } + } + + //In the end update all parents + Subject* aParent = aComposedNode->getParent(); + while( aParent ) + { + if( dynamic_cast( aParent ) ) + break; + + if( SubjectBloc* aSubjectBloc = dynamic_cast( aParent ) ) + { + update( aSubjectBloc->getNode(), dynamic_cast( aSubjectBloc->getParent() ) ); + break; + } + aParent = aParent->getParent(); + } + } + + if( SubjectSwitch* aSwitch = dynamic_cast( aSubject->getParent() ) ) + { + if ( YACSPrs_ElementaryNode* aNodePrs = getItem( aSwitch->getNode() ) ) + { + aNodePrs->updatePorts( true ); + + QPtrList aPorts = aNodePrs->getPortList(); + for (YACSPrs_Port* aPort = aPorts.first(); aPort; aPort = aPorts.next()) + { + if ( YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ) ) + update( aLabelPort ); + } + } + } + getCanvas()->update(); + } + // 1. In the Full mode we can create presentation for all types of links: data and control + // 2. In the Control mode we can create presentation only for control links + else if ( SubjectLink* aSL = dynamic_cast(theSubject) ) + { + DEBTRACE("YACSGui_Graph::createPrs: SubjectLink" ); + if ( getDMode() == YACSGui_Graph::FullId ) + { + Port* anOP = aSL->getSubjectOutPort()->getPort(); + Node* anON = aSL->getSubjectOutNode()->getNode(); + + Port* anIP = aSL->getSubjectInPort()->getPort(); + Node* anIN = aSL->getSubjectInNode()->getNode(); + + if ( !anOP || !anON || !anIP || !anIN ) return; + + YACSPrs_ElementaryNode* anONPrs = getItem(anON); + YACSPrs_ElementaryNode* anINPrs = getItem(anIN); + + if ( !anONPrs || !anINPrs ) return; + + YACSPrs_InOutPort* anOPPrs = dynamic_cast( anONPrs->getPortPrs( anOP ) ); + YACSPrs_InOutPort* anIPPrs = dynamic_cast( anINPrs->getPortPrs( anIP ) ); + + YACSPrs_Link* aLink = new YACSPrs_PortLink( SUIT_Session::session()->resourceMgr(), getCanvas(), + anIPPrs, anOPPrs ); + + aLink->show(); + + double anOZ = anOPPrs->z(); + double anIZ = anIPPrs->z(); + DEBTRACE("YACSGui_Graph::createPrs: z " << anOZ << "," << anIZ); + if ( anOZ > anIZ ) + anOPPrs->setZ( anOZ, anOPPrs->getNode()->isMoving() ); + else + anIPPrs->setZ( anIZ, anIPPrs->getNode()->isMoving() ); + + if ( getCanvas() ) getCanvas()->update(); + } + } + else if ( SubjectControlLink* aSCL = dynamic_cast(theSubject) ) + { + DEBTRACE("YACSGui_Graph::createPrs: SubjectControlLink" ); + Node* anON = aSCL->getSubjectOutNode()->getNode(); + Node* anIN = aSCL->getSubjectInNode()->getNode(); + + if ( !anON || !anIN ) return; + + Port* anOP = anON->getOutGate(); + Port* anIP = anIN->getInGate(); + + if ( !anOP || !anIP ) return; + + YACSPrs_ElementaryNode* anONPrs = getItem(anON); + YACSPrs_ElementaryNode* anINPrs = getItem(anIN); + + if ( !anONPrs || !anINPrs ) return; + + YACSPrs_InOutPort* anOPPrs = dynamic_cast( anONPrs->getPortPrs( anOP ) ); + YACSPrs_InOutPort* anIPPrs = dynamic_cast( anINPrs->getPortPrs( anIP ) ); + + YACSPrs_Link* aLink = new YACSPrs_PortLink( SUIT_Session::session()->resourceMgr(), getCanvas(), + anIPPrs, anOPPrs ); + + double anOZ = anOPPrs->z(); + double anIZ = anIPPrs->z(); + if ( anOZ > anIZ ) + anOPPrs->setZ( anOZ, anOPPrs->getNode()->isMoving() ); + else + anIPPrs->setZ( anIZ, anIPPrs->getNode()->isMoving() ); + + aLink->show(); + if ( getCanvas() ) getCanvas()->update(); + } +} + +//! Delete prs with the defined subject from graph +/*! + */ +void YACSGui_Graph::deletePrs(YACS::HMI::SubjectNode* theSubject, bool removeLabelPort ) +{ + if ( !theSubject ) return; + + if( YACSPrs_ElementaryNode* aPrs = getItem( theSubject->getNode() ) ) + { + if ( dynamic_cast(aPrs) || + dynamic_cast(aPrs) || + dynamic_cast(aPrs) || + dynamic_cast(aPrs) ) + theSubject->detach(this); + + if ( ComposedNode* aNodeToDelete = dynamic_cast(theSubject->getNode()) ) + { + // remove from canvas all canvas items corresponds to the constituents of the deleted composed node + list aNodeSet = aNodeToDelete->getAllRecursiveConstituents(); + for ( list::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + { + if ( YACSPrs_ElementaryNode* aChildPrs = getItem(*it) ) + { + if ( dynamic_cast(aChildPrs) || + dynamic_cast(aChildPrs) || + dynamic_cast(aChildPrs) || + dynamic_cast(aChildPrs) ) + aChildPrs->getSEngine()->detach(this); + + aChildPrs->hide(); + + if ( !dynamic_cast(aPrs) ) + { + SubjectNode* aChildSub = aChildPrs->getSEngine(); + // to remove body nodes properly (with all its links), when a father loop or switch node is removed + aChildSub->detach(aChildPrs); + deletePrs(aChildSub); + // clear the content of the property page of deleted node + aChildSub->update( REMOVE, 0, 0 ); + } + + removeItem(aChildPrs); + } + removeNode(*it); + } + } + + if( SubjectSwitch* aSwitch = dynamic_cast( theSubject->getParent() ) ) + aSwitch->removeNode( theSubject ); + + aPrs->hide(); + removeItem( aPrs ); + delete aPrs; + + if( removeLabelPort ) + { + SubjectComposedNode* aComposedNode = dynamic_cast( theSubject->getParent() ); + if( aComposedNode && !dynamic_cast( aComposedNode ) ) + { + if ( YACSPrs_ElementaryNode* aNodePrs = getItem( aComposedNode->getNode() ) ) + { + QPtrList aPorts = aNodePrs->getPortList(); + for (YACSPrs_Port* aPort = aPorts.first(); aPort; aPort = aPorts.next()) + { + if ( YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ) ) + { + if( aLabelPort->getSlaveNode() == theSubject->getNode() ) + aNodePrs->removeLabelPortPrs( aLabelPort ); + } + } + } + } + } + getCanvas()->update(); + } +} + +//! Returns true if it is needed to increase a size of block node presentation according to the size of its content +/*! + */ +bool YACSGui_Graph::isNeededToIncreaseBlocSize( YACS::ENGINE::Bloc* theBloc ) +{ + bool isNeedToArrange = false; + + if ( theBloc ) + { + YACSPrs_BlocNode* aNodePrs = dynamic_cast(getItem(theBloc)); + if ( aNodePrs ) + if ( aNodePrs->width() < aNodePrs->maxXContent() - aNodePrs->minXContent() + || + aNodePrs->getAreaRect().height() + 2*BLOCNODE_MARGIN < aNodePrs->maxYContent() - aNodePrs->minYContent() ) + isNeedToArrange = true; + } + + return isNeedToArrange; +} diff --git a/src/gui/YACSGui_Graph.h b/src/gui/YACSGui_Graph.h index 35d0dadcc..0be7e2e11 100644 --- a/src/gui/YACSGui_Graph.h +++ b/src/gui/YACSGui_Graph.h @@ -24,6 +24,9 @@ #include #include +#include +#include + #include #include @@ -43,23 +46,47 @@ class YACSPrs_LabelPort; class YACSPrs_Link; class YACSPrs_LabelLink; +struct Agraph_t; class LineConn2d_Model; -class YACSGui_Graph : public QxGraph_Prs +class YACSGui_Graph : public QxGraph_Prs, public YACS::HMI::GuiObserver { public: - YACSGui_Graph(YACSGui_Module*, QxGraph_Canvas*, YACS::ENGINE::Proc*); + enum { FullId = 0, ControlId, DataflowId, DataStreamId }; + +public: + YACSGui_Graph(YACSGui_Module*, QxGraph_Canvas*, YACS::HMI::GuiContext*); virtual ~YACSGui_Graph(); - YACS::ENGINE::Proc* getProc() const { return myProc; } + virtual void select(bool isSelected); + virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + YACS::ENGINE::Proc* getProc() const; + YACS::HMI::GuiContext* getContext() const { return myCProc; } YACSGui_Observer* getStatusObserver() const { return myNodeStatusObserver; } virtual void update(); - void update( YACS::ENGINE::Node* ); + void update( YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode* ); void update( YACSPrs_InOutPort* ); void update( YACSPrs_LabelPort* ); + virtual void show( bool theWithArrange = true ); + void viewModesConsistency( int theDModeFrom, int theDModeTo ); + + void createChildNodesPresentations( YACS::HMI::SubjectComposedNode* ); + + void updateNodePrs( int theNodeId, std::string thePortName, std::string thePortValue ); + + int arrangeNodesAlgo(YACS::ENGINE::Bloc* theBloc); + int arrangeNodes(YACS::ENGINE::ComposedNode* theBloc, Agraph_t* aSubGraph, int dep); + void createGraphvizNodes(YACS::ENGINE::ComposedNode* theBloc, Agraph_t* aSubGraph); + void arrangeCanvasNodes(YACS::ENGINE::ComposedNode* theBloc, Agraph_t* aSubGraph, int dep); + // store some functions to have possibility to arrange nodes only on the one giving level + int arrangeNodesWithinBloc(YACS::ENGINE::Bloc* theBloc); + void createGraphvizNodes(YACS::ENGINE::Bloc* theBloc, YACS::ENGINE::ComposedNode* theFather, Agraph_t* theGraph); + std::string getInNodeName(YACS::ENGINE::Bloc* theBloc, YACS::ENGINE::Node* theOutNode, YACS::ENGINE::Node* theInNode); + void rebuildLinks(); int addObjectToLine2dModel(YACSPrs_ElementaryNode* theNode, LineConn2d_Model* theLineModel, @@ -77,6 +104,7 @@ public: std::map& theNodePrs2ObjId); YACSPrs_ElementaryNode* getItem( YACS::ENGINE::Node* ); + void removeNode( YACS::ENGINE::Node* ); YACS::ENGINE::Node* getNodeById( const int theID ) const; @@ -89,6 +117,11 @@ public: void registerStatusObserverWithNode(YACS::ENGINE::Node* theNode); + void createPrs(YACS::HMI::Subject* theSubject); + void deletePrs(YACS::HMI::SubjectNode* theSubject, bool removeLabelPort = true ); + + bool isNeededToIncreaseBlocSize( YACS::ENGINE::Bloc* ); + private: YACSGui_Node* driver( YACS::ENGINE::Node* theNode ); void createLinksFromGivenOutPortPrs( YACSPrs_InOutPort* theOutPortPrs, @@ -97,14 +130,21 @@ private: private: typedef std::map DriverMap; - typedef std::map ItemMap; + typedef std::map > ItemMap; + typedef std::map > > Bloc2InsideLinksMap; YACSGui_Module* myModule; - YACS::ENGINE::Proc* myProc; // graph engine + YACS::HMI::GuiContext* myCProc; // context of corresponding Proc* DriverMap myDrivers; // map of update drivers for specific node types ItemMap myItems; // map of graphic items for a given engine node + Bloc2InsideLinksMap myBlocInsideLinks; // map of links from block to block ( BlocOut -> BlocIn ) inside a given block YACSGui_Observer* myNodeStatusObserver; + Agraph_t* _mainGraph; + std::multimap< YACS::ENGINE::Node*, YACS::ENGINE::Node* > _savedControlLinks; + int _maxdep; + int _bottom; + std::string _format; }; #endif diff --git a/src/gui/YACSGui_Graph_1.cxx b/src/gui/YACSGui_Graph_1.cxx new file mode 100644 index 000000000..89fb8af9a --- /dev/null +++ b/src/gui/YACSGui_Graph_1.cxx @@ -0,0 +1,1003 @@ +// Copyright (C) 2003 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 "YACSGui_Graph.h" +#include "YACSGui_Node.h" + +#include "YACSPrs_ElementaryNode.h" +#include "YACSPrs_BlocNode.h" +#include "YACSPrs_LoopNode.h" +#include "YACSPrs_Link.h" +#include "YACSPrs_Def.h" + +#include "QxGraph_Canvas.h" + +#include +#include +#include + +#include +#include +#include + +#ifdef HAVE_DOTNEATO_H + #include +#else + #include +#endif + +#include "utilities.h" + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; + +using namespace std; + +/*! Definition in dot per inch for the input: + * size of elementary nodes are in pixel in Qt, and given in inches to graphviz + */ +#define DPI 72. + +/*! Space to reserve (pixels) on top and below elementary nodes. + * Corresponds to the size of the lower and upper banner of bloc. + */ +#define BLOCB 30 + +//! Auto-arrange nodes inside a schema using Graphviz C API. +/*! + */ +int YACSGui_Graph::arrangeNodesAlgo( YACS::ENGINE::Bloc* theBloc ) +{ + DEBTRACE("YACSGui_Graph::arrangeNodesAlgo() " << theBloc->getName()); + _savedControlLinks.clear(); + _maxdep = 0; + _format="%1"; // --- standard format to convert float ex: 9.81 + //_format="%L1"; // --- localized format to convert float ex: 9,81 + + // ---- Create a graphviz context + + aginit(); + GVC_t* aGvc = gvContext(); + + // ---- Create a graph + + _mainGraph = agopen( (char*)( theBloc ? theBloc->getName().c_str() : "mainGraph" ), AGDIGRAPH ); + + // ---- Initialize and set attributes for the graph + + Agsym_t* anAttr; + if ( !(anAttr = agfindattr(_mainGraph, "compound"))) + anAttr = agraphattr(_mainGraph, "compound", "false"); + agxset(_mainGraph, anAttr->index, "true"); + + if ( !(anAttr = agfindattr(_mainGraph, "rankdir"))) + anAttr = agraphattr(_mainGraph, "rankdir", "TB"); + agxset(_mainGraph, anAttr->index, "LR"); + +// if ( !(anAttr = agfindattr(_mainGraph, "ordering"))) +// anAttr = agraphattr(_mainGraph, "ordering", "" ); +// agxset(_mainGraph, anAttr->index, "in" ); + + if ( !(anAttr = agfindattr(_mainGraph, "dpi"))) + anAttr = agraphattr(_mainGraph, "dpi", "72"); + agxset(_mainGraph, anAttr->index, "72"); // --- must be coherent with #define DPI + + // --- label is used to reserve place for bloc banners (adjust size with font !) + + if ( !(anAttr = agfindattr(_mainGraph, "label"))) + anAttr = agraphattr(_mainGraph, "label", "label"); + agxset(_mainGraph, anAttr->index, "myLabel"); + + if ( !(anAttr = agfindattr(_mainGraph, "labelloc"))) + anAttr = agraphattr(_mainGraph, "labelloc", "top"); + agxset(_mainGraph, anAttr->index, "top"); + + if ( !(anAttr = agfindattr(_mainGraph, "fontsize"))) + anAttr = agraphattr(_mainGraph, "fontsize", "24"); + agxset(_mainGraph, anAttr->index, "24"); + + // --- Initialize attributes for nodes + + if ( !(anAttr = agfindattr( _mainGraph->proto->n, "height"))) + anAttr = agnodeattr(_mainGraph, "height", "" ); + + if ( !(anAttr = agfindattr( _mainGraph->proto->n, "width"))) + anAttr = agnodeattr(_mainGraph, "width", "" ); + + if ( !(anAttr = agfindattr( _mainGraph->proto->n, "shape"))) + anAttr = agnodeattr(_mainGraph, "shape", "" ); + + if ( !(anAttr = agfindattr( _mainGraph->proto->n, "fixedsize"))) + anAttr = agnodeattr(_mainGraph, "fixedsize", "false" ); + + int curdep = -1; + arrangeNodes(theBloc, _mainGraph, curdep); + createGraphvizNodes(theBloc, _mainGraph); + DEBTRACE("end of graphviz input"); + + // ---- Bind graph to graphviz context - must be done before layout + // ---- Compute a layout + try + { +#ifdef HAVE_DOTNEATO_H + gvBindContext(aGvc, _mainGraph); + dot_layout(_mainGraph); +#else + //DEBTRACE("external render for test"); + //gvRenderFilename(aGvc, _mainGraph, "dot", "graph1.dot"); + DEBTRACE("compute layout"); + gvLayout(aGvc, _mainGraph, "dot"); + //DEBTRACE("external render for test"); + //gvRenderFilename(aGvc, _mainGraph, "dot", "graph2.dot"); +#endif + } + catch (std::exception &e) + { + DEBTRACE("Exception Graphviz layout: " << e.what()); + return 1; + } + catch (...) + { + DEBTRACE("Unknown Exception Graphviz layout "); + return 1; + } + DEBTRACE("start of display"); + // ---- layout Canvas nodes recursively + + curdep = -1; + arrangeCanvasNodes(theBloc, _mainGraph, curdep); + + DEBTRACE("clean up graphviz"); + // ---- Delete layout + +#ifdef HAVE_DOTNEATO_H + dot_cleanup(_mainGraph); +#else + gvFreeLayout(aGvc, _mainGraph); +#endif + + // ---- Free graph structures + + agclose(_mainGraph) ; + + // ---- Free context and return number of errors + +#ifndef HAVE_DOTNEATO_H + gvFreeContext( aGvc ); +#endif + + if ( dynamic_cast( theBloc ) ) + getCanvas()->update(); + + return 0; +} + + +void YACSGui_Graph::arrangeCanvasNodes(YACS::ENGINE::ComposedNode* theBloc, Agraph_t* aSubGraph, int dep) +{ + DEBTRACE("arrangeCanvasNodes, bloc: " << aSubGraph->name); + int curdep = dep +1; + int offX = 0; + int offY = 0; + DEBTRACE("dep="<< curdep << " maxdep= " << _maxdep << " offY=" << offY); + + + // ---- Rendering the graph : retrieve nodes positions + + // --- bloc bounding box from graphviz + + int llx = GD_bb( aSubGraph ).LL.x; + int lly = GD_bb( aSubGraph ).LL.y; + int urx = GD_bb( aSubGraph ).UR.x; + int ury = GD_bb( aSubGraph ).UR.y; + DEBTRACE("boundingBox " << aSubGraph->name << " (" << llx << "," << lly << ") (" << urx << "," << ury << ")"); + int bbHeight = (ury -lly); + int bbWhidth = (urx -llx); + if (curdep == 0) _bottom = bbHeight; + DEBTRACE(_bottom); + + if (!dynamic_cast(theBloc)) + { + YACSPrs_BlocNode* aBlocNodePrs = dynamic_cast(getItem(theBloc)); + if (aBlocNodePrs) + { + DEBTRACE("arrangeCanvasNodes " << llx + offX<<","<<_bottom -ury<<","<setIsCheckAreaNeeded(false); + aBlocNodePrs->resize(bbWhidth,bbHeight); + aBlocNodePrs->move(llx + offX,_bottom -ury); + //aBlocNodePrs->setX(llx + offX); + //aBlocNodePrs->setY(_bottom -ury); + aBlocNodePrs->setZ(aBlocNodePrs->z()); + aBlocNodePrs->setIsCheckAreaNeeded(true); + } + } + + // --- subgraphs + + list children = theBloc->edGetDirectDescendants(); + for ( list::iterator it = children.begin(); it != children.end(); it++ ) + { + if (ComposedNode* childBloc = dynamic_cast(*it)) + { + DEBTRACE("arrangeCanvasNodes ComposedNode" ); + string clusterName="cluster_"; + if (dynamic_cast(childBloc)) clusterName += childBloc->getName(); + else clusterName += getProc()->getChildName(childBloc); + DEBTRACE(clusterName); + Agraph_t* childGraph = agsubg(aSubGraph,(char*)clusterName.c_str()); + assert(childGraph); + arrangeCanvasNodes(childBloc, childGraph, curdep); + } + if (!dynamic_cast(*it)) + { + DEBTRACE("arrangeCanvasNodes not a Bloc" ); + string nodeName = getProc()->getChildName(*it); + Agnode_t* aNode = agnode(aSubGraph,(char*)nodeName.c_str()); + int aXCenter = ND_coord_i(aNode).x; + int aYCenter = ND_coord_i(aNode).y; + YACSPrs_ElementaryNode* aNodePrs = getItem(*it); + if ( aNodePrs ) + { + int aXLeft = aXCenter - aNodePrs->maxWidth()/2; + int aYTop = aYCenter + aNodePrs->maxHeight()/2; + + if ( dynamic_cast( aNodePrs ) && getDMode() == YACSGui_Graph::FullId ) + { + aXLeft += 3*TITLE_HEIGHT/2; + aYTop += 3*TITLE_HEIGHT/2; + } + + DEBTRACE("Node: " << nodeName << " aXCenter = " << aXCenter << " aYCenter = " << aYCenter); + DEBTRACE("Node: " << nodeName << " aXLeft = " << aXLeft << " aYTop = " << aYTop); + aNodePrs->setIsCheckAreaNeeded(false); + aNodePrs->move(aXLeft + offX,_bottom -(aYTop + offY)); + //aNodePrs->setX(aXLeft + offX); + //aNodePrs->setY(_bottom -(aYTop + offY)); + aNodePrs->setIsCheckAreaNeeded(true); + } + } + } +} + + + + +int YACSGui_Graph::arrangeNodes( YACS::ENGINE::ComposedNode* theBloc, Agraph_t* aSubGraph, int dep) +{ + DEBTRACE("YACSGui_Graph::arrangeNodes() " << theBloc->getName()); + + int curdep = dep +1; + if (curdep > _maxdep) + { + _maxdep = curdep; + DEBTRACE("Max level of nested blocs: "<< _maxdep); + } + int aRetVal = 0; + + // --- collect all Bloc children nodes of the given theBloc + + list children = theBloc->edGetDirectDescendants(); + for ( list::iterator it = children.begin(); it != children.end(); it++ ) + { + // iterates on a Bloc children to find a Bloc with the maximum nested level + if ( ComposedNode* childBloc = dynamic_cast( *it ) ) + { + string clusterName="cluster_"; + if (dynamic_cast(childBloc)) clusterName += childBloc->getName(); + else clusterName += getProc()->getChildName(childBloc); + + // --- create a subgraph for each bloc within a dummy cluster + // top and bottom labels reserve space for top and bottom of the bloc widget + + string topname = clusterName + "_top"; + Agraph_t* aClustertop = agsubg( aSubGraph, (char*)(topname.c_str())); + agset(aClustertop, "labelloc", "bottom"); + agset(aClustertop, "rankdir", "LR"); +// agset(aClustertop, "ordering", "in"); + + string bottomname = clusterName + "_bottom"; + Agraph_t* aClusterbottom = agsubg( aClustertop, (char*)(bottomname.c_str())); + agset(aClusterbottom, "labelloc", "top"); + agset(aClusterbottom, "rankdir", "LR"); +// agset(aClusterbottom, "ordering", "in"); + + Agraph_t* aCluster = agsubg(aClusterbottom , (char*)(clusterName.c_str())); + agset(aCluster, "labelloc", ""); + agset(aCluster, "rankdir", "LR"); +// agset(aCluster, "ordering", "in"); + DEBTRACE("Add Block node " << aCluster->name); + + aRetVal = arrangeNodes(childBloc, aCluster, curdep); + createGraphvizNodes(childBloc, aCluster); + } + } + return aRetVal; +} + + +void YACSGui_Graph::createGraphvizNodes( ComposedNode* theBloc, Agraph_t* aSubGraph ) +{ + DEBTRACE("YACSGui_Graph::createGraphvizNodes() " << theBloc->getName()); + + // ---- Create nodes (+ small dummy node for the bloc) + + if ( !dynamic_cast(theBloc) && !getItem(theBloc) ) return; + + Agnode_t* dummyNode; + if (dynamic_cast(theBloc)) + { + string dummyName = "dummy_"; + if (dynamic_cast(theBloc)) dummyName += theBloc->getName(); + else dummyName += getProc()->getChildName(theBloc); + DEBTRACE(dummyName); + dummyNode = agnode( aSubGraph, (char*)(dummyName.c_str()) ); + { + int nh = 10; + int nw = 10; + double lh = nh/DPI; + double lw = nw/DPI; + stringstream height, width; + height << lh; width << lw; + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"height")->index, (char*)(height.str().c_str())); + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"width")->index, (char*)(width.str().c_str())); + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"shape")->index, "box" ); + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"fixedsize")->index, "true" ); + + Agsym_t* anAttr; + if ( !(anAttr = agfindattr(_mainGraph->proto->n,"label")) ) + anAttr = agnodeattr(_mainGraph, "label", "label"); + agxset( dummyNode, anAttr->index, "" ); + } + } + else + { + dummyNode = agnode( aSubGraph, (char*)(getProc()->getChildName(theBloc).c_str()) ); + DEBTRACE("Add node in subgraph " << aSubGraph->name << ": " << dummyNode->name); + + // ---- Set attributes for the concrete node + int nh = getItem(theBloc)->maxHeight()+2*BLOCB; + int nw = getItem(theBloc)->maxWidth(); + double lh = nh/DPI; + double lw = nw/DPI; + // stringstream height, width; + // height << lh; width << lw; + // DEBTRACE(dummyNode->name << " (" << nh << "," << nw << ") = (" << height.str() << " ; " << width.str() <<")"); + QString height, width; + // height = QString("%L1").arg(lh, 0, 'g', 3 ); // Localized format with comma needed on some config (why ?) + // width = QString("%L1").arg(lw, 0, 'g', 3 ); + height = QString(_format.c_str()).arg(lh, 0, 'g', 3 ); // Localized format with comma needed on some config (why ?) + width = QString(_format.c_str()).arg(lw, 0, 'g', 3 ); + DEBTRACE(dummyNode->name << " (" << nh << "," << nw << ") = (" << height.latin1() << " ; " << width.latin1() <<")"); + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"height")->index, (char*)(height.latin1())); + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"width")->index, (char*)(width.latin1())); + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"shape")->index, "box" ); + agxset( dummyNode, agfindattr(_mainGraph->proto->n,"fixedsize")->index, "true" ); + } + + list children = theBloc->edGetDirectDescendants(); + for ( list::iterator it = children.begin(); it != children.end(); it++ ) + { + if ( !getItem(*it) ) continue; + + // --- create graphviz objects for all direct descendants except ComposedNodes + if (!dynamic_cast(*it)) + { + Agnode_t* aNode = agnode( aSubGraph, (char*)(getProc()->getChildName(*it).c_str()) ); + DEBTRACE("Add node in subgraph " << aSubGraph->name << ": " << aNode->name); + + // ---- Set attributes for the concrete node + int nh = getItem(*it)->maxHeight()+2*BLOCB; + int nw = getItem( *it )->maxWidth(); + double lh = nh/DPI; + double lw = nw/DPI; + // stringstream height, width; + // height << lh; width << lw; + // DEBTRACE(aNode->name << " (" << nh << "," << nw << ") = (" << height.str() << " ; " << width.str() <<")"); + QString height, width; +// height = QString("%L1").arg(lh, 0, 'g', 3 ); +// width = QString("%L1").arg(lw, 0, 'g', 3 ); + height = QString(_format.c_str()).arg(lh, 0, 'g', 3 ); + width = QString(_format.c_str()).arg(lw, 0, 'g', 3 ); + DEBTRACE(aNode->name << " (" << nh << "," << nw << ") = (" << height.latin1() << " ; " << width.latin1() <<")"); + agxset( aNode, agfindattr(_mainGraph->proto->n,"height")->index, (char*)(height.latin1())); + agxset( aNode, agfindattr(_mainGraph->proto->n,"width")->index, (char*)(width.latin1())); + agxset( aNode, agfindattr(_mainGraph->proto->n,"shape")->index, "box" ); + agxset( aNode, agfindattr(_mainGraph->proto->n,"fixedsize")->index, "true" ); + } + } + + // ---- Create edges (i.e. links) + + Agnode_t* aNode; + for ( aNode = agfstnode( aSubGraph ); aNode; aNode = agnxtnode( aSubGraph, aNode) ) + { + string aNodeName = aNode->name; + if (aNodeName.find("dummy_") != 0) + { + DEBTRACE("--tail node " << aNode->name); + Agnode_t* aTailNode = aNode; + Node* outNode = getProc()->getChildByName( string(aTailNode->name) ); + + // --- control link from node + { + OutGate *outGate = outNode->getOutGate(); + set setOfInGate = outGate->edSetInGate(); + set::const_iterator itin = setOfInGate.begin(); + for (; itin != setOfInGate.end(); ++itin) + { + Node *inNode = (*itin)->getNode(); + string inNodeName = getProc()->getChildName(inNode); + DEBTRACE("---control link from tail node: ---- "); + if (Node *inFather = theBloc->isInMyDescendance(inNode)) + { + DEBTRACE("---edge inside the bloc"); + Bloc *inBloc = dynamic_cast(inFather); + if (inBloc == theBloc) // link to a bloc whitch is a direct son + { + string inName=""; + if (dynamic_cast(inNode)) inName = "dummy_" + inNodeName; + else inName = inNodeName; + Agnode_t* aHeadNode = agnode( aSubGraph, (char*)(inName.c_str()) ); + Agedge_t* anEdge = agedge( aSubGraph, aTailNode, aHeadNode ); + DEBTRACE("---control link from tail node: ---- " << aNode->name << " --> " << inName); + } + else + { + if (inBloc) // link to a bloc whitch is a grandchild + { + string fatherName = "dummy_" + getProc()->getChildName(inFather); + Agnode_t* aHeadNode = agnode( aSubGraph, (char*)(fatherName.c_str()) ); + Agedge_t* anEdge = agedge( aSubGraph, aTailNode, aHeadNode ); + DEBTRACE("---control link from tail node: ---- " << aNode->name << " --> " << fatherName); + } + else // link to a son whitch is of another type of composed node + { + string fatherName = getProc()->getChildName(inFather); + Agnode_t* aHeadNode = agnode( aSubGraph, (char*)(fatherName.c_str()) ); + Agedge_t* anEdge = agedge( aSubGraph, aTailNode, aHeadNode ); + DEBTRACE("---control link from tail node: ---- " << aNode->name << " --> " << fatherName); + } + } + } + else + { + DEBTRACE("---edge going outside the current bloc scope, to memorize for later"); + _savedControlLinks.insert(pair(inNode, outNode)); + } + } + } + // --- datalink from node + { + list outPortList = outNode->getSetOfOutPort(); + list::const_iterator itou = outPortList.begin(); + for (; itou != outPortList.end(); ++itou) + { + set inPortList = (*itou)->edSetInPort(); + set::const_iterator itin = inPortList.begin(); + for (; itin != inPortList.end(); ++itin) + { + Node *inNode = (*itin)->getNode(); + string inNodeName = getProc()->getChildName(inNode); + DEBTRACE("------data link from tail node: ---- "); + if (Node *inFather = theBloc->isInMyDescendance(inNode)) + { + DEBTRACE("---edge inside the bloc"); + Bloc *inBloc = dynamic_cast(inFather); + if (inBloc == theBloc) // link to a bloc whitch is a direct son + { + string inName=""; + if (dynamic_cast(inNode)) inName = "dummy_" + inNodeName; + else inName = inNodeName; + Agnode_t* aHeadNode = agnode( aSubGraph, (char*)(inName.c_str()) ); + Agedge_t* anEdge = agedge( aSubGraph, aTailNode, aHeadNode ); + DEBTRACE("------data link from tail node: ---- " << aNode->name << " --> " << inName); + } + else + { + if (inBloc) // link to a bloc whitch is a grandchild + { + string fatherName = "dummy_" + getProc()->getChildName(inFather); + Agnode_t* aHeadNode = agnode( aSubGraph, (char*)(fatherName.c_str()) ); + Agedge_t* anEdge = agedge( aSubGraph, aTailNode, aHeadNode ); + DEBTRACE("------data link from tail node: ---- " << aNode->name << " --> " << fatherName); + } + else // link to a son whitch is of another type of composed node + { + string fatherName = getProc()->getChildName(inFather); + Agnode_t* aHeadNode = agnode( aSubGraph, (char*)(fatherName.c_str()) ); + Agedge_t* anEdge = agedge( aSubGraph, aTailNode, aHeadNode ); + DEBTRACE("------data link from tail node: ---- " << aNode->name << " --> " << fatherName); + } + } + } + else + { + DEBTRACE("---edge going outside the current bloc scope, to memorize for later"); + _savedControlLinks.insert(pair(inNode, outNode)); + } + } + } + } + // --- dummy node for the bloc --> all nodes + { + DEBTRACE("------------------------------------ dummy --> " << aNode->name); + Agnode_t* anEdgeNode = aNode; + Agedge_t* anEdge = agedge( aSubGraph, dummyNode, anEdgeNode ); + + // --- retreive arriving links saved previously + + DEBTRACE("--edge node " << aNode->name); + Node* inNode = outNode; + InGate *inGate = inNode->getInGate(); + + pair::iterator, multimap::iterator> ppp; + ppp = _savedControlLinks.equal_range(inNode); // --- saved edges comming to inNode + for(multimap::iterator itm = ppp.first; itm != ppp.second; ++itm) + { + Node *outNode = (*itm).second; + DEBTRACE("saved control link from Node: " << outNode->getName()); + string outName = ""; + if (dynamic_cast(outNode)) outName = "dummy_" + getProc()->getChildName(outNode); + else outName = getProc()->getChildName(outNode); + DEBTRACE("------------------------ saved: ---- " << outName << " --> " << aNode->name); + Agnode_t* aTailNode = agnode( aSubGraph, (char*)(outName.c_str()) ); + Agedge_t* anEdge = agedge( aSubGraph, aTailNode, anEdgeNode ); + } + _savedControlLinks.erase(_savedControlLinks.lower_bound(inNode), _savedControlLinks.upper_bound(inNode)); + } + } + } +} + +// store some functions to have possibility to arrange nodes only on the one giving level + +int YACSGui_Graph::arrangeNodesWithinBloc( Bloc* theBloc ) +{ + //printf(">> YACSGui_Graph::arrangeNodes() method was called\n"); + + aginit(); + + // ---- Create a graphviz context + GVC_t* aGvc = gvContext(); + + // ---- Create a graph + Agraph_t* aGraph = agopen( (char*)( theBloc ? theBloc->getName().c_str() : "aGraph" ), AGDIGRAPH ); + //printf(">> Create graph\n--------------\n"); + + // ---- Initialize and set attributes for the graph + // 1) compound attribute + Agsym_t* anAttr; + if ( !(anAttr = agfindattr( aGraph, "compound" )) ) + anAttr = agraphattr( aGraph, "compound", "false" ); + agxset( aGraph, anAttr->index, "true" ); + + // 2) mindist (minlen) attribute + if ( !(anAttr = agfindattr( aGraph, "mindist" )) ) + anAttr = agraphattr( aGraph, "mindist", "1.0" ); + agxset( aGraph, anAttr->index, (char*)( QString("%1").arg( (float)(8*HOOKPOINT_SIZE)/72., 0, 'g', 3 ).latin1() ) ); + + // 3) ordering attribute +// if ( !(anAttr = agfindattr( aGraph, "ordering" )) ) +// anAttr = agraphattr( aGraph, "ordering", "" ); +// agxset( aGraph, anAttr->index, "in" ); + + // 4) rankdir attribute + if ( !(anAttr = agfindattr( aGraph, "rankdir" )) ) + anAttr = agraphattr( aGraph, "rankdir", "TB" ); + agxset( aGraph, anAttr->index, "LR" ); + + // Initialize attributes for nodes + // 1) height attribute + if ( !(anAttr = agfindattr( aGraph->proto->n, "height" )) ) + anAttr = agnodeattr( aGraph, "height", "" ); + + // 2) width attribute + if ( !(anAttr = agfindattr( aGraph->proto->n, "width" )) ) + anAttr = agnodeattr( aGraph, "width", "" ); + + // 3) shape attribute + if ( !(anAttr = agfindattr( aGraph->proto->n, "shape" )) ) + anAttr = agnodeattr( aGraph, "shape", "" ); + + createGraphvizNodes( theBloc, theBloc, aGraph ); + + // ---- Initialize attributes for edges + // 1) headport attribute + if ( !(anAttr = agfindattr( aGraph->proto->e, "headport" )) ) + anAttr = agedgeattr( aGraph, "headport", "center" ); + + // 2) len attribute + if ( !(anAttr = agfindattr( aGraph->proto->e, "len" )) ) + anAttr = agedgeattr( aGraph, "len", + (char*)( QString("%1").arg( (float)(8*HOOKPOINT_SIZE)/72., 0, 'g', 3 ).latin1() ) ); + + // 3) lhead attribute (for blocks). TO BE IMPROVED. + if ( !(anAttr = agfindattr( aGraph->proto->e, "lhead" )) ) + anAttr = agedgeattr( aGraph, "lhead", "" ); + + // 4) ltail attribute (for blocks). TO BE IMPROVED. + if ( !(anAttr = agfindattr( aGraph->proto->e, "ltail" )) ) + anAttr = agedgeattr( aGraph, "ltail", "" ); + + // 5) tailport attribute + if ( !(anAttr = agfindattr( aGraph->proto->e, "tailport" )) ) + anAttr = agedgeattr( aGraph, "tailport", "center" ); + + // ---- Create edges (i.e. links) + Agnode_t* aNode; + for ( aNode = agfstnode( aGraph ); aNode; aNode = agnxtnode( aGraph, aNode) ) + { + //printf(">> tail node %s\n", aNode->name); + // lets, aNodes[i] is a tail (from) node of the link + Agnode_t* aTailNode = aNode; //aNodes[i]; + Node* aNodeEngine = theBloc->getChildByName( string(aTailNode->name) ); //getNodeByName( string(aTailNode->name) ); + YACSPrs_ElementaryNode* aNodePrs = getItem( aNodeEngine ); + if ( aNodePrs ) + { + QPtrList aPortList = aNodePrs->getPortList(); + for (YACSPrs_Port* aPort = aPortList.first(); aPort; aPort = aPortList.next()) + { + // data, stream and control links ... and label links (label links are considered here, but its have to be removed in the future) + YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); + if ( anIOPort ) + { + // take links from output ports of the node (i.e. from tail ports) + string aClassName = anIOPort->getEngine()->getNameOfTypeOfCurrentInstance(); + if ( !aClassName.compare(OutputPort::NAME) || + !aClassName.compare(OutputDataStreamPort::NAME) || + !aClassName.compare(OutputCalStreamPort::NAME) || + !aClassName.compare(OutGate::NAME) ) + { + list aLinks = anIOPort->getLinks(); + list::iterator it = aLinks.begin(); + for(; it != aLinks.end(); it++) + if ( YACSPrs_PortLink* aLink = dynamic_cast( *it ) ) + { + // search head node of the link + string aNodeName = getInNodeName(theBloc,aNodeEngine,aLink->getInputPort()->getNode()->getEngine()); + if ( aNodeName != "" ) + { + Agnode_t* aHeadNode = agnode( aGraph, (char*)(aNodeName.c_str()) ); + Agedge_t* anEdge = agedge( aGraph, aTailNode, aHeadNode ); + //printf(">> Add edge : %s -> %s\n", aTailNode->name, aHeadNode->name); + + // ---- Set attributes for the concrete edge + // 1) headport attribute + agxset( anEdge, agfindattr(aGraph->proto->e,"headport")->index, "w" ); + + // 2) tailport attribute + agxset( anEdge, agfindattr(aGraph->proto->e,"tailport")->index, "e" ); + } + } + } + } + else if ( YACSPrs_LabelPort* aLPort = dynamic_cast( aPort ) ) + { + // label links (its have to be removed in the future) + if ( aLPort->getSlaveNode() ) + { + string aNodeName = getInNodeName(theBloc,aNodeEngine,aLPort->getSlaveNode()); + if ( aNodeName != "" ) + { + Agnode_t* aHeadNode = agnode( aGraph, (char*)(aNodeName.c_str()) ); + Agedge_t* anEdge = agedge( aGraph, aTailNode, aHeadNode ); + //printf(">> Add edge : %s -> %s\n", aTailNode->name, aHeadNode->name); + + // ---- Set attributes for the concrete edge + // 1) headport attribute + agxset( anEdge, agfindattr(aGraph->proto->e,"headport")->index, "s" ); + + // 2) tailport attribute + agxset( anEdge, agfindattr(aGraph->proto->e,"tailport")->index, "e" ); + } + } + } + } + } + //printf("\n"); + } + + // check if any "OutBloc -> InBloc" links from myBlocInsideLinks map have to be added + // into aGraph corresponding to theBloc + if ( myBlocInsideLinks.find(theBloc) != myBlocInsideLinks.end() ) + { + list< pair > aBLinks = myBlocInsideLinks[theBloc]; + list< pair >::iterator aBLinksIt = aBLinks.begin(); + for ( ; aBLinksIt != aBLinks.end(); aBLinksIt++ ) + { + Bloc* anOutBloc = (*aBLinksIt).first; + Bloc* anInBloc = (*aBLinksIt).second; + + Agnode_t* aTailNode = agnode( aGraph, (char*)(anOutBloc->getName().c_str()) ); + Agnode_t* aHeadNode = agnode( aGraph, (char*)(anInBloc->getName().c_str()) ); + Agedge_t* anEdge = agedge( aGraph, aTailNode, aHeadNode ); + //printf(">> 11 Add edge : %s -> %s\n", aTailNode->name, aHeadNode->name); + + // ---- Set attributes for the concrete edge + // 1) headport attribute + agxset( anEdge, agfindattr(aGraph->proto->e,"headport")->index, "w" ); + + // 2) tailport attribute + agxset( anEdge, agfindattr(aGraph->proto->e,"tailport")->index, "e" ); + } + } + + //printf("--------------\n"); + + // ---- Bind graph to graphviz context - currently must be done before layout +#ifdef HAVE_DOTNEATO_H + gvBindContext( aGvc, aGraph ); + + // ---- Compute a layout + dot_layout( aGraph ); +#else + gvLayout( aGvc, aGraph, "dot" ); +#endif + + // ---- Rendering the graph : retrieve nodes positions + // bounding box from graphviz + //printf(">> GD_bb( aGraph ).LL.x = %d\n",GD_bb( aGraph ).LL.x); + //printf(">> GD_bb( aGraph ).UR.y = %d\n",GD_bb( aGraph ).UR.y); + int aBBheight = GD_bb( aGraph ).UR.y - GD_bb( aGraph ).LL.y; + if ( !dynamic_cast( theBloc ) ) + { + // we have to resize Bloc node before layouting its internal nodes + //printf(">> resize Block %s\n",theBloc->getName().c_str()); + int aBBwidth = GD_bb( aGraph ).UR.x - GD_bb( aGraph ).LL.x; + YACSPrs_BlocNode* aBlocNodePrs = dynamic_cast( getItem( theBloc ) ); + if ( aBlocNodePrs ) + { + int aXRight = aBlocNodePrs->width() + (aBBwidth - aBlocNodePrs->getAreaRect().width()) + BLOCNODE_MARGIN; + int aYBottom = aBlocNodePrs->height() + (aBBheight - aBlocNodePrs->getAreaRect().height()) + BLOCNODE_MARGIN; + aBlocNodePrs->resize( aXRight,aYBottom ); + //printf(">> aXRight = %d; aYBottom = %d\n",aXRight,aYBottom); + //printf(">> getAreaRect().x = %d, getAreaRect().y = %d\n", + // aBlocNodePrs->getAreaRect().x(),aBlocNodePrs->getAreaRect().y()); + aBlocNodePrs->setZ(aBlocNodePrs->z()); + } + } + for ( aNode = agfstnode( aGraph ); aNode; aNode = agnxtnode( aGraph, aNode)) + { + int aXCenter = ND_coord_i( aNode ).x; + int aYCenter = ND_coord_i( aNode ).y; + //printf(">> node %s graphviz center (%d,%d)\n", aNode->name, aXCenter, aYCenter); + + Node* aNodeEngine = theBloc->getChildByName( string(aNode->name) ); //getNodeByName( string(aNode->name) ); + YACSPrs_ElementaryNode* aNodePrs = getItem( aNodeEngine ); + if ( aNodePrs ) + { + // aXCenter is the same as horizontal center of the real node presentation + int aXLeft = aXCenter - aNodePrs->boundingRect().width()/2; //aNodePrs->maxWidth()/2 + 2*HOOKPOINT_SIZE; + + // now we have to recompute vertical center of the real node presentaion + // according to aYCenter + // NOTE: the lower left corner of the drawing is at the origin in graphviz, + // graphviz draws graphs from up to down + // -|----------------------> X + // | + // /|\ Y(gvz) + // | + // |=================-----> X' (X', Y') - a new canvas view coordinate + // | | system after layouting + // | bounding box | + // | from graphviz | + // | | + // |----------------------> X(gvz) + // | + // | + // \|/ Y (Y') + // | + int aYTop = aBBheight - ( aYCenter + aNodePrs->maxHeight()/2/*aNodePrs->boundingRect().height()/2*/ ); + //printf(">> aXLeft = %d, aYTop = %d\n",aXLeft,aYTop); + + if ( !dynamic_cast( theBloc ) ) + { + YACSPrs_BlocNode* aBlocNodePrs = dynamic_cast( getItem( theBloc ) ); + if ( aBlocNodePrs ) + { + aXLeft += aBlocNodePrs->getAreaRect().x() + BLOCNODE_MARGIN/2;// + 2*HOOKPOINT_SIZE; + aYTop += aBlocNodePrs->getAreaRect().y() + BLOCNODE_MARGIN/2; + //printf(">> +Area : aXLeft = %d, aYTop = %d\n",aXLeft,aYTop); + } + } + + if ( dynamic_cast( aNodePrs ) && getDMode() == YACSGui_Graph::FullId ) + { + aXLeft += 3*TITLE_HEIGHT/2; + aYTop += 3*TITLE_HEIGHT/2; + } + + // move presentation of the node + //printf(">> aNodePrs->oldX = %f, aNodePrs->oldY = %f\n",aNodePrs->x(),aNodePrs->y()); + //aNodePrs->setX( aXLeft ); aNodePrs->setY( aYTop ); + aNodePrs->move( aXLeft, aYTop ); + //printf(">> height = %d, width = %d\n",aNodePrs->height(),aNodePrs->width()); + + // print a new node's position for checking + //char buf[50]; + //sprintf(buf, "left=%d,top=%d", aXLeft, aYTop); + //printf(">> node %s at position (%s)\n\n", aNode->name, buf); + } + } + + // ---- Delete layout +#ifdef HAVE_DOTNEATO_H + dot_cleanup( aGraph ); +#else + gvFreeLayout( aGvc, aGraph ); +#endif + + // ---- Free graph structures + agclose( aGraph ); + + // ---- Free context and return number of errors + int aRetVal = 0;//gvFreeContext( aGvc ); + + //getCanvas()->update(); + + //printf(">> YACSGui_Graph::arrangeNodes() method was finished\n"); + + return aRetVal; +} + +void YACSGui_Graph::createGraphvizNodes( Bloc* theBloc, ComposedNode* theFather, Agraph_t* theGraph ) +{ + // ---- Create nodes + // NOTE: it is a test code for graphs without block nodes (clusters) only. TO BE IMPROVED. + if ( theFather ) + { + list aNodeSet = theFather->edGetDirectDescendants(); //getChildren(); //getAllRecursiveConstituents(); + for ( list::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + { + if ( !getItem( *it ) ) continue; + + // create graphviz objects for all not Block nodes and nodes not including into the Block + Agnode_t* aNode = agnode( theGraph, (char*)(theBloc->getChildName( *it ).c_str()) ); + //printf(">> Add node %s\n", aNode->name); + + // ---- Set attributes for the concrete node + // 1) height attribute + agxset( aNode, agfindattr(theGraph->proto->n,"height")->index, + (char*)( QString("%1").arg( (float)(getItem( *it )->maxHeight())/72., 0, 'g', 3 ).latin1() ) ); + + // 2) width attribute + agxset( aNode, agfindattr(theGraph->proto->n,"width")->index, + (char*)( QString("%1").arg( (float)(getItem( *it )->maxWidth())/72., 0, 'g', 3 ).latin1() ) ); + + //printf(">> height = %d, width = %d\n\n",getItem( *it )->maxHeight(),getItem( *it )->maxWidth()); + + // 3) shape attribute + agxset( aNode, agfindattr(theGraph->proto->n,"shape")->index, "box" ); + + // recurtion + if ( !dynamic_cast( *it ) ) + createGraphvizNodes( theBloc, dynamic_cast( *it ), theGraph ); + + /*if ( dynamic_cast( *it ) ) + { + // create graphviz objects for all Block nodes + Agraph_t* aCluster = agsubg( theGraph, (char*)((string("cluster")+getProc()->getChildName( *it )).c_str()) ); + printf(">> Add Block node %s\n", aCluster->name); + + // ---- Set attributes for the concrete node + Agsym_t* anAttr; + // 1) peripheries attribute + if ( !(anAttr = agfindattr( aCluster, "peripheries" )) ) + anAttr = agraphattr( theGraph, "peripheries", "1" ); + agxset( aCluster, anAttr->index, "4" ); + + // recurtion + createGraphvizNodes( dynamic_cast( *it ), aCluster ); + }*/ + } + } +} + +std::string YACSGui_Graph::getInNodeName(YACS::ENGINE::Bloc* theBloc, + YACS::ENGINE::Node* theOutNode, + YACS::ENGINE::Node* theInNode) +{ + Node* anInNode = theInNode; + Node* aStoredNode = anInNode; + + string aNodeName = ""; + + if ( !theBloc || !theOutNode || !theInNode ) + return aNodeName; + + try { + aNodeName = theBloc->getChildName(anInNode); + } + catch (YACS::Exception& ex) { + // check two cases: + // 1) when anInNode is in descendance of theBloc, but not direct + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // |theBloc - - - - - - - - - - - - - - - - - | + // | |another block | | + // | | - - - - - - - - - - - - - - | | + // | ______________ | |another block _________ || | + // | |theOutNode |__|____|______________|anInNode | || | + // | | | | | | | || | + // | |______________| | | |_________| || | + // | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _|| | + // | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| | + // |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| + // + // 2) when anInNode is not of descendance of theBloc + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // |aCommonFather | + // | - - - - - - - - - - - - | + // | |theBloc | - - - - - - - - - - - - - - - - - | + // | | | |another block | | + // | | | | - - - - - - - - - - - - - - | | + // | | ______________ | | |another block _________ || | + // | | |theOunNode |______|_______|____|______________|anInNode | || | + // | | | | | | | |_________| || | + // | | |______________| | | | || | + // | | | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _|| | + // | |_ _ _ _ _ _ _ _ _ _ _ _| |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| | + // |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| + // + while ( anInNode && anInNode->getFather() != theBloc && anInNode->getFather() != getProc() ) + // case 1 case 2 + { + anInNode = anInNode->getFather(); + } + + if ( anInNode->getFather() == theBloc ) + { // case 1 + aNodeName = theBloc->getChildName(anInNode); + } + else if ( anInNode->getFather() == getProc() ) + { // case 2 + anInNode = aStoredNode; + + Bloc* aBlocOut = 0; + Bloc* aBlocIn = 0; + // find the nearest common ancestor for anOutNode and anInNode + while ( anInNode->getFather() != getProc() ) + { + if ( aBlocOut = dynamic_cast(anInNode->getFather()->isInMyDescendance(theOutNode)) ) + { + aBlocIn = dynamic_cast(anInNode); + break; + } + anInNode = anInNode->getFather(); + } + + if ( aBlocOut && aBlocIn ) + { + if ( Bloc* aCommonFather = dynamic_cast(aBlocOut->getFather()) ) + { + if ( myBlocInsideLinks.find(aCommonFather) == myBlocInsideLinks.end() ) + myBlocInsideLinks.insert( make_pair( aCommonFather, + list >(1,make_pair(aBlocOut,aBlocIn)) ) ); + else + myBlocInsideLinks[aCommonFather].push_back( make_pair(aBlocOut,aBlocIn) ); + } + } + } + } + + return aNodeName; +} + diff --git a/src/gui/YACSGui_InlineNodePage.cxx b/src/gui/YACSGui_InlineNodePage.cxx new file mode 100644 index 000000000..8c857e4be --- /dev/null +++ b/src/gui/YACSGui_InlineNodePage.cxx @@ -0,0 +1,2188 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_InlineNodePage + Description : Page for inline function and inline service nodes properties +*/ + +YACSGui_InlineNodePage::YACSGui_InlineNodePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : InlineNodePage( theParent, theName, theFlags ), + YACSGui_NodePage(), + myIsNeedToReorder(false) +{ + if ( !myInputPortsGroupBox || !myOutputPortsGroupBox ) return; + + // the possibility to search is hided according to the Num. 14 from NEWS file + Search->hide(); + mySearch->hide(); + + //#undef HAVE_QEXTSCINTILLA_H +#ifdef HAVE_QEXTSCINTILLA_H + _myTextEdit = new QextScintilla( InPythonEditorGroupBox, "Python Editor" ); + _myTextEdit->setMinimumHeight(150); + InPythonEditorGroupBoxLayout->insertWidget(InPythonEditorGroupBoxLayout->findWidget(myTextEdit), + _myTextEdit ); + InPythonEditorGroupBoxLayout->remove(myTextEdit); + delete myTextEdit; + _myTextEdit->setUtf8(1); + QextScintillaLexerPython *lex = new QextScintillaLexerPython(_myTextEdit); + _myTextEdit->setLexer(lex); + _myTextEdit->setBraceMatching(QextScintilla::SloppyBraceMatch); + _myTextEdit->setAutoIndent(1); + _myTextEdit->setIndentationWidth(4); + _myTextEdit->setIndentationGuides(1); + _myTextEdit->setIndentationsUseTabs(0); + _myTextEdit->setAutoCompletionThreshold(2); +#endif + + QString aPortTypes = QString("Data Flow"); //";Data Stream (BASIC);Data Stream (CALCIUM);Data Stream (PALM)"); + QString aValueTypes = QString("Double;Int;String;Bool"); + + // Input Ports table + myInputPortsGroupBox->setTitle( tr("Input Ports") ); + myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + //aTable->setFixedHeight( 100 ); + aTable->setNumCols( 4 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) ); + aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) ); + aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) ); + aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) ); + aTable->setColumnWidth(0,58); + aTable->setColumnWidth(1,84); + aTable->setColumnWidth(2,80); + aTable->setCellType( -1, 0, YACSGui_Table::String ); + aTable->setCellType( -1, 1, YACSGui_Table::Combo ); + aTable->setCellType( -1, 2, YACSGui_Table::ComboSelect ); + //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column + + aTable->setParams( 0, 1, aPortTypes ); + aTable->setParams( 0, 2, aValueTypes ); + + aTable->setDefValue( 0, 1, "Data Flow" ); + aTable->setDefValue( 0, 2, "Double" ); + + aTable->setEditorSync(true); + + connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) ); + + connect( aTable, SIGNAL(selectButtonClicked( const int, const int )), this, SLOT(onSelectDataType( const int, const int )) ); + + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + myInputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + connect( myInputPortsGroupBox, SIGNAL(Inserted( const int )), this, SLOT(onInserted( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(MovedUp( const int )), this, SLOT(onMovedUp( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(MovedDown( const int )), this, SLOT(onMovedDown( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(Added( const int )), this, SLOT(onAdded( const int )) ); + connect( myInputPortsGroupBox, SIGNAL(Removed( const int )), this, SLOT(onRemoved( const int )) ); + + // Output Ports table + myOutputPortsGroupBox->setTitle( tr("Output Ports") ); + myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + aTable = myOutputPortsGroupBox->Table(); + //aTable->setFixedHeight( 100 ); + aTable->setNumCols( 5 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) ); + aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) ); + aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) ); + aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) ); + aTable->horizontalHeader()->setLabel( 4, tr( "Is in study" ) ); + aTable->setColumnWidth(0,58); + aTable->setColumnWidth(1,84); + aTable->setColumnWidth(2,80); + aTable->setCellType( -1, 0, YACSGui_Table::String ); + aTable->setCellType( -1, 1, YACSGui_Table::Combo ); + aTable->setCellType( -1, 2, YACSGui_Table::ComboSelect ); + //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column + aTable->setCellType( -1, 4, YACSGui_Table::Combo ); + + aTable->setParams( 0, 1, aPortTypes ); + aTable->setParams( 0, 2, aValueTypes ); + aTable->setParams( 0, 4, QString("Yes;No") ); + + aTable->setDefValue( 0, 1, "Data Flow" ); + aTable->setDefValue( 0, 2, "Double" ); + aTable->setDefValue( 0, 4, QString("Yes") ); + + aTable->setEditorSync(true); + + myPara = 0; + myIndex = 0; + + connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) ); + + connect( aTable, SIGNAL(selectButtonClicked( const int, const int )), this, SLOT(onSelectDataType( const int, const int )) ); + + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + myOutputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + connect( myOutputPortsGroupBox, SIGNAL(Inserted( const int )), this, SLOT(onInserted( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(MovedUp( const int )), this, SLOT(onMovedUp( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(MovedDown( const int )), this, SLOT(onMovedDown( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(Added( const int )), this, SLOT(onAdded( const int )) ); + connect( myOutputPortsGroupBox, SIGNAL(Removed( const int )), this, SLOT(onRemoved( const int )) ); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); + connect( mySearch, SIGNAL(returnPressed()), this, SLOT(onSearch()) ); +} + +YACSGui_InlineNodePage::~YACSGui_InlineNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); +} + +void YACSGui_InlineNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( dynamic_cast( theSNode->getNode() ) ) + { + YACSGui_NodePage::setSNode( theSNode ); + myIPList.clear(); + myOPList.clear(); + } +} + +void YACSGui_InlineNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + myNodeName->setReadOnly(false); + + ExecutionGroupBox->hide(); + + EditPortsGroupBox->setTitle( tr( "Edit Ports" ) ); + + YACSGui_Table* aTable; + + myInputPortsGroupBox->ShowBtn(); + myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + aTable = myInputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, false ); + aTable->setReadOnly( -1, 1, false ); + aTable->setReadOnly( -1, 2, false ); + + myOutputPortsGroupBox->ShowBtn(); + myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + aTable = myOutputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, false ); + aTable->setReadOnly( -1, 1, false ); + aTable->setReadOnly( -1, 2, false ); + + InPythonEditorGroupBox->show(); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + myNodeName->setReadOnly(true); + + ExecutionGroupBox->show(); + + EditPortsGroupBox->setTitle( tr( "Port List" ) ); + + YACSGui_Table* aTable; + + myInputPortsGroupBox->HideBtn(); + aTable = myInputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, true ); + aTable->setReadOnly( -1, 1, true ); + aTable->setReadOnly( -1, 2, true ); + + myOutputPortsGroupBox->HideBtn(); + aTable = myOutputPortsGroupBox->Table(); + aTable->setReadOnly( -1, 0, true ); + aTable->setReadOnly( -1, 1, true ); + aTable->setReadOnly( -1, 2, true ); + + InPythonEditorGroupBox->hide(); + } +} + +void YACSGui_InlineNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_InlineNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_InlineNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + DEBTRACE("YACSGui_InlineNodePage::notifyInPortValues"); + QStringList aValues; + + QStringList aPortNames; + myInputPortsGroupBox->Table()->strings( 0, aPortNames ); + + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + DEBTRACE((*it).latin1()); + + map::iterator it1 = theInPortName2Value.find( (*it).latin1() ); + if ( it1 != theInPortName2Value.end() ) + { + DEBTRACE((*it1).second); + aValues.append( QString((*it1).second.c_str()) ); + } + } + + if ( aPortNames.count() == aValues.count() ) + myInputPortsGroupBox->Table()->setStrings( 3, aValues ); +} + +void YACSGui_InlineNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + DEBTRACE("YACSGui_InlineNodePage::notifyOutPortValues"); + QStringList aValues; + + QStringList aPortNames; + myOutputPortsGroupBox->Table()->strings( 0, aPortNames ); + + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + DEBTRACE((*it).latin1()); + + map::iterator it1 = theOutPortName2Value.find( (*it).latin1() ); + if ( it1 != theOutPortName2Value.end() ) + { + DEBTRACE((*it1).second); + aValues.append( QString((*it1).second.c_str()) ); + } + } + + if ( aPortNames.count() == aValues.count() ) + myOutputPortsGroupBox->Table()->setStrings( 3, aValues ); +} + +void YACSGui_InlineNodePage::setDataType( YACS::ENGINE::TypeCode* theDataType ) +{ + DEBTRACE("YACSGui_InlineNodePage::setDataType"); + if ( mySelectDataTypeFor.myRow < 0 ) return; + + YACSGui_Table* aTable = 0; + if ( mySelectDataTypeFor.myIn ) + { + aTable = myInputPortsGroupBox->Table(); + + if ( myRow2DataTypeIn.find(mySelectDataTypeFor.myRow) != myRow2DataTypeIn.end() ) + myRow2DataTypeIn[mySelectDataTypeFor.myRow] = theDataType; + else + myRow2DataTypeIn.insert(make_pair(mySelectDataTypeFor.myRow,theDataType)); + } + else + { + aTable = myOutputPortsGroupBox->Table(); + + if ( myRow2DataTypeOut.find(mySelectDataTypeFor.myRow) != myRow2DataTypeOut.end() ) + myRow2DataTypeOut[mySelectDataTypeFor.myRow] = theDataType; + else + myRow2DataTypeOut.insert(make_pair(mySelectDataTypeFor.myRow,theDataType)); + } + + DEBTRACE("YACSGui_InlineNodePage::setDataType"); + if ( aTable ) + { + // update the content of the cell according to the selected data type + if ( YACSGui_TableComboSelectItem* aCSItem = + dynamic_cast(aTable->item( mySelectDataTypeFor.myRow, 2 )) ) + { + if( aCSItem->selectButton() && aCSItem->selectButton()->isOn() ) + aCSItem->selectButton()->setOn( false ); + + QString aTypeName(theDataType->name()); + aCSItem->showText(aTypeName); + aTable->setDefValue( mySelectDataTypeFor.myRow, 2, aTypeName ); + } + + mySelectDataTypeFor.myRow = -1; + } +} + +void YACSGui_InlineNodePage::checkModifications() +{ + DEBTRACE("YACSGui_InlineNodePage::checkModifications"); + if ( !getNode() ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + if ( myNodeName->text().compare(getNodeName()) != 0 ) isModified = true; + + if ( !isModified ) isModified = isPortsModified(); + if ( !isModified ) isModified = isPortsModified(false); + + if ( !isModified ) + // check the code modifications in the built-in Python code editor + if ( InlineNode* anIN = dynamic_cast( getNode() ) ) + { +#ifdef HAVE_QEXTSCINTILLA_H + QString theText = _myTextEdit->text(); +#else + QString theText = myTextEdit->text(); +#endif + //SCRUTE(theText); + DEBTRACE(theText); + //SCRUTE(anIN->getScript()); + DEBTRACE(anIN->getScript()); + if (theText.compare(QString(anIN->getScript())) != 0 ) isModified = true; + } + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::InlineNodeId); + } +} + +void YACSGui_InlineNodePage::onApply() +{ + DEBTRACE("YACSGui_InlineNodePage::onApply()"); + // Rename a node + if ( myNodeName ) + setNodeName( myNodeName->text() ); + + bool withFilling = ( myIPList.isEmpty() || myOPList.isEmpty() ); + + // Reset the list of input ports + setInputPorts(); + + // Reset the list of output ports + setOutputPorts(); + + // Reset Python function/script + if ( InlineNode* anIN = dynamic_cast( getNode() ) ) + anIN->setScript( scriptText().isEmpty() ? string("") : scriptText().latin1() ); + if ( InlineFuncNode* anIFN = dynamic_cast( getNode() ) ) + { + QString aText = scriptText(); + int aFromId = aText.find( QString("\ndef ") ) + QString("\ndef ").length(); + int aToId = aText.find( QString("("), aFromId ); + aText = aText.left( aToId ); + QString aFname = aText.right( aText.length() - aFromId ).stripWhiteSpace(); + anIFN->setFname( aFname.isEmpty() ? string("") : aFname.latin1() ); + } + + if ( myIsNeedToReorder ) + { + orderPorts(withFilling); + myIsNeedToReorder = false; + } + + resetStoredPortsMaps(); + resetDataTypeMaps(); + resetPLists(); + + updateBlocSize(); +} + +void YACSGui_InlineNodePage::updateState() +{ + DEBTRACE("YACSGui_InlineNodePage::updateState()"); + // Clear input ports table and output ports tables, if they are not empty + if ( myInputPortsGroupBox ) + { + myInputPortsGroupBox->Table()->setNumRows( 0 ); + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + if ( myOutputPortsGroupBox ) + { + myOutputPortsGroupBox->Table()->setNumRows( 0 ); + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Set node type: inline function or inline script + if ( dynamic_cast( getNode() ) ) + myNodeType->setText( tr( "INLINE_FUNCTION_NODE" ) ); // inline function node + else if ( dynamic_cast( getNode() ) ) + myNodeType->setText( tr( "INLINE_SCRIPT_NODE" ) ); // inline script node + + // Fill the table of input ports of the node + fillInputPortsTable(); + + // Fill the table of output ports of the node + fillOutputPortsTable(); + + // Show the body (script/function) of inline node + if ( InlineNode* anIN = dynamic_cast( getNode() ) ) + setScriptText( QString(anIN->getScript()) ); +} + +void YACSGui_InlineNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + +void YACSGui_InlineNodePage::onValueChanged( int theRow, int theCol ) +{ + DEBTRACE("YACSGui_InlineNodePage::onValueChanged " << theRow << " " << theCol); + if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() ) + { + if ( theCol == 1 ) // the port type was changed + { + if( aTable == myInputPortsGroupBox->Table() ) + aTable->setReadOnly( theRow, 3, false ); + } + + if ( theCol == 2 ) // the value type of the port was changed + { + setValueCellValidator( aTable, theRow ); + + if( aTable == myOutputPortsGroupBox->Table() ) + aTable->setReadOnly( theRow, 3, true ); + } + + if ( theCol == 1 || theCol == 2 ) // port type or value type was changed + { + if ( myInputPortsGroupBox->Table() == aTable ) + if ( myRow2StoredInPorts.find(theRow) != myRow2StoredInPorts.end() ) + myRow2StoredInPorts.erase(theRow); + + if ( myOutputPortsGroupBox->Table() == aTable ) + if ( myRow2StoredOutPorts.find(theRow) != myRow2StoredOutPorts.end() ) + myRow2StoredOutPorts.erase(theRow); + } + } +} + +void YACSGui_InlineNodePage::hideEvent( QHideEvent*) +{ + myPara = 0; + myIndex = 0; +#ifdef HAVE_QEXTSCINTILLA_H +// _myTextEdit->removeSelection(); // --- see if replacement ? +#else + myTextEdit->removeSelection(); +#endif +} + +void YACSGui_InlineNodePage::onSearch() +{ +#ifdef HAVE_QEXTSCINTILLA_H + if ( _myTextEdit && mySearch ) + { + if ( _myTextEdit->findFirst( mySearch->text(), true, false, true, &myPara, &myIndex ) ) + { + _myTextEdit->setSelection( myPara, myIndex, myPara, myIndex + mySearch->text().length() ); + myIndex += mySearch->text().length(); + } else { + myPara = 0; + myIndex = 0; + } + } +#else + if ( myTextEdit && mySearch ) + { + if ( myTextEdit->find( mySearch->text(), true, false, true, &myPara, &myIndex ) ) + { + myTextEdit->setSelection( myPara, myIndex, myPara, myIndex + mySearch->text().length() ); + myIndex += mySearch->text().length(); + } else { + myPara = 0; + myIndex = 0; + } + } +#endif +} + +void YACSGui_InlineNodePage::onInserted( const int theRow ) +{ + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredInPorts + if ( myRow2StoredInPorts.size() == 0 ) + return; + + if ( myRow2StoredInPorts.size() == 1 ) + { + if ( theRow == 0 ) + { + InPort* aPort = myRow2StoredInPorts[0]; + myRow2StoredInPorts.insert( std::make_pair(1,aPort) ); + myRow2StoredInPorts.erase(0); + } + } + else + { + map::iterator it = myRow2StoredInPorts.end(); + map::iterator itBeforeBegin = myRow2StoredInPorts.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + InPort* aPort = (*it).second; + + if ( aRow >= theRow ) + { + myRow2StoredInPorts.insert( std::make_pair(aRow+1,aPort) ); + myRow2StoredInPorts.erase(aRow); + } + } + } + + // change the content of myRow2DataTypeIn + if ( myRow2DataTypeIn.size() == 0 ) + return; + + if ( myRow2DataTypeIn.size() == 1 ) + { + if ( theRow == 0 ) + { + TypeCode* aTC = myRow2DataTypeIn[0]; + myRow2DataTypeIn.insert( std::make_pair(1,aTC) ); + myRow2DataTypeIn.erase(0); + } + } + else + { + map::iterator it = myRow2DataTypeIn.end(); + map::iterator itBeforeBegin = myRow2DataTypeIn.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + TypeCode* aTC = (*it).second; + + if ( aRow >= theRow ) + { + myRow2DataTypeIn.insert( std::make_pair(aRow+1,aTC) ); + myRow2DataTypeIn.erase(aRow); + } + } + } + + myIsNeedToReorder = true; + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredOutPorts + if ( myRow2StoredOutPorts.size() == 0 ) + return; + + if ( myRow2StoredOutPorts.size() == 1 ) + { + if ( theRow == 0 ) + { + OutPort* aPort = myRow2StoredOutPorts[0]; + myRow2StoredOutPorts.insert( std::make_pair(1,aPort) ); + myRow2StoredOutPorts.erase(0); + } + } + else + { + map::iterator it = myRow2StoredOutPorts.end(); + map::iterator itBeforeBegin = myRow2StoredOutPorts.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + OutPort* aPort = (*it).second; + + if ( aRow >= theRow ) + { + myRow2StoredOutPorts.insert( std::make_pair(aRow+1,aPort) ); + myRow2StoredOutPorts.erase(aRow); + } + } + } + + // change the content of myRow2DataTypeOut + if ( myRow2DataTypeOut.size() == 0 ) + return; + + if ( myRow2DataTypeOut.size() == 1 ) + { + if ( theRow == 0 ) + { + TypeCode* aTC = myRow2DataTypeOut[0]; + myRow2DataTypeOut.insert( std::make_pair(1,aTC) ); + myRow2DataTypeOut.erase(0); + } + } + else + { + map::iterator it = myRow2DataTypeOut.end(); + map::iterator itBeforeBegin = myRow2DataTypeOut.begin()--; + for ( it--; it != itBeforeBegin; it-- ) + { + int aRow = (*it).first; + TypeCode* aTC = (*it).second; + + if ( aRow >= theRow ) + { + myRow2DataTypeOut.insert( std::make_pair(aRow+1,aTC) ); + myRow2DataTypeOut.erase(aRow); + } + } + } + + myIsNeedToReorder = true; + } +} + +void YACSGui_InlineNodePage::onMovedUp( const int theUpRow ) +{ + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredInPorts + InPort* aPortToMoveDown = 0; + if ( myRow2StoredInPorts.find(theUpRow) != myRow2StoredInPorts.end() ) + { + aPortToMoveDown = myRow2StoredInPorts[theUpRow]; + myRow2StoredInPorts.erase(theUpRow); + } + + InPort* aPortToMoveUp = 0; + if ( myRow2StoredInPorts.find(theUpRow+1) != myRow2StoredInPorts.end() ) + { + aPortToMoveUp = myRow2StoredInPorts[theUpRow+1]; + myRow2StoredInPorts.erase(theUpRow+1); + } + + if ( aPortToMoveUp ) myRow2StoredInPorts.insert( std::make_pair(theUpRow,aPortToMoveUp)); + if ( aPortToMoveDown ) myRow2StoredInPorts.insert( std::make_pair(theUpRow+1,aPortToMoveDown)); + + // change the content of myRow2DataTypeIn + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeIn.find(theUpRow) != myRow2DataTypeIn.end() ) + { + aTCToMoveDown = myRow2DataTypeIn[theUpRow]; + myRow2DataTypeIn.erase(theUpRow); + } + + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeIn.find(theUpRow+1) != myRow2DataTypeIn.end() ) + { + aTCToMoveUp = myRow2DataTypeIn[theUpRow+1]; + myRow2DataTypeIn.erase(theUpRow+1); + } + + if ( aTCToMoveUp ) myRow2DataTypeIn.insert( std::make_pair(theUpRow,aTCToMoveUp)); + if ( aTCToMoveDown ) myRow2DataTypeIn.insert( std::make_pair(theUpRow+1,aTCToMoveDown)); + + myIsNeedToReorder = true; + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredOutPorts + OutPort* aPortToMoveDown = 0; + if ( myRow2StoredOutPorts.find(theUpRow) != myRow2StoredOutPorts.end() ) + { + aPortToMoveDown = myRow2StoredOutPorts[theUpRow]; + myRow2StoredOutPorts.erase(theUpRow); + } + + OutPort* aPortToMoveUp = 0; + if ( myRow2StoredOutPorts.find(theUpRow+1) != myRow2StoredOutPorts.end() ) + { + aPortToMoveUp = myRow2StoredOutPorts[theUpRow+1]; + myRow2StoredOutPorts.erase(theUpRow+1); + } + + if ( aPortToMoveUp ) myRow2StoredOutPorts.insert( std::make_pair(theUpRow,aPortToMoveUp)); + if ( aPortToMoveDown ) myRow2StoredOutPorts.insert( std::make_pair(theUpRow+1,aPortToMoveDown)); + + // change the content of myRow2DataTypeOut + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeOut.find(theUpRow) != myRow2DataTypeOut.end() ) + { + aTCToMoveDown = myRow2DataTypeOut[theUpRow]; + myRow2DataTypeOut.erase(theUpRow); + } + + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeOut.find(theUpRow+1) != myRow2DataTypeOut.end() ) + { + aTCToMoveUp = myRow2DataTypeOut[theUpRow+1]; + myRow2DataTypeOut.erase(theUpRow+1); + } + + if ( aTCToMoveUp ) myRow2DataTypeOut.insert( std::make_pair(theUpRow,aTCToMoveUp)); + if ( aTCToMoveDown ) myRow2DataTypeOut.insert( std::make_pair(theUpRow+1,aTCToMoveDown)); + + myIsNeedToReorder = true; + } +} + +void YACSGui_InlineNodePage::onMovedDown( const int theDownRow ) +{ + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredInPorts + InPort* aPortToMoveUp = 0; + if ( myRow2StoredInPorts.find(theDownRow) != myRow2StoredInPorts.end() ) + { + aPortToMoveUp = myRow2StoredInPorts[theDownRow]; + myRow2StoredInPorts.erase(theDownRow); + } + + InPort* aPortToMoveDown = 0; + if ( myRow2StoredInPorts.find(theDownRow-1) != myRow2StoredInPorts.end() ) + { + aPortToMoveDown = myRow2StoredInPorts[theDownRow-1]; + myRow2StoredInPorts.erase(theDownRow-1); + } + + if ( aPortToMoveDown ) myRow2StoredInPorts.insert( std::make_pair(theDownRow,aPortToMoveDown)); + if ( aPortToMoveUp ) myRow2StoredInPorts.insert( std::make_pair(theDownRow-1,aPortToMoveUp)); + + // change the content of myRow2DataTypeIn + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeIn.find(theDownRow) != myRow2DataTypeIn.end() ) + { + aTCToMoveUp = myRow2DataTypeIn[theDownRow]; + myRow2DataTypeIn.erase(theDownRow); + } + + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeIn.find(theDownRow-1) != myRow2DataTypeIn.end() ) + { + aTCToMoveDown = myRow2DataTypeIn[theDownRow-1]; + myRow2DataTypeIn.erase(theDownRow-1); + } + + if ( aTCToMoveDown ) myRow2DataTypeIn.insert( std::make_pair(theDownRow,aTCToMoveDown)); + if ( aTCToMoveUp ) myRow2DataTypeIn.insert( std::make_pair(theDownRow-1,aTCToMoveUp)); + + myIsNeedToReorder = true; + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredOutPorts + OutPort* aPortToMoveUp = 0; + if ( myRow2StoredOutPorts.find(theDownRow) != myRow2StoredOutPorts.end() ) + { + aPortToMoveUp = myRow2StoredOutPorts[theDownRow]; + myRow2StoredOutPorts.erase(theDownRow); + } + + OutPort* aPortToMoveDown = 0; + if ( myRow2StoredOutPorts.find(theDownRow-1) != myRow2StoredOutPorts.end() ) + { + aPortToMoveDown = myRow2StoredOutPorts[theDownRow-1]; + myRow2StoredOutPorts.erase(theDownRow-1); + } + + if ( aPortToMoveDown ) myRow2StoredOutPorts.insert( std::make_pair(theDownRow,aPortToMoveDown)); + if ( aPortToMoveUp ) myRow2StoredOutPorts.insert( std::make_pair(theDownRow-1,aPortToMoveUp)); + + // change the content of myRow2DataTypeOut + TypeCode* aTCToMoveUp = 0; + if ( myRow2DataTypeOut.find(theDownRow) != myRow2DataTypeOut.end() ) + { + aTCToMoveUp = myRow2DataTypeOut[theDownRow]; + myRow2DataTypeOut.erase(theDownRow); + } + + TypeCode* aTCToMoveDown = 0; + if ( myRow2DataTypeOut.find(theDownRow-1) != myRow2DataTypeOut.end() ) + { + aTCToMoveDown = myRow2DataTypeOut[theDownRow-1]; + myRow2DataTypeOut.erase(theDownRow-1); + } + + if ( aTCToMoveDown ) myRow2DataTypeOut.insert( std::make_pair(theDownRow,aTCToMoveDown)); + if ( aTCToMoveUp ) myRow2DataTypeOut.insert( std::make_pair(theDownRow-1,aTCToMoveUp)); + + myIsNeedToReorder = true; + } +} + +void YACSGui_InlineNodePage::onRemoved( const int theRow ) +{ + DEBTRACE("YACSGui_InlineNodePage::onRemoved: " << theRow); + if ( YACSGui_PlusMinusGrp* aGrpBox = ( YACSGui_PlusMinusGrp* )sender() ) + if ( myInputPortsGroupBox == aGrpBox ) + { + // change the content of myRow2StoredInPorts + int aRow; + DEBTRACE(myRow2StoredInPorts.size()); + for(aRow=theRow;aRowTable()->setDefValue( theRow, 2, "" ); + myInputPortsGroupBox->Table()->item( theRow, 2 )->setText("Double"); + } + else if ( myOutputPortsGroupBox == aGrpBox ) + { + myOutputPortsGroupBox->Table()->setDefValue( theRow, 2, "" ); + myOutputPortsGroupBox->Table()->item( theRow, 2 )->setText("Double"); + } +} + +void YACSGui_InlineNodePage::onSelectDataType( const int theRow, const int theCol ) +{ + DEBTRACE("YACSGui_InlineNodePage::onSelectDataType"); + if ( theCol == 2 && theRow >= 0 ) // the value type selection + { + if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() ) + { + YACSGui_TableComboSelectItem* aCSItem = dynamic_cast(aTable->item( theRow, theCol )); + if ( aCSItem && aCSItem->selectButton() && !aCSItem->selectButton()->isOn() ) + { + mySelectDataTypeFor.myRow = -1; + return; + } + + if ( aTable == myInputPortsGroupBox->Table() ) + { + if ( !mySelectDataTypeFor.myIn && mySelectDataTypeFor.myRow >= 0 ) + if ( YACSGui_TableComboSelectItem* aCSPrevItem = + dynamic_cast(aTable->item( mySelectDataTypeFor.myRow, theCol )) ) + if ( aCSPrevItem->selectButton() ) aCSPrevItem->selectButton()->setOn(false); + + mySelectDataTypeFor.myIn = true; + mySelectDataTypeFor.myRow = theRow; + } + else if ( aTable == myOutputPortsGroupBox->Table() ) + { + if ( mySelectDataTypeFor.myIn && mySelectDataTypeFor.myRow >= 0 ) + if ( YACSGui_TableComboSelectItem* aCSPrevItem = + dynamic_cast(aTable->item( mySelectDataTypeFor.myRow, theCol )) ) + if ( aCSPrevItem->selectButton() ) aCSPrevItem->selectButton()->setOn(false); + + mySelectDataTypeFor.myIn = false; + mySelectDataTypeFor.myRow = theRow; + } + } + } +} + +void YACSGui_InlineNodePage::fillInputPortsTable() +{ + DEBTRACE("YACSGui_InlineNodePage::fillInputPortsTable()"); + if ( !getNode() ) return; + + myRow2StoredInPorts.clear(); + myRow2DataTypeIn.clear(); + + QStringList aPortNames; + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + + QValueList aReadOnlyFlags; + + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + QStringList aPTCB = aTable->Params( 0, 1 ); + + int aRowId = 0; + list anInPortsEngine = getNode()->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + { + InPort* anInPort = *anInPortsIter; + + myRow2StoredInPorts.insert( std::make_pair(aRowId,anInPort) ); + myRow2DataTypeIn[aRowId]=anInPort->edGetType(); + + // Collect port names in the list + aPortNames.append( anInPort->getName() ); + + // Port type + if ( InputPort* anInputP = dynamic_cast(anInPort) ) + { + aPortTypes.append( aPTCB[0] ); + + int nbLinks = anInPort->edGetNumberOfLinks(); + aReadOnlyFlags.append( nbLinks > 0 ); + } + //else if ( InputBasicStreamPort* aBasicStreamP = dynamic_cast(anInPort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[1] ); + //} + else if ( InputCalStreamPort* aCalStreamP = dynamic_cast(anInPort) ) + { + aPortTypes.append( aPTCB[2] ); + aReadOnlyFlags.append( true ); + } + //else if ( InputPalmStreamPort* aPalmStreamP = dynamic_cast(anInPort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[3] ); + //} + else + { // take default value from combo box + aPortTypes.append( aPTCB[0] ); + aReadOnlyFlags.append( true ); + } + + // Value type + aValueTypes.append( getPortType( anInPort ) ); + + // Value + aValues.append( getPortValue( anInPort ) ); + + aRowId++; + } + + // Fill "Port name" column + aTable->setStrings( 0, aPortNames, true ); + + // Fill "Port type" column + aTable->setStrings( 1, aPortTypes, true ); + + // Fill "Value type" column + aTable->setStrings( 2, aValueTypes, true ); + + // set validator for input cell + for (int irow=0; irow < aTable->numRows(); irow++) + setValueCellValidator( aTable, irow); + + // Fill "Value" column + aTable->setStrings( 3, aValues, true ); + + // Set "Value" column read only (for linked ports) + for ( int i = 0, n = aTable->numRows(); i < n; i++ ) + { + aTable->setDefValue( i, 2, aValueTypes[i] ); + aTable->setReadOnly( i, 3, aReadOnlyFlags[ i ] ); + } + + if ( !aPortNames.empty() ) myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); +} + +void YACSGui_InlineNodePage::fillOutputPortsTable() +{ + DEBTRACE("YACSGui_InlineNodePage::fillOutputPortsTable()"); + if ( !getNode() ) return; + + myRow2StoredOutPorts.clear(); + myRow2DataTypeOut.clear(); + + QStringList aPortNames; + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + QStringList anIsInStudy; + + YACSGui_Table* aTable = myOutputPortsGroupBox->Table(); + QStringList aPTCB = aTable->Params( 0, 1 ); + + int aRowId = 0; + list anOutPortsEngine = getNode()->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + { + OutPort* anOutPort = *anOutPortsIter; + + myRow2StoredOutPorts.insert( std::make_pair(aRowId,anOutPort) ); + myRow2DataTypeOut[aRowId]=anOutPort->edGetType(); + + // Collect port names in the list + aPortNames.append( anOutPort->getName() ); + + // Port type + if ( OutputPort* anOutputP = dynamic_cast(anOutPort) ) + { + aPortTypes.append( aPTCB[0] ); + } + //else if ( OutputBasicStreamPort* aBasicStreamP = dynamic_cast(anOutPort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[1] ); + //} + else if ( OutputCalStreamPort* aCalStreamP = dynamic_cast(anOutPort) ) + { + aPortTypes.append( aPTCB[2] ); + } + //else if ( OutputPalmStreamPort* aPalmStreamP = dynamic_cast(anOutPort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[3] ); + //} + else + { // take default value from combo box + aPortTypes.append( aPTCB[0] ); + } + + // Value type + aValueTypes.append( getPortType( anOutPort ) ); + + // Value + aValues.append( getPortValue( anOutPort ) ); + + // Is in study + // There is no a such parameter either in engine or GUI at the current moment. + // TODO: we need to implement it at GUI side. + // As a temporary solution we set the default value + anIsInStudy.append( aTable->defValue( 0, 4 ) ); + + aRowId++; + } + + // Fill "Port name" column + aTable->setStrings( 0, aPortNames, true ); + + // Fill "Port type" column + aTable->setStrings( 1, aPortTypes, true ); + + // Fill "Value type" column + aTable->setStrings( 2, aValueTypes, true ); + + // Fill "Value" column + aTable->setStrings( 3, aValues, true ); + + // Fill "Is in study" column + aTable->setStrings( 4, anIsInStudy, true ); + + // Set "Value" column read only + for ( int i = 0, n = aTable->numRows(); i < n; i++ ) + { + aTable->setDefValue( i, 2, aValueTypes[i] ); + aTable->setReadOnly( i, 3, true ); + } + + if ( !aPortNames.empty() ) myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); +} + +QString YACSGui_InlineNodePage::getPortType( YACS::ENGINE::Port* thePort ) const +{ + QString aType; + + YACSGui_Table* aTable = 0; + if ( dynamic_cast(thePort) ) + aTable = myInputPortsGroupBox->Table(); + else if ( dynamic_cast(thePort) ) + aTable = myOutputPortsGroupBox->Table(); + + if ( !aTable ) return aType; + + QStringList aVTCB = aTable->Params( 0, 2 ); + + if ( DataPort* aDataPort = dynamic_cast(thePort) ) + { + DynType aDType = aDataPort->edGetType()->kind(); + if ( aDType > NONE && aDType < Objref ) + aType = aVTCB[aDType-1]; + else + aType = QString(aDataPort->edGetType()->name()); + } + + return aType; +} + +bool YACSGui_InlineNodePage::isStored( YACS::ENGINE::Port* thePort ) +{ + if ( InPort* anIP = dynamic_cast(thePort) ) + { + map::iterator it = myRow2StoredInPorts.begin(); + for ( ; it != myRow2StoredInPorts.end(); it++ ) + if ( (*it).second == thePort ) return true; + return false; + } + else if ( OutPort* anOP = dynamic_cast(thePort) ) + { + map::iterator it = myRow2StoredOutPorts.begin(); + for ( ; it != myRow2StoredOutPorts.end(); it++ ) + if ( (*it).second == thePort ) return true; + return false; + } + return true; // the gate ports are kept (not re-create) +} + +void YACSGui_InlineNodePage::resetStoredPortsMaps() +{ + DEBTRACE("YACSGui_InlineNodePage::resetStoredPortsMaps"); + myRow2StoredInPorts.clear(); + myRow2DataTypeIn.clear(); + + QStringList aIPortNames; + myInputPortsGroupBox->Table()->strings( 0, aIPortNames ); + + int aRowId = 0; + for ( QStringList::Iterator it = aIPortNames.begin(); it != aIPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + try { + if ( InputPort* aIDP = getNode()->getInputPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aIDP); + myRow2StoredInPorts[aRowId]=aIDP; + myRow2DataTypeIn[aRowId]=aIDP->edGetType(); + } + } + catch (YACS::Exception& ex) { + try { + if ( InputDataStreamPort* aIDSP = getNode()->getInputDataStreamPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aIDSP); + myRow2StoredInPorts[aRowId]=aIDSP; + myRow2DataTypeIn[aRowId]=aIDSP->edGetType(); + } + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + aRowId++; + } + + myRow2StoredOutPorts.clear(); + myRow2DataTypeOut.clear(); + + QStringList aOPortNames; + myOutputPortsGroupBox->Table()->strings( 0, aOPortNames ); + + aRowId = 0; + for ( QStringList::Iterator it = aOPortNames.begin(); it != aOPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + try { + if ( OutputPort* aODP = getNode()->getOutputPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aODP); + myRow2StoredOutPorts.insert( std::make_pair(aRowId,aODP) ); + myRow2DataTypeOut[aRowId]=aODP->edGetType(); + } + } + catch (YACS::Exception& ex) { + try { + if ( OutputDataStreamPort* aODSP = getNode()->getOutputDataStreamPort((*it).latin1()) ) + { + DEBTRACE("store port: " << aRowId << " " << aODSP); + myRow2StoredOutPorts.insert( std::make_pair(aRowId,aODSP) ); + myRow2DataTypeOut[aRowId]=aODSP->edGetType(); + } + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + aRowId++; + } +} + +void YACSGui_InlineNodePage::resetDataTypeMaps() +{ + DEBTRACE("YACSGui_InlineNodePage::resetDataTypeMaps"); +//Reset is done in resetStoredPortsMaps +// myRow2DataTypeIn.clear(); +// myRow2DataTypeOut.clear(); +} + +void YACSGui_InlineNodePage::resetPLists() +{ + DEBTRACE("YACSGui_InlineNodePage::resetPLists"); + resetIPLists(); + resetOPLists(); +} + +void YACSGui_InlineNodePage::resetIPLists() +{ + DEBTRACE("YACSGui_InlineNodePage::resetIPLists"); + myIPList.clear(); + + QStringList aIPortNames; + myInputPortsGroupBox->Table()->strings( 0, aIPortNames ); + + for ( QStringList::Iterator it = aIPortNames.begin(); it != aIPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + try { + if ( InPort* aIDP = getNode()->getInputPort((*it).latin1()) ) + myIPList.append(aIDP); + } + catch (YACS::Exception& ex) { + try { + if ( InPort* aIDSP = getNode()->getInputDataStreamPort((*it).latin1()) ) + myIPList.append(aIDSP); + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + } +} + +void YACSGui_InlineNodePage::resetOPLists() +{ + DEBTRACE("YACSGui_InlineNodePage::resetOPLists"); + myOPList.clear(); + + QStringList aOPortNames; + myOutputPortsGroupBox->Table()->strings( 0, aOPortNames ); + + for ( QStringList::Iterator it = aOPortNames.begin(); it != aOPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + try { + if ( OutPort* aODP = getNode()->getOutputPort((*it).latin1()) ) + myOPList.append(aODP); + } + catch (YACS::Exception& ex) { + try { + if ( OutPort* aODSP = getNode()->getOutputDataStreamPort((*it).latin1()) ) + myOPList.append(aODSP); + } + catch (YACS::Exception& ex) { + std::cerr << "INTERNAL ERROR. Unknown port " << (*it).latin1() << std::endl; + } + } + } +} + +void YACSGui_InlineNodePage::orderPorts( bool withFilling ) +{ + ElementaryNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + + QStringList aPortNames; + int aRowId; + + // order input ports according to the list of ports names in the table + myInputPortsGroupBox->Table()->strings( 0, aPortNames ); + + if ( withFilling || myIPList.isEmpty() ) + { // copy the list of engine ports into the ptr list + myIPList.clear(); + list anInPortsEngine = aNode->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + myIPList.append(*anInPortsIter); + } + + aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + InPort* anIP = myIPList.at(aRowId); + if ( !anIP ) return; + + if ( (*it).compare( QString(anIP->getName()) ) ) // diff. order + { + bool isDataStream = false; + InPort* anIPToMove = 0; + if ( dynamic_cast(anIP) ) + anIPToMove = aNode->getInputPort((*it).latin1()); + else if ( dynamic_cast(anIP) ) + { + anIPToMove = aNode->getInputDataStreamPort((*it).latin1()); + isDataStream = true; + } + + int engineId = -1; + if ( anIPToMove ) + engineId = myIPList.find( anIPToMove ); + + if ( engineId > -1 ) + { + if ( aRowId < engineId ) // it is needed to move up engine port + for ( int i=aRowId; iupdate( UP, + ( !isDataStream ? INPUTPORT : INPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anIPToMove] ); + + if ( aRowId > engineId ) // it is needed to move down engine port + for ( int i=engineId; iupdate( DOWN, + ( !isDataStream ? INPUTPORT : INPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anIPToMove] ); + } + } + + aRowId++; + } + + aPortNames.clear(); + + // order output ports according to the list of ports names in the table + myOutputPortsGroupBox->Table()->strings( 0, aPortNames ); + + if ( withFilling || myOPList.isEmpty() ) + { // copy the list of engine ports into the ptr list + myOPList.clear(); + list anOutPortsEngine = aNode->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + myOPList.append(*anOutPortsIter); + } + + aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + OutPort* anOP = myOPList.at(aRowId); + if ( !anOP ) return; + + if ( (*it).compare( QString(anOP->getName()) ) ) // diff. order + { + bool isDataStream = false; + OutPort* anOPToMove = 0; + if ( dynamic_cast(anOP) ) + anOPToMove = aNode->getOutputPort((*it).latin1()); + else if ( dynamic_cast(anOP) ) + { + anOPToMove = aNode->getOutputDataStreamPort((*it).latin1()); + isDataStream = true; + } + + int engineId = -1; + if ( anOPToMove ) + engineId = myOPList.find( anOPToMove ); + + if ( engineId > -1 ) + { + if ( aRowId < engineId ) // it is needed to move up engine port + for ( int i=aRowId; iupdate( UP, + ( !isDataStream ? OUTPUTPORT : OUTPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anOPToMove] ); + + if ( aRowId > engineId ) // it is needed to move down engine port + for ( int i=engineId; iupdate( DOWN, + ( !isDataStream ? OUTPUTPORT : OUTPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[anOPToMove] ); + } + } + + aRowId++; + } + + mySNode->update( UPDATE, 0, mySNode ); +} + +void YACSGui_InlineNodePage::setInputPorts() +{ + DEBTRACE("YACSGui_InlineNodePage::setInputPorts()"); + if ( !myInputPortsGroupBox ) return; + + ElementaryNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + + myInputPortsGroupBox->Table()->stopEdit(true); + + // remove old ports + list anInPortsEngine = aNode->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + if ( !isStored(*anInPortsIter) ) + { + DEBTRACE("remove port " << *anInPortsIter); + mySNode->update( REMOVE, + ( dynamic_cast(*anInPortsIter) ? INPUTPORT : INPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] ); + myIPList.take(myIPList.find(*anInPortsIter)); + + //aNode->edRemovePort(*anInPortsIter); + // remove port subject (and all subject links connected to this port) + mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] ); + } + + // read input data and input data stream ports from the table + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + + QStringList aPortNames; + QStringList aValues; + + aTable->strings( 0, aPortNames ); + aTable->strings( 3, aValues ); + + YACS::ENGINE::Catalog* aCatalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it,++aRowId) + { + DEBTRACE(aRowId << " " << *it); + if ( (*it).isEmpty() ) continue; + + if ( aPortNames.contains(*it) > 1 ) + { + std::string what("The node "); + what += mySNode->getName(); + what += " contains two or more "; + what+=(*it).latin1(); + what+=" input ports"; + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + what, + tr("BUT_OK")); + continue; + } + + // retrieve a type name of the input port as a string + std::string aType = ""; + + if (QTableItem* anItem = aTable->item( aRowId, 2 ) ) + { + if ( QComboBox* aCB = dynamic_cast(aTable->cellWidget( aRowId, 2 )) ) + { + if ( aCB->lineEdit() ) + aType = aCB->lineEdit()->text().latin1(); + } + else + aType = anItem->text().latin1(); + } + + TypeCode* aTC = 0; + bool toSwitch = true; + if ( !aType.empty() ) + { + QStringList aL = aTable->Params( aRowId, 2 ); + if ( aL.findIndex( QString(aType) ) == -1 ) toSwitch = false; + } + + if ( toSwitch ) + { + DEBTRACE("switch branch"); + switch ( DynType(aTable->intValueCombo( 2, aRowId ) + 1) ) + { + case Double: + aType = "double"; + break; + case Int: + aType = "int"; + break; + case String: + aType = "string"; + break; + case Bool: + aType = "bool"; + break; + case Objref: + //aType = "objref"; + break; + case Sequence: + //aType = "sequence"; + break; + case Array: + //aType = "array"; + break; + case Struct: + //aType = "struct"; + break; + default: + break; + } + } + else + { + DEBTRACE("no switch branch"); + if ( myRow2DataTypeIn.find(aRowId) != myRow2DataTypeIn.end() ) + aTC = myRow2DataTypeIn[aRowId]->clone(); + if ( !aTC ) + { + std::cerr << "Problem with data types initialization" << std::endl; + continue; + } + } + + GuiEvent anEvent = EDIT; + if ( aTable->intValueCombo( 1, aRowId ) == 0 ) // Data Flow port + { + DEBTRACE("Data flow port"); + InputPort* aIDP = 0; + if ( myRow2StoredInPorts.find(aRowId) != myRow2StoredInPorts.end() ) + { // ---- update port ---- + DEBTRACE("Update port"); + if ( aIDP = dynamic_cast(myRow2StoredInPorts[aRowId]) ) + { + aIDP->setName(*it); + aTC = aIDP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + DEBTRACE("Create port"); + if ( !toSwitch ) + { + aIDP = aNode->edAddInputPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectInputPort(..) to public method + mySNode->addSubjectInputPort( aIDP, *it ); + } + else + { + aIDP = dynamic_cast( dynamic_cast(mySNode)->addInputPort( aCatalog, aType, *it )->getPort() ); + aTC = aIDP->edGetType(); + } + + // ADD event will be emitted from hmi after subject creation => re-create port prs + anEvent = ADD; + + myIPList.append(aIDP); + } + + if ( aIDP ) + { +#ifdef _DEVDEBUG_ + if(!aValues[aRowId].isNull()) + std::cerr << aValues[aRowId] << std::endl; + else + std::cerr << "Qnull" << std::endl; +#endif + + // initialize new created input data port + double d; + int ii; + bool ok; + switch ( aTC->kind() ) + { + case Double: + d=aValues[aRowId].toDouble(&ok); + if(ok) + aIDP->edInit(d); + anEvent = EDIT; + break; + case Int: + ii= aValues[aRowId].toInt(&ok) ; + if(ok) + aIDP->edInit(ii); + anEvent = EDIT; + break; + case String: + if(aValues[aRowId] != "< ? >") + aIDP->edInit( aValues[aRowId].isEmpty() ? "" : aValues[aRowId].latin1() ); + anEvent = EDIT; + break; + case Bool: + if(aValues[aRowId] != "< ? >") + aIDP->edInit( aValues[aRowId].compare( aTable->Params(aRowId,3)[0] ) ? false : true ); + anEvent = EDIT; + break; + case Objref: + //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + anEvent = EDIT; + break; + case Sequence: + //aIDP->edInit( "" ); // TODO : create an Any* (i.e. SequenceAny*) with corresponding type and initialize with it + anEvent = EDIT; + break; + case Array: + //aIDP->edInit( "" ); // TODO : create an Any* (i.e. ArrayAny*) with corresponding type and initialize with it + anEvent = EDIT; + break; + case Struct: + //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + anEvent = EDIT; + break; + default: + break; + } + + if ( anEvent == EDIT ) + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDP]); + //else if ( anEvent == ADD ) + // mySNode->update( ADD, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDP]); + } + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 1 ) // Data Stream (BASIC) port + // aNode->edAddInputDataStreamPort( *it, aTC ); + // // TODO : initialize new created input data stream port + + else if ( aTable->intValueCombo( 1, aRowId ) == 2 ) // Data Stream (CALCIUM) port + { + InputDataStreamPort* aIDSP = 0; + if ( myRow2StoredInPorts.find(aRowId) != myRow2StoredInPorts.end() ) + { // ---- update port ---- + DEBTRACE("---- update port ---- " << *it); + if ( aIDSP = dynamic_cast(myRow2StoredInPorts[aRowId]) ) + { + aIDSP->setName(*it); + aTC = aIDSP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + DEBTRACE("---- create port ---- " << *it); + if ( aType.empty() ) + { + aIDSP = aNode->edAddInputDataStreamPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectIDSPort(..) to public method + mySNode->addSubjectIDSPort( aIDSP, *it ); + } + else + { + aIDSP = dynamic_cast( dynamic_cast(mySNode)->addIDSPort( aCatalog, aType, *it )->getPort() ); + aTC = aIDSP->edGetType(); + } + + // ADD event will be emitted => re-create port prs + anEvent = ADD; + + myIPList.append(aIDSP); + } + + // TODO : initialize new created input data stream port + + if ( aIDSP && anEvent == EDIT ) + mySNode->update( EDIT, INPUTDATASTREAMPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDSP]); + //else if ( anEvent == ADD ) + // mySNode->update( ADD, INPUTDATASTREAMPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDSP]); + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 3 ) // Data Stream (PALM) port + // aNode->edAddInputDataStreamPort( *it, aTC ); + // // TODO : initialize new created input data stream port + + } + + //resetIPLists(); +} + +void YACSGui_InlineNodePage::setOutputPorts() +{ + DEBTRACE("YACSGui_InlineNodePage::setOutputPorts()"); + if ( !myOutputPortsGroupBox ) return; + + ElementaryNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + + myOutputPortsGroupBox->Table()->stopEdit(true); + + // remove old ports + list anOutPortsEngine = aNode->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + if ( !isStored(*anOutPortsIter) ) + { + mySNode->update( REMOVE, + ( dynamic_cast(*anOutPortsIter) ? OUTPUTPORT : OUTPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] ); + myOPList.take(myOPList.find(*anOutPortsIter)); + + //aNode->edRemovePort(*anOutPortsIter); + // remove port subject (and all subject links connected to this port) + mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] ); + } + + // read output data and output data stream ports from the table + YACSGui_Table* aTable = myOutputPortsGroupBox->Table(); + + QStringList aPortNames; + QStringList aValues; + + aTable->strings( 0, aPortNames ); + + YACS::ENGINE::Catalog* aCatalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + if ( aPortNames.contains(*it) > 1 ) + { + std::string what("The node "); + what += mySNode->getName(); + what += " contains two or more "; + what+=(*it).latin1(); + what+=" output ports"; + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + what, + tr("BUT_OK")); + continue; + } + + // retrieve a type name of the input port as a string + std::string aType = ""; + + if (QTableItem* anItem = aTable->item( aRowId, 2 ) ) + { + if ( QComboBox* aCB = dynamic_cast(aTable->cellWidget( aRowId, 2 )) ) + { + if ( aCB->lineEdit() ) + aType = aCB->lineEdit()->text().latin1(); + } + else + aType = anItem->text().latin1(); + } + + TypeCode* aTC = 0; + bool toSwitch = true; + if ( !aType.empty() ) + { + QStringList aL = aTable->Params( aRowId, 2 ); + if ( aL.findIndex( QString(aType) ) == -1 ) toSwitch = false; + } + + if ( toSwitch ) + { + switch ( DynType(aTable->intValueCombo( 2, aRowId ) + 1) ) + { + case Double: + aType = "double"; + break; + case Int: + aType = "int"; + break; + case String: + aType = "string"; + break; + case Bool: + aType = "bool"; + break; + case Objref: + //aType = "objref"; + break; + case Sequence: + //aType = "sequence"; + break; + case Array: + //aType = "array"; + break; + case Struct: + //aType = "struct"; + break; + default: + break; + } + } + else + { + if ( myRow2DataTypeOut.find(aRowId) != myRow2DataTypeOut.end() ) + aTC = myRow2DataTypeOut[aRowId]->clone(); + if ( !aTC ) + { + std::cerr << "Problem with data types initialization" << std::endl; + aRowId++; + continue; + } + } + + GuiEvent anEvent = EDIT; + if ( aTable->intValueCombo( 1, aRowId ) == 0 ) // Data Flow port + { + OutputPort* aODP = 0; + if ( myRow2StoredOutPorts.find(aRowId) != myRow2StoredOutPorts.end() ) + { // ---- update port ---- + DEBTRACE("---- update port ---- " << *it); + if ( aODP = dynamic_cast(myRow2StoredOutPorts[aRowId]) ) + { + aODP->setName(*it); + aTC = aODP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + DEBTRACE("---- create port ---- " << *it); + if ( !toSwitch ) + { + aODP = aNode->edAddOutputPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectOutputPort(..) to public method + mySNode->addSubjectOutputPort( aODP, *it ); + } + else + { + aODP = dynamic_cast( dynamic_cast(mySNode)->addOutputPort( aCatalog, aType, *it )->getPort() ); + aTC = aODP->edGetType(); + } + + // ADD event will be emitted from hmi after subject creation => re-create port prs + anEvent = ADD; + + myOPList.append(aODP); + } + + if ( aODP && anEvent == EDIT ) + mySNode->update( EDIT, OUTPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aODP]); + + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 1 ) // Data Stream (BASIC) port + // aNode->edAddOutputDataStreamPort( *it, aTC ); + + else if ( aTable->intValueCombo( 1, aRowId ) == 2 ) // Data Stream (CALCIUM) port + { + OutputDataStreamPort* aODSP = 0; + if ( myRow2StoredOutPorts.find(aRowId) != myRow2StoredOutPorts.end() ) + { // ---- update port ---- + if ( aODSP = dynamic_cast(myRow2StoredOutPorts[aRowId]) ) + { + aODSP->setName(*it); + aTC = aODSP->edGetType(); + // EDIT event will be emitted => only update port prs + } + } + else + { // ---- create port ---- + if ( aType.empty() ) + { + aODSP = aNode->edAddOutputDataStreamPort( *it, aTC ); + // here we need also to create a port subject + // this is a temporary solution solution, bcause of SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method => we can not retrieve all value types + // from the _typeMap of the Catalog ("objref","sequence","array","struct" are not available from _typeMap now) + // => we need to change SubjectNode::addSubjectODSPort(..) to public method + mySNode->addSubjectODSPort( aODSP, *it ); + } + else + { + aODSP = dynamic_cast( dynamic_cast(mySNode)->addODSPort( aCatalog, aType, *it )->getPort() ); + aTC = aODSP->edGetType(); + } + + // ADD event will be emitted => re-create port prs + anEvent = ADD; + + myOPList.append(aODSP); + } + + if ( aODSP && anEvent == EDIT ) + mySNode->update( EDIT, OUTPUTDATASTREAMPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aODSP]); + + } + + //else if ( aTable->intValueCombo( 1, aRowId ) == 3 ) // Data Stream (PALM) port + // aNode->edAddOutputDataStreamPort( *it, aTC ); + + // TODO : Remember "Is in study" flag for output pirt + // ... + + aRowId++; + } + + //resetOPLists(); +} + +YACS::ENGINE::TypeCode* YACSGui_InlineNodePage::createTypeCode( YACS::ENGINE::DynType theType, + YACSGui_Table* theTable, + int theRowId ) +{ + TypeCode* aTC = 0; + + switch (theType) + { + case Double: + case Int: + case String: + case Bool: + aTC = new TypeCode(theType); + break; + case Objref: + { + if ( theTable->intValueCombo( 1, theRowId ) == 2 ) // Data Stream (CALCIUM) port + aTC = new TypeCodeObjref("CALCIUM","CALCIUM"); + else if ( theTable->intValueCombo( 1, theRowId ) == 1 ) // Data Stream (BASIC) port + aTC = new TypeCodeObjref("BASIC","BASIC"); + else if ( theTable->intValueCombo( 1, theRowId ) == 3 ) // Data Stream (PALM) port + aTC = new TypeCodeObjref("PALM","PALM"); + else + aTC = new TypeCodeObjref("",""); + } + break; + case Sequence: + aTC = new TypeCodeSeq("","",(new TypeCode(Double))); + break; + case Array: + aTC = new TypeCodeArray("","",(new TypeCode(Double)),0); + break; + case Struct: + aTC = new TypeCodeStruct("",""); + break; + default: + break; + } + + return aTC; +} + +QString YACSGui_InlineNodePage::scriptText() const +{ +#ifdef HAVE_QEXTSCINTILLA_H + return _myTextEdit->text(); +#else + return myTextEdit->text(); +#endif +} + +void YACSGui_InlineNodePage::setScriptText( const QString& txt ) +{ +#ifdef HAVE_QEXTSCINTILLA_H + _myTextEdit->setText( txt ); +#else + myTextEdit->setText( txt ); +#endif +} + +bool YACSGui_InlineNodePage::isPortsModified( bool theInput ) +{ + bool isModified = false; + + if ( !getNode() ) return isModified; + // read data and data stream ports from the table + YACSGui_Table* aTable = 0; + if ( theInput ) aTable = myInputPortsGroupBox->Table(); + else aTable = myOutputPortsGroupBox->Table(); + if ( !aTable ) return isModified; + aTable->stopEdit(true); + + QStringList aPortNames; + aTable->strings( 0, aPortNames ); + + if ( ( theInput ? aPortNames.count() != getNode()->getNumberOfInputPorts() : + aPortNames.count() != getNode()->getNumberOfOutputPorts() ) ) isModified = true; + else + { + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + + aTable->strings( 1, aPortTypes ); + aTable->strings( 2, aValueTypes ); + aTable->strings( 3, aValues ); + + QStringList aPTCB = aTable->Params( 0, 1 ); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + Port* aPort = 0; + try { + aPort = ( theInput ? (Port*)(getNode()->getInPort(*it)) : (Port*)(getNode()->getOutPort(*it)) ); + } + catch (...) {} + + if ( aPort ) + { + DEBTRACE("isPortsModified: " << getPortValue( aPort ) << " " << getPortType( aPort ) ); + QString value=aValues[aRowId]; + QString valtype=aValueTypes[aRowId]; + if(value.isNull()) + value="< ? >"; + if(valtype.isNull()) + valtype="< ? >"; + DEBTRACE(value<<","<(aPort) ) + aPortType = aPTCB[2]; + + if ( aPortType.compare(aPortTypes[aRowId]) != 0 ) + { + isModified = true; + break; + } + + //if ( !theInput ) + // TODO: compare "Is in study" fields (not yet in use) + } + else // this case means that we renamed any port or added a new one (i.e. check port name) + { + isModified = true; + break; + } + aRowId++; + } + } + return isModified; +} + diff --git a/src/gui/YACSGui_InputPanel.cxx b/src/gui/YACSGui_InputPanel.cxx new file mode 100644 index 000000000..8071e485a --- /dev/null +++ b/src/gui/YACSGui_InputPanel.cxx @@ -0,0 +1,1117 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +QColor getColor( int theStatus ) +{ + QColor aColor; + switch (theStatus) + { + case UNDEFINED: aColor = Qt::lightGray; break; + case INVALID: aColor = Qt::red; break; + case READY: aColor = Qt::green; break; + case TOLOAD: aColor = Qt::darkYellow; break; + case LOADED: aColor = Qt::darkMagenta; break; + case TOACTIVATE: aColor = Qt::darkCyan; break; + case ACTIVATED: aColor = Qt::darkBlue; break; + case DESACTIVATED: aColor = Qt::gray; break; + case DONE: aColor = Qt::darkGreen; break; + case SUSPENDED: aColor = Qt::gray; break; + case LOADFAILED: aColor.setHsv(320,255,255); break; + case EXECFAILED: aColor.setHsv( 20,255,255); break; + case PAUSE: aColor.setHsv(180,255,255); break; + case INTERNALERR: aColor.setHsv(340,255,255); break; + case DISABLED: aColor.setHsv( 40,255,255); break; + case FAILED: aColor.setHsv( 20,255,255); break; + case ERROR: aColor.setHsv( 0,255,255); break; + default: aColor = Qt::lightGray; + } + return aColor; +} + +std::string portValueType( YACS::ENGINE::TypeCode* theTC ) +{ + std::string aType = ""; + switch ( theTC->kind() ) + { + case Double: aType = "double"; break; + case Int: aType = "int"; break; + case String: aType = "string"; break; + case Bool: aType = "bool"; break; + case Objref: aType = "objref"; break; + case Sequence: aType = "sequence"; break; + case Array: aType = "array"; break; + case Struct: aType = "struct"; break; + default: break; + } + return aType; +} + +QString getText( int theStatus ) +{ + QString aText; + switch (theStatus) + { + case UNDEFINED: aText = "UNDEFINED"; break; + case INVALID: aText = "INVALID"; break; + case READY: aText = "READY"; break; + case TOLOAD: aText = "TOLOAD"; break; + case LOADED: aText = "LOADED"; break; + case TOACTIVATE: aText = "TOACTIVATE"; break; + case ACTIVATED: aText = "ACTIVATED"; break; + case DESACTIVATED: aText = "DESACTIVATED"; break; + case DONE: aText = "DONE"; break; + case SUSPENDED: aText = "SUSPENDED"; break; + case LOADFAILED: aText = "LOADFAILED"; break; + case EXECFAILED: aText = "EXECFAILED"; break; + case PAUSE: aText = "PAUSE"; break; + case INTERNALERR: aText = "INTERNALERR"; break; + case DISABLED: aText = "DISABLED"; break; + case FAILED: aText = "FAILED"; break; + case ERROR: aText = "ERROR"; break; + default: break; + } + return aText; +} + +/* + Class : YACSGui_InputPanel::BtnStyle + Description : Style for buttons with text aligned to the left border +*/ + +class YACSGui_InputPanel::BtnStyle : public QWindowsStyle +{ +public: + + virtual void drawControl( ControlElement element, + QPainter *p, + const QWidget *widget, + const QRect &r, + const QColorGroup &cg, + SFlags how = Style_Default, + const QStyleOption& = QStyleOption::Default ) const; +}; + +void YACSGui_InputPanel::BtnStyle::drawControl( ControlElement element, + QPainter *p, + const QWidget *widget, + const QRect &r, + const QColorGroup &cg, + SFlags flags, + const QStyleOption& opt ) const +{ + if ( element != CE_PushButtonLabel ) + QWindowsStyle::drawControl( element, p, widget, r, cg, flags, opt ); + else + { +#ifndef QT_NO_PUSHBUTTON + const QPushButton *button = (const QPushButton *) widget; + QRect ir = r; + + if ( button->isDown() || button->isOn() ) + { + flags |= Style_Sunken; + ir.moveBy(pixelMetric(PM_ButtonShiftHorizontal, widget), + pixelMetric(PM_ButtonShiftVertical, widget)); + } + + int tf=AlignVCenter | ShowPrefix; + if (!styleHint(SH_UnderlineAccelerator, widget, QStyleOption::Default, 0)) + tf |= NoAccel; + + tf |= AlignLeft; + ir.setLeft( 10 ); + drawItem(p, ir, tf, cg, + flags & Style_Enabled, button->pixmap(), button->text(), + button->text().length(), &(cg.buttonText()) ); + + // draw arrow + PrimitiveElement aPE = button->isOn() ? PE_ArrowUp : PE_ArrowDown; + int h = r.height(); + QRect aRect( r.right() - h, r.top(), h, h ); + SFlags aFlags = Style_Default | Style_Enabled; + drawPrimitive( aPE, p, aRect, cg, aFlags, QStyleOption( QColor( 0, 0, 255 ) ) ); + + if (flags & Style_HasFocus) + drawPrimitive( PE_FocusRect, p, subRect( SR_PushButtonFocusRect, widget ), cg, flags ); +#endif + } +} + + +/* + Class : YACSGui_InputPanel + Description : Dockable window containing push buttons and corresponding widgets +*/ + +//======================================================================= +// name : YACSGui_InputPanel +// Purpose : Constructor +//======================================================================= +YACSGui_InputPanel::YACSGui_InputPanel( YACSGui_Module* theModule ) + : QDockWindow( QDockWindow::InDock, theModule && theModule->getApp() ? theModule->application()->desktop() : 0 ), + myModule(theModule), + myApplyBtn(0), + myCancelBtn(0) +{ + QScrollView* scrollView = new QScrollView( this ); + + // Create main frame and main layout + QFrame* aMainFrame = new QFrame( scrollView->viewport() ); + scrollView->addChild( aMainFrame ); + scrollView->setResizePolicy( QScrollView::AutoOneFit ); + + myMainLayout = new QVBoxLayout( aMainFrame, MARGIN, SPACING); + + // create an empty property pages + createPage( YACSGui_InputPanel::ContainerId ); + createPage( YACSGui_InputPanel::ComponentId ); + createPage( YACSGui_InputPanel::SchemaId ); + createPage( YACSGui_InputPanel::InDataNodeId ); + createPage( YACSGui_InputPanel::OutDataNodeId ); + createPage( YACSGui_InputPanel::InStudyNodeId ); + createPage( YACSGui_InputPanel::OutStudyNodeId ); + createPage( YACSGui_InputPanel::InlineNodeId ); + createPage( YACSGui_InputPanel::ServiceNodeId ); + createPage( YACSGui_InputPanel::ForLoopNodeId ); + createPage( YACSGui_InputPanel::ForEachLoopNodeId ); + createPage( YACSGui_InputPanel::WhileLoopNodeId ); + createPage( YACSGui_InputPanel::SwitchNodeId ); + createPage( YACSGui_InputPanel::BlockNodeId ); + createPage( YACSGui_InputPanel::LinkId ); + createPage( YACSGui_InputPanel::DataTypeId ); + + // myMainLayout->addStretch( 1 ); + + // Add "Apply" and "Close" buttons + QGroupBox* aGrpBtns = new QGroupBox( aMainFrame, "GroupButtons" ); + aGrpBtns->setColumnLayout(0, Qt::Vertical ); + aGrpBtns->layout()->setSpacing( 0 ); aGrpBtns->layout()->setMargin( 0 ); + aGrpBtns->setFrameStyle( QFrame::NoFrame ); + //aGrpBtns->setFrameStyle( QFrame::StyledPanel ); + QHBoxLayout* aGrpBtnsLayout = new QHBoxLayout( aGrpBtns->layout() ); + aGrpBtnsLayout->setAlignment( Qt::AlignTop ); + aGrpBtnsLayout->setSpacing( 0 ); aGrpBtnsLayout->setMargin( 0 ); + + myApplyBtn = new QPushButton( tr( "APPLY_BTN" ), aGrpBtns ); + connect( myApplyBtn, SIGNAL( clicked() ), this, SLOT( onApply() ) ); + + myCancelBtn = new QPushButton( tr( "CLOSE_BTN" ), aGrpBtns ); + connect( myCancelBtn, SIGNAL( clicked() ), this, SLOT( onClose() ) ); + + aGrpBtnsLayout->addWidget( myApplyBtn ); + aGrpBtnsLayout->addItem ( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + aGrpBtnsLayout->addWidget( myCancelBtn ); + + myMainLayout->addWidget( aGrpBtns ); + myMainLayout->addSpacing( SPACING ); + + updateState(); + + setWidget( scrollView ); + scrollView->show(); +} + +//======================================================================= +// name : ~YACSGui_InputPanel +// Purpose : Destructor +//======================================================================= +YACSGui_InputPanel::~YACSGui_InputPanel() +{ + myMainBtns.clear(); + myPages.clear(); +} + +//================================================================ +// Function : setBtnText +// Purpose : +//================================================================ +void YACSGui_InputPanel::setBtnText( const QString& theText, const int thePageId ) +{ + if ( myMainBtns.contains( thePageId ) ) + myMainBtns[ thePageId ]->setText( theText ); +} + +//======================================================================= +// name : getPage +// Purpose : +//======================================================================= +QWidget* YACSGui_InputPanel::getPage( const int thePageId, + const bool theWithCreate ) +{ + if ( myPages.contains( thePageId ) ) + return myPages[ thePageId ]; + else if ( theWithCreate ) + { + createPage( thePageId ); + return myPages.contains( thePageId ) ? myPages[ thePageId ] : 0; + } + + QWidget* aWid = 0; + return aWid; +} + +//============================================================================= +// Function : getPageId +// Purpose : +//============================================================================= +int YACSGui_InputPanel::getPageId( QWidget* thePage ) const +{ + int anId = -1; + if ( thePage != 0 ) + { + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + QWidget* aPage = anIter.data(); + if ( aPage == thePage ) + { + anId = anIter.key(); + break; + } + } + } + + return anId; +} + +//============================================================================= +// Function : insertPage +// Purpose : Insert page in input panel. If this is already present in input panel +// then it is not inserted. if theBeforePageId == -1 then page is added +// at the end. Method returns identifier of inserted page or -1 if page +// is not inserted. +//============================================================================= +int YACSGui_InputPanel::insertPage( QWidget*, + const int thePageId, + const int theBeforePageId, + const int theStretch ) const +{ + +} + +//======================================================================= +// name : removePage +// Purpose : +//======================================================================= +void YACSGui_InputPanel::removePage( QWidget* thePage ) +{ + if ( !thePage ) return; + + int anId = getPageId(thePage); + + if ( myMainBtns.find(anId) != myMainBtns.end() ) + { + QPushButton* aBtn = myMainBtns[anId]; + myMainBtns.erase(anId); + delete aBtn; + } + + if ( myPages.find(anId) != myPages.end() ) + myPages.erase(anId); +} + +//======================================================================= +// name : sizeHint +// Purpose : +//======================================================================= +QSize YACSGui_InputPanel::sizeHint() const +{ + int w = QFontMetrics( font() ).width( QString("0"), 1 ) * 30; + return QSize( w, QDockWindow::sizeHint().height() ); + //return QDockWindow::sizeHint(); +} + +//======================================================================= +// name : isOn +// Purpose : +//======================================================================= +bool YACSGui_InputPanel::isOn( const int i ) const +{ + bool res = false; + if ( myMainBtns.contains( i ) ) + res = myMainBtns[i]->isOn(); + return res; +} + +//======================================================================= +// name : setOn +// Purpose : +//======================================================================= +void YACSGui_InputPanel::setOn( const bool on, const int i ) +{ + if ( myMainBtns.contains( i ) ) + myMainBtns[i]->setOn( on ); +} + +//======================================================================= +// name : isVisible +// Purpose : +//======================================================================= +bool YACSGui_InputPanel::isVisible( const int i ) const +{ + DEBTRACE("YACSGui_InputPanel::isVisible " << i); + bool res = false; + if ( myMainBtns.contains( i ) ) + res = myMainBtns[i]->isVisibleTo( myMainBtns[i]->parentWidget() ); + return res; +} + +//======================================================================= +// name : setVisible +// Purpose : +//======================================================================= +void YACSGui_InputPanel::setVisible( const bool on, const int i ) +{ + if ( myMainBtns.contains( i ) ) + myMainBtns[i]->setShown( on ); + if ( myPages.contains( i ) ) + myPages[i]->setShown( on && myMainBtns[i]->isOn() ); +} + +//======================================================================= +// name : setExclusiveVisible +// Purpose : +//======================================================================= +void YACSGui_InputPanel::setExclusiveVisible( const bool on, const std::list ids ) +{ + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + int anId = anIter.key(); + + bool aVisibility = on; + if ( std::find(ids.begin(), ids.end(), anId) == ids.end() ) + aVisibility = !on; + + if ( myMainBtns.contains( anId ) ) myMainBtns[anId]->setShown( aVisibility ); + myPages[anId]->setShown( aVisibility && myMainBtns[anId]->isOn() ); + } +} + +//======================================================================= +// name : getVisiblePagesIds +// Purpose : +//======================================================================= +std::list YACSGui_InputPanel::getVisiblePagesIds() +{ + list aRetList; + + for ( QMap< int, QWidget* >::const_iterator anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + int anId = anIter.key(); + if ( isVisible(anId) ) aRetList.push_back(anId); + } + + return aRetList; +} + +//======================================================================= +// name : setMode +// Purpose : +//======================================================================= +void YACSGui_InputPanel::setMode( const YACSGui_InputPanel::PageMode theMode, const int thePageId ) +{ + switch( thePageId ) + { + case SchemaId: + { + if ( YACSGui_SchemaPage* page = dynamic_cast(myPages[thePageId]) ) + page->setMode( theMode ); + } + break; + case InDataNodeId: + case OutDataNodeId: + case InStudyNodeId: + case OutStudyNodeId: + case InlineNodeId: + case ServiceNodeId: + case ForLoopNodeId: + case ForEachLoopNodeId: + case WhileLoopNodeId: + case SwitchNodeId: + case BlockNodeId: + { + if ( YACSGui_NodePage* page = dynamic_cast(myPages[thePageId]) ) + page->setMode( theMode ); + } + break; + case DataTypeId: + { + if ( YACSGui_DataTypePage* page = dynamic_cast(myPages[thePageId]) ) + page->setMode( theMode ); + } + break; + default: + break; + } +} + +//================================================================ +// Function : getPrefferedSize +// Purpose : +//================================================================ +QSize YACSGui_InputPanel::getPrefferedSize() +{ + setUpdatesEnabled( false ); + + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + if ( isVisible(anIter.key()) ) + anIter.data()->updateGeometry(); + + QSize aSize = this->sizeHint() * 1.44; + setUpdatesEnabled( true ); + repaint(); + return aSize; +} + +//================================================================ +// Function : emitApply +// Purpose : +//================================================================ +void YACSGui_InputPanel::emitApply( const int theId ) +{ + emit Apply( theId ); +} + +//======================================================================= +// name : onMainBtn +// Purpose : SLOT. Called when main button ( i.e. button used for show/hide +// windows of input panel clicked ) +//======================================================================= +void YACSGui_InputPanel::onMainBtn( bool ) +{ + updateState(); +} + +//======================================================================= +// name : onApplyEnabled +// Purpose : SLOT. Called when "Apply" button should be disabled or enabled. +//======================================================================= +void YACSGui_InputPanel::onApplyEnabled( bool enable ) +{ + myApplyBtn->setEnabled(enable); +} + +//======================================================================= +// name : onApply +// Purpose : SLOT. Called when "Apply" button clicked. Emit signal with +// Corresponding id. +//======================================================================= +void YACSGui_InputPanel::onApply() +{ + DEBTRACE("YACSGui_InputPanel::onApply"); + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + int anId = anIter.key(); + if ( isVisible(anId) ) + { + switch(anId) { + case ContainerId: { + YACSGui_ContainerPage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case ComponentId: { + YACSGui_ComponentPage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case SchemaId: { + YACSGui_SchemaPage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case InDataNodeId: + case OutDataNodeId: + case InStudyNodeId: + case OutStudyNodeId: { + DEBTRACE("YACSGui_InputPanel::onApply"); + YACSGui_DataNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case InlineNodeId: { + DEBTRACE("YACSGui_InputPanel::onApply"); + YACSGui_InlineNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case ServiceNodeId: { + YACSGui_ServiceNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case ForLoopNodeId: { + YACSGui_ForLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case ForEachLoopNodeId: { + YACSGui_ForEachLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case WhileLoopNodeId: { + YACSGui_WhileLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case SwitchNodeId: { + YACSGui_SwitchNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case BlockNodeId: { + YACSGui_BlockNodePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + // ... + case LinkId: { + YACSGui_LinkPage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + case DataTypeId: { + YACSGui_DataTypePage* page = dynamic_cast(myPages[anId]); + if(page) + page->onApply(); + break; + } + default: + break; + } + emit Apply( anId ); + } + } + + // export the modified schema (i.e. an active schema!) into + // the temporary XML file, which will be used for create execution objects + myModule->temporaryExport(); +} + +//======================================================================= +// name : onClose +// Purpose : SLOT. Called when "Close" button clicked. +//======================================================================= +void YACSGui_InputPanel::onClose() +{ + hide(); + if(getModule()->getGuiMode() == YACSGui_Module::NewMode) { + getModule()->setGuiMode(YACSGui_Module::EditMode); + if(getModule()->activeTreeView()) + getModule()->activeTreeView()->syncPageTypeWithSelection(); + } + onApplyEnabled(true); +} + +//======================================================================= +// name : onNotifyNodeStatus +// Purpose : +//======================================================================= +void YACSGui_InputPanel::onNotifyNodeStatus( int theNodeId, int theStatus ) +{ + DEBTRACE("YACSGui_InputPanel::onNotifyNodeStatus: " << theNodeId << " " << theStatus); + if ( Node::idMap.count(theNodeId) == 0 ) return; + Node* aNode= Node::idMap[theNodeId]; + + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + int anId = anIter.key(); + if ( isVisible(anId) ) + { + switch(anId) { + case InDataNodeId: + case OutDataNodeId: + case InStudyNodeId: + case OutStudyNodeId: { + YACSGui_DataNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + case InlineNodeId: { + YACSGui_InlineNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + case ServiceNodeId: { + YACSGui_ServiceNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + case ForLoopNodeId: { + YACSGui_ForLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + case ForEachLoopNodeId: { + YACSGui_ForEachLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + case WhileLoopNodeId: { + YACSGui_WhileLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + case SwitchNodeId: { + YACSGui_SwitchNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + case BlockNodeId: { + YACSGui_BlockNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyNodeStatus(theStatus); + break; + } + default: + break; + } + } + } +} + +//======================================================================= +// name : onNotifyInPortValues +// Purpose : +//======================================================================= +void YACSGui_InputPanel::onNotifyInPortValues( int theNodeId, + std::map theInPortName2Value ) +{ + DEBTRACE("onNotifyInPortValues: " << theNodeId); + if ( Node::idMap.count(theNodeId) == 0 ) return; + Node* aNode= Node::idMap[theNodeId]; + + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + int anId = anIter.key(); + if ( isVisible(anId) ) + { + switch(anId) { + case InDataNodeId: + case OutDataNodeId: + case InStudyNodeId: + case OutStudyNodeId: { + YACSGui_DataNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + case InlineNodeId: { + YACSGui_InlineNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + case ServiceNodeId: { + YACSGui_ServiceNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + case ForLoopNodeId: { + YACSGui_ForLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + case ForEachLoopNodeId: { + YACSGui_ForEachLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + case WhileLoopNodeId: { + YACSGui_WhileLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + case SwitchNodeId: { + YACSGui_SwitchNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + case BlockNodeId: { + YACSGui_BlockNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyInPortValues(theInPortName2Value); + break; + } + default: + break; + } + } + } +} + +//======================================================================= +// name : onNotifyOutPortValues +// Purpose : +//======================================================================= +void YACSGui_InputPanel::onNotifyOutPortValues( int theNodeId, + std::map theOutPortName2Value ) +{ + DEBTRACE("YACSGui_InputPanel::onNotifyOutPortValues" << theNodeId); + if ( Node::idMap.count(theNodeId) == 0 ) return; + Node* aNode= Node::idMap[theNodeId]; + + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + int anId = anIter.key(); + if ( isVisible(anId) ) + { + switch(anId) { + case InDataNodeId: + case OutDataNodeId: + case InStudyNodeId: + case OutStudyNodeId: { + YACSGui_DataNodePage* page = dynamic_cast(myPages[anId]); + DEBTRACE("Notify"); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + case InlineNodeId: { + YACSGui_InlineNodePage* page = dynamic_cast(myPages[anId]); + DEBTRACE("Notify"); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + case ServiceNodeId: { + YACSGui_ServiceNodePage* page = dynamic_cast(myPages[anId]); + DEBTRACE("Notify"); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + case ForLoopNodeId: { + YACSGui_ForLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + case ForEachLoopNodeId: { + YACSGui_ForEachLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + case WhileLoopNodeId: { + YACSGui_WhileLoopNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + case SwitchNodeId: { + YACSGui_SwitchNodePage* page = dynamic_cast(myPages[anId]); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + case BlockNodeId: { + YACSGui_BlockNodePage* page = dynamic_cast(myPages[anId]); + DEBTRACE("Notify"); + if(page && page->getNode() == aNode) + page->notifyOutPortValues(theOutPortName2Value); + break; + } + default: + break; + } + } + } +} + +//======================================================================= +// name : updateState +// Purpose : +//======================================================================= +void YACSGui_InputPanel::updateState() +{ + DEBTRACE("YACSGui_InputPanel::updateState()"); + QMap< int, QWidget* >::const_iterator anIter; + for ( anIter = myPages.begin(); anIter != myPages.end(); ++anIter ) + { + int anId = anIter.key(); + QPushButton* b = myMainBtns.contains( anId ) ? myMainBtns[ anId ] : 0; + QWidget* page = myPages.contains( anId ) ? myPages[ anId ] : 0; + if ( b && page ) + page->setShown( b->isVisibleTo( b->parentWidget() ) && b->isOn() ); + } +} + +//======================================================================= +// name : createPage +// Purpose : +//======================================================================= +void YACSGui_InputPanel::createPage( const int thePageId ) +{ + DEBTRACE("YACSGui_InputPanel::createPage"); + // Create buttons and frames inside the main frame + if ( !myMainLayout ) return; + QFrame* aMainFrame = dynamic_cast( myMainLayout->parent() ); + if ( !aMainFrame ) return; + + // Create a drop down button + QPushButton* button = new QPushButton( aMainFrame ); + + QWidget* page = 0; + switch ( thePageId ) + { + case ContainerId: + page = new YACSGui_ContainerPage( aMainFrame ); + break; + case ComponentId: + page = new YACSGui_ComponentPage( aMainFrame ); + break; + case SchemaId: + page = new YACSGui_SchemaPage( aMainFrame ); + break; + case InDataNodeId: + case OutDataNodeId: + case InStudyNodeId: + case OutStudyNodeId: + page = new YACSGui_DataNodePage(thePageId, aMainFrame ); + break; + case InlineNodeId: + page = new YACSGui_InlineNodePage( aMainFrame ); + break; + case ServiceNodeId: + page = new YACSGui_ServiceNodePage( aMainFrame ); + break; + case ForLoopNodeId: + page = new YACSGui_ForLoopNodePage( aMainFrame ); + break; + case ForEachLoopNodeId: + page = new YACSGui_ForEachLoopNodePage( aMainFrame ); + break; + case WhileLoopNodeId: + page = new YACSGui_WhileLoopNodePage( aMainFrame ); + break; + case SwitchNodeId: + page = new YACSGui_SwitchNodePage( aMainFrame ); + break; + case BlockNodeId: + page = new YACSGui_BlockNodePage( aMainFrame ); + break; + case LinkId: + break; + case DataTypeId: + page = new YACSGui_DataTypePage( aMainFrame ); + break; + default: + break; + } + + // Use only if the drop down button is created for each property page + if ( !page ) + { + delete button; + return; + } + + if ( myApplyBtn && myCancelBtn ) + { + int anIndex; + if ( thePageId == ContainerId ) anIndex = 0; + if ( thePageId == ComponentId ) anIndex = 2; + else anIndex = myMainLayout->findWidget(myApplyBtn->parentWidget()) - 1; + + myMainLayout->insertWidget( anIndex, page ); + myMainLayout->insertWidget( anIndex, button ); + } + else + { + myMainLayout->insertWidget( -1, button ); + myMainLayout->insertWidget( -1, page ); + } + + myMainBtns.insert( thePageId, button ); + myPages.insert( thePageId, page ); + + // Set custom style for drawing buttons with text aligned to the left border + static BtnStyle aStyle; + button->setStyle( &aStyle ); + + QFont aFont = button->font(); + aFont.setBold( true ); + button->setFont( aFont ); + button->setPaletteForegroundColor( QColor( 0, 0, 0 ) ); + button->setToggleButton( true ); + button->setOn(true); + + // Set titles for property pages as the text on the drop down button + switch ( thePageId ) + { + case ContainerId: + myMainBtns[ContainerId]->setText(tr( "Container Properties" )); + break; + case ComponentId: + myMainBtns[ComponentId]->setText(tr( "Component Properties" )); + break; + case SchemaId: + myMainBtns[SchemaId]->setText( tr( "Schema Properties" ) ); + break; + case InDataNodeId: + case OutDataNodeId: + case InStudyNodeId: + case OutStudyNodeId: + case InlineNodeId: + case ServiceNodeId: + case ForLoopNodeId: + case ForEachLoopNodeId: + case WhileLoopNodeId: + case SwitchNodeId: + case BlockNodeId: + myMainBtns[thePageId]->setText( tr( "Node Properties" ) ); + break; + case LinkId: + break; + case DataTypeId: + myMainBtns[thePageId]->setText( tr( "Data Type Properties" ) ); + break; + default: + break; + } + + // Connect signals and slots + if ( myMainBtns.contains( thePageId ) ) + connect( myMainBtns[ thePageId ], SIGNAL( toggled( bool ) ), SLOT( onMainBtn( bool ) ) ); +} + diff --git a/src/gui/YACSGui_InputPanel.h b/src/gui/YACSGui_InputPanel.h new file mode 100644 index 000000000..df89f7b5c --- /dev/null +++ b/src/gui/YACSGui_InputPanel.h @@ -0,0 +1,1039 @@ +// Copyright (C) 2003 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 YACSGui_InputPanel_HeaderFile +#define YACSGui_InputPanel_HeaderFile + +#include "yacsconfig.h" +#include "schemapage.h" +#include "containerpage.h" +#include "componentpage.h" +#include "inlinenodepage.h" +#include "forloopnodepage.h" +#include "foreachloopnodepage.h" +#include "whileloopnodepage.h" +#include "switchnodepage.h" +#include "blocknodepage.h" +#include "servicenodepage.h" +#include "datatypepage.h" +#include "datanodepage.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef HAVE_QEXTSCINTILLA_H +#include +#include +#endif + +class YACSGui_Module; +class YACSGui_PropertyPage; +class YACSGui_Table; + +class QPushButton; +class QScrollView; +class QVBoxLayout; +class QLineEdit; +class QButtonGroup; +class QComboBox; + +//================================================================================================== + +std::string portValueType( YACS::ENGINE::TypeCode* theTC ); +QString getText( int theStatus ); +QColor getColor( int theStatus ); + + +//================================================================================================== + +/* + Class : YACSGui_InputPanel + Description : Dockable window containing push buttons and corresponding widgets +*/ +class YACSGui_InputPanel : public QDockWindow +{ + Q_OBJECT + +protected: + + class BtnStyle; + +public: + + enum { ContainerId=0, ComponentId, SchemaId, InlineNodeId, ServiceNodeId, + InDataNodeId, OutDataNodeId, InStudyNodeId, OutStudyNodeId, + ForLoopNodeId, ForEachLoopNodeId, WhileLoopNodeId, SwitchNodeId, BlockNodeId, + LinkId, DataNodeId, DataTypeId, LastId = DataTypeId }; + + typedef enum { EditMode, RunMode, NewMode } PageMode; + +public: + YACSGui_InputPanel( YACSGui_Module* ); + virtual ~YACSGui_InputPanel(); + + void setBtnText( const QString& theText, + const int thePageId ); + + QWidget* getPage( const int thePageId, const bool theWithCreate = true ); + YACSGui_Module* getModule() const { return myModule; } + int getPageId( QWidget* thePage ) const; + int insertPage( QWidget* thePage, + const int thePageId = -1, + const int theBeforePageId = -1, + const int theStretch = 0 ) const; + void removePage( QWidget* thePage ); + + virtual QSize sizeHint() const; + + bool isOn( const int ) const; + void setOn( const bool, const int ); + + bool isVisible( const int ) const; + void setVisible( const bool , const int ); + void setExclusiveVisible( const bool , const std::list ); + std::list getVisiblePagesIds(); + + void setMode( const YACSGui_InputPanel::PageMode, const int ); + + QSize getPrefferedSize(); + + void emitApply( const int theId ); + +public slots: + void onNotifyNodeStatus( int theNodeId, int theStatus ); + void onNotifyInPortValues( int theNodeId, + std::map theInPortName2Value ); + void onNotifyOutPortValues( int theNodeId, + std::map theOutPortName2Value ); + void onApplyEnabled( bool ); + +signals: + void Apply( const int theId ); + +private slots: + void onMainBtn( bool ); + void onApply(); + void onClose(); + +private: + void updateState(); + void createPage( const int thePageId ); + +private: + QMap< int, QPushButton* > myMainBtns; + QMap< int, QWidget* > myPages; + + QVBoxLayout* myMainLayout; + QPushButton* myApplyBtn; + QPushButton* myCancelBtn; + + YACSGui_Module* myModule; +}; + + +//=================== rnv (to be removed) ========================================================== + +/* + Class : YACSGui_PropertyPage + Description : This class is used for parameters of input panel. + All pages of input panel must be derived from it +*/ + +class YACSGui_PropertyPage : public QFrame +{ + Q_OBJECT + +public: + YACSGui_PropertyPage( QWidget*, YACSGui_Module* ); + virtual ~YACSGui_PropertyPage(); + + QScrollView* getView() const { return myView; } + +signals: + +public slots: + virtual void onApply(); + +protected: + YACSGui_Module* myModule; + QScrollView* myView; +}; + +//================================================================================================== + +/* + Class : YACSGui_YACSORBContainerDialog + Description : Dialog for container properties used for loading YACSGui ORAB engine +*/ +class YACSGui_YACSORBContainerDialog : public QDialog +{ + Q_OBJECT + +public: + YACSGui_YACSORBContainerDialog( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_YACSORBContainerDialog(); + + Engines::MachineParameters getParams() const { return myParams; } + +public slots: + virtual void onApply(); + +protected slots: + void onShowAdvanced(); + void fillHostNames() const; + +private: + void updateState(); + Engines::MachineParameters myParams; + ContainerPage* myPage; +}; + +//================================================================================================== + +/* + Class : YACSGui_ContainerPage + Description : Page for container properties +*/ +class YACSGui_ContainerPage : public ContainerPage, public YACS::HMI::GuiObserver +{ + Q_OBJECT + +public: + YACSGui_ContainerPage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_ContainerPage(); + + virtual void select( bool isSelected ); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + YACSGui_InputPanel* getInputPanel() const; + + void setSContainer( YACS::HMI::SubjectContainer* theSContainer ); + + YACS::ENGINE::Container* getContainer() const; + YACS::ENGINE::SalomeContainer* getSalomeContainer() const; + + QString getDefinitionName() const; + bool setDefinitionName( const QString& ); + + QString getExecutionName() const; + void setExecutionName( const QString& ); + + void fillHostNames() const; + QString getHostName() const; + void setHostName( const QString& ); + + int getMemMb() const; + void setMemMb(const int); + + int getCpuClock() const; + void setCpuClock(const int); + + int getNbProcPerNode() const; + void setNbProcPerNode(const int); + + int getNbNode() const; + void setNbNode(const int); + + bool getMpiUsage() const; + void setMpiUsage(const bool); + + QString getParallelLib() const; + void setParallelLib( const QString& ); + + int getNbComponentNodes() const; + void setNbComponentNodes(const int); + + QString getWorkingDir() const; + void setWorkingDir( const QString& ); + + void checkModifications( bool& theWarnToShow, bool& theToApply ); + +public slots: + virtual void onApply(); + +protected slots: + void onShowAdvanced(); + +private: + void updateState(); + YACS::HMI::SubjectContainer* mySContainer; +}; + +//================================================================================================== + +/* + Class : YACSGui_ComponentPage + Description : Page for component properties +*/ +class YACSGui_ComponentPage : public ComponentPage, public YACS::HMI::GuiObserver +{ + Q_OBJECT + +public: + typedef enum { SALOME, SALOMEPython, CPP, CORBA } ComponentType; + +public: + YACSGui_ComponentPage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_ComponentPage(); + + virtual void select( bool isSelected ); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + YACSGui_InputPanel* getInputPanel() const; + + void setSComponent( YACS::HMI::SubjectComponent* theSComponent, bool isEdit = true ); + + YACS::ENGINE::ComponentInstance* getComponent() const; + + QString getComponentName() const; + QString getInstanceName() const; + + void setComponentType(); + ComponentType getComponentType() const; + + QString getContainerName() const; + void setContainer(); + + void checkModifications( bool& theWarnToShow, bool& theToApply ); + +public slots: + virtual void onApply(); + +protected slots: + void onContainerChanged( const QString& ); + +private: + void fillContainerNames(); + void updateState(); + YACS::HMI::SubjectComponent* mySComponent; + ComponentType myType; + bool myEditComp; +}; + +//================================================================================================== + +/* + Class : YACSGui_SchemaPage + Description : Page for schema properties +*/ +class YACSGui_SchemaPage : public SchemaPage, public YACS::HMI::GuiObserver +{ + Q_OBJECT + +public: + YACSGui_SchemaPage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_SchemaPage(); + + virtual void select( bool isSelected ); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + void setSProc( YACS::HMI::SubjectProc* theProc ); + + YACS::ENGINE::Proc* getProc() const; + + QString getSchemaName() const; + void setSchemaName( const QString& ); + + int getViewMode() const; + void setViewMode( const int ); + YACSGui_InputPanel* getInputPanel() const; + + void setMode( const YACSGui_InputPanel::PageMode ); + Engines::MachineParameters getParams() const { return myParams; } + + void checkModifications(); + +public slots: + virtual void onAddAllNextToRun(); + virtual void onRemoveAllNextToRun(); + virtual void onNextStepClicked( QListViewItem* theItem ); + + virtual void onNotifyNextSteps( std::list theNextSteps ); + + void fillHostNames() const; + virtual void onApply(); + +private: + void updateState(); + + YACS::HMI::SubjectProc* mySProc; + YACSGui_InputPanel::PageMode myMode; + Engines::MachineParameters myParams; + + std::map myMapNextSteps; +}; + +//================================================================================================== + +/* + Class : YACSGui_NodePage + Description : Basic page for node properties +*/ +class YACSGui_NodePage : public YACS::HMI::GuiObserver +{ +public: + typedef enum { SALOMEService, CORBAService, CPPNode, ServiceInline, XMLNode, + InlineFunction, InlineScript,DATANode, + FOR, FOREACH, WHILE, SWITCH, Block, Unknown } NodeType; + + typedef enum { UnknownType, + Input, SeqAnyInput, AnyInput, ConditionInput, InputCorba, InputPy, InputXml, + InputBasicStream, InputCalStream, InputPalmStream, InputDataStream, + Output, AnyOutput, OutputCorba, OutputPy, OutputXml, + OutputBasicStream, OutputCalStream, OutputPalmStream, OutputDataStream } PortType; + + struct SelectDataTypeFor + { + bool myIn; + int myRow; + }; + +public: + YACSGui_NodePage(); + ~YACSGui_NodePage(); + + virtual void select( bool isSelected ); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + YACSGui_InputPanel* getInputPanel() const; + + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + YACS::ENGINE::Node* getNode() const; + YACS::HMI::SubjectNode* getSNode() const { return mySNode; } + + QString getNodeName() const; + void setNodeName( const QString& ); + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + void setValueCellValidator( YACSGui_Table* theTable, int theRow ); + + virtual void notifyNodeStatus( int theStatus ) {} + virtual void notifyNodeProgress() {} + virtual void notifyInPortValues( std::map theInPortName2Value ) {} + virtual void notifyOutPortValues( std::map theOutPortName2Value ) {} + virtual void notifyNodeCreateBody( YACS::HMI::Subject* theSubject ) {} + virtual void notifyNodeCreateNode( YACS::HMI::Subject* theSubject ) {} + + bool isSelectDataType(); + +protected: + virtual void updateState(); + void updateBlocSize(); + + PortType getDataPortType( YACS::ENGINE::Port* ) const; + QString getPortValue( YACS::ENGINE::Port* ) const; + + YACS::HMI::SubjectNode* mySNode; + NodeType myType; + YACSGui_InputPanel::PageMode myMode; + + SelectDataTypeFor mySelectDataTypeFor; +}; + +//================================================================================================== + +/* + Class : YACSGui_InlineNodePage + Description : Page for inline function and inline service nodes properties +*/ +class YACSGui_InlineNodePage : public InlineNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_InlineNodePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_InlineNodePage(); + + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + + virtual void setDataType( YACS::ENGINE::TypeCode* theDataType ); + + void checkModifications(); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + virtual void hideEvent( QHideEvent* ); + + QString scriptText() const; + void setScriptText( const QString& ); + + bool isPortsModified( bool theInput = true ); + +protected slots: + void onNodeNameChanged( const QString& ); + void onValueChanged( int, int ); + void onSearch(); + void onInserted( const int theRow ); + void onMovedUp( const int theUpRow ); + void onMovedDown( const int theDownRow ); + void onAdded( const int theRow ); + void onRemoved( const int theRow ); + void onSelectDataType( const int theRow, const int theCol ); + +protected: +#ifdef HAVE_QEXTSCINTILLA_H + QextScintilla *_myTextEdit; +#endif + +private: + void fillInputPortsTable(); + void fillOutputPortsTable(); + QString getPortType( YACS::ENGINE::Port* ) const; + void setInputPorts(); + void setOutputPorts(); + YACS::ENGINE::TypeCode* createTypeCode( YACS::ENGINE::DynType, YACSGui_Table*, int ); + bool isStored( YACS::ENGINE::Port* ); + void resetStoredPortsMaps(); + void resetDataTypeMaps(); + void resetPLists(); + void resetIPLists(); + void resetOPLists(); + void orderPorts( bool withFilling = false ); + + std::map myRow2StoredInPorts; + std::map myRow2StoredOutPorts; + std::map myRow2DataTypeIn; + std::map myRow2DataTypeOut; + + QPtrList myIPList; + QPtrList myOPList; + bool myIsNeedToReorder; + int myPara; + int myIndex; +}; + + +//================================================================================================== + +/* + Class : YACSGui_DataNodePage + Description : Generic Page for data nodes properties (in or out, study or not) +*/ +class YACSGui_DataNodePage : public DataNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_DataNodePage( int pageid, + QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_DataNodePage(); + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + + virtual void setDataType( YACS::ENGINE::TypeCode* theDataType ); + + void checkModifications(); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + virtual void hideEvent( QHideEvent* ); + + // QString scriptText() const; + // void setScriptText( const QString& ); + + bool isPortsModified( bool theInput = true ); + +protected slots: + void onNodeNameChanged( const QString& ); + void onValueChanged( int, int ); + void onSearch(); + void onInserted( const int theRow ); + void onMovedUp( const int theUpRow ); + void onMovedDown( const int theDownRow ); + void onAdded( const int theRow ); + void onRemoved( const int theRow ); + void onSelectDataType( const int theRow, const int theCol ); + + //protected: + //#ifdef HAVE_QEXTSCINTILLA_H + // QextScintilla *_myTextEdit; + //#endif + +private: + void fillInputPortsTable(); + void fillOutputPortsTable(); + QString getPortType( YACS::ENGINE::Port* ) const; + void setInputPorts(); + void setOutputPorts(); + YACS::ENGINE::TypeCode* createTypeCode( YACS::ENGINE::DynType, YACSGui_Table*, int ); + bool isStored( YACS::ENGINE::Port* ); + void resetStoredPortsMaps(); + void resetDataTypeMaps(); + void resetPLists(); + void resetIPLists(); + void resetOPLists(); + void orderPorts( bool withFilling = false ); + void setProperties(); + + std::map myRow2StoredInPorts; + std::map myRow2StoredOutPorts; + std::map myRow2DataTypeIn; + std::map myRow2DataTypeOut; + + QPtrList myIPList; + QPtrList myOPList; + bool myIsNeedToReorder; + int myPara; + int myIndex; + int myPageId; + bool _isInput; + bool _isStudy; + QString _fileName; + QString _studyName; + int _studyId; +}; + + +//================================================================================================== + +/* + Class : YACSGui_ServiceNodePage + Description : Page for SALOME and CORBA service nodes properties +*/ +class YACSGui_ServiceNodePage : public ServiceNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_ServiceNodePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_ServiceNodePage(); + + virtual void setSCNode( YACS::HMI::SubjectComposedNode* theSCNode ); + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + virtual void setComponent( YACS::ENGINE::ComponentInstance* theComponent ); + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + + void checkModifications( bool& theWarnToShow, bool& theToApply ); + +signals: + void enableApply( bool ); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + virtual void hideEvent( QHideEvent* ); + + QString scriptText() const; + void setScriptText( const QString& ); + +protected slots: + void onNodeNameChanged( const QString& ); + void onValueChanged( int, int ); + void onSearch(); + void onBrowse( ); + void onInstanceNameChanged(const QString&); + void onCatalogMethodClicked( QListViewItem* ); + void onCatalogChanged( int ); + +private: + void updateServices(); + void fillInstanceNames(); + void fillInputPortsTable( YACS::ENGINE::Node* ); + void fillOutputPortsTable( YACS::ENGINE::Node* ); + QString getPortType( YACS::ENGINE::Port* ) const; + void setInputPorts(); + void setOutputPorts(); + YACS::ENGINE::TypeCode* createTypeCode( YACS::ENGINE::DynType, YACSGui_Table*, int ); + void buildTree( YACS::ENGINE::Node* theNode, + QListViewItem* nodeLabel, + QListViewItem* compoNodeLabel); + + protected: +#ifdef HAVE_QEXTSCINTILLA_H + QextScintilla *_myTextEdit; +#endif + +private: + YACS::ENGINE::ComponentInstance* myComponent; + QString myComponentName; + YACS::HMI::SubjectComposedNode* mySCNode; + std::map > myServiceMap; + std::map myProcNodesMap; + std::string myProcName; + int myPara; + int myIndex; +}; + +//================================================================================================== + +/* + Class : YACSGui_ForLoopNodePage + Description : Page for FOR node properties +*/ +class YACSGui_ForLoopNodePage : public ForLoopNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_ForLoopNodePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_ForLoopNodePage(); + + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + virtual void notifyNodeCreateBody( YACS::HMI::Subject* theSubject ); + + void checkModifications(); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + +protected slots: + void onNodeNameChanged( const QString& ); +}; + +//================================================================================================== + +/* + Class : YACSGui_ForEachLoopNodePage + Description : Page for FOR node properties +*/ +class YACSGui_ForEachLoopNodePage : public ForEachLoopNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_ForEachLoopNodePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_ForEachLoopNodePage(); + + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + virtual void notifyNodeCreateBody( YACS::HMI::Subject* theSubject ); + + void checkModifications(); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + +protected slots: + void onNodeNameChanged( const QString& ); + void onSeqOfSamplesChanged( const QString& ); +}; + +//================================================================================================== + +/* + Class : YACSGui_WhileLoopNodePage + Description : Page for WHILE node properties +*/ +class YACSGui_WhileLoopNodePage : public WhileLoopNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_WhileLoopNodePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_WhileLoopNodePage(); + + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + virtual void notifyNodeCreateBody( YACS::HMI::Subject* theSubject ); + + void checkModifications(); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + +protected slots: + void onNodeNameChanged( const QString& ); +}; + +//================================================================================================== + +/* + Class : YACSGui_SwitchNodePage + Description : Page for SWITCH node properties +*/ +class YACSGui_SwitchNodePage : public SwitchNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_SwitchNodePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_SwitchNodePage(); + + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + void setChild( YACS::HMI::SubjectNode* theChildNode ); + + bool isSelectChild() const; + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + virtual void notifyNodeCreateNode( YACS::HMI::Subject* theSubject ); + + void checkModifications(); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + +protected slots: + void onNodeNameChanged( const QString& ); + void onValueChanged( int, int ); + void onInitSelection( const int theRow, const int theCol ); + void onNewItem( const int theRow, const int theCol ); + void onAdded( const int theRow ); + void onInserted( const int theRow ); + void onMovedUp( const int theUpRow ); + void onMovedDown( const int theDownRow ); + void onRemoved( const int theRow ); + +private: + void updateLabelPorts(); + void setSwitchCases(); + + bool myIsSelectChild; + std::map myRow2ChildMap; + std::list myRowsOfSelectedChildren; // for children selected from tree view +}; + +//================================================================================================== + +/* + Class : YACSGui_BlockNodePage + Description : Page for block node properties +*/ +class YACSGui_BlockNodePage : public BlockNodePage, public YACSGui_NodePage +{ + Q_OBJECT + +public: + YACSGui_BlockNodePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_BlockNodePage(); + + virtual void setSNode( YACS::HMI::SubjectNode* theSNode ); + + void setChild( YACS::HMI::SubjectNode* theChildNode ); + + bool isSelectChild() const; + + virtual void setMode( const YACSGui_InputPanel::PageMode ); + + virtual void notifyNodeStatus( int theStatus ); + virtual void notifyNodeProgress(); + virtual void notifyInPortValues( std::map theInPortName2Value ); + virtual void notifyOutPortValues( std::map theOutPortName2Value ); + virtual void notifyNodeCreateNode( YACS::HMI::Subject* theSubject ); + + void checkModifications(); + +public slots: + virtual void onApply(); + +protected: + virtual void updateState(); + +protected slots: + void onNodeNameChanged( const QString& ); + void onInitSelection( const int theRow, const int theCol ); + void onNewItem( const int theRow, const int theCol ); + void onAdded( const int theRow ); + void onInserted( const int theRow ); + void onMovedUp( const int theUpRow ); + void onMovedDown( const int theDownRow ); + void onRemoved( const int theRow ); + +private: + void setDirectChildren(); + + bool myIsSelectChild; + std::map myRow2ChildMap; + std::list myRowsOfSelectedChildren; // for children selected from tree view +}; + +//========================================================================================================= + +/* + Class : YACSGui_DataTypePage + Description : Page for data type import +*/ +class YACSGui_DataTypePage : public DataTypePage, public YACS::HMI::GuiObserver +{ + Q_OBJECT + +public: + YACSGui_DataTypePage( QWidget* theParent = 0, + const char* theName = 0, + WFlags theFlags = 0 ); + virtual ~YACSGui_DataTypePage(); + + virtual void select( bool isSelected ); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + void setSDataType( YACS::HMI::SubjectDataType* theProc ); + + YACS::ENGINE::TypeCode* getTypeCode() const; + + QString getDataTypeName() const; + + YACSGui_InputPanel* getInputPanel() const; + + void setMode( const YACSGui_InputPanel::PageMode ); + +signals: + void enableApply( bool ); + +public slots: + virtual void onApply(); + +protected slots: + void onBrowse( ); + void onCatalogDataTypeClicked( QListViewItem* ); + void onCatalogChanged( int ); + +private: + void updateState(); + void buildTree( YACS::ENGINE::Catalog* theTC, QListViewItem* theParent ); + + + YACS::HMI::SubjectDataType* mySDataType; + YACSGui_InputPanel::PageMode myMode; + + std::map myDataTypeMap; + std::map myProcDataTypesMap; + std::string myProcName; +}; + +//========================================================================================================= + +/* + Class : YACSGui_LinkPage + Description : Page for link properties +*/ +class YACSGui_LinkPage : public YACSGui_PropertyPage +{ + Q_OBJECT + +public: + typedef enum { Control, DataFlow, DataStream } LinkType; + +public: + YACSGui_LinkPage( QWidget* theParent, YACSGui_Module* ); + virtual ~YACSGui_LinkPage(); + + void setLink( YACS::ENGINE::Port* theOut, YACS::ENGINE::Port* theIn ); + + QString getLinkName() const; + +public slots: + virtual void onApply(); + +private: + void updateState(); + + YACS::ENGINE::Port* myOut; + YACS::ENGINE::Port* myIn; + LinkType myType; +}; + +#endif diff --git a/src/gui/YACSGui_LinkPage.cxx b/src/gui/YACSGui_LinkPage.cxx new file mode 100644 index 000000000..cb51137e0 --- /dev/null +++ b/src/gui/YACSGui_LinkPage.cxx @@ -0,0 +1,124 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_LinkPage + Description : Page for link properties +*/ + +YACSGui_LinkPage::YACSGui_LinkPage( QWidget* theParent, YACSGui_Module* theModule ) + : YACSGui_PropertyPage( theParent, theModule ), + myOut( 0 ), + myIn( 0 ) +{ + +} + +YACSGui_LinkPage::~YACSGui_LinkPage() +{ +} + +void YACSGui_LinkPage::onApply() +{ +} diff --git a/src/gui/YACSGui_LogViewer.h b/src/gui/YACSGui_LogViewer.h new file mode 100644 index 000000000..7b9fde325 --- /dev/null +++ b/src/gui/YACSGui_LogViewer.h @@ -0,0 +1,68 @@ +// Copyright (C) 2003 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 YACSGui_Graph_LogViewer +#define YACSGui_Graph_LogViewer + +#include +#include +#include +#include + + +#include + +class LogViewer : public QDialog { +public: + LogViewer(const std::string& txt, QWidget *parent=0, const char *name=0,WFlags f = 0) : QDialog(parent,name,FALSE,f) + { + mytext=txt; + QVBoxLayout* vb = new QVBoxLayout(this,8); + vb->setAutoAdd(TRUE); + browser = new QTextBrowser( this ); + browser->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + browser->setTextFormat( QTextEdit::PlainText ); + browser->setWordWrap(QTextEdit::NoWrap); + browser->setReadOnly(1); + browser->setText(txt); + button= new QPushButton("Close",this); + connect(button,SIGNAL(clicked()),this, SLOT(close())); + resize(500,500); + } + ~LogViewer() + { + //std::cerr << "~LogViewer()" << std::endl; + } + void readFile(const std::string& filename) + { + std::fstream f(filename.c_str()); + std::stringstream hfile; + hfile << f.rdbuf(); + browser->setText(mytext+"\n\n"+ hfile.str()); + f.close(); + } + +private: + std::string mytext; + QPushButton* button; + QTextBrowser* browser; +}; + +#endif diff --git a/src/gui/YACSGui_Module.cxx b/src/gui/YACSGui_Module.cxx index 2e311cf2e..5ce2f679a 100644 --- a/src/gui/YACSGui_Module.cxx +++ b/src/gui/YACSGui_Module.cxx @@ -20,43 +20,108 @@ #include -#include +#include #include #include #include -#include +#include +//#include #include #include #include #include "YACSGui_RunMode.h" +#include +#include +#include +#include #include #include +#include #include +#include + +#include +#include +#include #include #include #include #include +#include +#include +#include #include +#include +#include +#include #include +#include +#include +#include #include #include #include +#include #include // for test presentations #include // for test presentations +#include + +#include +#include // for a test function +#include // for a test function #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LinkInfo.hxx" + #include -#include +#include +#include "SALOMEDS_Study.hxx" +#include "SALOMEDS_Tool.hxx" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include #include // for debug only #include "utilities.h" +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS; using namespace YACS::ENGINE; +using namespace YACS::HMI; + +using namespace std; extern "C" @@ -72,8 +137,12 @@ extern "C" */ YACSGui_Module::YACSGui_Module() : SalomeApp_Module( "YACS" ) { - MESSAGE("YACSGui_Module::YACSGui_Module()"); + DEBTRACE("YACSGui_Module::YACSGui_Module()"); _myRunMode = 0; + myInputPanel = 0; + myCatalog = 0; + myGuiMode = YACSGui_Module::EmptyMode; + myBlockWindowActivateSignal = false; } //! Destructor. @@ -81,7 +150,7 @@ YACSGui_Module::YACSGui_Module() : SalomeApp_Module( "YACS" ) */ YACSGui_Module::~YACSGui_Module() { - MESSAGE("YACSGui_Module::~YACSGui_Module()"); + DEBTRACE("YACSGui_Module::~YACSGui_Module()"); } //! Initialize module. @@ -89,12 +158,25 @@ YACSGui_Module::~YACSGui_Module() */ void YACSGui_Module::initialize( CAM_Application* theApp ) { - MESSAGE("YACSGui_Module::initialize"); + DEBTRACE("YACSGui_Module::initialize"); SalomeApp_Module::initialize(theApp); - InitYACSGuiGen( dynamic_cast( theApp ) ); + //InitYACSGuiGen( dynamic_cast( theApp ) ); + createSComponent(); + updateObjBrowser(); createActions(); createMenus(); + createPopups(); + + RuntimeSALOME::setRuntime(); + fillNodeTypesMap(); + + if ( theApp && theApp->desktop() ) + connect( theApp->desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ), + this, SLOT(onWindowActivated( SUIT_ViewWindow* )) ); + + connect( getApp()->objectBrowser()->listView(), SIGNAL( doubleClicked( QListViewItem* ) ), + this, SLOT ( onDblClick( QListViewItem* ) ) ); } //! Creates module actions. @@ -102,7 +184,7 @@ void YACSGui_Module::initialize( CAM_Application* theApp ) */ void YACSGui_Module::createActions() { - MESSAGE("YACSGui_Module::createActions()"); + DEBTRACE("YACSGui_Module::createActions()"); QPixmap aPixmap; QWidget* aDesktop = application()->desktop(); SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr(); @@ -111,112 +193,271 @@ void YACSGui_Module::createActions() return; // Menu "File" - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_NEW_DATAFLOW")); - createAction( NewDataflowId, tr("TOP_NEW_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_NEW_DATAFLOW"), tr("STB_NEW_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onNewDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_MODIFY_DATAFLOW")); - createAction( ModifyDataflowId, tr("TOP_MODIFY_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_MODIFY_DATAFLOW"), tr("STB_MODIFY_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onModifyDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_MODIFY_SUPERV_DATAFLOW")); - createAction( ModifySupervDataflowId, tr("TOP_MODIFY_SUPERV_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_MODIFY_SUPERV_DATAFLOW"), tr("STB_MODIFY_SUPERV_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onModifySupervDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_IMPORT_DATAFLOW")); - createAction( ImportDataflowId, tr("TOP_IMPORT_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_IMPORT_DATAFLOW"), tr("STB_IMPORT_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onImportDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_IMPORT_SUPERV_DATAFLOW")); - createAction( ImportSupervDataflowId, tr("TOP_IMPORT_SUPERV_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_IMPORT_SUPERV_DATAFLOW"), tr("STB_IMPORT_SUPERV_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onImportSupervDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_EXPORT_DATAFLOW")); - createAction( ExportDataflowId, tr("TOP_EXPORT_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_EXPORT_DATAFLOW"), tr("STB_EXPORT_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onExportDataflow())); - - // Menu "Supervisor" - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_ADD_NODE")); - createAction( AddNodeId, tr("TOP_ADD_NODE"), QIconSet(aPixmap), - tr("MEN_ADD_NODE"), tr("STB_ADD_NODE"), - 0, aDesktop, false, this, SLOT(onAddNode())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_SUSPEND_RESUME_DATAFLOW")); - createAction( SuspendResumeDataflowId, tr("TOP_SUSPEND_RESUME_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_SUSPEND_RESUME_DATAFLOW"), tr("STB_SUSPEND_RESUME_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onSuspendResumeDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_RUN_DATAFLOW")); - createAction( RunDataflowId, tr("TOP_RUN_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_RUN_DATAFLOW"), tr("STB_RUN_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onRunDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_REMOTE_RUN_DATAFLOW")); - createAction( RemoteRunDataflowId, tr("TOP_REMOTE_RUN_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_REMOTE_RUN_DATAFLOW"), tr("STB_REMOTE_RUN_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onRemoteRunDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_KILL_DATAFLOW")); - createAction( KillDataflowId, tr("TOP_KILL_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_KILL_DATAFLOW"), tr("STB_KILL_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onKillDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_TOGGLESTOPONERROR")); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_IMPORT_YACS_SCHEMA")); + createAction( ImportSchemaId, tr("TOP_IMPORT_YACS_SCHEMA"), QIconSet(aPixmap), + tr("MEN_IMPORT_YACS_SCHEMA"), tr("STB_IMPORT_YACS_SCHEMA"), + 0, aDesktop, false, this, SLOT(onImportSchema())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_IMPORT_SUPERV_SCHEMA")); + createAction( ImportSupervSchemaId, tr("TOP_IMPORT_SUPERV_SCHEMA"), QIconSet(aPixmap), + tr("MEN_IMPORT_SUPERV_SCHEMA"), tr("STB_IMPORT_SUPERV_SCHEMA"), + 0, aDesktop, false, this, SLOT(onImportSupervSchema())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_EXPORT_SCHEMA")); + createAction( ExportSchemaId, tr("TOP_EXPORT_SCHEMA"), QIconSet(aPixmap), + tr("MEN_EXPORT_SCHEMA"), tr("STB_EXPORT_SCHEMA"), + 0, aDesktop, false, this, SLOT(onExportSchema())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_SCHEMA")); + createAction( NewSchemaId, tr("TOP_NEW_SCHEMA"), QIconSet(aPixmap), + tr("MEN_NEW_SCHEMA"), tr("STB_NEW_SCHEMA"), + 0, aDesktop, false, this, SLOT(onNewSchema())); + + // Menu "Create" + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_CONTAINER")); + createAction( NewContainerId, tr("TOP_NEW_CONTAINER"), QIconSet(aPixmap), + tr("MEN_NEW_CONTAINER"), tr("STB_NEW_CONTAINER"), + 0, aDesktop, false, this, SLOT(onNewContainer())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_SALOME_COMPONENT")); + createAction( NewSalomeComponentId, tr("TOP_NEW_SALOME_COMPONENT"), QIconSet(aPixmap), + tr("MEN_NEW_SALOME_COMPONENT"), tr("STB_NEW_SALOME_COMPONENT"), + 0, aDesktop, false, this, SLOT(onNewSalomeComponent())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_SALOMEPYTHON_COMPONENT")); + createAction( NewSalomePythonComponentId, tr("TOP_NEW_SALOMEPYTHON_COMPONENT"), QIconSet(aPixmap), + tr("MEN_NEW_SALOMEPYTHON_COMPONENT"), tr("STB_NEW_SALOMEPYTHON_COMPONENT"), + 0, aDesktop, false, this, SLOT(onNewSalomePythonComponent())); + action(NewSalomePythonComponentId)->setEnabled(false); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_CORBA_COMPONENT")); + createAction( NewCorbaComponentId, tr("TOP_NEW_CORBA_COMPONENT"), QIconSet(aPixmap), + tr("MEN_NEW_CORBA_COMPONENT"), tr("STB_NEW_CORBA_COMPONENT"), + 0, aDesktop, false, this, SLOT(onNewCorbaComponent())); + action(NewCorbaComponentId)->setEnabled(false); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_SALOME_SERVICE_NODE")); + createAction( NewSalomeServiceNodeId, tr("TOP_NEW_SALOME_SERVICE_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_SALOME_SERVICE_NODE"), tr("STB_NEW_SALOME_SERVICE_NODE"), + 0, aDesktop, false, this, SLOT(onSalomeServiceNode())); + +// aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_CORBA_SERVICE_NODE")); +// createAction( NewCorbaServiceNodeId, tr("TOP_NEW_CORBA_SERVICE_NODE"), QIconSet(aPixmap), +// tr("MEN_NEW_CORBA_SERVICE_NODE"), tr("STB_NEW_CORBA_SERVICE_NODE"), +// 0, aDesktop, false, this, SLOT(onCorbaServiceNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_CPP_NODE")); + createAction( NewCppNodeId, tr("TOP_NEW_CPP_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_CPP_NODE"), tr("STB_NEW_CPP_NODE"), + 0, aDesktop, false, this, SLOT(onCppNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_SERVICE_INLINE_NODE")); + createAction( NewServiceInlineNodeId, tr("TOP_NEW_SERVICE_INLINE_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_SERVICE_INLINE_NODE"), tr("STB_NEW_SERVICE_INLINE_NODE"), + 0, aDesktop, false, this, SLOT(onServiceInlineNode())); + action(NewServiceInlineNodeId)->setEnabled(false); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_XML_NODE")); + createAction( NewXmlNodeId, tr("TOP_NEW_XML_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_XML_NODE"), tr("STB_NEW_XML_NODE"), + 0, aDesktop, false, this, SLOT(onXMLNode())); + action(NewXmlNodeId)->setEnabled(false); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_IN_DATANODE")); + createAction( NewInDataNodeId, tr("TOP_NEW_IN_DATANODE"), QIconSet(aPixmap), + tr("MEN_NEW_IN_DATANODE"), tr("STB_NEW_IN_DATANODE"), + 0, aDesktop, false, this, SLOT(onInDataNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_OUT_DATANODE")); + createAction( NewOutDataNodeId, tr("TOP_NEW_OUT_DATANODE"), QIconSet(aPixmap), + tr("MEN_NEW_OUT_DATANODE"), tr("STB_NEW_OUT_DATANODE"), + 0, aDesktop, false, this, SLOT(onOutDataNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_IN_STUDYNODE")); + createAction( NewInStudyNodeId, tr("TOP_NEW_IN_STUDYNODE"), QIconSet(aPixmap), + tr("MEN_NEW_IN_STUDYNODE"), tr("STB_NEW_IN_STUDYNODE"), + 0, aDesktop, false, this, SLOT(onInStudyNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_OUT_STUDYNODE")); + createAction( NewOutStudyNodeId, tr("TOP_NEW_OUT_STUDYNODE"), QIconSet(aPixmap), + tr("MEN_NEW_OUT_STUDYNODE"), tr("STB_NEW_OUT_STUDYNODE"), + 0, aDesktop, false, this, SLOT(onOutStudyNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_INLINE_SCRIPT_NODE")); + createAction( NewInlineScriptNodeId, tr("TOP_NEW_INLINE_SCRIPT_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_INLINE_SCRIPT_NODE"), tr("STB_NEW_INLINE_SCRIPT_NODE"), + 0, aDesktop, false, this, SLOT(onInlineScriptNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_INLINE_FUNCTION_NODE")); + createAction( NewInlineFunctionNodeId, tr("TOP_NEW_INLINE_FUNCTION_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_INLINE_FUNCTION_NODE"), tr("STB_NEW_INLINE_FUNCTION_NODE"), + 0, aDesktop, false, this, SLOT(onInlineFunctionNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_BLOCK_NODE")); + createAction( NewBlockNodeId, tr("TOP_NEW_BLOCK_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_BLOCK_NODE"), tr("STB_NEW_BLOCK_NODE"), + 0, aDesktop, false, this, SLOT(onBlockNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_FOR_LOOP_NODE")); + createAction( NewForLoopNodeId, tr("TOP_NEW_FOR_LOOP_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_FOR_LOOP_NODE"), tr("STB_NEW_FOR_LOOP_NODE"), + 0, aDesktop, false, this, SLOT(onFORNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_FOREACH_LOOP_NODE")); + createAction( NewForeachLoopNodeId, tr("TOP_NEW_FOREACH_LOOP_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_FOREACH_LOOP_NODE"), tr("STB_NEW_FOREACH_LOOP_NODE"), + 0, aDesktop, false, this, SLOT(onFOREACHNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_WHILE_LOOP_NODE")); + createAction( NewWhileLoopNodeId, tr("TOP_NEW_WHILE_LOOP_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_WHILE_LOOP_NODE"), tr("STB_NEW_WHILE_LOOP_NODE"), + 0, aDesktop, false, this, SLOT(onWHILENode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_SWITCH_NODE")); + createAction( NewSwitchLoopNodeId, tr("TOP_NEW_SWITCH_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_SWITCH_NODE"), tr("STB_NEW_SWITCH_NODE"), + 0, aDesktop, false, this, SLOT(onSWITCHNode())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_FROM_LIBRARY_NODE")); + createAction( NewFromLibraryNodeId, tr("TOP_NEW_FROM_LIBRARY_NODE"), QIconSet(aPixmap), + tr("MEN_NEW_FROM_LIBRARY_NODE"), tr("STB_NEW_FROM_LIBRARY_NODE"), + 0, aDesktop, false, this, SLOT(onNodeFromLibrary())); + action(NewFromLibraryNodeId)->setEnabled(false); + + + // Menu "Execute" (edit gui mode) + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_EXECUTION")); + createAction( NewExecutionId, tr("TOP_NEW_EXECUTION"), QIconSet(aPixmap), + tr("MEN_NEW_EXECUTION"), tr("STB_NEW_EXECUTION"), + 0, aDesktop, false, this, SLOT(onCreateExecution())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_BATCH_EXECUTION")); + createAction( NewBatchExecutionId, tr("TOP_NEW_BATCH_EXECUTION"), QIconSet(aPixmap), + tr("MEN_NEW_BATCH_EXECUTION"), tr("STB_NEW_BATCH_EXECUTION"), + 0, aDesktop, false, this, SLOT(onCreateBatchExecution())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_LOAD_EXECUTION_STATE")); + createAction( ReloadExecutionId, tr("TOP_LOAD_EXECUTION_STATE"), QIconSet(aPixmap), + tr("MEN_LOAD_EXECUTION_STATE"), tr("STB_LOAD_EXECUTION_STATE"), + 0, aDesktop, false, this, SLOT(onReloadExecution())); + //action(ReloadExecutionId)->setEnabled(false); + + //Menu "Execute" (run gui mode) + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_STARTRESUME")); + createAction( StartResumeId, tr("TOP_STARTRESUME"), QIconSet(aPixmap), + tr("MEN_STARTRESUME"), tr("STB_STARTRESUME"), + 0, aDesktop, false, this, SLOT(onStartResume())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_PAUSE")); + createAction( PauseId, tr("TOP_PAUSE"), QIconSet(aPixmap), + tr("MEN_PAUSE"), tr("STB_PAUSE"), + 0, aDesktop, false, this, SLOT(onPause())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_ABORT")); + createAction( AbortId, tr("TOP_ABORT"), QIconSet(aPixmap), + tr("MEN_ABORT"), tr("STB_ABORT"), + 0, aDesktop, false, this, SLOT(onAbort())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_RESET")); + createAction( ResetId, tr("TOP_RESET"), QIconSet(aPixmap), + tr("MEN_RESET"), tr("STB_RESET"), + 0, aDesktop, false, this, SLOT(onReset())); + + { + QIconSet runws; + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_WITHOUTSTOP_ACTIVE_MODE")); + runws.setPixmap( aPixmap, QIconSet::Automatic, QIconSet::Normal, QIconSet::On); + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_WITHOUTSTOP_MODE")); + runws.setPixmap( aPixmap, QIconSet::Automatic, QIconSet::Normal,QIconSet::Off); + createAction( WithoutStopModeId, tr("TOP_WITHOUTSTOP_MODE"), runws, + tr("MEN_WITHOUTSTOP_MODE"), tr("STB_WITHOUTSTOP_MODE"), + 0, aDesktop, true, this, SLOT(onWithoutStopMode())); + action(WithoutStopModeId)->setOn(true); + } + { + QIconSet runws; + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_BREAKPOINTS_ACTIVE_MODE")); + runws.setPixmap( aPixmap, QIconSet::Automatic, QIconSet::Normal, QIconSet::On); + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_BREAKPOINTS_MODE")); + runws.setPixmap( aPixmap, QIconSet::Automatic, QIconSet::Normal,QIconSet::Off); + createAction( BreakpointsModeId, tr("TOP_BREAKPOINTS_MODE"), runws, + tr("MEN_BREAKPOINTS_MODE"), tr("STB_BREAKPOINTS_MODE"), + 0, aDesktop, true, this, SLOT(onBreakpointsMode())); + } + { + QIconSet runws; + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_STEPBYSTEP_ACTIVE_MODE")); + runws.setPixmap( aPixmap, QIconSet::Automatic, QIconSet::Normal, QIconSet::On); + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_STEPBYSTEP_MODE")); + runws.setPixmap( aPixmap, QIconSet::Automatic, QIconSet::Normal,QIconSet::Off); + createAction( StepByStepModeId, tr("TOP_STEPBYSTEP_MODE"), runws, + tr("MEN_STEPBYSTEP_MODE"), tr("STB_STEPBYSTEP_MODE"), + 0, aDesktop, true, this, SLOT(onStepByStepMode())); + } + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_TOGGLESTOPONERROR")); createAction( ToggleStopOnErrorId, tr("TOP_TOGGLESTOPONERROR"), QIconSet(aPixmap), tr("MEN_TOGGLESTOPONERROR"), tr("STB_TOGGLESTOPONERROR"), - 0, aDesktop, false, this, SLOT(onToggleStopOnError())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_FILTERNEXTSTEPS")); - createAction( FilterNextStepsId, tr("TOP_FILTERNEXTSTEPS"), QIconSet(aPixmap), - tr("MEN_FILTERNEXTSTEPS"), tr("STB_FILTERNEXTSTEPS"), - 0, aDesktop, false, this, SLOT(onFilterNextSteps())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_ADD_DATAFLOW_IN_STUDY")); - createAction( AddDataflowInStudyId, tr("TOP_ADD_DATAFLOW_IN_STUDY"), QIconSet(aPixmap), - tr("MEN_ADD_DATAFLOW_IN_STUDY"), tr("STB_ADD_DATAFLOW_IN_STUDY"), - 0, aDesktop, false, this, SLOT(onAddDataflowInStudy())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_CHANGE_INFORMATIONS")); - createAction( ChangeInformationsId, tr("TOP_CHANGE_INFORMATIONS"), QIconSet(aPixmap), - tr("MEN_CHANGE_INFORMATIONS"), tr("STB_CHANGE_INFORMATIONS"), - 0, aDesktop, false, this, SLOT(onChangeInformations())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_SAVEDATAFLOWSTATE")); - createAction( SaveDataflowStateId, tr("TOP_SAVEDATAFLOWSTATE"), QIconSet(aPixmap), - tr("MEN_SAVEDATAFLOWSTATE"), tr("STB_SAVEDATAFLOWSTATE"), - 0, aDesktop, false, this, SLOT(onSaveDataflowState())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_RELOAD_DATAFLOW")); - createAction( ReloadDataflowId, tr("TOP_RELOAD_DATAFLOW"), QIconSet(aPixmap), - tr("MEN_RELOAD_DATAFLOW"), tr("STB_RELOAD_DATAFLOW"), - 0, aDesktop, false, this, SLOT(onReloadDataflow())); - - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_REBUILD_LINKS")); - createAction( RebuildLinksId, tr("TOP_REBUILD_LINKS"), QIconSet(aPixmap), - tr("MEN_REBUILD_LINKS"), tr("STB_REBUILD_LINKS"), - 0, aDesktop, false, this, SLOT(onRebuildLinks())); + 0, aDesktop, true, this, SLOT(onToggleStopOnError())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_EXECUTE_BATCH")); + createAction( ExecuteInBatchId, tr("TOP_EXECUTE_BATCH"), QIconSet(aPixmap), + tr("MEN_EXECUTE_BATCH"), tr("STB_EXECUTE_BATCH"), + 0, aDesktop, false, this, SLOT(onExecuteInBatch())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_CONNECT_TO_RUNNING")); + createAction( ConnectToRunningId, tr("TOP_CONNECT_TO_RUNNING"), QIconSet(aPixmap), + tr("MEN_CONNECT_TO_RUNNING"), tr("STB_CONNECT_TO_RUNNING"), + 0, aDesktop, false, this, SLOT(onConnectToRunning())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_SAVE_EXECUTION_STATE")); + createAction( SaveExecutionStateId, tr("TOP_SAVE_EXECUTION_STATE"), QIconSet(aPixmap), + tr("MEN_SAVE_EXECUTION_STATE"), tr("STB_SAVE_EXECUTION_STATE"), + 0, aDesktop, false, this, SLOT(onSaveExecutionState())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_NEW_EDITION")); + createAction( NewEditionId, tr("TOP_NEW_EDITION"), QIconSet(aPixmap), + tr("MEN_NEW_EDITION"), tr("STB_NEW_EDITION"), + 0, aDesktop, false, this, SLOT(onCreateEdition())); + + // Popup "Schema" + //createAction( SetActiveId, tr("TOP_SET_ACTIVE"), QIconSet(), + // tr("MEN_SET_ACTIVE"), tr("STB_SET_ACTIVE"), + // 0, aDesktop, false, this, SLOT(onSetActive())); + - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_FULL_VIEW")); + // View mode section of "Dataflow" toolbar + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_FULL_VIEW")); createAction( FullViewId, tr("TOP_FULL_VIEW"), QIconSet(aPixmap), tr("MEN_FULL_VIEW"), tr("STB_FULL_VIEW"), 0, aDesktop, false, this, SLOT(onFullView())); - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_CONTROL_VIEW")); + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_CONTROL_VIEW")); createAction( ControlViewId, tr("TOP_CONTROL_VIEW"), QIconSet(aPixmap), tr("MEN_CONTROL_VIEW"), tr("STB_CONTROL_VIEW"), 0, aDesktop, false, this, SLOT(onControlView())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_DATAFLOW_VIEW")); + createAction( DataFlowViewId, tr("TOP_DATAFLOW_VIEW"), QIconSet(aPixmap), + tr("MEN_DATAFLOW_VIEW"), tr("STB_DATAFLOW_VIEW"), + 0, aDesktop, false, this, SLOT(onDataFlowView())); + action(DataFlowViewId)->setEnabled(false); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_DATASTREAM_VIEW")); + createAction( DataStreamViewId, tr("TOP_DATASTREAM_VIEW"), QIconSet(aPixmap), + tr("MEN_DATASTREAM_VIEW"), tr("STB_DATASTREAM_VIEW"), + 0, aDesktop, false, this, SLOT(onDataStreamView())); + action(DataStreamViewId)->setEnabled(false); - aPixmap = aResourceMgr->loadPixmap("YACSGui", tr("ICON_TABLE_VIEW")); - createAction( TableViewId, tr("TOP_TABLE_VIEW"), QIconSet(aPixmap), - tr("MEN_TABLE_VIEW"), tr("STB_TABLE_VIEW"), - 0, aDesktop, false, this, SLOT(onTableView())); - + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_ARRANGE_NODES")); + createAction( ArrangeNodesId, tr("TOP_ARRANGE_NODES"), QIconSet(aPixmap), + tr("MEN_ARRANGE_NODES"), tr("STB_ARRANGE_NODES"), + 0, aDesktop, false, this, SLOT(onArrangeNodes())); + + aPixmap = aResourceMgr->loadPixmap("YACS", tr("ICON_REBUILD_LINKS")); + createAction( RebuildLinksId, tr("TOP_REBUILD_LINKS"), QIconSet(aPixmap), + tr("MEN_REBUILD_LINKS"), tr("STB_REBUILD_LINKS"), + 0, aDesktop, false, this, SLOT(onRebuildLinks())); } //! Creates module menus. @@ -224,58 +465,263 @@ void YACSGui_Module::createActions() */ void YACSGui_Module::createMenus() { - MESSAGE("YACSGui_Module::createMenus"); + DEBTRACE("YACSGui_Module::createMenus"); int fileId = createMenu( tr( "MEN_FILE" ), -1, -1 ); - createMenu( NewDataflowId, fileId, 10 ); - createMenu( ModifyDataflowId, fileId, 10 ); - createMenu( ModifySupervDataflowId, fileId, 10 ); - createMenu( ImportDataflowId, fileId, 10 ); - createMenu( ImportSupervDataflowId, fileId, 10 ); - createMenu( ExportDataflowId, fileId, 10 ); - - int supervisorId = createMenu( tr( "MEN_SUPERVISOR" ), -1, -1, 10 ); - createMenu( AddNodeId, supervisorId, -1 ); - createMenu( separator(), supervisorId, -1 ); - createMenu( SuspendResumeDataflowId, supervisorId, -1 ); - createMenu( RemoteRunDataflowId, supervisorId, -1 ); - createMenu( RunDataflowId, supervisorId, -1 ); - createMenu( KillDataflowId, supervisorId, -1 ); - createMenu( separator(), supervisorId, -1 ); - createMenu( ToggleStopOnErrorId, supervisorId, -1 ); - createMenu( separator(), supervisorId, -1 ); - createMenu( AddDataflowInStudyId, supervisorId, -1 ); - createMenu( ChangeInformationsId, supervisorId, -1 ); - createMenu( separator(), supervisorId, -1 ); - createMenu( SaveDataflowStateId, supervisorId, -1 ); - createMenu( ReloadDataflowId, supervisorId, -1 ); - createMenu( RebuildLinksId, supervisorId, -1 ); - - int dataflowTbId = createTool( tr("TOOLBAR_DATAFLOW") ); - createTool( NewDataflowId, dataflowTbId ); - createTool( ModifyDataflowId, dataflowTbId ); - createTool( ModifySupervDataflowId, dataflowTbId ); - createTool( ImportDataflowId, dataflowTbId ); - createTool( ImportSupervDataflowId, dataflowTbId ); - createTool( ExportDataflowId, dataflowTbId ); - createTool( separator(), dataflowTbId ); - createTool( AddDataflowInStudyId, dataflowTbId ); - createTool( separator(), dataflowTbId ); - createTool( ReloadDataflowId, dataflowTbId ); - createTool( RebuildLinksId, dataflowTbId ); - createTool( separator(), dataflowTbId ); - createTool( FullViewId, dataflowTbId ); - createTool( ControlViewId, dataflowTbId ); - createTool( TableViewId, dataflowTbId ); - createTool( separator(), dataflowTbId ); - createTool( SaveDataflowStateId, dataflowTbId ); - + //@ createMenu( NewDataflowId, fileId, 10 ); + //@ createMenu( ModifyDataflowId, fileId, 10 ); + //@ createMenu( ModifySupervDataflowId, fileId, 10 ); + int importSchemaId = createMenu( tr( "MEN_IMPORT_SCHEMA" ), fileId, 11, 10 ); + createMenu( ImportSchemaId, importSchemaId, -1 ); + createMenu( ImportSupervSchemaId, importSchemaId, -1 ); + createMenu( ExportSchemaId, fileId, 10 ); + createMenu( NewSchemaId, fileId, 10 ); + + int createId = createMenu( tr( "MEN_CREATE" ), -1, -1, 10 ); + createMenu( NewContainerId, createId, -1 ); + int newComponentId = createMenu( tr("MEN_NEW_COMPONENT"), createId ); + createMenu( NewSalomeComponentId, newComponentId, -1 ); + createMenu( NewSalomePythonComponentId, newComponentId, -1 ); + createMenu( NewCorbaComponentId, newComponentId, -1 ); + int newNodeId = createMenu( tr("MEN_NEW_NODE"), createId ); + createMenu( NewSalomeServiceNodeId, newNodeId, -1 ); + //createMenu( NewCorbaServiceNodeId, newNodeId, -1 ); + createMenu( NewCppNodeId, newNodeId, -1 ); + createMenu( NewServiceInlineNodeId, newNodeId, -1 ); + createMenu( NewXmlNodeId, newNodeId, -1 ); + createMenu( NewInlineScriptNodeId, newNodeId, -1 ); + createMenu( NewInlineFunctionNodeId, newNodeId, -1 ); + createMenu( NewInDataNodeId, newNodeId, -1 ); + createMenu( NewOutDataNodeId, newNodeId, -1 ); + createMenu( NewInStudyNodeId, newNodeId, -1 ); + createMenu( NewOutStudyNodeId, newNodeId, -1 ); + createMenu( NewBlockNodeId, newNodeId, -1 ); + createMenu( NewForLoopNodeId, newNodeId, -1 ); + createMenu( NewForeachLoopNodeId, newNodeId, -1 ); + createMenu( NewWhileLoopNodeId, newNodeId, -1 ); + createMenu( NewSwitchLoopNodeId, newNodeId, -1 ); + createMenu( NewFromLibraryNodeId, newNodeId, -1 ); + + //Menu "Execute" (edit gui mode) + int execId = createMenu( tr( "MEN_EXECUTE" ), -1, -1, 10 ); + createMenu( NewExecutionId, execId, -1 ); + createMenu( ReloadExecutionId, execId, -1 ); + createMenu( NewBatchExecutionId, execId, -1 ); + + //Menu "Execute" (run gui mode) + createMenu( WithoutStopModeId, execId, -1 ); + createMenu( BreakpointsModeId, execId, -1 ); + createMenu( StepByStepModeId, execId, -1 ); + + createMenu( separator(),execId, -1 ); + + createMenu( ToggleStopOnErrorId, execId, -1 ); + + createMenu( separator(),execId, -1 ); + + createMenu( StartResumeId, execId, -1 ); + createMenu( PauseId, execId, -1 ); + createMenu( AbortId, execId, -1 ); + createMenu( ResetId, execId, -1 ); + + createMenu( separator(),execId, -1 ); + + createMenu( ExecuteInBatchId, execId, -1 ); + createMenu( ConnectToRunningId, execId, -1 ); + + createMenu( separator(),execId, -1 ); + + createMenu( SaveExecutionStateId, execId, -1 ); + createMenu( NewEditionId, execId, -1 ); + + //Toolbar "Schema" + + myToolBars[SchemaTbId] = new QtxToolBar(true ,application()->desktop()); + action(NewSchemaId)->addTo(myToolBars[SchemaTbId]); + myToolButtons[ImportBtnId] = new SUIT_ToolButton(myToolBars[SchemaTbId],"import_btn"); + myToolButtons[ImportBtnId]->AddAction(action(ImportSchemaId)); + myToolButtons[ImportBtnId]->AddAction(action(ImportSupervSchemaId)); + myToolBars[SchemaTbId]->setLabel(tr("TOOLBAR_SCHEMA")); + action(ExportSchemaId)->addTo(myToolBars[SchemaTbId]); + + + //Toolbar "Creation" + myToolBars[CreationTbId]= new QtxToolBar(true ,application()->desktop()); + myToolBars[CreationTbId]->setLabel(tr("TOOLBAR_CREATION")); + action(NewContainerId)->addTo(myToolBars[CreationTbId]); + myToolButtons[NewContainerBtnId] = new SUIT_ToolButton(myToolBars[CreationTbId], "new_container_btn"); + myToolButtons[NewContainerBtnId]->AddAction(action(NewSalomeComponentId)); + myToolButtons[NewContainerBtnId]->AddAction(action(NewSalomePythonComponentId)); + myToolButtons[NewContainerBtnId]->AddAction(action(NewCorbaComponentId)); + + myToolButtons[NewNodeBtn] = new SUIT_ToolButton(myToolBars[CreationTbId], "new_node_btn"); + myToolButtons[NewNodeBtn]->AddAction(action(NewSalomeServiceNodeId)); + //myToolButtons[NewNodeBtn]->AddAction(action(NewCorbaServiceNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewCppNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewServiceInlineNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewXmlNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewInlineScriptNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewInlineFunctionNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewInDataNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewOutDataNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewInStudyNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewOutStudyNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewBlockNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewForLoopNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewForeachLoopNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewWhileLoopNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewSwitchLoopNodeId)); + myToolButtons[NewNodeBtn]->AddAction(action(NewFromLibraryNodeId)); + + //Toolbar "Execute" (edit gui mode) int executionTbId = createTool( tr("TOOLBAR_EXECUTION") ); - createTool( SuspendResumeDataflowId, executionTbId ); - createTool( RemoteRunDataflowId, executionTbId ); - createTool( RunDataflowId, executionTbId ); - createTool( separator(), executionTbId ); - createTool( KillDataflowId, executionTbId ); - createTool( ToggleStopOnErrorId, executionTbId ); + createTool( NewExecutionId, executionTbId); + createTool( NewBatchExecutionId, executionTbId); + createTool( ReloadExecutionId, executionTbId); + + //Toolbar "Execute" (run gui mode) + + QActionGroup* anExeModeGroup = new QActionGroup( application()->desktop() ); + anExeModeGroup->setExclusive( true ); + anExeModeGroup->add(action(WithoutStopModeId)); + anExeModeGroup->add(action(BreakpointsModeId)); + anExeModeGroup->add(action(StepByStepModeId)); + anExeModeGroup->addTo(toolMgr()->toolBar(executionTbId)); +// createTool( WithoutStopModeId, executionTbId); +// createTool( BreakpointsModeId, executionTbId); +// createTool( StepByStepModeId, executionTbId); + +// createTool( separator(), executionTbId); + +// createTool( ToggleStopOnErrorId, executionTbId); + +// createTool( separator(), executionTbId); + + createTool( StartResumeId, executionTbId); + createTool( PauseId, executionTbId); + createTool( AbortId, executionTbId); + createTool( ResetId, executionTbId); + + createTool( separator(), executionTbId); + + createTool( ExecuteInBatchId, executionTbId); + createTool( ConnectToRunningId, executionTbId); + + createTool( separator(), executionTbId); + + createTool( SaveExecutionStateId, executionTbId); + createTool( NewEditionId, executionTbId); + + //Toolbar "Visualization" + int visualizationTbId = createTool( tr("TOOLBAR_VISUALIZATION") ); + createTool( FullViewId, visualizationTbId); + createTool( ControlViewId, visualizationTbId); + createTool( DataFlowViewId, visualizationTbId); + createTool( DataStreamViewId, visualizationTbId); + createTool( ArrangeNodesId, visualizationTbId); + createTool( RebuildLinksId, visualizationTbId); +} + +//! Creates module popups. +/*! + */ +void YACSGui_Module::createPopups() +{ + QString rule = "client='ObjectBrowser' and selcount = 1 and $ObjectType = { 'SchemaObject' }"; + + //Execute menu + popupMgr()->insert( action(NewExecutionId), -1, 0 ); + popupMgr()->insert( action(ReloadExecutionId), -1, 0 ); + popupMgr()->setRule( action(NewExecutionId), rule, true ); + popupMgr()->setRule( action(ReloadExecutionId), rule, true ); + + rule = "client='ObjectBrowser' and selcount = 1 and $ObjectType = { 'RunObject' }"; + + //Edit menu + popupMgr()->insert( action(NewEditionId), -1, 0 ); + popupMgr()->setRule( action(NewEditionId), rule, true ); + + rule = "client='ObjectBrowser' and selcount = 1 and $ObjectType in { 'SchemaObject' 'RunObject' }"; + + // Schema popup + //popupMgr()->insert( action(SetActiveId), -1, 1 ); + //popupMgr()->setRule( action(SetActiveId), rule, true ); +} + +void YACSGui_Module::createPreferences() +{ + int tabId = addPreference( tr( "PREF_TAB_SETTINGS" ) ); + + int genGroup = addPreference( tr( "PREF_GROUP_GENERAL" ), tabId ); + setPreferenceProperty( genGroup, "columns", 1 ); + + addPreference( tr( "Link draw color" ), genGroup, LightApp_Preferences::Color, "YACSGui", "link_draw_color" ); + addPreference( tr( "Stream link draw color" ), genGroup, LightApp_Preferences::Color, "YACSGui", "stream_link_draw_color" ); + addPreference( tr( "Link select color" ), genGroup, LightApp_Preferences::Color, "YACSGui", "link_select_color" ); + addPreference( tr( "Link hilight color" ), genGroup, LightApp_Preferences::Color, "YACSGui", "link_hilight_color" ); + + /* + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + resMgr->setValue( "YACSGui", "link_draw_color", LINKDRAW_COLOR ); + resMgr->setValue( "YACSGui", "stream_link_draw_color", STREAMLINKDRAW_COLOR ); + resMgr->setValue( "YACSGui", "link_hilight_color", LINK_HILIGHT_COLOR ); + resMgr->setValue( "YACSGui", "link_select_color", LINK_SELECT_COLOR ); + */ +} + +//! Creates module Input Page. +/*! + */ +void YACSGui_Module::createInputPanel() +{ + DEBTRACE("YACSGui_Module::createInputPanel"); + // create input panel + if (!myInputPanel) { + myInputPanel = new YACSGui_InputPanel( this ); + + int aWidth = myInputPanel->getPrefferedSize().width(); + + myInputPanel->setFixedExtentWidth( aWidth ); + application()->desktop()->moveDockWindow( myInputPanel, Qt::DockRight ); + myInputPanel->setResizeEnabled( true ); + myInputPanel->setVerticallyStretchable( true ); + myInputPanel->setCloseMode( QDockWindow::Always ); + myInputPanel->setCaption( tr( "INPUT_PANEL" ) ); + myInputPanel->widget()->show(); + myInputPanel->hide(); + + getApp()->desktop()->setAppropriate( myInputPanel, false ); + + connect( myInputPanel, SIGNAL( Apply( const int ) ), this, SLOT( onApplyInputPanel( const int ) ) ); + } +} + +//! Creates tree view for the given schema. +/*! + */ +void YACSGui_Module::createTreeView( YACS::HMI::SubjectProc* theSProc, YACSGui_DataModel::ObjectType theType ) +{ + if ( theSProc ) + { + SalomeApp_Study* study = dynamic_cast(getApp()->activeStudy() ); + if ( !study ) return; + + int aStudyId = study->id(); + if ( Proc* aProc = dynamic_cast(theSProc->getNode()) ) + { + int aVMId = viewManagerId( aProc ); // id of view manager for the given proc + YACSGui_TreeView* aTV = treeView( aStudyId, aVMId ); + if ( !aTV ) + { + if ( theType == YACSGui_DataModel::SchemaObject ) + // here the aVMId is index of the 2D schema view in edition mode + addTreeView( createTreeView( theSProc, WT_EditTreeView ), aStudyId, aVMId ); + else if ( theType == YACSGui_DataModel::RunObject ) + // activate 2D schema view in execution mode, and get its id, use it as aVMId + addTreeView( createTreeView( theSProc, WT_RunTreeView ), aStudyId, aVMId ); + } + activateTreeView( aStudyId, aVMId ); + } + } } //! Defines which windows should be created. @@ -283,9 +729,10 @@ void YACSGui_Module::createMenus() */ void YACSGui_Module::windows( QMap& mappa ) const { - MESSAGE("YACSGui_Module::windows"); + DEBTRACE("YACSGui_Module::windows"); mappa.insert( LightApp_Application::WT_ObjectBrowser, Qt::DockLeft ); mappa.insert( LightApp_Application::WT_PyConsole, Qt::DockBottom ); + mappa.insert( LightApp_Application::WT_LogWindow, Qt::DockBottom ); } //! Defines viewer type. @@ -293,8 +740,9 @@ void YACSGui_Module::windows( QMap& mappa ) const */ void YACSGui_Module::viewManagers( QStringList& lst ) const { - MESSAGE("YACSGui_Module::viewManagers"); - lst.append( QxGraph_Viewer::Type() ); + DEBTRACE("YACSGui_Module::viewManagers"); + if(myWindowsMap.size()>0) + lst.append( QxGraph_Viewer::Type() ); } @@ -303,12 +751,24 @@ void YACSGui_Module::viewManagers( QStringList& lst ) const */ bool YACSGui_Module::activateModule( SUIT_Study* theStudy ) { - MESSAGE("YACSGui_Module::activateModule"); + DEBTRACE("YACSGui_Module::activateModule"); bool bOk = SalomeApp_Module::activateModule( theStudy ); setMenuShown( true ); setToolShown( true ); + setGuiMode(YACSGui_Module::InitMode); + + //RuntimeSALOME::setRuntime(); + + /* + connect( getApp()->objectBrowser()->listView(), SIGNAL( doubleClicked( QListViewItem* ) ), + this, SLOT ( onDblClick( QListViewItem* ) ) ); + */ + + connect( getApp()->objectBrowser()->listView(), SIGNAL( expanded( QListViewItem* ) ), + this, SLOT ( onExpanded( QListViewItem* ) ) ); + connect( getApp()->objectBrowser()->listView(), SIGNAL( collapsed( QListViewItem* ) ), + this, SLOT ( onCollapsed( QListViewItem* ) ) ); - RuntimeSALOME::setRuntime(); return bOk; } @@ -317,9 +777,28 @@ bool YACSGui_Module::activateModule( SUIT_Study* theStudy ) */ bool YACSGui_Module::deactivateModule( SUIT_Study* theStudy ) { - MESSAGE("YACSGui_Module::deactivateModule"); + DEBTRACE("YACSGui_Module::deactivateModule"); + setGuiMode(YACSGui_Module::EmptyMode); setMenuShown( false ); setToolShown( false ); + + // Hide input panel + if ( myInputPanel ) + myInputPanel->hide(); + + // Hide an active tree view + if ( getApp()->activeStudy() ) + { + int sId = getApp()->activeStudy()->id(); + if ( myTreeViews.find( sId ) != myTreeViews.end() ) + myTreeViews[sId]->hide(); + } + + /* + disconnect( getApp()->objectBrowser()->listView(), SIGNAL( doubleClicked( QListViewItem* ) ), + this, SLOT ( onDblClick( QListViewItem* ) ) ); + */ + return SalomeApp_Module::deactivateModule( theStudy ); } @@ -328,19 +807,22 @@ bool YACSGui_Module::deactivateModule( SUIT_Study* theStudy ) */ QString YACSGui_Module::engineIOR() const { - MESSAGE("YACSGui_Module::engineIOR"); - CORBA::String_var anIOR = getApp()->orb()->object_to_string( InitYACSGuiGen( getApp() ) ); - return QString( anIOR.in() ); + DEBTRACE("YACSGui_Module::engineIOR"); + //CORBA::String_var anIOR = getApp()->orb()->object_to_string( InitYACSGuiGen( getApp() ) ); + //return QString( anIOR.in() ); + + // returns default IOR + return getApp()->defaultEngineIOR(); } //! Gets a reference to the module's engine /*! */ -YACSGui_ORB::YACSGui_Gen_ptr YACSGui_Module::InitYACSGuiGen( SalomeApp_Application* app ) +YACS_ORB::YACS_Gen_ptr YACSGui_Module::InitYACSGuiGen( SalomeApp_Application* app ) { - MESSAGE("YACSGui_Module::InitYACSGuiGen"); - Engines::Component_var comp = app->lcc()->FindOrLoad_Component( "YACSContainer","YACSGui" ); - YACSGui_ORB::YACSGui_Gen_ptr clr = YACSGui_ORB::YACSGui_Gen::_narrow(comp); + DEBTRACE("YACSGui_Module::InitYACSGuiGen"); + Engines::Component_var comp = app->lcc()->FindOrLoad_Component( /*"YACSContainer"*/"FactoryServerPy", "YACS" ); + YACS_ORB::YACS_Gen_ptr clr = YACS_ORB::YACS_Gen::_narrow(comp); ASSERT(!CORBA::is_nil(clr)); return clr; } @@ -348,619 +830,2992 @@ YACSGui_ORB::YACSGui_Gen_ptr YACSGui_Module::InitYACSGuiGen( SalomeApp_Applicati void YACSGui_Module::createGraph( SUIT_ViewManager* theVM ) { - MESSAGE("YACSGui_Module::createGraph"); + DEBTRACE("YACSGui_Module::createGraph"); QxGraph_ViewWindow* aVW = dynamic_cast( theVM->getActiveView() ); if ( aVW ) { // create graph with null Proc : waiting for import operation! - YACS::ENGINE::Proc* aProc = 0; + YACS::HMI::GuiContext* aCProc = 0; YACSGui_Loader::PrsDataMap aPrsData; YACSGui_Loader::PortLinkDataMap aPortLinkData; YACSGui_Loader::LabelLinkDataMap aLabelLinkData; - displayGraph( aProc, aPrsData, aPortLinkData, aLabelLinkData ); + displayGraph( aCProc, aPrsData, aPortLinkData, aLabelLinkData ); } } -//! Private slot. Creates a new empty dataflow. /*! - */ -void YACSGui_Module::onNewDataflow() + Creates tree view by flag. + \param theFlag - identificator of tree view type +*/ +YACSGui_TreeView* YACSGui_Module::createTreeView( YACS::HMI::SubjectProc* theSProc, const WindowTypes theFlag ) { - MESSAGE("YACSGui_Module::onNewDataflow"); - printf("YACSGui_Module::newDataflow\n"); - SUIT_ViewManager* aVM = getApp()->createViewManager( QxGraph_Viewer::Type() ); - createGraph(aVM); -} + YACSGui_TreeView* wid = 0; -//! Private slot. Imports uneditable dataflow from the XML file(choosing via a file dialog) -/*! - */ -void YACSGui_Module::onImportDataflow() -{ - MESSAGE("YACSGui_Module::onImportDataflow"); - ImportDataflowFromFile(false); + QxGraph_ViewWindow* aVW = 0; + + if ( !theSProc ) return wid; + + if ( Proc* aProc = dynamic_cast(theSProc->getNode()) ) + { + WindowsMap::iterator anIterator = myWindowsMap.find(aProc); + if (anIterator != myWindowsMap.end()) aVW = (*anIterator).second; + if ( !aVW ) return wid; + + if ( theFlag == WT_EditTreeView ) + wid = new YACSGui_EditionTreeView( this, theSProc, aVW/*getApp()->desktop()*/ ); + else if ( theFlag == WT_RunTreeView ) + wid = new YACSGui_RunTreeView( this, theSProc, aVW/*getApp()->desktop()*/ ); + } + + return wid; } - -//! Private slot. Imports editable dataflow from the XML file(choosing via a file dialog) + /*! - */ -void YACSGui_Module::onModifyDataflow() + Returns the index of the view manager, which shows the given schema. + \param theProc - a schema engine object +*/ +int YACSGui_Module::viewManagerId( YACS::ENGINE::Proc* theProc ) { - MESSAGE("YACSGui_Module::onModifyDataflow"); - ImportDataflowFromFile(true); + // get active study id + if ( !getApp()->activeStudy() ) + return -1; + int aStudyId = getApp()->activeStudy()->id(); + + ViewManagerList aVMs; + getApp()->viewManagers( QxGraph_Viewer::Type(), aVMs ); + + for ( QPtrListIterator it( aVMs ); it.current(); ++it ) + { + if ( it.current()->study()->id() == aStudyId ) + if ( QxGraph_Viewer* aV = dynamic_cast( it.current()->getViewModel() ) ) + { + if ( YACSGui_Graph* aG = dynamic_cast( aV->getCanvas()->getPrs() ) ) + if ( aG->getProc() == theProc ) + return it.current()->getId(); + } + } + + return -1; } -//! Private slot. Imports uneditable SUPERV dataflow from the XML file(choosing via a file dialog) +//! Private slot. Creates a new empty dataflow. /*! */ -void YACSGui_Module::onImportSupervDataflow() +void YACSGui_Module::onNewSchema() { - MESSAGE("YACSGui_Module::onImportSupervDataflow"); - ImportDataflowFromFile(false, true); + DEBTRACE("YACSGui_Module::onNewSchema"); + + // TODO: create an empty Proc* + RuntimeSALOME* aRuntimeSALOME = YACS::ENGINE::getSALOMERuntime(); + Proc* aProc = aRuntimeSALOME->createProc("newSchema"); + + // create GuiContext for Proc* + GuiContext* aCProc = new GuiContext(); + GuiContext::setCurrent( aCProc ); + aCProc->setProc( aProc ); + + aProc->setEdition(true); + + // create schema object in the Object Browser + QString name = ""; + CreateNewSchema( name, aProc ); + aProc->setName( name ); + + // create new ViewManager for the new empty schema + createNewViewManager( EditMode, aProc ); + + // create Input Panel + createInputPanel(); + + // create graph + QxGraph_Canvas* aCanvas = getCanvas(); + if ( !aCanvas ) return; + + YACSGui_Graph* aGraph = new YACSGui_Graph( this, aCanvas, aCProc ); + aGraph->show(); + + // create and activate the edition tree view for the new schema + createTreeView( aCProc->getSubjectProc(), YACSGui_DataModel::SchemaObject ); + + if ( !myCatalog ) loadCatalog(); } - -//! Private slot. Imports editable SUPERV dataflow from the XML file(choosing via a file dialog) + +//! Public slot. Edit data types of the schema. /*! */ -void YACSGui_Module::onModifySupervDataflow() +void YACSGui_Module::onEditDataTypes() { - MESSAGE("YACSGui_Module::onModifySupervDataflow"); - ImportDataflowFromFile(true, true); + } -//! Private slot. Exports current dataflow to XML file. +//! Public slot. Creates data type for the schema. /*! */ -void YACSGui_Module::onExportDataflow() +void YACSGui_Module::onCreateDataType() { - MESSAGE("YACSGui_Module::onExportDataflow"); - if ( !activeGraph() ) - return; - Proc* aProc = activeGraph()->getProc(); - if ( !aProc ) - return; - - QString aFileName = SUIT_FileDlg::getFileName( application()->desktop(), aProc->getName(), "*.xml", tr("TLT_EXPORT_DATAFLOW"), false ); - if (aFileName.isEmpty()) - return; - - YACSGui_VisitorSaveSchema aWriter( this, aProc ); - aWriter.openFileSchema( aFileName ); - aWriter.visitProc( aProc ); - aWriter.closeFileSchema(); + } - -//! Private slot. Reloads current dataflow. + +//! Public slot. Import data type from the catalog. /*! */ -void YACSGui_Module::onReloadDataflow() +void YACSGui_Module::onImportDataType() { - MESSAGE("YACSGui_Module::onReloadDataflow"); - YACSGui_Graph* aGraph = activeGraph(); - if (aGraph) - { - aGraph->setToUpdate(true); - aGraph->update(); + if ( myInputPanel ) { + YACSGui_DataTypePage* aDTPage = + dynamic_cast( myInputPanel->getPage( YACSGui_InputPanel::DataTypeId ) ); + if ( aDTPage ) + { + list aPagesIds; + + myInputPanel->setOn( true, YACSGui_InputPanel::DataTypeId ); + myInputPanel->setMode( YACSGui_InputPanel::NewMode, YACSGui_InputPanel::DataTypeId ); + aPagesIds.push_back(YACSGui_InputPanel::DataTypeId); + + myInputPanel->setExclusiveVisible( true, aPagesIds ); + myInputPanel->show(); + } } } -//! Private slot. Rebuilds dataflow links. +//! Private slot. Creates a new container. /*! */ -void YACSGui_Module::onRebuildLinks() +void YACSGui_Module::onNewContainer() { - MESSAGE("YACSGui_Module::onRebuildLinks"); - YACSGui_Graph* aGraph = activeGraph(); - if (aGraph) aGraph->rebuildLinks(); -} + DEBTRACE("YACSGui_Module::onNewContainer()"); -//! Private slot. Open dialog for add node to current dataflow. -/*! - */ -void YACSGui_Module::onAddNode() -{ - MESSAGE("YACSGui_Module::onAddNode"); - YACSGui_Graph* aGraph = activeGraph(); - if (!aGraph) + if ( SubjectProc* aSchema = GuiContext::getCurrent()->getSubjectProc() ) + { + stringstream aName; + aName << "container" << GuiContext::getCurrent()->getNewId(CONTAINER); + + bool aRet = aSchema->addContainer(aName.str()); + if ( !aRet ) { SUIT_MessageBox::warn1(getApp()->desktop(), tr("WARNING"), - tr("MSG_NO_DATAFLOW_SELECTED"), + GuiContext::getCurrent()->_lastErrorMessage, tr("BUT_OK")); return; } + temporaryExport(); + } +} - YACSGui_DataModel* aModel = getDataModel(); - if ( aModel && !aModel->isEditable(activeGraph()->getProc()) ) +//! Private slot. Creates a new SALOME component. +/*! + */ +void YACSGui_Module::onNewSalomeComponent() +{ + DEBTRACE("YACSGui_Module::onNewSalomeComponent()"); + + YACSGui_EditionTreeView* anETV = dynamic_cast( activeTreeView() ); + if ( !anETV ) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_NO_ANY_CONTAINER_SELECTED_IN_TREE_VIEW"), + tr("BUT_OK")); + return; + } + + Subject* aSub = anETV->getSelectedSubject(); + if ( !aSub ) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_NO_ANY_CONTAINER_SELECTED_IN_TREE_VIEW"), + tr("BUT_OK")); + return; + } + + if ( SubjectContainer* aCont = dynamic_cast(aSub) ) + { + stringstream aName; + aName << "component" << GuiContext::getCurrent()->getNewId(COMPONENT); + + SubjectComponent* aRet = GuiContext::getCurrent()->getSubjectProc()->addComponent(aName.str()); + if ( !aRet ) { SUIT_MessageBox::warn1(getApp()->desktop(), tr("WARNING"), - tr("MSG_DATAFLOW_NOT_EDITABLE"), + GuiContext::getCurrent()->_lastErrorMessage, tr("BUT_OK")); return; } + + aRet->associateToContainer(aCont); + aCont->update(ADD, COMPONENT, aRet); + temporaryExport(); + } } - -//! Private slot. Starts dataflow execution. + +//! Private slot. Creates a new SALOME Python component. /*! - */ -void YACSGui_Module::onRunDataflow() + */ +void YACSGui_Module::onNewSalomePythonComponent() { - MESSAGE("YACSGui_Module::onRunDataflow"); - YACSGui_Executor* anExecutor = findExecutor(); - if (anExecutor) - anExecutor->runDataflow(); + DEBTRACE("YACSGui_Module::onNewSalomePythonComponent() --- NOT YET IMPLEMENTED!"); } -//! Private slot. Starts remote dataflow execution. +//! Private slot. Creates a new CORBA component. /*! - */ -void YACSGui_Module::onRemoteRunDataflow() + */ +void YACSGui_Module::onNewCorbaComponent() { - MESSAGE("YACSGui_Module::onRemoteRunDataflow"); - YACSGui_Executor* anExecutor = findExecutor(); - if (anExecutor) - anExecutor->runDataflow(true); + DEBTRACE("YACSGui_Module::onNewCorbaComponent() --- NOT YET IMPLEMENTED!"); } -//! Private slot. Kills dataflow execution. +//! Private slot. Creates a new SALOME service node. /*! */ -void YACSGui_Module::onKillDataflow() +void YACSGui_Module::onSalomeServiceNode() { - MESSAGE("YACSGui_Module::onKillDataflow"); - YACSGui_Executor* anExecutor = findExecutor(); - if (anExecutor) - { - if (!anExecutor->isRunning()) - { - SUIT_MessageBox::warn1(getApp()->desktop(), - tr("WARNING"), - tr("MSG_DATAFLOW_IS_NOT_RUNNING"), - tr("BUT_OK")); - return; - } - } - anExecutor->stopDataflow(); - //myExecutors[aProc] = 0; //@ + //createNode(SALOMENODE); + if ( activeTreeView() ) + { + if( YACSGui_EditionTreeView* anETV = dynamic_cast( activeTreeView() ) ) + if ( Subject* aSub = anETV->getSelectedSubject() ) + { + if ( SubjectComponent* aSComp = dynamic_cast(aSub) ) + { + createNode(SALOMENODE); + return; + } + } + + setGuiMode(YACSGui_Module::NewMode); + activeTreeView()->syncPageTypeWithSelection(); + } } -//! Private slot. Suspends or resumes dataflow execution. +//! Private slot. Creates a new service inline node. /*! */ -void YACSGui_Module::onSuspendResumeDataflow() +void YACSGui_Module::onServiceInlineNode() { - MESSAGE("YACSGui_Module::onSuspendResumeDataflow"); - YACSGui_Executor* anExecutor = findExecutor(); - if (anExecutor) - { - RunModeMap::iterator anIterator = _runModeMap.find(anExecutor); - YACSGui_RunMode* aRunMode = 0; - if (anIterator != _runModeMap.end()) - aRunMode = (*anIterator).second; - else - { - aRunMode = new YACSGui_RunMode(anExecutor, application()->desktop()); - _runModeMap[anExecutor] = aRunMode; - } - if (!aRunMode->isShown()) - aRunMode->show(); - } + createNode(SALOMEPYTHONNODE); } -void YACSGui_Module::onFilterNextSteps() +//! Private slot. Creates a new CORBA service node. +/*! + */ +void YACSGui_Module::onCorbaServiceNode() { - MESSAGE("YACSGui_Module::onFilterNextSteps --- NOT YET IMPLEMENTED!"); - YACSGui_Executor* anExecutor = findExecutor(); - if (anExecutor) - { - } + createNode(CORBANODE); } -void YACSGui_Module::onSaveDataflowState() +//! Private slot. Creates a new "node-node" service node. +/*! + */ +void YACSGui_Module::onNodeNodeServiceNode() { - MESSAGE("YACSGui_Module::onSaveDataflowState --- NOT YET IMPLEMENTED!"); - YACSGui_Executor* anExecutor = findExecutor(); - if (anExecutor) - { - } + DEBTRACE("YACSGui_Module::onNodeNodeServiceNode --- NOT YET IMPLEMENTED!"); + //createNode(NODENODE); } -void YACSGui_Module::onToggleStopOnError() +//! Private slot. Creates a new cpp node. +/*! + */ +void YACSGui_Module::onCppNode() { - MESSAGE("YACSGui_Module::onToggleStopOnError"); - YACSGui_Executor* anExecutor = findExecutor(); - if (anExecutor) - { - anExecutor->setStopOnError(true); - } + createNode(CPPNODE); } -//! Private slot. Add current dataflow to study. +//! Private slot. Creates a new XML node. /*! */ -void YACSGui_Module::onAddDataflowInStudy() +void YACSGui_Module::onXMLNode() { - MESSAGE("YACSGui_Module::onAddDataflowInStudy"); - YACSGui_Graph* aGraph = activeGraph(); - - if (aGraph) { - Proc* aProc = aGraph->getProc(); - if (!aProc) - aProc = new Proc("NewDataflow"); - YACSGui_DataModel* aModel = getDataModel(); - if (aModel) - aModel->addData(aProc); - } + createNode(XMLNODE); } -//! Private slot. TD: what's this ? +//! Private slot. Creates a new input data node. /*! */ -void YACSGui_Module::onChangeInformations() +void YACSGui_Module::onInDataNode() { - MESSAGE("YACSGui_Module::onChangeInformations --- NOT YET IMPLEMENTED!"); + createNode(PRESETNODE); } -//! Private slot. Switch current dataflow to full view mode. +//! Private slot. Creates a new output data node. /*! */ -void YACSGui_Module::onFullView() +void YACSGui_Module::onOutDataNode() { - MESSAGE("YACSGui_Module::onFullView --- NOT YET IMPLEMENTED!"); + createNode(OUTNODE); } -//! Private slot. Switch current dataflow to control view mode. +//! Private slot. Creates a new input study node. /*! */ -void YACSGui_Module::onControlView() +void YACSGui_Module::onInStudyNode() { - MESSAGE("YACSGui_Module::onControlView --- NOT YET IMPLEMENTED!"); + createNode(STUDYINNODE); } -//! Private slot. Switch current dataflow to table view mode. +//! Private slot. Creates a new output study node. /*! */ -void YACSGui_Module::onTableView() +void YACSGui_Module::onOutStudyNode() { - MESSAGE("YACSGui_Module::onTableView --- NOT YET IMPLEMENTED!"); + createNode(STUDYOUTNODE); } -//! Creates and displays presentation of a calculation graph. +//! Private slot. Creates a new inline script node. /*! - * \param theGraph - graph to be displayed - * \param thePrsData - map of node coordinates and dimensions */ -YACSGui_Graph* YACSGui_Module::displayGraph( YACS::ENGINE::Proc* theGraph, - const YACSGui_Loader::PrsDataMap& thePrsData, - const YACSGui_Loader::PortLinkDataMap& thePortLinkData, - const YACSGui_Loader::LabelLinkDataMap& theLabelLinkData) +void YACSGui_Module::onInlineScriptNode() { - MESSAGE("YACSGui_Module::displayGraph"); - YACSGui_Graph* aGraph = 0; - - QxGraph_Canvas* aCanvas = getCanvas(); - if ( !aCanvas ) - return aGraph; - - aGraph = new YACSGui_Graph( this, aCanvas, theGraph ); - aGraph->show(); - - // Update node geometry - // TODO: not optimal, graph is redrawn twice - - // before and after node geometry is applied - to be improved... - bool needToUpdate = false; - if ( thePrsData.size() ) - { - for ( YACSGui_Loader::PrsDataMap::const_iterator it = thePrsData.begin(); it != thePrsData.end(); it++ ) - { - YACSPrs_ElementaryNode* anItem = aGraph->getItem( (*it).first ); - YACSGui_Loader::PrsData aData = (*it).second; - - if ( !anItem ) - continue; - - YACSPrs_BlocNode* aBloc = dynamic_cast(anItem); - if ( aBloc ) - { - aBloc->resize( (int)aData.width, (int)aData.height ); - } - - anItem->setIsCheckAreaNeeded(false); - anItem->move( aData.x, aData.y ); - anItem->setIsCheckAreaNeeded(true); - anItem->setZ( aData.z ); - } - needToUpdate = true; - } - - // Update port links presentations - if ( thePortLinkData.size() ) - { - for ( YACSGui_Loader::PortLinkDataMap::const_iterator it = thePortLinkData.begin(); it != thePortLinkData.end(); it++ ) - { - // (*it).first.first is an output port engine - // (*it).first.second is an input port engine - YACSPrs_ElementaryNode* aFromNodePrs = aGraph->getItem( (*it).first.first->getNode() ); - if ( !aFromNodePrs ) continue; - - std::list aLinksPrs = aFromNodePrs->getPortPrs( (*it).first.first )->getLinks(); - for ( std::list::iterator itL = aLinksPrs.begin(); itL != aLinksPrs.end(); itL++ ) - { - if ( YACSPrs_PortLink* aPortLink = dynamic_cast( *itL ) ) - { - if ( aPortLink->getInputPort()->getEngine() == (*it).first.second ) - { - aPortLink->setPoints((*it).second); - aPortLink->merge(); - } - } - } - } - needToUpdate = true; - } - - // Update label links presentations - if ( theLabelLinkData.size() ) - { - for ( YACSGui_Loader::LabelLinkDataMap::const_iterator it = theLabelLinkData.begin(); it != theLabelLinkData.end(); it++ ) - { - YACSPrs_ElementaryNode* aSlaveNodePrs = aGraph->getItem( (*it).first ); - if ( !aSlaveNodePrs ) continue; - - if ( YACSPrs_LabelLink* aLinkPrs = aSlaveNodePrs->getLabelLink() ) - { - aLinkPrs->setPoints((*it).second); - aLinkPrs->merge(); - } - } - needToUpdate = true; - } - - if ( needToUpdate ) aCanvas->update(); + createNode(PYTHONNODE); } -//! Returns the presentation of a given calculation graph. +//! Private slot. Creates a new inline function node. /*! */ -YACSGui_Graph* YACSGui_Module::getGraph( YACS::ENGINE::Proc* theGraph ) +void YACSGui_Module::onInlineFunctionNode() { - MESSAGE("YACSGui_Module::getGraph"); - YACSGui_Graph* aGraph = 0; - // TODO - find a graph in all viewers - // ... - // TEMPORARY solution: - if ( activeGraph() && activeGraph()->getProc() == theGraph ) - { - aGraph = activeGraph(); - } - - return aGraph; + createNode(PYFUNCNODE); } -//! Returns the presentation of a the calculation graph corresponding to the active view. +//! Private slot. Creates a new block node. /*! */ -YACSGui_Graph* YACSGui_Module::activeGraph() +void YACSGui_Module::onBlockNode() { - MESSAGE("YACSGui_Module::activeGraph"); - YACSGui_Graph* aGraph = 0; - QxGraph_Canvas* aCanvas = getCanvas(); - if ( aCanvas ) - // Assume that there's the one and only prs per a canvas - aGraph = dynamic_cast( aCanvas->getPrs() ); - return aGraph; + createNode(BLOC); } -//! Returns the graph viewer instance +//! Private slot. Creates a new FOR loop node. /*! */ -QxGraph_Viewer* YACSGui_Module::getViewer() +void YACSGui_Module::onFORNode() { - MESSAGE("YACSGui_Module::getViewer"); - QxGraph_Viewer* aViewer = 0; - QxGraph_ViewManager* aVM = - dynamic_cast( getApp()->getViewManager( QxGraph_Viewer::Type(), true ) ); - if ( aVM ) - aViewer = dynamic_cast( aVM->getViewModel() ); - return aViewer; + createNode(FORLOOP); } -//! Returns the canvas for graph drawing +//! Private slot. Creates a new FOREACH loop node. /*! */ -QxGraph_Canvas* YACSGui_Module::getCanvas() +void YACSGui_Module::onFOREACHNode() { - MESSAGE("YACSGui_Module::getCanvas"); - QxGraph_Canvas* aCanvas = 0; - QxGraph_Viewer* aViewer = getViewer(); - if ( aViewer ) - aCanvas = aViewer->getCanvas(); - return aCanvas; + createNode(FOREACHLOOP); } -void YACSGui_Module::createElementaryNodePrs() +//! Private slot. Creates a new WHILE loop node. +/*! + */ +void YACSGui_Module::onWHILENode() { - MESSAGE("YACSGui_Module::createElementaryNodePrs --- NOT YET IMPLEMENTED!"); - /* if ( myGraph ) - { - YACS::ENGINE::Node* aNode = 0; // temporary solution for test - YACSPrs_ElementaryNode* anElemNode = - new YACSPrs_ElementaryNode(SUIT_Session::session()->resourceMgr(), myGraph->getCanvas(), aNode); - myGraph->getCanvas()->getPrs()->addItem(anElemNode); // add item for the current display mode - anElemNode->show(); - myGraph->getCanvas()->update(); - }*/ + createNode(WHILELOOP); } -//! Create new instance of data model and return it. +//! Private slot. Creates a new SWITCH node. /*! */ -CAM_DataModel* YACSGui_Module::createDataModel() +void YACSGui_Module::onSWITCHNode() { - MESSAGE("YACSGui_Module::createDataModel"); - return new YACSGui_DataModel( this ); + createNode(SWITCH); } -//! Retuns data model. +//! Private slot. Loads a new from the library. /*! */ -YACSGui_DataModel* YACSGui_Module::getDataModel() const +void YACSGui_Module::onNodeFromLibrary() { - MESSAGE("YACSGui_Module::getDataModel"); - YACSGui_DataModel* aModel = dynamic_cast( dataModel() ); - return aModel; + DEBTRACE("YACSGui_Module::onNodeFromLibrary --- NOT YET IMPLEMENTED!"); } -//! Load dataflow from file. +//! Private slot. Imports uneditable dataflow from the XML file(choosing via a file dialog) /*! - * \param setEditable - define if the dataflow wiil be editable. */ -void YACSGui_Module::ImportDataflowFromFile(const bool setEditable, bool fromSuperv) +void YACSGui_Module::onImportSchema() { - MESSAGE("YACSGui_Module::ImportDataflowFromFile"); - QString caption; - if (fromSuperv) - { - if (setEditable) - caption = QString(tr("TLT_MODIFY_SUPERV_DATAFLOW")); - else - caption = QString(tr("TLT_IMPORT_SUPERV_DATAFLOW")); - } - else - { - if (setEditable) - caption = QString(tr("TLT_MODIFY_DATAFLOW")); - else - caption = QString(tr("TLT_IMPORT_DATAFLOW")); + DEBTRACE("YACSGui_Module::onImportSchema"); + + if ( !myCatalog ) loadCatalog(); + + QString aFileName = SUIT_FileDlg::getFileName( application()->desktop(), "", "*.xml", tr("TLT_IMPORT_SCHEMA"), true ); + if ( GuiContext* aCProc = ImportProcFromFile(aFileName, EditMode, false) ) + if ( Proc* aProc = aCProc->getProc() ) + { + aProc->setEdition(true); + + // create schema object in the Object Browser + CreateNewSchema(aFileName,aProc); + + // create and activate the edition tree view for the imported schema + createTreeView( aCProc->getSubjectProc(), YACSGui_DataModel::SchemaObject ); + YACSGui_TreeView* ATV=activeTreeView(); + if ( ATV ) + ATV->setSelected(ATV->firstChild(),true); } - QString aFileName = SUIT_FileDlg::getFileName( application()->desktop(), "", "*.xml", caption, true ); +} - if (aFileName.isEmpty()) - return; - QString tmpFileName = aFileName; +//! Private slot. Imports uneditable SUPERV dataflow from the XML file(choosing via a file dialog) +/*! + */ +void YACSGui_Module::onImportSupervSchema() +{ + DEBTRACE("YACSGui_Module::onImportSupervSchema"); - if (fromSuperv) - { - YACSGui_ORB::YACSGui_Gen_ptr engineRef = InitYACSGuiGen(getApp()); - try - { - tmpFileName = engineRef->convertSupervFile(aFileName); - } - catch(...) - { - std::cerr<<"Unexpected exception in convertSupervFile " <desktop(), - tr("WARNING"), - tr("Unexpected exception in convertSupervFile"), - tr("BUT_OK")); - return; - } - } - - //TD: Here check if the study already contains a graph imported from the same file - - YACSGui_Loader aLoader; - - try - { - Proc* aProc = 0; - if (!tmpFileName.isEmpty()) - aProc = aLoader.load(tmpFileName); - - //TD: Check the result of file loading - if (!aProc) - { - SUIT_MessageBox::error1(getApp()->desktop(), - tr("ERROR"), - tr("MSG_IMPORT_FILE_ERROR"), - tr("BUT_OK")); - return; - } + if ( !myCatalog ) loadCatalog(); - aProc->setName(QFileInfo(aFileName).fileName ()); - - SUIT_ViewManager* aVM = getApp()->createViewManager( QxGraph_Viewer::Type() ); + // switch to edition mode + //setGuiMode(YACSGui_Module::EditMode); - // set caption for graph's view window - QxGraph_ViewWindow* aVW = dynamic_cast( aVM->getActiveView() ); - if ( aVW ) aVW->setCaption(QFileInfo(aFileName).fileName ()); + QString aFileName = SUIT_FileDlg::getFileName( application()->desktop(), "", "*.xml", tr("TLT_IMPORT_SUPERV_SCHEMA"), true ); + if ( GuiContext* aCProc = ImportProcFromFile(aFileName, EditMode, false, true) ) + if ( Proc* aProc = aCProc->getProc() ) + { + aProc->setEdition(true); - YACSGui_DataModel* aModel = getDataModel(); - if (aModel) - aModel->add(aProc, setEditable); - // TD: add graph to study. + // create schema object in the Object Browser + CreateNewSchema(aFileName,aProc); - int w, h; - const YACSGui_Loader::PrsDataMap& aPrsData = aLoader.getPrsData( aProc, w, h ); - const YACSGui_Loader::PortLinkDataMap& aPortLinkData = aLoader.getPortLinkData( aProc ); - const YACSGui_Loader::LabelLinkDataMap& aLabelLinkData = aLoader.getLabelLinkData( aProc ); - if ( aVW ) - { - if ( w > 0 && h > 0 ) - aVW->getViewModel()->getCanvas()->resize( w, h ); - displayGraph( aProc, aPrsData, aPortLinkData, aLabelLinkData ); - } - } - catch (YACS::Exception& ex) - { - std::cerr<<"YACSGui_Module::importDataflow: " <getSubjectProc(), YACSGui_DataModel::SchemaObject ); + YACSGui_TreeView* ATV=activeTreeView(); + if ( ATV ) + ATV->setSelected(ATV->firstChild(),true); + + temporaryExport(); } } -//! Returns or create executor for a given graph. +//! Private slot. Exports current dataflow to XML file. /*! */ -YACSGui_Executor* YACSGui_Module::getExecutor( YACS::ENGINE::Proc* theProc ) +void YACSGui_Module::onExportSchema() { - MESSAGE("YACSGui_Module::getExecutor"); - YACSGui_Executor* anExecutor = 0; - - ExecutorMap::iterator anIterator = myExecutors.find(theProc); - if (anIterator != myExecutors.end()) - anExecutor = (*anIterator).second; - - if (!anExecutor) - { - anExecutor = new YACSGui_Executor(this, theProc); - anExecutor->setGraph(activeGraph()); - myExecutors[theProc] = anExecutor; - } - - return anExecutor; + DEBTRACE("YACSGui_Module::onExportSchema"); + if ( !activeGraph() ) + return; + Proc* aProc = activeGraph()->getProc(); + if ( !aProc ) + return; + + QString aFileName = SUIT_FileDlg::getFileName( application()->desktop(), aProc->getName(), "*.xml", tr("TLT_EXPORT_SCHEMA"), false ); + if (aFileName.isEmpty()) + return; + + YACSGui_VisitorSaveSchema aWriter( this, aProc ); + aWriter.openFileSchema( aFileName ); + aWriter.visitProc( aProc ); + aWriter.closeFileSchema(); +} + +//! Private slot. Reloads current dataflow. +/*! + */ +void YACSGui_Module::onReloadDataflow() +{ + DEBTRACE("YACSGui_Module::onReloadDataflow"); + YACSGui_Graph* aGraph = activeGraph(); + if (aGraph) + { + aGraph->setToUpdate(true); + aGraph->update(); + } } -//! Returns executor for active graph or nul if no active graph +//! Private slot. Auto-arrange dataflow nodes. /*! */ -YACSGui_Executor* YACSGui_Module::findExecutor() +void YACSGui_Module::onArrangeNodes() { - MESSAGE("YACSGui_Module::findExecutor"); + DEBTRACE("YACSGui_Module::onArrangeNodes"); YACSGui_Graph* aGraph = activeGraph(); - YACSGui_Executor* anExecutor = 0; - Proc* aProc = 0; if (aGraph) - aProc = aGraph->getProc(); - - if (!aGraph || !aProc) + { + int anErr = 0; + + anErr = aGraph->arrangeNodesAlgo(aGraph->getProc()); + if ( anErr ) + SUIT_MessageBox::error1(getApp()->desktop(), + tr("ERROR"), + tr("MSG_ARRANGE_NODES_ERROR"), + tr("BUT_OK")); + else temporaryExport(); + } +} + +//! Private slot. Rebuilds dataflow links. +/*! + */ +void YACSGui_Module::onRebuildLinks() +{ + DEBTRACE("YACSGui_Module::onRebuildLinks"); + YACSGui_Graph* aGraph = activeGraph(); + if (aGraph) + { + aGraph->rebuildLinks(); + temporaryExport(); + } +} + +//! Private slot. Starts local dataflow execution. +/*! + */ +void YACSGui_Module::onRunDataflow() +{ + DEBTRACE("YACSGui_Module::onRunDataflow"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + anExecutor->runDataflow(); +} + +//! Private slot. Starts remote dataflow execution. +/*! + */ +void YACSGui_Module::onRemoteRunDataflow() +{ + DEBTRACE("YACSGui_Module::onRemoteRunDataflow"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + anExecutor->runDataflow(true); +} + +//! Private slot. Kills dataflow execution. +/*! + */ +void YACSGui_Module::onKillDataflow() +{ + DEBTRACE("YACSGui_Module::onKillDataflow"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + { + if (!anExecutor->isRunning()) { SUIT_MessageBox::warn1(getApp()->desktop(), tr("WARNING"), - tr("MSG_NO_DATAFLOW_LOADED"), + tr("MSG_DATAFLOW_IS_NOT_RUNNING"), tr("BUT_OK")); - return 0; + return; + } + anExecutor->stopDataflow(); + //myExecutors[aProc] = 0; //@ + } +} + +//! Private slot. Suspends or resumes dataflow execution. +/*! + */ +void YACSGui_Module::onSuspendResumeDataflow() +{ + DEBTRACE("YACSGui_Module::onSuspendResumeDataflow"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + { + RunModeMap::iterator anIterator = _runModeMap.find(anExecutor); + YACSGui_RunMode* aRunMode = 0; + if (anIterator != _runModeMap.end()) + aRunMode = (*anIterator).second; + else + { + aRunMode = new YACSGui_RunMode(anExecutor, application()->desktop()); + _runModeMap[anExecutor] = aRunMode; + } + if (!aRunMode->isShown()) + aRunMode->show(); + } +} + +void YACSGui_Module::onFilterNextSteps() +{ + DEBTRACE("YACSGui_Module::onFilterNextSteps --- NOT YET IMPLEMENTED!"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + { + } +} + +void YACSGui_Module::onSaveDataflowState() +{ + DEBTRACE("YACSGui_Module::onSaveDataflowState --- NOT YET IMPLEMENTED!"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + { + } +} + +//! A test function: put values of all ouput ports of the schema into the study +/*! + */ +void YACSGui_Module::publishInStudy(YACSGui_Graph* theGraph) +{ + /*abd + if (aModel) + { + YACSGui_ModuleObject* aRoot = dynamic_cast( aModel->root() ); + if( aRoot ) + { + // get SComponent from root data object + _PTR(SComponent) aSComp( aRoot->object() ); + + _PTR(Study) aStudy = (( SalomeApp_Study* )(getApp()->activeStudy()))->studyDS(); + _PTR(StudyBuilder) aBuilder ( aStudy->NewBuilder() ); + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + + Proc* aProc = theGraph->getProc(); + _PTR(SObject) aSObj = aStudy->FindObject(aProc->getName()); + if ( !aSObj ) + { // create a new schema SObject + printf(">> create a new schema SObject\n"); + aSObj = aBuilder->NewObject(aSComp); + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + aName->SetValue(aProc->getName()); + } + + if ( aProc->getState() == YACS::DONE ) + { + _PTR(SObject) aResult; + _PTR(ChildIterator) anIterator ( aStudy->NewChildIterator(aSObj) ); + for (; anIterator->More(); anIterator->Next()) { + if (anIterator->Value()->FindAttribute(anAttr, "AttributeName")) { + aName = _PTR(AttributeName) ( anAttr ); + //if (strcmp(aName->Value().c_str(), myStartTimeString) == 0) { + aResult = anIterator->Value(); + break; + //} + } + } + + if ( !aResult ) + { + // create a new "Run ... " SObject + printf("create a new Run ... SObject\n"); + aResult = aBuilder->NewObject( aSObj ); + anAttr = aBuilder->FindOrCreateAttribute(aResult, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + aName->SetValue("Run ..."); + + // iterates on all schema nodes and create a new node SObject for each node, + // which has any output port + set aNodeSet = aProc->getAllRecursiveConstituents(); + for ( set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + { + YACSPrs_ElementaryNode* aNodePrs = theGraph->getItem(*it); + if ( !aNodePrs ) return; + + list aDataPorts = (*it)->getSetOfOutputPort(); + list aDataStreamPorts = (*it)->getSetOfOutputDataStreamPort(); + + if ( !aDataPorts.empty() || !aDataStreamPorts.empty() ) + { + // create a new node SObject + printf(">> create a new node SObject\n"); + aSObj = aBuilder->NewObject( aResult ); + anAttr = aBuilder->FindOrCreateAttribute(aSObj, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + aName->SetValue( (*it)->getRootNode()->getChildName(*it) ); + + _PTR(SObject) aPSObj; + + // create output data port SObjects + for ( list::iterator itDP = aDataPorts.begin(); itDP != aDataPorts.end(); itDP++ ) + { + printf(">> create output data port SObjects\n"); + aPSObj = aBuilder->NewObject( aSObj ); + anAttr = aBuilder->FindOrCreateAttribute(aPSObj, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + aName->SetValue( (*itDP)->getName() ); + anAttr = aBuilder->FindOrCreateAttribute(aPSObj, "AttributeIOR"); + _PTR(AttributeIOR) anIORAttr ( anAttr ); + anIORAttr->SetValue(aNodePrs->getPortPrs(*itDP)->getValue()); + } + + // create output data stream port SObjects + for ( list::iterator itDSP = aDataStreamPorts.begin(); itDSP != aDataStreamPorts.end(); itDSP++ ) + { + printf(">> create output data stream port SObjects\n"); + aPSObj = aBuilder->NewObject( aSObj ); + anAttr = aBuilder->FindOrCreateAttribute(aPSObj, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + aName->SetValue( (*itDSP)->getName() ); + anAttr = aBuilder->FindOrCreateAttribute(aPSObj, "AttributeIOR"); + _PTR(AttributeIOR) anIORAttr ( anAttr ); + anIORAttr->SetValue(aNodePrs->getPortPrs(*itDSP)->getValue()); + } + } + + } // end loop on nodes + + } + } + } + }*/ +} + +//! Private slot. TD: what's this ? +/*! + */ +void YACSGui_Module::onChangeInformations() +{ + DEBTRACE("YACSGui_Module::onChangeInformations --- NOT YET IMPLEMENTED!"); +} + +//! Private slot. Switch current schema to full view mode. +/*! + */ +void YACSGui_Module::onFullView() +{ + DEBTRACE("YACSGui_Module::onFullView"); + + YACSGui_Graph* aGraph = activeGraph(); + if (aGraph) + { + int aPrevMode = aGraph->getDMode(); + if ( aPrevMode != YACSGui_Graph::FullId ) + { + QCanvas* aCanvas = aGraph->getCanvas(); + if ( !aCanvas ) return; + + aGraph->hide(); // canvas is 0 for all presentations + aCanvas->setChanged( QRect(0,0,aCanvas->width(),aCanvas->height()) ); + aCanvas->update(); + + aGraph->setDMode(YACSGui_Graph::FullId); + aGraph->setToUpdate(true); + aGraph->show(); // set canvas for full view presentations + aCanvas->update(); + + //aGraph->viewModesConsistency(aPrevMode,YACSGui_Graph::FullId); + + //if ( QCanvas* aCanvas = aGraph->getCanvas() ) + //{ + // aCanvas->setChanged( QRect(0,0,aCanvas->width(),aCanvas->height()) ); + // aCanvas->update(); + //} + } + } +} + +//! Private slot. Switch current schema to control view mode. +/*! + */ +void YACSGui_Module::onControlView() +{ + DEBTRACE("YACSGui_Module::onControlView"); + + YACSGui_Graph* aGraph = activeGraph(); + if (aGraph) + { + int aPrevMode = aGraph->getDMode(); + if ( aPrevMode != YACSGui_Graph::ControlId ) + { + aGraph->hide(); + + aGraph->setDMode(YACSGui_Graph::ControlId); + aGraph->setToUpdate(true); + aGraph->show(); + + //aGraph->viewModesConsistency(aPrevMode,YACSGui_Graph::ControlId); + + if ( QCanvas* aCanvas = aGraph->getCanvas() ) + { + aCanvas->setChanged( QRect(0,0,aCanvas->width(),aCanvas->height()) ); + aCanvas->update(); + } + } + } +} + +//! Private slot. Switch current schema to data flow view mode. +/*! + */ +void YACSGui_Module::onDataFlowView() +{ + DEBTRACE("YACSGui_Module::onDataFlowView --- NOT YET IMPLEMENTED!"); +} + +//! Private slot. Switch current schema to data stream view mode. +/*! + */ +void YACSGui_Module::onDataStreamView() +{ + DEBTRACE("YACSGui_Module::onDataStreamView --- NOT YET IMPLEMENTED!"); +} + +//! Private slot. Switch current dataflow to table view mode. +/*! + */ +void YACSGui_Module::onTableView() +{ + DEBTRACE("YACSGui_Module::onTableView --- NOT YET IMPLEMENTED!"); +} + +//! Private slot. Selects the original object in the object browser if a reference object is double clicked. +/*! + */ +void YACSGui_Module::onDblClick( QListViewItem* theItem ) +{ + DEBTRACE("YACSGui_Module::onDblClick"); + OB_ListItem* item = dynamic_cast( theItem ); + if ( !item ) return; + + if ( SalomeApp_DataObject* aDataObj = dynamic_cast( item->dataObject() ) ) + { + if ( aDataObj && getApp()->checkDataObject(aDataObj) ) + { + QString anEntry = aDataObj->entry(); + + YACSGui_DataModel::ObjectType anObjType = getDataModel()->objectType( anEntry.latin1() ); + if ( anObjType == YACSGui_DataModel::SchemaObject || anObjType == YACSGui_DataModel::RunObject ) + { + SalomeApp_Study* study = dynamic_cast(getApp()->activeStudy() ); + if ( !study ) return; + + _PTR(SObject) aObj = aDataObj->object(); + if ( Proc* aProc = getDataModel()->getProc( aObj ) ) + { + //ensure YACS is active module + getApp()->activateModule("YACS"); + //switch to edition or run mode (depends on anObjType) + if(anObjType == YACSGui_DataModel::SchemaObject) + setGuiMode(YACSGui_Module::EditMode); + else if(anObjType == YACSGui_DataModel::RunObject) + setGuiMode(YACSGui_Module::RunMode); + + // show edition tree view + int aStudyId = study->id(); + int aVMId = viewManagerId( aProc ); // id of view manager for the given proc + if ( aVMId == -1 ) + { // create a new one view manager and view window + GuiContext* aCProc = 0; + + QxGraph_ViewWindow* aVW = createNewViewManager( myGuiMode, aProc ); + if ( aVW ) + { + int w, h, l, t; + double xscale, yscale; + YACSGui_Loader aLoader; + const YACSGui_Loader::PrsDataMap& aPrsData = aLoader.getPrsData( aProc, w, h, l, t, xscale, yscale ); + const YACSGui_Loader::PortLinkDataMap& aPortLinkData = aLoader.getPortLinkData( aProc ); + const YACSGui_Loader::LabelLinkDataMap& aLabelLinkData = aLoader.getLabelLinkData( aProc ); + + // create GuiContext for Proc* + aCProc = new GuiContext(); + GuiContext::setCurrent( aCProc ); + aCProc->setProc( aProc ); + + displayGraph( aCProc, aPrsData, aPortLinkData, aLabelLinkData, l, t, xscale, yscale ); + } + + // create Input Panel + createInputPanel(); + + // create and activate the tree view for the created schema + createTreeView( aCProc ? aCProc->getSubjectProc() : 0, anObjType ); + } + else + { + // activate correspondiong view window + activateViewWindow( aProc ); + // activate correspondiong tree view + activateTreeView( aStudyId, aVMId ); + } + + } + } } + } +} + +//! Private slot. Set an expanded folder icon for the expanded data object (YACSGui_DataObject) in the Object Browser. +/*! + */ +void YACSGui_Module::onExpanded( QListViewItem* theItem ) +{ + OB_ListItem* item = dynamic_cast( theItem ); + if ( !item ) return; + + if ( SalomeApp_DataObject* aDataObj = dynamic_cast( item->dataObject() ) ) + { + aDataObj->setOpen( true ); + theItem->setPixmap( 0, aDataObj->icon() ); + } +} + +//! Private slot. Set a collapsed folder icon for the collapsed data object (YACSGui_DataObject) in the Object Browser. +/*! + */ +void YACSGui_Module::onCollapsed( QListViewItem* theItem ) +{ + OB_ListItem* item = dynamic_cast( theItem ); + if ( !item ) return; + + if ( SalomeApp_DataObject* aDataObj = dynamic_cast( item->dataObject() ) ) + { + aDataObj->setOpen( false ); + theItem->setPixmap( 0, aDataObj->icon() ); + } +} + +//! Private slot. Update tree in the Object Browser and 2D schema view according to applying changes in the Input Panel. +/*! + */ +void YACSGui_Module::onApplyInputPanel( const int theId ) +{ + DEBTRACE("YACSGui_Module::onApplyInputPanel"); + + if ( !myInputPanel ) return; + + YACSGui_EditionTreeView* anETV = dynamic_cast( activeTreeView() ); + if ( !anETV ) return; + + // get the list of items selected in the edition tree view + list aSelList = anETV->getSelected(); - anExecutor = getExecutor(aProc); - return anExecutor; + // check if the current selection is a single selection + if ( aSelList.size() == 1 ) + { + switch ( theId ) + { + case YACSGui_InputPanel::ContainerId: + break; + case YACSGui_InputPanel::ComponentId: + break; + case YACSGui_InputPanel::SchemaId: + if ( YACSGui_SchemaPage* aSPage = + dynamic_cast( myInputPanel->getPage( YACSGui_InputPanel::SchemaId ) ) ) + { // this is a schema view item + if ( Proc* aSchema = aSPage->getProc() ) + { + SalomeApp_DataObject* aDataObj = dynamic_cast( getDataModel()->getDataObject(aSchema) ); + if ( !aDataObj ) return; + + // update Object Browser: + getApp()->objectBrowser()->updateTree(aDataObj,true); + + // update 2D schema view (if this schema is active): + // a.) update caption for active 2D view (edition mode) + if ( activeGraph()->getProc() == aSchema ) + { + QxGraph_ViewWindow* aVW = dynamic_cast( getApp()->activeViewManager()->getActiveView() ); + if ( aVW ) aVW->setCaption( QString(aSchema->getName()) ); + } + + _PTR(SObject) aSObj = aDataObj->object(); + if ( aSObj ) + { + _PTR(Study) aStudy = (( SalomeApp_Study* )(getApp()->activeStudy()))->studyDS(); + _PTR(ChildIterator) anIterator ( aStudy->NewChildIterator(aSObj) ); + for (; anIterator->More(); anIterator->Next()) + { // iterates on all run sub-objects of the given schema + Proc* aCorrSchema = getDataModel()->getProc( anIterator->Value() ); + + // b.) update caption for corresponding 2D views in run mode + WindowsMap::iterator anItWM = myWindowsMap.find( aCorrSchema ); + if (anItWM != myWindowsMap.end()) + if (QxGraph_ViewWindow* aVW = (*anItWM).second) + aVW->setCaption( QString(aCorrSchema->getName()) ); + + // b.) update all corresponding run tree views if any + int aVMId = viewManagerId( aCorrSchema ); + if (YACSGui_RunTreeView* aRTV = dynamic_cast( treeView( (( SalomeApp_Study* )(getApp()->activeStudy()))->id(), + aVMId ) ) ) + aRTV->update(); + } + } + + // 2) update presentation according to new view mode + if ( activeGraph()->getProc() == aSchema ) + { + // ... + } + } + } + break; + case YACSGui_InputPanel::InlineNodeId: + break; + case YACSGui_InputPanel::LinkId: + break; + default: + break; + } + } } -YACSGui_RunMode* YACSGui_Module::getRunMode(YACSGui_Executor* executor) +//! Creates and displays presentation of a calculation graph. +/*! + * \param theGraph - graph to be displayed + * \param thePrsData - map of node coordinates and dimensions + */ +YACSGui_Graph* YACSGui_Module::displayGraph( YACS::HMI::GuiContext* theCGraph, + const YACSGui_Loader::PrsDataMap& thePrsData, + const YACSGui_Loader::PortLinkDataMap& thePortLinkData, + const YACSGui_Loader::LabelLinkDataMap& theLabelLinkData, + const int& theLeft, const int& theTop, + const double& theXscale, const double& theYscale) { - RunModeMap::iterator anIterator = _runModeMap.find(executor); - YACSGui_RunMode* aRunMode = 0; - if (anIterator != _runModeMap.end()) - aRunMode = _runModeMap[executor]; - //SCRUTE(aRunMode); - return aRunMode; + DEBTRACE("YACSGui_Module::displayGraph: " << theLeft << " " << theTop << " " << theXscale << " " << theYscale); + YACSGui_Graph* aGraph = 0; + + if ( !theCGraph ) return aGraph; + + QxGraph_Canvas* aCanvas = getCanvas(); + if ( !aCanvas ) + return aGraph; + + aGraph = new YACSGui_Graph( this, aCanvas, theCGraph ); + aGraph->show(); + + // Update node geometry + // TODO: not optimal, graph is redrawn twice - + // before and after node geometry is applied - to be improved... + bool needToUpdate = false; + if ( thePrsData.size() ) + { + for ( YACSGui_Loader::PrsDataMap::const_iterator it = thePrsData.begin(); it != thePrsData.end(); it++ ) + { + YACSPrs_ElementaryNode* anItem = aGraph->getItem( (*it).first ); + YACSGui_Loader::PrsData aData = (*it).second; + + if ( !anItem ) + continue; + + YACSPrs_BlocNode* aBloc = dynamic_cast(anItem); + if ( aBloc ) + { + aBloc->resize( (int)aData.width, (int)aData.height ); + } + + anItem->setIsCheckAreaNeeded(false); + anItem->move( aData.x, aData.y ); + anItem->setIsCheckAreaNeeded(true); + anItem->setZ( aData.z ); + } + needToUpdate = true; + } + + // Update port links presentations + if ( thePortLinkData.size() ) + { + for ( YACSGui_Loader::PortLinkDataMap::const_iterator it = thePortLinkData.begin(); it != thePortLinkData.end(); it++ ) + { + // (*it).first.first is an output port engine + // (*it).first.second is an input port engine + YACSPrs_ElementaryNode* aFromNodePrs = aGraph->getItem( (*it).first.first->getNode() ); + if ( !aFromNodePrs ) continue; + + list aLinksPrs = aFromNodePrs->getPortPrs( (*it).first.first )->getLinks(); + for ( list::iterator itL = aLinksPrs.begin(); itL != aLinksPrs.end(); itL++ ) + { + if ( YACSPrs_PortLink* aPortLink = dynamic_cast( *itL ) ) + { + if ( aPortLink->getInputPort()->getEngine() == (*it).first.second ) + { + aPortLink->setPoints((*it).second); + aPortLink->merge(); + } + } + } + } + needToUpdate = true; + } + + // Update label links presentations + if ( theLabelLinkData.size() ) + { + for ( YACSGui_Loader::LabelLinkDataMap::const_iterator it = theLabelLinkData.begin(); it != theLabelLinkData.end(); it++ ) + { + YACSPrs_ElementaryNode* aSlaveNodePrs = aGraph->getItem( (*it).first ); + if ( !aSlaveNodePrs ) continue; + + if ( YACSPrs_LabelLink* aLinkPrs = aSlaveNodePrs->getLabelLink() ) + { + aLinkPrs->setPoints((*it).second); + aLinkPrs->merge(); + } + } + needToUpdate = true; + } + + QxGraph_CanvasView* aCV = getViewWindow(theCGraph->getProc())->getViewModel()->getCurrentView(); + if ( aCV ) + { + if ( theXscale < 0 || theYscale < 0 ) + { + int w = 0, h = 0; + int l = 99999999, t = 99999999; + QCanvasItemList litem = aCanvas->allItems(); + for (QCanvasItemList::Iterator it = litem.begin(); it != litem.end(); ++it) { + QRect r = (*it)->boundingRect(); + if (w < r.right()) w = r.right(); + if (h < r.bottom()) h = r.bottom(); + if (l > r.left()) l = r.left(); + if (t > r.top()) t = r.top(); + } + double s = 1000./((double)w); + double s1 = 700./((double)h); + if(s1 < s)s=s1; + if(s < 1.) + { + aCV->setContentsPos(0,0); + QWMatrix m; + m.scale(s, s); + aCV->setWorldMatrix(m); + needToUpdate = true; + } + } + else + { + if ( theLeft != 0 || theTop != 0 ) + { + aCV->setContentsPos(theLeft,theTop); + needToUpdate = true; + } + if ( theXscale != 1 || theYscale != 1 ) + { + QWMatrix aWM = aCV->worldMatrix(); + aWM.scale(theXscale,theYscale); + aCV->setWorldMatrix(aWM); + needToUpdate = true; + } + } + } + if ( needToUpdate ) aCanvas->update(); +} + +//! Returns the presentation of a given calculation graph. +/*! + */ +YACSGui_Graph* YACSGui_Module::getGraph( YACS::ENGINE::Proc* theProc ) +{ + DEBTRACE("YACSGui_Module::getGraph"); + YACSGui_Graph* aGraph = 0; + + // find a graph in all viewers: + // get active study id + if ( !getApp()->activeStudy() ) + return aGraph; + int aStudyId = getApp()->activeStudy()->id(); + + WindowsMap::iterator anIterator = myWindowsMap.find(theProc); + if (anIterator != myWindowsMap.end()) + if ( QxGraph_ViewWindow* aVW = (*anIterator).second ) + if ( QxGraph_Viewer* aV = aVW->getViewModel() ) + aGraph = dynamic_cast( aV->getCanvas()->getPrs() ); + + /*ViewManagerList aVMs; + getApp()->viewManagers( aVMs ); + + for ( QPtrListIterator it( aVMs ); it.current(); ++it ) + { + if ( it.current()->study()->id() == aStudyId ) + if ( QxGraph_Viewer* aV = dynamic_cast( it.current()->getViewModel() ) ) + if ( aGraph = dynamic_cast( aV->getCanvas()->getPrs() ) ) + if ( aGraph->getProc() == theProc ) + break; + }*/ + + return aGraph; +} + +//! Returns the presentation of a the calculation graph corresponding to the active view. +/*! + */ +YACSGui_Graph* YACSGui_Module::activeGraph() +{ + DEBTRACE("YACSGui_Module::activeGraph"); + YACSGui_Graph* aGraph = 0; + + getApp()->activateModule("YACS"); + // get active view manager + SUIT_ViewManager* anActVM = getApp()->activeViewManager(); + + // check its type + if ( anActVM && anActVM->getType() == QxGraph_Viewer::Type() ) + { + if ( QxGraph_ViewManager* aVM = dynamic_cast( anActVM ) ) + { + if ( QxGraph_Viewer* aViewer = dynamic_cast( aVM->getViewModel() ) ) + { + if ( QxGraph_Canvas* aCanvas = aViewer->getCanvas() ) + aGraph = dynamic_cast( aCanvas->getPrs() ); + } + } + } + + /*QxGraph_Canvas* aCanvas = getCanvas(); + if ( aCanvas ) + // Assume that there's the one and only prs per a canvas + aGraph = dynamic_cast( aCanvas->getPrs() );*/ + + return aGraph; +} + +//! Returns the graph view window for the given proc +/*! + */ +QxGraph_ViewWindow* YACSGui_Module::getViewWindow( YACS::ENGINE::Proc* theProc ) +{ + DEBTRACE("YACSGui_Module::getViewWindow"); + QxGraph_ViewWindow* aVW = 0; + + if ( !theProc ) return aVW; + + WindowsMap::iterator anIterator = myWindowsMap.find(theProc); + if (anIterator != myWindowsMap.end()) aVW = (*anIterator).second; + + return aVW; +} + +//! Returns the graph viewer instance +/*! + */ +QxGraph_Viewer* YACSGui_Module::getViewer() +{ + DEBTRACE("YACSGui_Module::getViewer"); + QxGraph_Viewer* aViewer = 0; + QxGraph_ViewManager* aVM = + dynamic_cast( getApp()->getViewManager( QxGraph_Viewer::Type(), true ) ); + if ( aVM ) + aViewer = dynamic_cast( aVM->getViewModel() ); + return aViewer; +} + +//! Returns the canvas for graph drawing +/*! + */ +QxGraph_Canvas* YACSGui_Module::getCanvas() +{ + DEBTRACE("YACSGui_Module::getCanvas"); + QxGraph_Canvas* aCanvas = 0; + QxGraph_Viewer* aViewer = getViewer(); + if ( aViewer ) + aCanvas = aViewer->getCanvas(); + return aCanvas; +} +/*! + \brief Update viewer. Invalidate whole canvas rect and update it. +*/ +void YACSGui_Module::updateViewer() +{ + DEBTRACE("YACSGui_Module::updateViewer"); + QxGraph_Canvas* aCanvas = getCanvas(); + if ( aCanvas ) + { + aCanvas->setChanged( QRect( 0, 0, aCanvas->width(), aCanvas->height() ) ); + aCanvas->update(); + } +} + +void YACSGui_Module::createElementaryNodePrs() +{ + DEBTRACE("YACSGui_Module::createElementaryNodePrs --- NOT YET IMPLEMENTED!"); + /* if ( myGraph ) + { + YACS::ENGINE::Node* aNode = 0; // temporary solution for test + YACSPrs_ElementaryNode* anElemNode = + new YACSPrs_ElementaryNode(SUIT_Session::session()->resourceMgr(), myGraph->getCanvas(), aNode); + myGraph->getCanvas()->getPrs()->addItem(anElemNode); // add item for the current display mode + anElemNode->show(); + myGraph->getCanvas()->update(); + }*/ +} + +//! Create SComponent for the YACS module. +/*! + */ +void YACSGui_Module::createSComponent() +{ + DEBTRACE("YACSGui_Module::createSComponent"); + _PTR(Study) aStudy = (( SalomeApp_Study* )(getApp()->activeStudy()))->studyDS(); + _PTR(StudyBuilder) aBuilder ( aStudy->NewBuilder() ); + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + + // Find or create "YACS" SComponent in the study + _PTR(SComponent) aComponent = aStudy->FindComponent("YACS"); + if ( !aComponent ) { + aComponent = aBuilder->NewComponent("YACS"); + anAttr = aBuilder->FindOrCreateAttribute(aComponent, "AttributeName"); + aName = _PTR(AttributeName) ( anAttr ); + aName->SetValue( getApp()->moduleTitle( "YACS" ).latin1() ); + + anAttr = aBuilder->FindOrCreateAttribute(aComponent, "AttributePixMap"); + _PTR(AttributePixMap) aPixmap ( anAttr ); + aPixmap->SetPixMap( "YACS_MODULE_ICON" ); + + aBuilder->DefineComponentInstance( aComponent, engineIOR() ); + } +} + +//! Load services from Module Catalog +/*! + */ +void YACSGui_Module::loadCatalog() +{ + DEBTRACE("YACSGui_Module::loadCatalog"); + RuntimeSALOME* aRuntimeSALOME = YACS::ENGINE::getSALOMERuntime(); + + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + SALOME_NamingService* namingService = anApp->namingService(); + CORBA::Object_ptr obj = namingService->Resolve("/Kernel/ModulCatalog"); + SALOME_ModuleCatalog::ModuleCatalog_var aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj); + if (CORBA::is_nil(aModuleCatalog)) { + DEBTRACE("ModuleCatalog is NULL"); + return; + } + + CORBA::ORB_ptr orb = aRuntimeSALOME->getOrb(); + string anIOR = orb->object_to_string( aModuleCatalog ); + DEBTRACE("ModuleCatalog - " << anIOR.c_str()); + + myCatalog = aRuntimeSALOME->loadCatalog( "session", anIOR ); + //add the session catalog to runtime so it can use it when parsing xml files + aRuntimeSALOME->addCatalog(myCatalog); + + std::string errors=myCatalog->getErrors(); + if(errors != "") + { + getApp()->logWindow()->putMessage("The session catalog has errors : some nodes will be unavailable\n"+errors); + + LogViewer* log=new LogViewer("The session catalog has errors : some nodes will be unavailable\n"+errors,getApp()->desktop(),"dialog",WDestructiveClose); + log->show(); + } + + YACS::YACSLoader* _loader = new YACS::YACSLoader(); + _loader->registerProcCataLoader(); + +// SALOME_ModuleCatalog::ListOfComponents_var aComponentList = aModuleCatalog->GetComponentList(); +// long aNbComp = aComponentList->length(); +// printf("Number of components - %d\n", aNbComp); +// for( int i = 0; i < aNbComp; i++ ) +// { +// SALOME_ModuleCatalog::Acomponent_ptr aComponent = aModuleCatalog->GetComponent( (char*)aComponentList[i] ); +// printf("Component N%d - %s ", i, (char*)aComponent->componentusername() ); + +// SALOME_ModuleCatalog::ListOfInterfaces* anInterfaceList = aComponent->GetInterfaceList(); +// long aNbInterf = anInterfaceList->length(); +// printf("(%d)\n", aNbInterf); +// for ( int j = 0; j < aNbInterf; j++ ) +// { +// SALOME_ModuleCatalog::DefinitionInterface* anInterface = aComponent->GetInterface( (char*)(*anInterfaceList)[j] ); +// printf(" Interface N%d - %s ", j, (char*)anInterface->interfacename ); + +// long aNbServices = anInterface->interfaceservicelist.length(); +// printf("(%d)\n", aNbServices); +// for ( int k = 0; k < aNbServices; k++ ) +// { +// SALOME_ModuleCatalog::Service* Service = &(anInterface->interfaceservicelist[k]); +// printf(" Service N%d - %s\n", k, (char*)Service->ServiceName ); +// } +// } +// } +} + +//! Create new instance of data model and return it. +/*! + */ +CAM_DataModel* YACSGui_Module::createDataModel() +{ + DEBTRACE("YACSGui_Module::createDataModel"); + return new YACSGui_DataModel( this ); +} + +//! Retuns data model. +/*! + */ +YACSGui_DataModel* YACSGui_Module::getDataModel() const +{ + DEBTRACE("YACSGui_Module::getDataModel"); + YACSGui_DataModel* aModel = dynamic_cast( dataModel() ); + return aModel; +} + +void YACSGui_Module::CreateNewSchema( QString& theName, YACS::ENGINE::Proc* theProc, const bool updateOB ) +{ + YACSGui_DataModel* aModel = getDataModel(); + if (aModel) + { + aModel->createNewSchema( theName, theProc ); + if ( updateOB ) + updateObjBrowser(); + } +} + +//! Load dataflow from file. +/*! + * \param setEditable - define if the dataflow will be editable. + */ +YACS::HMI::GuiContext* YACSGui_Module::ImportProcFromFile( const QString& theFilePath, + const YACSGui_Module::GuiMode theMode, + const bool setEditable, + bool fromSuperv ) +{ + DEBTRACE("YACSGui_Module::ImportProcFromFile " << theFilePath.latin1()); + if (theFilePath.isEmpty()) + return 0; + QString tmpFileName = theFilePath; + DEBTRACE(fromSuperv); + if (fromSuperv) + { + //YACS_ORB::YACS_Gen_ptr engineRef = InitYACSGuiGen(getApp()); + try + { + char file[]="/tmp/XXXXXX"; + mkstemp(file); + tmpFileName=file; + + std::string outfile(SALOMEDS_Tool::GetTmpDir() + "salomeloader_output"); + std::string call="salomeloader.sh " +theFilePath+ " " + file + " > " + outfile; + DEBTRACE(call); + int ret=system(call.c_str()); + if(ret != 0) + { + // read file with logs + std::fstream f(outfile.c_str()); + std::stringstream hfile; + hfile << f.rdbuf(); + f.close(); + + //Problem in execution + int status=WEXITSTATUS(ret); + if(status == 1) + { + getApp()->logWindow()->putMessage( QString("Problems in conversion: some errors but an incomplete proc has nevertheless been created") + + QString("\n\n"+ hfile.str()) ); + } + else if(status == 2) + { + getApp()->logWindow()->putMessage( QString("Problems in conversion: a fatal error has been encountered. The proc can't be created") + + QString("\n\n"+ hfile.str()) ); + return 0; + } + else + { + DEBTRACE("Unknown problem: " << ret ); + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("Unexpected exception in salomeloader"), + tr("BUT_OK")); + return 0; + } + } + //tmpFileName = engineRef->convertSupervFile(theFilePath); + } + catch(...) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("Unexpected exception in convertSupervFile"), + tr("BUT_OK")); + return 0; + } + } + + //TD: Here check if the study already contains a graph imported from the same file + + YACSGui_Loader aLoader; + GuiContext* aCProc = 0; + + try + { + Proc* aProc = 0; + DEBTRACE(tmpFileName); + if (!tmpFileName.isEmpty()) + aProc = aLoader.load(tmpFileName); + + //TD: Check the result of file loading + if (!aProc) + { + SUIT_MessageBox::error1(getApp()->desktop(), + tr("ERROR"), + tr("MSG_IMPORT_FILE_ERROR"), + tr("BUT_OK")); + return 0; + } + + //Print errors logged if any + Logger* logger=aProc->getLogger("parser"); + getApp()->logWindow()->putMessage("Load schema: "+theFilePath); + if(!logger->isEmpty()) + { + getApp()->logWindow()->putMessage("Problems when loading: the proc is probably not completely built\n\n"+logger->getStr()); + + //LogViewer* log=new LogViewer(txt,getApp()->desktop(),"dialog",WDestructiveClose); + //log->show(); + } + + QString name = QFileInfo(theFilePath).baseName (); + aProc->setName( name ); + + QxGraph_ViewWindow* aVW = createNewViewManager( theMode, aProc ); + createInputPanel(); + + if ( aVW ) + { + int w, h, l=0, t=0; + double xscale=1., yscale=1.; + const YACSGui_Loader::PrsDataMap& aPrsData = aLoader.getPrsData( aProc, w, h, l, t, xscale, yscale ); + DEBTRACE("PrsData: " <setProc( aProc ); + aCProc->setXMLSchema( tmpFileName.latin1() ); + // from now we have to use GuiContext* instead of Proc* in the YACSGui_Graph + + displayGraph( aCProc, aPrsData, aPortLinkData, aLabelLinkData, l, t, xscale, yscale ); + } + } + catch (YACS::Exception& ex) + { + DEBTRACE("YACSGui_Module::importSchema: " <getProc(); + ExecutorMap::iterator anIterator = myExecutors.find(aProc); + if (anIterator != myExecutors.end()) + anExecutor = (*anIterator).second; + } + return anExecutor; +} + +//! Returns or create executor for a given graph. +/*! + * If the CORBA engine associated to the graph does not exists, it is instanciated. + */ +YACSGui_Executor* YACSGui_Module::getExecutor( YACS::ENGINE::Proc* theProc ) +{ + DEBTRACE("YACSGui_Module::getExecutor"); + YACSGui_Executor* anExecutor = 0; + + ExecutorMap::iterator anIterator = myExecutors.find(theProc); + if (anIterator != myExecutors.end()) + anExecutor = (*anIterator).second; + + if (!anExecutor) + { + Engines::MachineParameters params; + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( anApp ) + { + anApp->lcc()->preSet(params); + } + if (GuiContext *context = GuiContext::getCurrent()) + { + params.container_name = context->getYACSCont().first.c_str(); + params.hostname = context->getYACSCont().second.c_str(); + } + + Engines::Component_var comp = getApp()->lcc()->LoadComponent( params, "YACS" ); + YACS_ORB::YACS_Gen_ptr clr = YACS_ORB::YACS_Gen::_narrow(comp); + ASSERT(!CORBA::is_nil(clr)); + + anExecutor = new YACSGui_Executor(this, theProc); + anExecutor->setGraph(activeGraph()); + anExecutor->setEngineRef(clr); + + myExecutors[theProc] = anExecutor; + } + + return anExecutor; +} + +//! Returns executor for active graph or nul if no active graph +/*! + * If there is an active graph, the corresponding executor is returned or created, + * and the corresponding CORBA engine is instanciated (see YACSGui_Module::getExecutor). + */ +YACSGui_Executor* YACSGui_Module::findExecutor() +{ + DEBTRACE("YACSGui_Module::findExecutor"); + YACSGui_Graph* aGraph = activeGraph(); + YACSGui_Executor* anExecutor = 0; + Proc* aProc = 0; + if (aGraph) + aProc = aGraph->getProc(); + //DEBTRACE(aGraph); + //DEBTRACE(aProc); + if (!aGraph || !aProc) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_NO_DATAFLOW_LOADED"), + tr("BUT_OK")); + return 0; + } + + anExecutor = getExecutor(aProc); + return anExecutor; +} + +YACSGui_RunMode* YACSGui_Module::getRunMode(YACSGui_Executor* executor) +{ + RunModeMap::iterator anIterator = _runModeMap.find(executor); + YACSGui_RunMode* aRunMode = 0; + if (anIterator != _runModeMap.end()) + aRunMode = _runModeMap[executor]; + //DEBTRACE(aRunMode); + return aRunMode; +} + +//! Fill the Input Panel with the property pages according to the Object Browser selection +/*! + */ +void YACSGui_Module::selectionChanged() +{ + DEBTRACE("YACSGui_Module::selectionChanged"); + DataObjectList objlist; + getApp()->objectBrowser()->getSelected( objlist ); + + // check if the current selection is a single selection + // Template 1: it may be used in the future + /*if ( objlist.count() == 1 ) + { + } + else if (...) + { + }*/ + + // Template 2: it may be used in the future + /*for ( DataObjectListIterator it( objlist ); it.current(); ++it ) + { + LightApp_DataObject* obj = dynamic_cast( it.current() ); + if ( obj && getApp()->checkDataObject(obj) ) + { + QString anEntry = obj->entry(); + printf("==> anEntry = %s\n",anEntry.latin1()); + } + }*/ +} + +LightApp_Selection* YACSGui_Module::createSelection() const +{ + DEBTRACE("YACSGui_Module::createSelection"); + return new YACSGui_Selection(); +} + +/*! Get selection from SALOME object browser. Get a schema name and a schema file name from selection. + * If the schema as already been executed and saved under a fixed name: /tmp/YACS/"aSchemaName"-modified, + * use this schema file name. + * + * Create a file run name based on current date and time. + * If the schema file name coresponds to an existing file, copy the schema file under the run name. + * Else save the proc under the run name. + * + * Import the run name file and create a specific GuiContext. + * + */ +void YACSGui_Module::onCreateExecution() +{ + DEBTRACE("YACSGui_Module::onCreateExecution"); + DataObjectList objlist; + getApp()->objectBrowser()->getSelected( objlist ); + + // check if the current selection is a single selection + if ( objlist.count() == 1 ) + { + SalomeApp_DataObject* obj = dynamic_cast( objlist.getFirst() ); + if ( obj && getDataModel()->objectType( obj->entry() ) == YACSGui_DataModel::SchemaObject ) + { + _PTR(SObject) sobj = obj->object(); + Proc* aProc = getDataModel()->getProc(sobj); + if (!aProc) + return; + + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + _PTR(AttributeParameter) aType; + if ( sobj->FindAttribute( anAttr, "AttributeParameter" ) ) + { + aType = _PTR(AttributeParameter) ( anAttr ); + QFile aSchemaFile( aType->GetString("FilePath") ); + DEBTRACE(aSchemaFile.name().latin1()); + + if ( !sobj->FindAttribute( anAttr, "AttributeName" ) ) + return; + + + YACSGui_SchemaPage* aSPage + = dynamic_cast(myInputPanel->getPage(YACSGui_InputPanel::SchemaId)); + if (!aSPage) + return; + + // --- check first the validity of the proc + + // Check validity + if(!aProc->isValid()) + { + + std::string msg="The YACS schema is not valid : can not create a new execution\n\n"; + msg=msg+aProc->getErrorReport(); + getApp()->logWindow()->putMessage(msg); + LogViewer* log=new LogViewer(msg,getApp()->desktop(),"dialog",WDestructiveClose); + log->show(); + return; + } + + // Check consistency + LinkInfo info(LinkInfo::ALL_DONT_STOP); + aProc->checkConsistency(info); + if(info.areWarningsOrErrors()) + { + std::string msg="The YACS schema is not consistent : can not create a new execution\n\n"; + msg=msg+info.getGlobalRepr(); + getApp()->logWindow()->putMessage(msg); + LogViewer* log=new LogViewer(msg,getApp()->desktop(),"dialog",WDestructiveClose); + log->show(); + return; + } + + aName = _PTR(AttributeName)( anAttr ); + QString aSchemaName = aName->Value(); + DEBTRACE(aSchemaName.latin1()); + + QString tmpDir = SALOMEDS_Tool::GetTmpDir(); + QDir aTmpDir( tmpDir ); + aTmpDir.mkdir( "YACSGui" ); + aTmpDir.cd( "YACSGui", false ); + + QDateTime curTime = QDateTime::currentDateTime(); + QString aRunName = aSchemaName + "_" + curTime.toString( "yyyyMMdd_hhmmss" ); + aRunName = aTmpDir.absFilePath(aRunName); + DEBTRACE(aRunName.latin1()); + + DEBTRACE("save proc under aRunName"); + + YACSGui_VisitorSaveSchema aWriter( this, aProc ); + aWriter.openFileSchema( aRunName ); + aWriter.visitProc( aProc ); + aWriter.closeFileSchema(); + + if ( GuiContext* aCProc = ImportProcFromFile( aRunName, RunMode, false) ) + if ( Proc* aProc = aCProc->getProc() ) + { + getDataModel()->createNewRun( sobj, aRunName, aProc ); + updateObjBrowser(); + + // create and activate the run tree view for the create run object + createTreeView( aCProc->getSubjectProc(), YACSGui_DataModel::RunObject ); + + //onWithoutStopMode(); + } + } // AttributeParameter + } //obj entry + } //objlist +} + +//! Private slot. Create new execution in batch mode. +/*! + */ +void YACSGui_Module::onCreateBatchExecution() +{ + DEBTRACE("YACSGui_Module::onCreateBatchExecution() --- NOT YET IMPLEMENTED!"); +} + +void YACSGui_Module::onReloadExecution() +{ + DEBTRACE("YACSGui_Module::onReloadExecution()"); + + // switch to run mode + setGuiMode(YACSGui_Module::RunMode); + + // get file with schema state + QString aFileName = SUIT_FileDlg::getFileName( application()->desktop(), "", "*.xml", tr("TLT_LOAD_SCHEMA_STATE"), true ); + if (aFileName.isEmpty()) + return; + + // create execution in an order way + onCreateExecution(); + + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + { + // set the load state file name to the executor of the new created (in run mode) schema copy + anExecutor->setLoadStateFile(aFileName.latin1()); + cout<<">> anExecutor = "<getProc() ) + { + // update nodes states inside the schema (2D view) + string aProcName = aProc->getName(); // workaround to correctly reading XML with saved states in the GUI side + aProc->setName("proc"); + aProc->init(); + aProc->exUpdateState(); + stateLoader* aStateLoader = new stateLoader(new stateParser(),aProc); + aStateLoader->parse(aFileName.latin1()); + aProc->setName(aProcName); + + // update nodes states inside the schema (tree view) + if ( YACSGui_RunTreeView* aRunTV = dynamic_cast(activeTreeView()) ) + { + aRunTV->onNotifyStatus(aProc->getState()); + list aNodeSet = aProc->getAllRecursiveConstituents(); + for ( list::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + { + aRunTV->onNotifyNodeStatus((*it)->getNumId(), (*it)->getState()); + } + } + } +} + +/*! Private slot. Start execution. + */ +void YACSGui_Module::onStartResume() +{ + DEBTRACE("YACSGui_Module::onStartResume()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + if ( anExecutor->checkEndOfDataFlow(false) ) // finished or not started + { + anExecutor->runDataflow(true); // remote run only + } + else // in progress (suspended or running) + { + anExecutor->resumeDataflow(); + } +} + +/*! Private slot. Start execution. +/*! + */ +void YACSGui_Module::onExecute() +{ + DEBTRACE("YACSGui_Module::onExecute()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + if ( anExecutor->checkEndOfDataFlow(false) ) // finished or not started + { + if ( anExecutor->getCurrentExecMode() == YACS_ORB::STEPBYSTEP ) + anExecutor->setContinueMode(); + anExecutor->runDataflow(true); // remote run only + } + else // in progress (suspended or running) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_DATAFLOW_IS_CURRENTLY_RUNNING_ABORT"), + tr("BUT_OK")); + return; + } +} + +void YACSGui_Module::onExecuteStBy() +{ + DEBTRACE("YACSGui_Module::onExecuteStBy()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + if ( anExecutor->checkEndOfDataFlow(false) ) // finished or not started + { + anExecutor->setStepByStepMode(); + anExecutor->runDataflow(true); // remote run only + } + else // in progress (suspended or running) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_DATAFLOW_IS_CURRENTLY_RUNNING_ABORT"), + tr("BUT_OK")); + return; + } +} + +void YACSGui_Module::onExecuteInBatch() +{ + DEBTRACE("YACSGui_Module::onExecuteInBatch() --- NOT YET IMPLEMENTED!"); +} + +void YACSGui_Module::onPause() +{ + DEBTRACE("YACSGui_Module::onPause()"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + if ( !anExecutor->checkEndOfDataFlow(false) ) // in progress (suspended or running) + anExecutor->suspendDataflow(); +} + +void YACSGui_Module::onResume() +{ + DEBTRACE("YACSGui_Module::onResume()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + if ( !anExecutor->checkEndOfDataFlow(false) ) // in progress (suspended or running) + anExecutor->resumeDataflow(); +} + +/*void YACSGui_Module::onSuspendResume() +{ + DEBTRACE("YACSGui_Module::onSuspendResume()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + if ( !anExecutor->checkEndOfDataFlow(false) ) // in progress (suspended or running) + anExecutor->suspendResumeDataflow(); +}*/ + +void YACSGui_Module::onAbort() +{ + DEBTRACE("YACSGui_Module::onAbort()"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + { + if (!anExecutor->isRunning()) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_DATAFLOW_IS_NOT_RUNNING"), + tr("BUT_OK")); + return; + } + anExecutor->killDataflow(); + } +} + +void YACSGui_Module::onReset() +{ + DEBTRACE("YACSGui_Module::onReset()"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + if ( anExecutor->checkEndOfDataFlow(false) ) // finished or not started + { + YACS::ExecutorState aSchemaState = YACS::NOTYETINITIALIZED; + YACS::StatesForNode aNodeState = YACS::READY; + + YACSGui_RunTreeView* aRunTV = dynamic_cast(activeTreeView()); + if ( !aRunTV ) return; + + if ( !myInputPanel ) return; + + // notify schema view item in the tree view + aRunTV->onNotifyStatus(aSchemaState); + + list aChildren = anExecutor->getProc()->getAllRecursiveConstituents(); + list::iterator it = aChildren.begin(); + for ( ; it != aChildren.end(); it++ ) + { + (*it)->setState( aNodeState ); + + // notify node presentation in 2D view + YACSGui_Graph* aGraph = anExecutor->getGraph(); + if ( aGraph ) + { + if ( YACSPrs_ElementaryNode* aNodePrs = aGraph->getItem( *it ) ) + aNodePrs->update(); + else + { + if ( dynamic_cast( (*it)->getFather() ) ) + { + if ( YACSPrs_ElementaryNode* aFELNodePrs = aGraph->getItem( (*it)->getFather() ) ) + { + // transmit event to ForEachLoop node + aFELNodePrs->update(); + + // transmit event from the last clone node to original loop body node + if ( (*it) == (dynamic_cast( (*it)->getFather() ))->getNodes().back() ) + { + list aFELChildren = dynamic_cast( (*it)->getFather() )->edGetDirectDescendants(); + for( list::iterator iter = aFELChildren.begin(); iter != aFELChildren.end(); iter++ ) + if ( YACSPrs_ElementaryNode* aFELBodyNodePrs = aGraph->getItem(*iter) ) + aFELBodyNodePrs->updateForEachLoopBody(*it); + } + } + } + } + } + + // notify node view item in the tree view + aRunTV->onNotifyNodeStatus( (*it)->getNumId(), aNodeState ); + + // notify node property page + myInputPanel->onNotifyNodeStatus( (*it)->getNumId(), aNodeState ); + } + } + else // in progress (suspended or running) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_DATAFLOW_IS_CURRENTLY_RUNNING"), + tr("BUT_OK")); + return; + } +} + +void YACSGui_Module::onWithoutStopMode() +{ + DEBTRACE("YACSGui_Module::onWithoutStopMode()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) anExecutor->setContinueMode(); +} + +void YACSGui_Module::onBreakpointsMode() +{ + DEBTRACE("YACSGui_Module::onBreakpointsMode()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) anExecutor->setBreakpointMode(); +} + +void YACSGui_Module::onStepByStepMode() +{ + DEBTRACE("YACSGui_Module::onStepByStepMode()"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) anExecutor->setStepByStepMode(); +} + +void YACSGui_Module::onSaveExecutionState() +{ + DEBTRACE("YACSGui_Module:: onSaveExecutionState()"); + YACSGui_Executor* anExecutor = lookForExecutor(); + if (anExecutor) + { + if ( anExecutor->getExecutorState() == YACS::NOTYETINITIALIZED + || + anExecutor->getExecutorState() == YACS::PAUSED + || + anExecutor->getExecutorState() == YACS::STOPPED + || + anExecutor->getExecutorState() == YACS::FINISHED ) + { + + if ( !activeGraph() ) return; + Proc* aProc = activeGraph()->getProc(); + if ( !aProc ) return; + + QString aDef = aProc->getName(); + aDef = aDef.left( aDef.findRev(".xml") ) + "_state.xml"; + QString aFileName = SUIT_FileDlg::getFileName( application()->desktop(), aDef, "*.xml", tr("TLT_SAVE_SCHEMA_STATE"), false ); + if (aFileName.isEmpty()) + return; + + anExecutor->saveState(aFileName.latin1()); + } + else // in progress (suspended or running) + { + SUIT_MessageBox::warn1(getApp()->desktop(), + tr("WARNING"), + tr("MSG_DATAFLOW_IS_CURRENTLY_RUNNING"), + tr("BUT_OK")); + return; + } + } +} + +void YACSGui_Module::onCreateEdition() +{ + DEBTRACE("YACSGui_Module::onCreateEdition"); + // get a FilePath from the selected run object in the object browser + DataObjectList objlist; + getApp()->objectBrowser()->getSelected( objlist ); + + // check if the current selection is a single selection + if ( objlist.count() == 1 ) + { + SalomeApp_DataObject* obj = dynamic_cast( objlist.getFirst() ); + if ( obj && getDataModel()->objectType( obj->entry() ) == YACSGui_DataModel::RunObject ) + { + _PTR(SObject) sobj = obj->object(); + _PTR(GenericAttribute) anAttr; + _PTR(AttributeName) aName; + _PTR(AttributeParameter) aType; + if ( sobj->FindAttribute( anAttr, "AttributeParameter" ) ) + { + aType = _PTR(AttributeParameter) ( anAttr ); + QString aRunFileName = aType->GetString("FilePath"); + + if ( QFile::exists(aRunFileName) ) + { + QFile aRunFile(aRunFileName); + + // create a new file with name FilePath+"-modified" and copy FilePath content into it + QString tmpDir = SALOMEDS_Tool::GetTmpDir(); + QDir aTmpDir( tmpDir ); + aTmpDir.mkdir( "YACS" ); + aTmpDir.cd( "YACS", false ); + + if ( Proc* aProcRun = getDataModel()->getProc( sobj ) ) + { + QDateTime curTime = QDateTime::currentDateTime(); + QString anEditionName = aProcRun->getName() + "_modified_" + curTime.toString( "yyyyMMdd_hhmmss" ); + anEditionName = aTmpDir.absFilePath(anEditionName); + + if ( aRunFile.open( IO_ReadOnly ) ) + { + QFile anEditionFile( anEditionName ); + if ( anEditionFile.open( IO_WriteOnly ) ) + { + QTextStream aRunTS( &aRunFile ), anEditionTS( &anEditionFile ); + while( !aRunTS.atEnd() ) + anEditionTS << aRunTS.readLine() << "\n"; + anEditionFile.close(); + aRunFile.close(); + } + else + { + printf( "Can't open temp edition file: %s\n", QFileInfo( anEditionFile ).absFilePath().latin1() ); + return; + } + } + else + { + printf( "Can't open run file: %s\n", QFileInfo( aRunFile ).absFilePath().latin1() ); + return; + } + + // import proc from anEditionName file, create SObject, 2D view and tree view for it + if ( GuiContext* aCProc = ImportProcFromFile(anEditionName, EditMode, false) ) + if ( Proc* aProcEdition = aCProc->getProc() ) + { + // create schema object in the Object Browser + CreateNewSchema(anEditionName,aProcEdition); + + // create and activate the edition tree view for the imported schema + createTreeView( aCProc->getSubjectProc(), YACSGui_DataModel::SchemaObject ); + } + } + } + } + } + } +} + +void YACSGui_Module::onConnectToRunning() +{ + DEBTRACE("YACSGui_Module:: onConnectToRunning()--- NOT YET IMPLEMENTED!"); +} + +void YACSGui_Module::onToggleStopOnError() +{ + DEBTRACE("YACSGui_Module::onToggleStopOnError"); + YACSGui_Executor* anExecutor = findExecutor(); + if (anExecutor) + { + if ( !anExecutor->isStopOnError() ) + anExecutor->setStopOnError(true); + else + anExecutor->unsetStopOnError(); + } +} + + +/*! + Adds tree view of a schema into the module internal structure. + \param theTreeView - tree view to be added + \param theStudyId - study id + \param theId - key for window (i.e. the index of the corresponding view manager <=> 2D view presentation) + theId used how identificator of tree view in the list. +*/ +void YACSGui_Module::addTreeView( YACSGui_TreeView* theTreeView, + const int theStudyId, + const int theId ) +{ + if ( !theTreeView ) + return; + + int sId = theStudyId; + if ( theStudyId < 0 ) + { + if ( !getApp()->activeStudy() ) + return; + sId = getApp()->activeStudy()->id(); + } + + if ( myTreeViews.find( sId ) == myTreeViews.end() ) + { // there is no widget container for the given study => insert it + LightApp_WidgetContainer* newWC = new LightApp_WidgetContainer( sId, getApp()->desktop() ); + //connect( newWC, SIGNAL( destroyed ( QObject* ) ), this, SLOT( onWCDestroyed( QObject* ) ) ); + // the widget container is destroyed on study closing + myTreeViews.insert( make_pair( sId, newWC ) ); + getApp()->desktop()->moveDockWindow( myTreeViews[sId], Qt::DockLeft ); + + myTreeViews[sId]->setResizeEnabled( true ); + myTreeViews[sId]->setCloseMode( QDockWindow::Always ); + myTreeViews[sId]->setName( QString( "dock_window_%1_%2" ).arg( sId ).arg( theId ) ); + myTreeViews[sId]->setFixedExtentWidth( theTreeView->width() ); + myTreeViews[sId]->setFixedExtentHeight( theTreeView->height() ); + + getApp()->desktop()->setAppropriate( myTreeViews[sId], false ); + } + + QFont f = theTreeView->font(); + + myTreeViews[sId]->insert( theId, theTreeView ); + theTreeView->setFont(f); +} + +/*! + Returns tree view with the given index in the given study. + \param theStudyId - study id + \param theId - key for window +*/ +YACSGui_TreeView* YACSGui_Module::treeView( const int theStudyId, const int theId ) const +{ + YACSGui_TreeView* aTV = 0; + + TreeViewMap::const_iterator anIt = myTreeViews.find( theStudyId ); + if ( anIt != myTreeViews.end() ) + aTV = dynamic_cast( anIt->second->widget( theId ) ); + + return aTV; +} + + +/*! + Removes tree view with the given index in the given study (if, e.g., a schema was deleted from Object Browser). + \param theStudyId - study id + \param theId - key for window +*/ +void YACSGui_Module::removeTreeView( const int theStudyId, const int theId ) +{ + int sId = theStudyId; + if ( theStudyId < 0 ) + { + if ( !getApp()->activeStudy() ) + return; + sId = getApp()->activeStudy()->id(); + } + + if ( myTreeViews.find( sId ) == myTreeViews.end() ) return; + + QWidget* wid = myTreeViews[sId]->widget( theId ); + if ( YACSGui_TreeView* aTV = dynamic_cast(wid) ) + aTV->clearSelection(); + myTreeViews[sId]->remove( theId ); + delete wid; + + bool anIsEmpty = myTreeViews[sId]->isEmpty(); + QDockWindow* dw = myTreeViews[sId]; + if ( !anIsEmpty ) dw->show(); + else if ( dw->isShown() ) dw->hide(); +} + +/*! + Returns true, if tree view with the given index in the given study is shown, + and false - otherwise. + \param theStudyId - study id + \param theId - key for window +*/ +bool YACSGui_Module::isTreeViewShown( const int theStudyId, const int theId ) +{ + bool aRet = false; + + return aRet; +} + +/*! + Returns active tree view in the active study +*/ +YACSGui_TreeView* YACSGui_Module::activeTreeView() const +{ + DEBTRACE("YACSGui_Module::activeTreeView"); + YACSGui_TreeView* aTV = 0; + + if ( !getApp()->activeStudy() ) + return aTV; + + int aStudyId = getApp()->activeStudy()->id(); + TreeViewMap::const_iterator anIt = myTreeViews.find( aStudyId ); + TreeViewActiveMap::const_iterator anActIt = myActiveTreeViews.find( aStudyId ); + if ( anIt != myTreeViews.end() && anActIt != myActiveTreeViews.end() ) + aTV = dynamic_cast( anIt->second->widget( anActIt->second ) ); + + return aTV; +} + +/*! + Returns active tree view in the given study +*/ +YACSGui_TreeView* YACSGui_Module::activeTreeView( const int theStudyId ) const +{ + DEBTRACE("YACSGui_Module::activeTreeView"); + YACSGui_TreeView* aTV = 0; + + TreeViewMap::const_iterator anIt = myTreeViews.find( theStudyId ); + TreeViewActiveMap::const_iterator anActIt = myActiveTreeViews.find( theStudyId ); + if ( anIt != myTreeViews.end() && anActIt != myActiveTreeViews.end() ) + aTV = dynamic_cast( anIt->second->widget( anActIt->second ) ); + + return aTV; +} + +/*! + Set the given tree view as active +*/ +void YACSGui_Module::activateTreeView( const int theStudyId, const int theId ) +{ + DEBTRACE("YACSGui_Module::activateTreeView: " << theId); + // hide Input Panel of the selected item in the current active tree view + setInputPanelVisibility(false); + + TreeViewMap::const_iterator anIt = myTreeViews.find( theStudyId ); + if ( anIt == myTreeViews.end() ) + return; + + anIt->second->activate( theId ); + anIt->second->show(); + + // change the content of active tree view map + if ( myActiveTreeViews.find(theStudyId) == myActiveTreeViews.end() ) + myActiveTreeViews.insert( make_pair( theStudyId, theId ) ); + else + myActiveTreeViews[theStudyId] = theId; + + // show Input Panel of the selected item in the new active tree view + setInputPanelVisibility(true); +} + +/*! + Show or hide Input Panel of the selected item in the current active tree view +*/ +void YACSGui_Module::setInputPanelVisibility( const bool theOn ) +{ + DEBTRACE("YACSGui_Module::setInputPanelVisibility"); + YACSGui_TreeView* anATV = activeTreeView(); + if ( !anATV ) return; + + // get the list of items selected in the current active edition tree view + list aSelList = anATV->getSelected(); + + // check if the current selection is not empty (if it is true => the Input Panel is currently visible => hide it) + if ( !aSelList.empty() && myInputPanel ) + if ( theOn ) anATV->syncPageTypeWithSelection(); + else myInputPanel->hide(); +} + +/*! + Connects arrange nodes algorithm to the signal emitted when the size (the height in fact) of node presentation is changed +*/ +//void YACSGui_Module::connectArrangeNodes( YACSPrs_ElementaryNode* theItem ) +//{ +// connect( theItem, SIGNAL(portsChanged()), this, SLOT(onArrangeNodes()) ); +//} + +/*! + Sets current selected schema as current +*/ +void YACSGui_Module::onSetActive() +{ + DEBTRACE( "YACSGui_Module::onSetActive() not implemented yet" ); +} + +//! Public. Set gui mode by ObjectType +/*! + */ +void YACSGui_Module::setGuiMode( YACSGui_DataModel::ObjectType theType ) +{ + DEBTRACE("YACSGui_Module::setGuiMode()"); + switch( theType ) + { + case YACSGui_DataModel::SchemaObject: + { + setGuiMode( YACSGui_Module::EditMode ); + break; + } + case YACSGui_DataModel::RunObject: + { + setGuiMode( YACSGui_Module::RunMode ); + break; + } + default: //UnknownObject + setGuiMode( YACSGui_Module::EmptyMode ); + } +} + +//! Public. Set gui mode to theMode +/*! + */ +void YACSGui_Module::setGuiMode(YACSGui_Module::GuiMode theMode) +{ + DEBTRACE("YACSGui_Module::setGuiMode()"); + if (theMode == YACSGui_Module::EmptyMode) + { + setBaseActionShown(false); + setModifyActionShown(false); + setRunActionShown(false); + setVisualizationActionShown(false); + myGuiMode = theMode; + return; + } + DEBTRACE(theMode); + DEBTRACE(getGuiMode()); + + if(theMode == getGuiMode()) + return; + else + { + setBaseActionShown(true); + switch(theMode) + { + case YACSGui_Module::InitMode: + DEBTRACE("YACSGui_Module::setGuiMode"); + setModifyActionShown(false); + setRunActionShown(false); + setVisualizationActionShown(false); + myGuiMode = theMode; + break; + case YACSGui_Module::EditMode: + case YACSGui_Module::NewMode: + DEBTRACE("YACSGui_Module::setGuiMode"); + setModifyActionShown(true); + setRunActionShown(false); + setVisualizationActionShown(true); + myGuiMode = theMode; + break; + case YACSGui_Module::RunMode: + DEBTRACE("YACSGui_Module::setGuiMode"); + setModifyActionShown(false); + setRunActionShown(true); + setVisualizationActionShown(true); + myGuiMode = theMode; + break; + default: + printf("YACSGui_Module::setGuiMode(): incorrect gui mode\n"); + break; + } + } +} + +YACSGui_Module::GuiMode YACSGui_Module::getGuiMode() const +{ + return myGuiMode; +} + +//! Private. Show/Hide modification action in the toolbars and menus +/*! + */ +void YACSGui_Module::setModifyActionShown(const bool on) +{ + //For menus + //Menu "File" + setMenuShown( ExportSchemaId,on ); + + //Menu "Create" + setMenuShown( NewContainerId,on ); + setMenuShown( NewSalomeComponentId,on ); + setMenuShown( NewSalomePythonComponentId,on ); + setMenuShown( NewCorbaComponentId,on ); + setMenuShown( NewSalomeServiceNodeId, on ); + //setMenuShown( NewCorbaServiceNodeId, on ); + setMenuShown( NewCppNodeId, on ); + setMenuShown( NewServiceInlineNodeId,on ); + setMenuShown( NewXmlNodeId,on ); + setMenuShown( NewInDataNodeId,on ); + setMenuShown( NewOutDataNodeId,on ); + setMenuShown( NewInStudyNodeId,on ); + setMenuShown( NewOutStudyNodeId,on ); + setMenuShown( NewInlineScriptNodeId,on ); + setMenuShown( NewInlineFunctionNodeId,on ); + setMenuShown( NewBlockNodeId,on ); + setMenuShown( NewForLoopNodeId,on ); + setMenuShown( NewForeachLoopNodeId,on ); + setMenuShown( NewWhileLoopNodeId,on ); + setMenuShown( NewSwitchLoopNodeId,on ); + setMenuShown( NewFromLibraryNodeId,on ); + + //Menu "Execute" + setMenuShown( NewExecutionId, on ); + setMenuShown( NewBatchExecutionId, on ); + setMenuShown( ReloadExecutionId, on); + + //For toolbars + //"Schema" and "Create" toolbars + action(ExportSchemaId)->setVisible(on); + action(NewContainerId)->setVisible(on); + + if(on == true) { + myToolButtons[NewContainerBtnId]->show(); + myToolButtons[NewNodeBtn]->show(); + } + else { + myToolButtons[NewContainerBtnId]->hide(); + myToolButtons[NewNodeBtn]->hide(); + } + + //"Execute" toolbar + setToolShown( NewExecutionId, on ); + setToolShown( NewBatchExecutionId, on ); + setToolShown( ReloadExecutionId, on); +} + +//! Private. Show/Hide visualization actions in the toolbar +/*! + */ +void YACSGui_Module::setVisualizationActionShown(const bool on) +{ + //"Visualization" toolbar + setToolShown( FullViewId, on ); + setToolShown( ControlViewId, on ); + setToolShown( DataFlowViewId, on ); + setToolShown( DataStreamViewId, on ); + setToolShown( ArrangeNodesId, on ); + setToolShown( RebuildLinksId, on); +} + +//! Private. Show/Hide Base actions(create schema and import dataflow) in the toolbars and menus +/*! + */ +void YACSGui_Module::setBaseActionShown(const bool on) +{ + action(NewSchemaId)->setVisible(on); + action(ImportSchemaId)->setVisible(on); + action(ImportSupervSchemaId)->setVisible(on); + if(on) + myToolButtons[ImportBtnId]->show(); + else + myToolButtons[ImportBtnId]->hide(); +} + +//! Private. Show/Hide run actions in the toolbars and menus +/*! + */ +void YACSGui_Module::setRunActionShown(const bool on) +{ + //For menus + //Menu "Execute" + setMenuShown( StartResumeId, on ); + //setMenuShown( ExecuteId, on ); + //setMenuShown( ExecuteStById, on ); + setMenuShown( PauseId, on ); + //setMenuShown( ResumeId, on ); + setMenuShown( AbortId, on); + setMenuShown( ResetId, on ); + setMenuShown( WithoutStopModeId, on ); + setMenuShown( BreakpointsModeId, on ); + setMenuShown( StepByStepModeId, on ); + setMenuShown( ToggleStopOnErrorId, on ); + //setMenuShown( StopOnErrorId, on ); + setMenuShown( ExecuteInBatchId, on ); + setMenuShown( ConnectToRunningId, on ); + setMenuShown( SaveExecutionStateId, on ); + setMenuShown( NewEditionId, on ); + + + //For toolbars + //"Visualization" toolbar + setToolShown( FullViewId, on ); + setToolShown( ControlViewId, on ); + setToolShown( DataFlowViewId, on ); + setToolShown( DataStreamViewId, on ); + setToolShown( ArrangeNodesId, on ); + setToolShown( RebuildLinksId, on); + + //"Execute" toolbar + setToolShown( StartResumeId, on ); + //setToolShown( ExecuteId, on ); + //setToolShown( ExecuteStById, on ); + setToolShown( PauseId, on ); + setToolShown( AbortId, on); + //setToolShown( ResumeId, on ); + setToolShown( ResetId, on ); + setToolShown( WithoutStopModeId, on ); + setToolShown( BreakpointsModeId, on ); + setToolShown( StepByStepModeId, on ); + setToolShown( ToggleStopOnErrorId, on ); + //setToolShown( StopOnErrorId, on ); + setToolShown( ExecuteInBatchId, on ); + setToolShown( ConnectToRunningId, on ); + setToolShown( SaveExecutionStateId, on ); + setToolShown( NewEditionId, on ); + //setToolShown( SuspendResumeDataflowId, on); +} + +QxGraph_ViewWindow* YACSGui_Module::createNewViewManager( YACSGui_Module::GuiMode theMode, + Proc* theProc, + int width, + int height ) +{ + DEBTRACE("YACSGui_Module::createNewViewManager"); + // switch to theMode + setGuiMode( theMode ); + + // create 2D view of a schema or a run obejct + SUIT_ViewManager* aVM = getApp()->createViewManager( QxGraph_Viewer::Type() ); + connect( aVM, SIGNAL(deleteView(SUIT_ViewWindow*)), + this, SLOT(onWindowClosed(SUIT_ViewWindow*)) ); + + // set caption for graph's view window + QxGraph_ViewWindow* aVW = dynamic_cast( aVM->getActiveView() ); + if ( aVW && theProc) + { + aVW->setCaption( theProc->getName() ); + myWindowsMap.insert( make_pair( theProc, aVW ) ); + } + + if ( aVW && width > 0 && height > 0 ) + aVW->getViewModel()->getCanvas()->resize( width, height ); + + if ( aVW ) + if ( QxGraph_CanvasView* aCV = aVW->getViewModel()->getCurrentView() ) + connect( aCV, SIGNAL(viewOperationDone()), this, SLOT(temporaryExport()) ); + + return aVW; +} + +void YACSGui_Module::activateViewWindow( Proc* theProc ) +{ + DEBTRACE("YACSGui_Module::activateViewWindow: " << theProc); + if ( theProc ) + { + WindowsMap::iterator anIterator = myWindowsMap.find(theProc); + if (anIterator != myWindowsMap.end()) + { + QxGraph_ViewWindow* aVW = (*anIterator).second; + if ( aVW ) + { + myBlockWindowActivateSignal = true; + aVW->setFocus(); + myBlockWindowActivateSignal = false; + + if ( YACSGui_Graph* aGraph = getGraph( theProc ) ) + GuiContext::setCurrent( aGraph->getContext() ); + } + } + } +} + +void YACSGui_Module::onWindowActivated( SUIT_ViewWindow* theVW ) +{ + DEBTRACE("YACSGui_Module::onWindowActivated: " << myBlockWindowActivateSignal); + if ( myBlockWindowActivateSignal ) return; + + YACSGui_DataModel* model = getDataModel(); + + if ( !model ) + return; + + SalomeApp_Study* study = dynamic_cast(getApp()->activeStudy() ); + DEBTRACE("YACSGui_Module::onWindowActivated study: " << study); + if ( !study ) + return; + + if ( QxGraph_ViewWindow* aVW = dynamic_cast( theVW ) ) + { + Proc* aProc=0; + WindowsMap::iterator anIt = myWindowsMap.begin(); + while( anIt != myWindowsMap.end() ) // TODO: replace the cycle with the approach used in the getGraph(...) method (see also onNewSchema() method) + { + if( (*anIt).second == theVW ) + { + SalomeApp_DataObject* sobj = dynamic_cast( model->getDataObject( (*anIt).first ) ); + if ( sobj ) + { + //ensure YACS is active module + getApp()->activateModule("YACS"); + getApp()->objectBrowser()->setSelected( sobj ); + YACSGui_DataModel::ObjectType anObjType = model->objectType( sobj->entry() ) ; + aProc=(*anIt).first; + + if(anObjType == YACSGui_DataModel::SchemaObject) + setGuiMode(YACSGui_Module::EditMode); + else if(anObjType == YACSGui_DataModel::RunObject) + setGuiMode(YACSGui_Module::RunMode); + + int aStudyId = study->id(); + int aVMId = viewManagerId( aProc ); + activateViewWindow( aProc ); + activateTreeView( aStudyId, aVMId ); + } + return; + } + anIt++; + } + } +} + +void YACSGui_Module::onWindowClosed( SUIT_ViewWindow* theVW ) +{ + DEBTRACE("YACSGui_Module::onWindowClosed"); + if ( QxGraph_ViewWindow* aVW = dynamic_cast( theVW ) ) + { + WindowsMap::iterator anIt = myWindowsMap.begin(); + while( anIt != myWindowsMap.end() ) // TODO: replace the cycle with the approach used in the getGraph(...) method (see also onNewSchema() method) + { + if( (*anIt).second == aVW ) + { + if ( !getApp()->activeStudy() ) return; + removeTreeView( getApp()->activeStudy()->id(), viewManagerId( (*anIt).first ) ); + myWindowsMap.erase( anIt ); + + if ( YACSGui_Graph* aGraph = activeGraph() ) + GuiContext::setCurrent( aGraph->getContext() ); + + return; + } + anIt++; + } + } +} + +//! Export the current active schema (modified schema) into the temporary XML file, which will be used for create execution objects +/*! + */ +void YACSGui_Module::temporaryExport() +{ + // get active schema + YACSGui_Graph* aGraph = activeGraph(); + if ( !aGraph ) return; + + Proc* aSchema = aGraph->getProc(); + if ( !aSchema ) return; + + QString aSchemaName(aSchema->getName()); + + QString tmpDir("/tmp/YACS"); + QDir aTmpDir( tmpDir ); + if ( !aTmpDir.exists() ) + { + aTmpDir = QDir("/tmp"); + aTmpDir.mkdir( "YACS" ); + aTmpDir.cd( "YACS", false ); + } + + // the temporary file name for modified schema + QString anEditionName = aSchemaName + "_modified"; + if ( aTmpDir.exists(anEditionName) ) + aTmpDir.remove(anEditionName); + + anEditionName = aTmpDir.absFilePath(anEditionName); + + YACSGui_VisitorSaveSchema aWriter( this, aSchema ); + aWriter.openFileSchema( anEditionName ); + aWriter.visitProc( aSchema ); + aWriter.closeFileSchema(); +} + +//! Returns a kind of a node as a string, which is using in the built-in catalog node maps +/*! + */ +std::string YACSGui_Module::getNodeType( YACS::ENGINE::Node* theNode ) +{ + //if ( getApp()->activeModule() != this ) return ""; + + ServiceNode* aSNode = dynamic_cast(theNode); + if ( aSNode ) + { + ComponentInstance* aComp = aSNode->getComponent(); + if ( aComp && !aComp->getCompoName().empty() ) + return ""; // the given node is not an empty template + } + + YACS::ENGINE::Catalog* aCatalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + if ( !aCatalog ) return ""; + + map::iterator it = aCatalog->_nodeMap.begin(); + for ( ; it != aCatalog->_nodeMap.end(); it++ ) + if ( ProcInvoc::getTypeOfNode((*it).second) == ProcInvoc::getTypeOfNode(theNode) ) + return (*it).first; + + map::iterator itC = aCatalog->_composednodeMap.begin(); + for ( ; itC != aCatalog->_composednodeMap.end(); itC++ ) + if ( ProcInvoc::getTypeOfNode((*itC).second) == ProcInvoc::getTypeOfNode(theNode) ) + return (*itC).first; + + return ""; +} + +std::string YACSGui_Module::getNodeType( YACS::HMI::TypeOfElem theElemType ) +{ + string aType = ""; + if ( myNodeTypeMap.find(theElemType) != myNodeTypeMap.end() ) + aType = myNodeTypeMap[theElemType]; + return aType; +} + +void YACSGui_Module::fillNodeTypesMap() +{ + myNodeTypeMap[BLOC] = getNodeType(new Bloc("")); + myNodeTypeMap[FOREACHLOOP] = getNodeType(new ForEachLoop("",Runtime::_tc_double)); + myNodeTypeMap[FORLOOP] = getNodeType(new ForLoop("")); + myNodeTypeMap[WHILELOOP] = getNodeType(new WhileLoop("")); + myNodeTypeMap[SWITCH] = getNodeType(new Switch("")); + myNodeTypeMap[PYTHONNODE] = getNodeType(new PythonNode("")); + myNodeTypeMap[PYFUNCNODE] = getNodeType(new PyFuncNode("")); + myNodeTypeMap[CORBANODE] = getNodeType(new CORBANode("")); + myNodeTypeMap[SALOMENODE] = getNodeType(new SalomeNode("")); + myNodeTypeMap[CPPNODE] = getNodeType(new CppNode("")); + myNodeTypeMap[SALOMEPYTHONNODE] = getNodeType(new SalomePythonNode("")); + myNodeTypeMap[XMLNODE] = getNodeType(new XmlNode("")); + myNodeTypeMap[PRESETNODE] = getNodeType(new PresetNode("")); + myNodeTypeMap[OUTNODE] = getNodeType(new OutNode("")); + myNodeTypeMap[STUDYINNODE] = getNodeType(new StudyInNode("")); + myNodeTypeMap[STUDYOUTNODE] = getNodeType(new StudyOutNode("")); +} + +void YACSGui_Module::createNode( YACS::HMI::TypeOfElem theElemType, std::string theCompo, std::string theService ) +{ + DEBTRACE("YACSGui_Module::createNode " << theElemType<<","<getBuiltinCatalog(); + if ( !aCatalog ) return; + + YACSGui_Graph* aGraph = activeGraph(); + if( !aGraph ) return; + + if( YACSGui_EditionTreeView* anETV = dynamic_cast( activeTreeView() ) ) + if ( Subject* aSub = anETV->getSelectedSubject() ) + { + if ( SubjectSwitch* aSwitch = dynamic_cast(aSub) ) + { + stringstream aName; + string aType = getNodeType(theElemType); + aName << aType << GuiContext::getCurrent()->getNewId(theElemType); + + map bodyMap = aSwitch->getBodyMap(); + int aSwCase = 0; + if (bodyMap.empty()) + { + aSwCase = Switch::ID_FOR_DEFAULT_NODE; + } + else + { + map::reverse_iterator rit = bodyMap.rbegin(); + if ((*rit).first == Switch::ID_FOR_DEFAULT_NODE) + aSwCase = 1; + else + aSwCase = (*rit).first + 1; + } + aSwitch->addNode(aCatalog, "", aType, aName.str(), aSwCase); + temporaryExport(); + } + else if ( SubjectForLoop* aForLoop = dynamic_cast(aSub) ) + { + DEBTRACE("Create body loop"); + createBody( theElemType, aSub, aCatalog, theCompo, theService ); + } + else if ( SubjectForEachLoop* aForEachLoop = dynamic_cast(aSub) ) + { + createBody( theElemType, aSub, aCatalog, theCompo, theService ); + } + else if ( SubjectWhileLoop* aWhileLoop = dynamic_cast(aSub) ) + { + createBody( theElemType, aSub, aCatalog, theCompo, theService ); + } + else if ( SubjectComponent* aSComp = dynamic_cast(aSub) ) + { + ComponentInstance* aComp = aSComp->getComponent(); + if ( !aComp /*|| aComp->getKind() != SalomeComponent::KIND*/ ) return; + + if ( SubjectProc* aSchema = GuiContext::getCurrent()->getSubjectProc() ) + if ( theElemType == SALOMENODE || theElemType == SALOMEPYTHONNODE + || + theElemType == CORBANODE && aComp->getKind() == CORBAComponent::KIND ) + { + stringstream aName; + string aType = getNodeType(theElemType); + aName << aType << GuiContext::getCurrent()->getNewId(theElemType); + + string aCompoName = ""; + if ( !myCatalog ) loadCatalog(); + if ( theElemType == SALOMENODE && myCatalog ) + { + aCatalog = myCatalog; + aCompoName = aComp->getCompoName(); + + ComponentDefinition* aCompoDef = 0; + if ( aCatalog->_componentMap.count(aCompoName) > 0 ) + aCompoDef = aCatalog->_componentMap[aCompoName]; + if( aCompoDef && !aCompoDef->_serviceMap.empty() ) + aType = aCompoDef->_serviceMap.begin()->first; + } + + if ( SubjectServiceNode* aSNode = dynamic_cast(aSchema->addNode(aCatalog, aCompoName, aType, aName.str())) ) + aSNode->associateToComponent(aSComp); + + temporaryExport(); + } + } + else if ( SubjectProc* aSchema = dynamic_cast(aSub) ) + { + stringstream aName; + string aType = getNodeType(theElemType); + aName << aType << GuiContext::getCurrent()->getNewId(theElemType); + + aSchema->addNode(aCatalog, "", aType, aName.str()); + temporaryExport(); + } + else if ( SubjectBloc* aBloc = dynamic_cast(aSub) ) + { + stringstream aName; + string aType = getNodeType(theElemType); + aName << aType << GuiContext::getCurrent()->getNewId(theElemType); + + aBloc->addNode(aCatalog, "", aType, aName.str()); + if( SubjectComposedNode* aParent = dynamic_cast(aBloc->getParent()) ) + aGraph->update(aBloc->getNode(), aParent); + temporaryExport(); + } + } + else if ( SubjectProc* aSchema = GuiContext::getCurrent()->getSubjectProc() ) + { + stringstream aName; + string aType = getNodeType(theElemType); + aName << aType << GuiContext::getCurrent()->getNewId(theElemType); + + aSchema->addNode(aCatalog, "", aType, aName.str()); + temporaryExport(); + } +} + +YACS::HMI::SubjectNode* YACSGui_Module::createBody( YACS::HMI::TypeOfElem theElemType, + YACS::HMI::Subject* theSubject, + YACS::ENGINE::Catalog* theCatalog, + std::string theCompo, + std::string theService ) +{ + DEBTRACE("YACSGui_Module::createBody"); + SubjectNode* aBodyNode = 0; + + if( !theCatalog ) return aBodyNode; + + SubjectComposedNode* aComposedNode = dynamic_cast( theSubject ); + if( !aComposedNode ) return aBodyNode; + + YACSGui_Graph* aGraph = activeGraph(); + if( !aGraph ) return aBodyNode; + + // remove current body node (if exists) + if( SubjectNode* aChildNode = aComposedNode->getChild() ) + { + if( SUIT_MessageBox::warn2(getApp()->desktop(), + tr("WRN_WARNING"), + QString("Body node is already exist. Do you want to remove it?"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 1) == 1 ) + return aBodyNode; + + aComposedNode->update( REMOVE, + ProcInvoc::getTypeOfNode( aChildNode->getNode() ), + aChildNode ); + // clear the content of the property page of deleted node + aChildNode->update( REMOVE, 0, 0 ); + + aGraph->removeNode( aChildNode->getNode() ); + + aComposedNode->destroy( aChildNode ); + } + + stringstream aName; + string aType = getNodeType(theElemType); + aName << aType << GuiContext::getCurrent()->getNewId(theElemType); + aBodyNode = aComposedNode->addNode( theCatalog, + theCompo, + ( theService.empty() ? aType : theService ), + aName.str() ); + temporaryExport(); + + return aBodyNode; } diff --git a/src/gui/YACSGui_Module.h b/src/gui/YACSGui_Module.h index 9b06798ff..3009f3287 100644 --- a/src/gui/YACSGui_Module.h +++ b/src/gui/YACSGui_Module.h @@ -21,46 +21,96 @@ #ifndef YACSGui_Module_HeaderFile #define YACSGui_Module_HeaderFile +#include #include #include #include CORBA_CLIENT_HEADER(yacsgui) #include +#include #include +#include +#include + #include class SUIT_ViewWindow; class SUIT_ViewManager; -class YACSGui_DataModel; class YACSGui_Graph; class YACSGui_Executor; class QxGraph_Viewer; +class QxGraph_ViewWindow; class QxGraph_Canvas; class YACSGui_RunMode; +class YACSGui_InputPanel; +class YACSGui_TreeView; +class LightApp_WidgetContainer; + +class QListViewItem; +class SUIT_ToolButton; + +class Catalog; -class SalomeApp_Application; class YACSGui_Module : public SalomeApp_Module { Q_OBJECT public: + + typedef enum { WT_EditTreeView = LightApp_Application::WT_User, WT_RunTreeView } WindowTypes; + enum { // Menu "File" - NewDataflowId, ModifyDataflowId, ImportDataflowId, ExportDataflowId, - ModifySupervDataflowId, ImportSupervDataflowId, + ImportSchemaId, ExportSchemaId, + ImportSupervSchemaId, NewSchemaId, + + // Menu "Create" + NewContainerId, + NewSalomeComponentId, NewSalomePythonComponentId, NewCorbaComponentId, + NewSalomeServiceNodeId, NewCorbaServiceNodeId, NewCppNodeId, + NewServiceInlineNodeId, NewXmlNodeId, NewInlineScriptNodeId, + NewInlineFunctionNodeId, NewBlockNodeId, NewForLoopNodeId, NewForeachLoopNodeId, + NewWhileLoopNodeId, NewSwitchLoopNodeId, NewFromLibraryNodeId, + NewInDataNodeId, NewOutDataNodeId, NewInStudyNodeId, NewOutStudyNodeId, + + //Menu "Execute" (edit gui mode) + NewExecutionId, NewBatchExecutionId, ReloadExecutionId, + + //Menu "Execute" (run gui mode) + StartResumeId, + /*ExecuteId, ExecuteStById,*/ + PauseId, /*ResumeId,*/ AbortId, ResetId, + WithoutStopModeId, BreakpointsModeId, StepByStepModeId, ToggleStopOnErrorId, + ExecuteInBatchId, ConnectToRunningId, + SaveExecutionStateId, NewEditionId, + // Menu "Supervisor" - AddNodeId, - RunDataflowId, RemoteRunDataflowId, KillDataflowId, SuspendResumeDataflowId, - ToggleStopOnErrorId, FilterNextStepsId, + /*AddNodeId, + RunDataflowId, RemoteRunDataflowId, KillDataflowId, SuspendResumeDataflowId, + ToggleStopOnErrorId, FilterNextStepsId, AddDataflowInStudyId, ChangeInformationsId, SaveDataflowStateId, ReloadDataflowId, - RebuildLinksId, + */ + + // Popup menu + SetActiveId, // View mode section of "Dataflow" toolbar - FullViewId, ControlViewId, TableViewId + FullViewId, ControlViewId, DataFlowViewId, DataStreamViewId, + ArrangeNodesId, RebuildLinksId }; - + + enum GuiMode { + EmptyMode, + InitMode, + EditMode, + RunMode, + NewMode + }; + enum{ImportBtnId=1,NewContainerBtnId,NewNodeBtn}; + enum{SchemaTbId, CreationTbId}; + public: YACSGui_Module(); ~YACSGui_Module(); @@ -68,20 +118,24 @@ public: virtual void initialize( CAM_Application* ); QString engineIOR() const; - static YACSGui_ORB::YACSGui_Gen_ptr InitYACSGuiGen( SalomeApp_Application* ); + static YACS_ORB::YACS_Gen_ptr InitYACSGuiGen( SalomeApp_Application* ); YACSGui_DataModel* getDataModel() const; - + virtual void windows( QMap& ) const; virtual void viewManagers( QStringList& ) const; - YACSGui_Graph* displayGraph( YACS::ENGINE::Proc*, + YACSGui_Graph* displayGraph( YACS::HMI::GuiContext*, const YACSGui_Loader::PrsDataMap&, const YACSGui_Loader::PortLinkDataMap&, - const YACSGui_Loader::LabelLinkDataMap&); + const YACSGui_Loader::LabelLinkDataMap&, + const int& = 0, const int& = 0, + const double& = 1., const double& = 1. ); YACSGui_Graph* getGraph( YACS::ENGINE::Proc* ); YACSGui_Graph* activeGraph(); + QxGraph_ViewWindow* getViewWindow( YACS::ENGINE::Proc* ); + QxGraph_Viewer* getViewer(); QxGraph_Canvas* getCanvas(); void updateViewer(); @@ -90,24 +144,94 @@ public: YACSGui_RunMode* getRunMode(YACSGui_Executor* executor); + YACSGui_InputPanel* getInputPanel() const { return myInputPanel; } + + virtual void selectionChanged(); + void setGuiMode( GuiMode ); + void setGuiMode( YACSGui_DataModel::ObjectType ); + GuiMode getGuiMode() const; + + virtual LightApp_Selection* createSelection() const; + void addTreeView( YACSGui_TreeView* theTreeView, const int theStudyId, const int theId ); + YACSGui_TreeView* treeView( const int theStudyId, const int theId ) const; + void removeTreeView( const int theStudyId, const int theId ); + bool isTreeViewShown( const int theStudyId, const int theId ); + YACSGui_TreeView* activeTreeView() const; + YACSGui_TreeView* activeTreeView( const int theStudyId ) const; + void activateTreeView( const int theStudyId, const int theId ); + void setInputPanelVisibility( const bool theOn ); + + //void connectArrangeNodes( YACSPrs_ElementaryNode* theItem ); + + YACS::ENGINE::Catalog* getCatalog() const { return myCatalog; } + + YACSGui_Executor* lookForExecutor(); + YACSGui_Executor* getExecutor( YACS::ENGINE::Proc* ); + YACSGui_Executor* findExecutor(); + + std::string getNodeType( YACS::HMI::TypeOfElem theElemType ); + + YACS::HMI::SubjectNode* createBody( YACS::HMI::TypeOfElem theElemType, + YACS::HMI::Subject* theSubject, + YACS::ENGINE::Catalog* theCatalog, + std::string theCompo = "", + std::string theService = "" ); + public slots: virtual bool activateModule( SUIT_Study* ); virtual bool deactivateModule( SUIT_Study* ); + void onArrangeNodes(); -protected: + void onFullView(); + void onControlView(); + void onDataFlowView(); + void onDataStreamView(); + + void temporaryExport(); + + protected: + void createSComponent(); + void loadCatalog(); + void publishInStudy(YACSGui_Graph* theGraph); // a test function virtual CAM_DataModel* createDataModel(); void createGraph( SUIT_ViewManager* ); + YACSGui_TreeView* createTreeView( YACS::HMI::SubjectProc*, const WindowTypes ); + int viewManagerId( YACS::ENGINE::Proc* theProc ); private slots: - void onNewDataflow(); - void onImportDataflow(); - void onModifyDataflow(); - void onImportSupervDataflow(); - void onModifySupervDataflow(); - void onExportDataflow(); - - void onAddNode(); + void onImportSchema(); + void onImportSupervSchema(); + void onExportSchema(); + void onEditDataTypes(); + void onCreateDataType(); + void onImportDataType(); + + void onNewContainer(); + void onNewSalomeComponent(); + void onNewSalomePythonComponent(); + void onNewCorbaComponent(); + void onNewSchema(); + + void onSalomeServiceNode(); + void onServiceInlineNode(); + void onCorbaServiceNode(); + void onNodeNodeServiceNode(); + void onCppNode(); + void onXMLNode(); + void onInDataNode(); + void onOutDataNode(); + void onInStudyNode(); + void onOutStudyNode(); + void onInlineScriptNode(); + void onInlineFunctionNode(); + void onBlockNode(); + void onFORNode(); + void onFOREACHNode(); + void onWHILENode(); + void onSWITCHNode(); + void onNodeFromLibrary(); + void onReloadDataflow(); void onRebuildLinks(); @@ -117,33 +241,100 @@ private slots: void onRemoteRunDataflow(); void onFilterNextSteps(); void onSaveDataflowState(); + void onCreateExecution(); + void onCreateBatchExecution(); + void onReloadExecution(); + void onStartResume(); + void onExecute(); + void onExecuteStBy(); + void onExecuteInBatch(); + void onPause(); + void onResume(); + //void onSuspendResume(); + void onAbort(); + void onReset(); + void onWithoutStopMode(); + void onBreakpointsMode(); + void onStepByStepMode(); + void onSaveExecutionState(); + void onCreateEdition(); + void onConnectToRunning(); void onToggleStopOnError(); - - void onAddDataflowInStudy(); + void onChangeInformations(); - void onFullView(); - void onControlView(); void onTableView(); + void onDblClick( QListViewItem* ); + void onExpanded( QListViewItem* theItem ); + void onCollapsed( QListViewItem* theItem ); + + void onApplyInputPanel( const int theId ); + + void onSetActive(); + + void onWindowActivated( SUIT_ViewWindow* ); + void onWindowClosed( SUIT_ViewWindow* ); + private: void createActions(); void createMenus(); + void createPreferences(); + void createPopups(); + void createInputPanel(); + void createTreeView( YACS::HMI::SubjectProc*, YACSGui_DataModel::ObjectType ); + + void setModifyActionShown(bool on); + void setBaseActionShown(bool on); + void setVisualizationActionShown(bool on); + void setRunActionShown(bool on); - void ImportDataflowFromFile(const bool setEditable, bool fromSuperv = false); + void CreateNewSchema( QString&, YACS::ENGINE::Proc*, const bool = true); + YACS::HMI::GuiContext* ImportProcFromFile( const QString& filePath, + const GuiMode, + const bool setEditable, + bool fromSuperv = false); void createElementaryNodePrs(); // for test presentations - YACSGui_Executor* getExecutor( YACS::ENGINE::Proc* ); - YACSGui_Executor* findExecutor(); + QxGraph_ViewWindow* createNewViewManager( GuiMode, YACS::ENGINE::Proc*, int = 0, int = 0 ); + void activateViewWindow( YACS::ENGINE::Proc* ); + + void fillNodeTypesMap(); + std::string getNodeType( YACS::ENGINE::Node* theNode ); + void createNode( YACS::HMI::TypeOfElem theElemType, + std::string theCompo = "", + std::string theService = "" ); + private: typedef std::map ExecutorMap; + typedef std::map WindowsMap; typedef std::map RunModeMap; + typedef std::map TreeViewMap; + typedef std::map TreeViewActiveMap; + typedef std::map ToolButtonMap; + typedef std::map ToolBarMap; + typedef std::map NodeTypeMap; + + YACS::ENGINE::Catalog* myCatalog; + + ExecutorMap myExecutors; + RunModeMap _runModeMap; + YACSGui_RunMode* _myRunMode; + + YACSGui_InputPanel* myInputPanel; + GuiMode myGuiMode; + + TreeViewMap myTreeViews; + TreeViewActiveMap myActiveTreeViews; + ToolButtonMap myToolButtons; + ToolBarMap myToolBars; + + WindowsMap myWindowsMap; + bool myBlockWindowActivateSignal; - ExecutorMap myExecutors; - RunModeMap _runModeMap; - YACSGui_RunMode* _myRunMode; + NodeTypeMap myNodeTypeMap; }; #endif diff --git a/src/gui/YACSGui_Node.cxx b/src/gui/YACSGui_Node.cxx index 4e2bc5e2e..cbe45d536 100644 --- a/src/gui/YACSGui_Node.cxx +++ b/src/gui/YACSGui_Node.cxx @@ -18,6 +18,9 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +#include +#include + #include #include @@ -33,6 +36,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include #include #include @@ -40,6 +53,12 @@ #include #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; +using namespace YACS::HMI; + /*! * =========================== YACSGui_Node =========================== !*/ @@ -71,7 +90,9 @@ SUIT_ResourceMgr* YACSGui_Node::resMgr() const * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_Node::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_Node::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { if ( !myGraph ) return; @@ -107,14 +128,22 @@ YACSGui_ServiceNode::~YACSGui_ServiceNode() * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_ServiceNode::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_ServiceNode::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { + DEBTRACE("YACSGui_ServiceNode::update " << theItem); if ( !graph() ) return; if ( !theItem ) { - theItem = new YACSPrs_ServiceNode( resMgr(), 0, theEngine); - graph()->registerStatusObserverWithNode(theEngine); + SubjectNode* aSNode = theParent->getChild(theEngine); + DEBTRACE(aSNode); + if ( aSNode ) + { + theItem = new YACSPrs_ServiceNode( resMgr(), graph()->getCanvas(), aSNode ); + graph()->registerStatusObserverWithNode(theEngine); + } } else { @@ -147,14 +176,20 @@ YACSGui_InlineNode::~YACSGui_InlineNode() * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_InlineNode::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_InlineNode::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { if ( !graph() ) return; if ( !theItem ) { - theItem = new YACSPrs_InlineNode( resMgr(), 0, theEngine); - graph()->registerStatusObserverWithNode(theEngine); + SubjectNode* aINode = theParent->getChild(theEngine); + if ( aINode ) + { + theItem = new YACSPrs_InlineNode( resMgr(), graph()->getCanvas(), aINode ); + graph()->registerStatusObserverWithNode(theEngine); + } } else { @@ -187,14 +222,21 @@ YACSGui_IfNode::~YACSGui_IfNode() * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_IfNode::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_IfNode::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { if ( !graph() ) return; if ( !theItem ) { - theItem = new YACSPrs_IfNode( resMgr(), 0, theEngine); - graph()->registerStatusObserverWithNode(theEngine); + SubjectComposedNode* aCNode = dynamic_cast( theParent->getChild(theEngine) ); + if ( aCNode ) + { + theItem = new YACSPrs_IfNode( resMgr(), graph()->getCanvas(), aCNode ); + graph()->registerStatusObserverWithNode(theEngine); + graph()->createChildNodesPresentations( aCNode ); + } } else { @@ -227,14 +269,22 @@ YACSGui_SwitchNode::~YACSGui_SwitchNode() * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_SwitchNode::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_SwitchNode::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { if ( !graph() ) return; if ( !theItem ) { - theItem = new YACSPrs_SwitchNode( resMgr(), 0, theEngine); - graph()->registerStatusObserverWithNode(theEngine); + SubjectSwitch* aSNode = dynamic_cast( theParent->getChild(theEngine) ); + if ( aSNode ) + { + theItem = new YACSPrs_SwitchNode( resMgr(), graph()->getCanvas(), aSNode ); + graph()->registerStatusObserverWithNode(theEngine); + graph()->createChildNodesPresentations( aSNode ); + aSNode->attach( graph() ); + } } else { @@ -267,14 +317,22 @@ YACSGui_LoopNode::~YACSGui_LoopNode() * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_LoopNode::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_LoopNode::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { if ( !graph() ) return; if ( !theItem ) { - theItem = new YACSPrs_LoopNode( resMgr(), 0, theEngine); - graph()->registerStatusObserverWithNode(theEngine); + SubjectComposedNode* aLNode = dynamic_cast( theParent->getChild(theEngine) ); + if ( aLNode ) + { + theItem = new YACSPrs_LoopNode( resMgr(), graph()->getCanvas(), aLNode ); + graph()->registerStatusObserverWithNode(theEngine); + graph()->createChildNodesPresentations( aLNode ); + aLNode->attach( graph() ); + } } else { @@ -307,14 +365,22 @@ YACSGui_ForEachLoopNode::~YACSGui_ForEachLoopNode() * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_ForEachLoopNode::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_ForEachLoopNode::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { if ( !graph() ) return; if ( !theItem ) { - theItem = new YACSPrs_ForEachLoopNode( resMgr(), 0, theEngine); - graph()->registerStatusObserverWithNode(theEngine); + SubjectComposedNode* aFELNode = dynamic_cast( theParent->getChild(theEngine) ); + if ( aFELNode ) + { + theItem = new YACSPrs_ForEachLoopNode( resMgr(), graph()->getCanvas(), aFELNode ); + graph()->registerStatusObserverWithNode(theEngine); + graph()->createChildNodesPresentations( aFELNode ); + aFELNode->attach( graph() ); + } } else { @@ -347,38 +413,112 @@ YACSGui_BlocNode::~YACSGui_BlocNode() * New graphic items should be created with a null canvas pointer. * They can be added to a canvas by QxGraph_Prs::show() and removed from it by hide(). */ -void YACSGui_BlocNode::update(YACS::ENGINE::Node* theEngine, YACSPrs_ElementaryNode*& theItem ) +void YACSGui_BlocNode::update(YACS::ENGINE::Node* theEngine, + YACS::HMI::SubjectComposedNode* theParent, + YACSPrs_ElementaryNode*& theItem ) { + DEBTRACE("YACSGui_BlocNode::update"); if ( !graph() ) return; if ( !theItem ) { - YACSPrs_BlocNode* aBlocPrs = new YACSPrs_BlocNode( resMgr(), 0, theEngine, - YACSPrs_BlocNode::Expanded, level(theEngine) ); + DEBTRACE("YACSGui_BlocNode::update"); YACS::ENGINE::Bloc* aBloc = dynamic_cast( theEngine ); if ( aBloc ) { + SubjectBloc* aBNode = dynamic_cast( theParent->getChild(theEngine) ); + if ( aBNode ) + { + // create children presentations (and, of course, subjects) + graph()->createChildNodesPresentations( aBNode ); + + // collect created children presentations in the list + std::set aNodePrsSet; + std::set aNodeSet; + graph()->getAllBlocChildren(aBloc, aNodeSet); + for ( std::set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + if ( graph()->getItem( *it ) ) + aNodePrsSet.insert( graph()->getItem( *it ) ); + + YACSPrs_BlocNode* aBlocPrs = new YACSPrs_BlocNode( resMgr(), graph()->getCanvas(), + aBNode, + YACSPrs_BlocNode::Expanded, + level(theEngine) ); + aBlocPrs->setChildren( aNodePrsSet ); + + theItem = aBlocPrs; + + graph()->registerStatusObserverWithNode(theEngine); + aBNode->attach( graph() ); + } + } + } + else + { + // TODO - Here any parameters of exisiting items should be updated + // ... + + // NB: this case is actual if the content of the block node (i.e. the set of child nodes) was changed + YACSPrs_BlocNode* aBlocPrs = dynamic_cast( theItem ); + YACS::ENGINE::Bloc* aBloc = dynamic_cast( theEngine ); + DEBTRACE("YACSGui_BlocNode::update "<< aBlocPrs <<","<< aBloc); + if ( aBlocPrs && aBloc ) + { + // get old set of children: make it independent from the block + std::set anOldChildren = aBlocPrs->getChildren(); + DEBTRACE(anOldChildren.size()); + for ( std::set::iterator it = anOldChildren.begin(); it != anOldChildren.end(); it++ ) + { + DEBTRACE(*it); + (*it)->setIsInBloc(false); + (*it)->setSelfMoving(true); + } + + // collect presentations of the new children in the list: set new children list to the block std::set aNodePrsSet; std::set aNodeSet; graph()->getAllBlocChildren(aBloc, aNodeSet); + DEBTRACE(aNodeSet.size()); for ( std::set::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + if ( graph()->getItem( *it ) ) + aNodePrsSet.insert( graph()->getItem( *it ) ); + + DEBTRACE(aNodePrsSet.size()); + aBlocPrs->setChildren( aNodePrsSet ); + + // remove control links of the new children + for ( std::set::iterator childIt = aNodePrsSet.begin(); childIt != aNodePrsSet.end(); childIt++ ) + { + YACSPrs_ElementaryNode* aPrs = *childIt; + if( anOldChildren.count( aPrs ) ) + continue; + std::list aControlLinks = aPrs->getSEngine()->getSubjectControlLinks(); + for( std::list::iterator iter = aControlLinks.begin(); iter != aControlLinks.end(); iter++ ) + { + SubjectControlLink* aControlLink = *iter; + if( SubjectNode* anOutNode = aControlLink->getSubjectOutNode() ) + if( YACSPrs_ElementaryNode* aParentPrs = graph()->getItem( anOutNode->getNode() ) ) + aParentPrs->removeLinkPrs( aControlLink ); + } + } + + Bloc* aFather = aBloc; + bool isNeedToArrange = true; + if ( !anOldChildren.empty() || aNodeSet.empty() ) + isNeedToArrange = graph()->isNeededToIncreaseBlocSize(aFather); + while ( isNeedToArrange && aFather && !dynamic_cast(aFather) ) { - if ( !graph()->getItem( *it ) ) graph()->update( *it ); - aNodePrsSet.insert( graph()->getItem( *it ) ); + graph()->arrangeNodesWithinBloc(aFather); + aFather = dynamic_cast(aFather->getFather()); + isNeedToArrange = graph()->isNeededToIncreaseBlocSize(aFather); } - aBlocPrs->setChildren( aNodePrsSet ); + graph()->getCanvas()->update(); theItem = aBlocPrs; - - graph()->registerStatusObserverWithNode(theEngine); } - } - else - { - // TODO - Here any parameters of exisiting items should be updated - // ... - theItem->update(); + + //theItem->update(); } } diff --git a/src/gui/YACSGui_Node.h b/src/gui/YACSGui_Node.h index 21d6d876c..5b477c62a 100644 --- a/src/gui/YACSGui_Node.h +++ b/src/gui/YACSGui_Node.h @@ -24,6 +24,7 @@ #include #include +#include class SUIT_ResourceMgr; @@ -40,7 +41,7 @@ class YACSGui_Node YACSGui_Node(YACSGui_Graph*); virtual ~YACSGui_Node(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); protected: YACSGui_Graph* graph() const { return myGraph; } @@ -60,7 +61,7 @@ class YACSGui_ServiceNode : public YACSGui_Node YACSGui_ServiceNode(YACSGui_Graph*); virtual ~YACSGui_ServiceNode(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); }; @@ -74,7 +75,7 @@ class YACSGui_InlineNode : public YACSGui_Node YACSGui_InlineNode(YACSGui_Graph*); virtual ~YACSGui_InlineNode(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); }; @@ -88,7 +89,7 @@ class YACSGui_IfNode : public YACSGui_Node YACSGui_IfNode(YACSGui_Graph*); virtual ~YACSGui_IfNode(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); }; @@ -102,7 +103,7 @@ class YACSGui_SwitchNode : public YACSGui_Node YACSGui_SwitchNode(YACSGui_Graph*); virtual ~YACSGui_SwitchNode(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); }; @@ -116,7 +117,7 @@ class YACSGui_LoopNode : public YACSGui_Node YACSGui_LoopNode(YACSGui_Graph*); virtual ~YACSGui_LoopNode(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); }; @@ -130,7 +131,7 @@ class YACSGui_ForEachLoopNode : public YACSGui_Node YACSGui_ForEachLoopNode(YACSGui_Graph*); virtual ~YACSGui_ForEachLoopNode(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); }; @@ -144,7 +145,7 @@ class YACSGui_BlocNode : public YACSGui_Node YACSGui_BlocNode(YACSGui_Graph*); virtual ~YACSGui_BlocNode(); - virtual void update(YACS::ENGINE::Node*, YACSPrs_ElementaryNode*&); + virtual void update(YACS::ENGINE::Node*, YACS::HMI::SubjectComposedNode*, YACSPrs_ElementaryNode*&); int level(YACS::ENGINE::Node* theEngine); }; diff --git a/src/gui/YACSGui_NodePage.cxx b/src/gui/YACSGui_NodePage.cxx new file mode 100644 index 000000000..d6a117468 --- /dev/null +++ b/src/gui/YACSGui_NodePage.cxx @@ -0,0 +1,616 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + +/* + Class : YACSGui_NodePage + Description : Basic page for node properties +*/ + +YACSGui_NodePage::YACSGui_NodePage() + : GuiObserver(), + mySNode( 0 ), + myType( Unknown ) //? +{ + mySelectDataTypeFor.myRow = -1; +} + +YACSGui_NodePage::~YACSGui_NodePage() +{ + if ( mySNode ) mySNode->detach(this); +} + +void YACSGui_NodePage::select( bool isSelected ) +{ + DEBTRACE(">> YACSGui_NodePage::select"); +} + +void YACSGui_NodePage::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSGui_NodePage::update " << event << " " << type); + switch (event) + { + case ADD: + { + // check if the parent of the son is a loop + if( SubjectNode* aSNode = dynamic_cast( son->getParent() ) ) + { + if ( dynamic_cast( aSNode->getNode() ) || dynamic_cast( aSNode->getNode() ) ) + notifyNodeCreateBody( son ); + else if ( dynamic_cast( aSNode->getNode() ) || dynamic_cast( aSNode->getNode() ) ) + notifyNodeCreateNode( son ); + } + } + break; + case REMOVE: + { + if ( !type && !son && mySNode ) + { + mySNode->detach(this); + mySNode = 0; + } + } + break; + case UPDATEPROGRESS: + notifyNodeProgress(); + break; + default: + GuiObserver::update(event, type, son); + } +} + +YACSGui_InputPanel* YACSGui_NodePage::getInputPanel() const +{ + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( !anApp ) + return 0; + + YACSGui_Module* aModule = dynamic_cast( anApp->activeModule() ); + if( !aModule ) + return 0; + + return aModule->getInputPanel(); +} + +void YACSGui_NodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + DEBTRACE("YACSGui_NodePage::setSNode "); + if ( !theSNode ) + return; + //DEBTRACE(theSNode->getName()); + + bool isNeedToUpdatePortValues = false; + if ( mySNode != theSNode ) + { + if ( mySNode ) mySNode->detach(this); //detach from old node + mySNode = theSNode; + mySNode->attach(this); // attach to new node + + // specify the node type + Node* aNode = getNode(); + if ( dynamic_cast(aNode) ) + myType = InlineFunction; + else if ( dynamic_cast(aNode) ) + myType = InlineScript; + else if ( dynamic_cast(aNode) ) + myType = SALOMEService; + else if ( dynamic_cast(aNode) ) + myType = CORBAService; + else if ( dynamic_cast(aNode) ) + myType = CPPNode; + else if ( dynamic_cast(aNode) ) + myType = ServiceInline; + else if ( dynamic_cast(aNode) ) + myType = XMLNode; + else if ( dynamic_cast(aNode) ) + myType = DATANode; + else if ( dynamic_cast(aNode) ) + myType = FOR; + else if ( dynamic_cast(aNode) ) + myType = FOREACH; + else if ( dynamic_cast(aNode) ) + myType = WHILE; + else if ( dynamic_cast(aNode) ) + myType = SWITCH; + else if ( dynamic_cast(aNode) ) + myType = Block; + + if ( aNode ) + { + notifyNodeStatus( getNode()->getState() ); + notifyNodeProgress(); + } + + isNeedToUpdatePortValues = true; + } + + updateState(); + + DEBTRACE("NeedToUpdatePortValues? " << isNeedToUpdatePortValues << " " << myType); + if ( (isNeedToUpdatePortValues || myType == SALOMEService || myType == InlineFunction|| myType == InlineScript + || myType == XMLNode ||myType==DATANode) && getNode() ) + { + DEBTRACE("YACSGui_NodePage::setSNode "); + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( !anApp ) return; + + YACSGui_Module* aModule = dynamic_cast( anApp->activeModule() ); + if( !aModule ) return; + + YACSGui_Graph* aGraph = aModule->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + DEBTRACE("elementary node"); + //MESSAGE("elementary node"); + map anInPortName2Value; + list IPs = getNode()->getSetOfInPort(); + list::iterator itIP = IPs.begin(); + DEBTRACE("Input ports"); + for ( ; itIP!=IPs.end(); itIP++ ) + { + InPort* aPort = *itIP; + if ( !aPort ) + continue; + + YACSPrs_InOutPort* aPortPrs = anItem->getPortPrs( aPort ); + if ( !aPortPrs ) + continue; + + QString aCurrVal = aPortPrs->getCurrentValue(); + if ( aCurrVal.isNull() ) + continue; + + anInPortName2Value.insert( + make_pair( aPort->getName(), string( aCurrVal.latin1() ) ) ); + + //printf(">> Name = %s, Value = %s\n", + // (*itIP)->getName().c_str(), + // anItem->getPortPrs(*itIP)->getCurrentValue().latin1()); + + } + DEBTRACE("Notify"); + notifyInPortValues( anInPortName2Value ); + + map anOutPortName2Value; + list OPs = getNode()->getSetOfOutPort(); + list::iterator itOP = OPs.begin(); + DEBTRACE("Output ports"); + for ( ; itOP!=OPs.end(); itOP++ ) + { + OutPort* aPort = *itOP; + if ( !aPort ) + continue; + + YACSPrs_InOutPort* aPortPrs = anItem->getPortPrs( aPort ); + if ( !aPortPrs ) + continue; + + QString aCurrVal = aPortPrs->getCurrentValue(); + if ( aCurrVal.isNull() ) + continue; + + anOutPortName2Value.insert( + make_pair( aPort->getName(), string( aCurrVal.latin1() ) ) ); + + //printf(">> Name = %s, Value = %s\n", + // (*itOP)->getName().c_str(), + // anItem->getPortPrs(*itOP)->getCurrentValue().latin1()); + } + DEBTRACE("Notify"); + notifyOutPortValues( anOutPortName2Value ); + } + } +} + +YACS::ENGINE::Node* YACSGui_NodePage::getNode() const +{ + return ( mySNode ? mySNode->getNode() : 0 ); +} + +QString YACSGui_NodePage::getNodeName() const +{ + return ( mySNode ? QString( mySNode->getName() ) : QString("") ); +} + +void YACSGui_NodePage::setNodeName( const QString& theName ) +{ + if ( getNode() ) + { + try + { + getNode()->setName( theName.latin1() ); + } + catch (YACS::Exception& ex) + { + SUIT_MessageBox::error1(getInputPanel()->getModule()->getApp()->desktop(), + QObject::tr("ERROR"), + ex.what(), + QObject::tr("BUT_OK")); + + std::cerr << ex.what() << std::endl; + return; + } + mySNode->update( RENAME, 0, mySNode ); + } +} + +void YACSGui_NodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + myMode = theMode; +} + +void YACSGui_NodePage::setValueCellValidator( YACSGui_Table* theTable, int theRow ) +{ + DEBTRACE("YACSGui_NodePage::setValueCellValidator " << theRow); + QString aVT = theTable->item( theRow, 2 )->text(); + //DEBTRACE(aVT.latin1()); + if ( !aVT.compare(QString("Double")) ) + theTable->setCellType( theRow, 3, YACSGui_Table::Double ); + else if ( !aVT.compare(QString("Int")) ) + theTable->setCellType( theRow, 3, YACSGui_Table::Int ); + else if ( !aVT.compare(QString("Bool")) ) + { + theTable->setCellType( theRow, 3, YACSGui_Table::Combo ); + theTable->setParams( theRow, 3, QString("True;False") ); + } + else // i.e. "String" or "Objref" or "Sequence" or "Array" or "Struct" + theTable->setCellType( theRow, 3, YACSGui_Table::String ); +} + +bool YACSGui_NodePage::isSelectDataType() +{ + if ( mySelectDataTypeFor.myRow >= 0 ) return true; + return false; +} + +void YACSGui_NodePage::updateState() +{ +} + +void YACSGui_NodePage::updateBlocSize() +{ + if ( SubjectBloc* aSB = dynamic_cast(mySNode->getParent()) ) + { + //aSB->update( EDIT, 0, aSB ); + + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + Bloc* aFather = dynamic_cast(aSB->getNode()); + if ( !aFather ) return; + + bool isNeedToArrange = aGraph->isNeededToIncreaseBlocSize(aFather); + while ( isNeedToArrange && aFather && !dynamic_cast(aFather) ) + { + aGraph->arrangeNodesWithinBloc(aFather); + aFather = dynamic_cast(aFather->getFather()); + isNeedToArrange = aGraph->isNeededToIncreaseBlocSize(aFather); + } + aGraph->getCanvas()->update(); + } +} + +YACSGui_NodePage::PortType YACSGui_NodePage::getDataPortType(YACS::ENGINE::Port* thePort) const +{ + DEBTRACE("YACSGui_NodePage::getDataPortType" ); + if ( dynamic_cast(thePort) ) + { + if ( dynamic_cast(thePort) ) + { + if ( SeqAnyInputPort* aSeqAnyP = dynamic_cast(thePort) ) + { + return SeqAnyInput; + } + else if ( AnyInputPort* anAnyP = dynamic_cast(thePort) ) + { + return AnyInput; + } + else if ( ConditionInputPort* aConditionP = dynamic_cast(thePort) ) + { + return ConditionInput; + } + else if ( InputCorbaPort* aCorbaP = dynamic_cast(thePort) ) + { + return InputCorba; + } + else if ( InputPyPort* aPyP = dynamic_cast(thePort) ) + { + return InputPy; + } + else if ( InputXmlPort* aXmlP = dynamic_cast(thePort) ) + { + return InputXml; + } + //else if ( InputBasicStreamPort* aBasicStreamP = dynamic_cast(thePort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + //} + else if ( InputCalStreamPort* aCalStreamP = dynamic_cast(thePort) ) + { + return InputCalStream; + } + //else if ( InputPalmStreamPort* aPalmStreamP = dynamic_cast(thePort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + //} + else if ( InputDataStreamPort* aDataStreamP = dynamic_cast(thePort) ) + { + return InputDataStream; + } + else if ( InputPort* anInputP = dynamic_cast(thePort) ) + { // one of previous types is not detected + return Input; + } + } + else if ( dynamic_cast(thePort) ) + { + if ( AnyOutputPort* anAnyP = dynamic_cast(thePort) ) + { + return AnyOutput; + } + else if ( OutputCorbaPort* aCorbaP = dynamic_cast(thePort) ) + { + return OutputCorba; + } + else if ( OutputPyPort* aPyP = dynamic_cast(thePort) ) + { + return OutputPy; + } + else if ( OutputXmlPort* aXmlP = dynamic_cast(thePort)) + { + return OutputXml; + } + //else if ( OutputBasicStreamPort* aBasicStreamP = dynamic_cast(thePort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + //} + else if ( OutputCalStreamPort* aCalStreamP = dynamic_cast(thePort) ) + { + return OutputCalStream; + } + //else if ( OutputPalmStreamPort* aPalmStreamP = dynamic_cast(thePort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + //} + else if ( OutputDataStreamPort* aCalStreamP = dynamic_cast(thePort) ) + { + return OutputDataStream; + } + else if ( OutputPort* anOutputP = dynamic_cast(thePort) ) + { // one of previous types is not detected + return Output; + } + } + } + return UnknownType; +} + +//! Returns value of port as a string +/*! + * + */ +QString YACSGui_NodePage::getPortValue(YACS::ENGINE::Port* thePort) const +{ + DEBTRACE("YACSGui_NodePage::getPortValue" ); + QString aValue; + + PortType aType = getDataPortType(thePort); + + if( aType == Input ) + { + } + else if( aType == SeqAnyInput ) + { + SeqAnyInputPort* aSeqAnyP = dynamic_cast(thePort); + Any* anAny = aSeqAnyP->getValue(); + if ( !anAny ) aValue = QString("[ ? ]"); + else toString(anAny, aValue); + } + else if( aType == AnyInput ) + { + AnyInputPort* anAnyP = dynamic_cast(thePort); + toString(anAnyP->getValue(), aValue); + } + else if( aType == ConditionInput ) + { + ConditionInputPort* aConditionP = dynamic_cast(thePort); + aValue = QString( aConditionP->getValue() ? "True" : "False" ); + } + else if( aType == InputCorba ) + { + InputCorbaPort* aCorbaP = dynamic_cast(thePort); + toString( aCorbaP->getAny(), aValue ); + } + else if( aType == InputPy ) + { + InputPyPort* aPyP = dynamic_cast(thePort); + toString( aPyP->getPyObj(), aValue ); + } + else if( aType == InputXml ) + { + if(InputStudyPort* aPort=dynamic_cast(thePort)) + { + DEBTRACE( aPort->getData()); + aValue=aPort->getData(); + } + else + { + InputXmlPort* aPort = dynamic_cast(thePort); + DEBTRACE( aPort->dump()); + toString(aPort->dump(),aPort->edGetType(),aValue); + } + } + else if( aType == InputBasicStream ) + { + } + else if( aType == InputCalStream ) + { + aValue = QString("data stream"); + } + else if( aType == InputPalmStream ) + { + } + else if( aType == InputDataStream ) + { + aValue = QString("data stream"); + } + else if( aType == Output ) + { + } + else if( aType == AnyOutput ) + { + AnyOutputPort* anAnyP = dynamic_cast(thePort); + toString(anAnyP->getValue(), aValue); + } + else if( aType == OutputCorba ) + { + OutputCorbaPort* aCorbaP = dynamic_cast(thePort); + toString( aCorbaP->getAny(), aValue ); + } + else if( aType == OutputPy ) + { + OutputPyPort* aPyP = dynamic_cast(thePort); + toString( aPyP->get(), aValue ); + } + else if( aType == OutputXml ) + { + if(OutputStudyPort* aPort=dynamic_cast(thePort)) + { + DEBTRACE( aPort->getData()); + aValue=aPort->getData(); + } + else + { + OutputXmlPort* aPort = dynamic_cast(thePort); + DEBTRACE(aPort->dump()); + toString(aPort->dump(),aPort->edGetType(),aValue); + } + } + else if( aType == OutputBasicStream ) + { + } + else if( aType == OutputCalStream ) + { + aValue = QString("data stream"); + } + else if( aType == OutputPalmStream ) + { + } + else if( aType == OutputDataStream ) + { + aValue = QString("data stream"); + } + + return aValue; +} + diff --git a/src/gui/YACSGui_Observer.cxx b/src/gui/YACSGui_Observer.cxx index 9f8839bc6..0c0903133 100644 --- a/src/gui/YACSGui_Observer.cxx +++ b/src/gui/YACSGui_Observer.cxx @@ -17,6 +17,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +#include "YACSPrs_toString.h" #include "YACSGui_Observer.h" #include "YACSGui_Graph.h" @@ -24,6 +25,8 @@ #include "YACSGui_Executor.h" #include "YACSPrs_ElementaryNode.h" #include "YACSGui_RunMode.h" +#include "YACSGui_TreeView.h" +#include "YACSGui_InputPanel.h" #include "SALOME_Event.hxx" @@ -37,6 +40,9 @@ #include #include "utilities.h" +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; using namespace std; @@ -54,23 +60,29 @@ YACSGui_Observer::YACSGui_Observer(YACSGui_Graph* theGraph): void YACSGui_Observer::notifyObserver(YACS::ENGINE::Node* object, const std::string& event) { - //MESSAGE("YACSGui_Observer::notifyObserver(YACS::ENGINE::Node* object, const std::string& event)"); + DEBTRACE("YACSGui_Observer::notifyObserver(YACS::ENGINE::Node* object, const std::string& event)"); + if ( !myGraph ) printf("==> null graph\n"); + if (event == "status") { + DEBTRACE("==> status"); if ( myGraph && !myGraph->getItem(object) ) { + DEBTRACE("==> status 1"); if ( dynamic_cast( object->getFather() ) && myGraph->getItem(object->getFather()) ) { + DEBTRACE("==> status 2"); // transmit event to ForEachLoop node ProcessVoidEvent( new TVoidMemFunEvent( myGraph->getItem(object->getFather()), &YACSPrs_ElementaryNode::update ) ); // transmit event from the last clone node to original loop body node if ( object == (dynamic_cast( object->getFather() ))->getNodes().back() ) { - std::set aChildren = dynamic_cast( object->getFather() )->edGetDirectDescendants(); - for(std::set::iterator iter=aChildren.begin();iter!=aChildren.end();iter++) + DEBTRACE("==> status 3"); + std::list aChildren = dynamic_cast( object->getFather() )->edGetDirectDescendants(); + for(std::list::iterator iter=aChildren.begin();iter!=aChildren.end();iter++) if ( myGraph->getItem(*iter) ) ProcessVoidEvent( new TVoidMemFun1ArgEvent( myGraph->getItem(*iter), &YACSPrs_ElementaryNode::updateForEachLoopBody, @@ -80,23 +92,28 @@ void YACSGui_Observer::notifyObserver(YACS::ENGINE::Node* object, const std::str } else if ( myGraph && myGraph->getItem(object) ) { + DEBTRACE("==> status 4"); if ( dynamic_cast( object ) && object->getState() == YACS::TOACTIVATE ) { + DEBTRACE("==> status 5"); std::vector aCloneNodes = dynamic_cast(object)->getNodes(); for(std::vector::iterator iter=aCloneNodes.begin();iter!=aCloneNodes.end();iter++) myGraph->registerStatusObserverWithNode(*iter); } else - ProcessVoidEvent( new TVoidMemFunEvent( myGraph->getItem(object), &YACSPrs_ElementaryNode::update ) ); + { + DEBTRACE("==> status 6"); + ProcessVoidEvent( new TVoidMemFunEvent( myGraph->getItem(object), &YACSPrs_ElementaryNode::update ) ); + } } } } void YACSGui_Observer::notifyObserver(const int theID, const std::string& theEvent) { - //MESSAGE("YACSGui_Observer::notifyObserver(const int theID, const std::string& theEvent)"); + DEBTRACE("YACSGui_Observer::notifyObserver(const int theID, const std::string& theEvent)"); // Get node by its id YACS::ENGINE::Node* aNode = myGraph->getNodeById(theID); @@ -107,7 +124,7 @@ void YACSGui_Observer::notifyObserver(const int theID, const std::string& theEve void YACSGui_Observer::notifyObserver(const std::string& theName, const std::string& theEvent) { - //MESSAGE("YACSGui_Observer::notifyObserver(const std::string& theName, const std::string& theEvent)"); + DEBTRACE("YACSGui_Observer::notifyObserver(const std::string& theName, const std::string& theEvent)"); // Get node by its name YACS::ENGINE::Node* aNode = myGraph->getNodeByName(theName); @@ -122,7 +139,7 @@ void YACSGui_Observer::notifyObserver(const std::string& theName, const std::str */ void YACSGui_Observer::setNodeState(const int theID, const int theState) { - //MESSAGE("YACSGui_Observer::setNodeState(const int theID, const int theState)"); + DEBTRACE("YACSGui_Observer::setNodeState(const int theID, const int theState)"); // Get node by its id YACS::ENGINE::Node* aNode = myGraph->getNodeById(theID); @@ -137,7 +154,7 @@ void YACSGui_Observer::setNodeState(const int theID, const int theState) */ void YACSGui_Observer::setNodeState(const std::string& theName, const int theState) { - //MESSAGE("YACSGui_Observer::setNodeState " << theName << " " << theState); + DEBTRACE("YACSGui_Observer::setNodeState " << theName << " " << theState); // Get node by its name YACS::ENGINE::Node* aNode = 0; @@ -158,11 +175,11 @@ Observer_i::Observer_i(YACS::ENGINE::Proc* guiProc, YACSGui_Module* guiMod, YACSGui_Executor* guiExec) { - //MESSAGE("Observer_i::Observer_i"); + DEBTRACE("Observer_i::Observer_i"); _guiProc = guiProc; _guiMod = guiMod; _guiExec = guiExec; - _engineProc = YACSGui_ORB::ProcExec::_nil(); + _engineProc = YACS_ORB::ProcExec::_nil(); myImpl = 0; } @@ -172,11 +189,11 @@ Observer_i::~Observer_i() void Observer_i::setConversion() { - //MESSAGE("Observer_i::setConversion"); + DEBTRACE("Observer_i::setConversion"); assert(!CORBA::is_nil(_engineProc)); - YACSGui_ORB::stringArray_var engineNames; - YACSGui_ORB::longArray_var engineIds; - //MESSAGE("---"); + YACS_ORB::stringArray_var engineNames; + YACS_ORB::longArray_var engineIds; + //DEBTRACE("---"); _engineProc->getIds(engineIds.out(), engineNames.out()); int iLength = engineIds->length(); int nLength = engineNames->length(); @@ -186,11 +203,11 @@ void Observer_i::setConversion() string aName = ""; aName = engineNames[i]; int iEng = engineIds[i]; - //MESSAGE("--- " << aName << " " << iEng); + //DEBTRACE("--- " << aName << " " << iEng); if (aName != "_root_") { int iGui = _guiProc->getChildByName(aName)->getNumId(); - //MESSAGE("---"); + //DEBTRACE("---"); _guiToEngineMap[iGui] = iEng; _engineToGuiMap[iEng] = iGui; } @@ -206,7 +223,7 @@ void Observer_i::setConversion() //! process YACS events in main thread (see postEvent) bool Observer_i::event(QEvent *e) { - //MESSAGE("Observer_i::event"); + DEBTRACE("Observer_i::event"); if (e->type() == YACS_EVENT) { YACSEvent *ye = (YACSEvent*)e; @@ -216,22 +233,36 @@ bool Observer_i::event(QEvent *e) if (event == "executor") // --- Executor notification: state { - //MESSAGE("Observer_i::run executor"); + DEBTRACE("Observer_i::run executor"); int execState = _engineProc->getExecutorState(); + YACSGui_RunMode* theRunMode = _guiMod->getRunMode(_guiExec); - if (theRunMode) + YACSGui_RunTreeView* aRunTV = dynamic_cast(_guiMod->activeTreeView()); + + list nextSteps; + if ( theRunMode || aRunTV ) + if ((execState == YACS::WAITINGTASKS) || (execState == YACS::PAUSED)) + { + YACS_ORB::stringArray_var nstp = _engineProc->getTasksToLoad(); + for (CORBA::ULong i=0; ilength(); i++) + nextSteps.push_back(nstp[i].in()); + } + + if ( theRunMode ) { theRunMode->onNotifyStatus(execState); - list nextSteps; - if ((execState == YACS::WAITINGTASKS) || (execState == YACS::PAUSED)) - { - YACSGui_ORB::stringArray_var nstp = _engineProc->getTasksToLoad(); - for (CORBA::ULong i=0; ilength(); i++) - nextSteps.push_back(nstp[i].in()); - } - theRunMode->onNotifyNextSteps(nextSteps); + theRunMode->onNotifyNextSteps(nextSteps); } - } + + if ( aRunTV ) + { + aRunTV->onNotifyStatus(execState); + + if ( YACSGui_InputPanel* anIP = _guiMod->getInputPanel() ) + if ( YACSGui_SchemaPage* aSPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::SchemaId ) ) ) + aSPage->onNotifyNextSteps(nextSteps); + } + } else // --- Node notification { if (!myImpl) @@ -250,19 +281,121 @@ bool Observer_i::event(QEvent *e) if (event == "status") // --- Node notification: status { - //MESSAGE("Observer_i::run status"); + DEBTRACE("Observer_i::run status"); int aState = _engineProc->getNodeState(numid); if (aState < 0) return true; + YACSGui_RunMode* theRunMode = _guiMod->getRunMode(_guiExec); if (theRunMode) theRunMode->onNotifyNodeStatus(iGui, aState); + + if ( YACSGui_RunTreeView* aRunTV = dynamic_cast(_guiMod->activeTreeView()) ) + aRunTV->onNotifyNodeStatus(iGui, aState); + + if ( YACSGui_InputPanel* anIP = _guiMod->getInputPanel() ) + { + anIP->onNotifyNodeStatus(iGui, aState); + + map > aGuiNodeId2InPortsValues; + list IPs = aNode->getSetOfInPort(); + list::iterator itIP = IPs.begin(); + for ( ; itIP!=IPs.end(); itIP++ ) + { + int aEngineNodeId = numid; + int aGuiNodeId = iGui; + if ( dynamic_cast(aNode) ) + { + Node* aChildNode = (*itIP)->getNode(); + if ( aNode != aChildNode ) + { // the event is emitted for a child node of a composed node + // (with numid corresponded to a composed node) + aGuiNodeId = aChildNode->getNumId(); + aEngineNodeId = _guiToEngineMap[aGuiNodeId]; + } + } + string aDump = _engineProc->getInPortValue(aEngineNodeId,(*itIP)->getName().c_str()); + DEBTRACE("on status change, inport value: " << (*itIP)->getName() << " " << aDump); + /* + QString aValue(aDump); + aValue = aValue.right(aValue.length()-(aValue.find(">",aValue.find(">")+1)+1)); + aValue = aValue.left(aValue.find("<")); + if ( aValue.isEmpty() ) aValue = QString("< ? >"); + */ + QString aValue; + toString(aDump,(*itIP)->edGetType(),aValue); + DEBTRACE(aValue); + + if ( aGuiNodeId2InPortsValues.find(aGuiNodeId) == aGuiNodeId2InPortsValues.end() ) + { + map aPName2PValue; + aPName2PValue.insert( make_pair((*itIP)->getName(),string(aValue.latin1())) ); + aGuiNodeId2InPortsValues.insert( make_pair( aGuiNodeId, aPName2PValue ) ); + } + else + aGuiNodeId2InPortsValues[aGuiNodeId].insert( make_pair((*itIP)->getName(),string(aValue.latin1()) ) ); + + _guiMod->getGraph(_guiProc)->updateNodePrs(aGuiNodeId, + (*itIP)->getName(), + string(aValue.latin1())); + } + map >::iterator itMI = aGuiNodeId2InPortsValues.begin(); + for( ; itMI!=aGuiNodeId2InPortsValues.end(); itMI++ ) + anIP->onNotifyInPortValues((*itMI).first,(*itMI).second); + + map > aGuiNodeId2OutPortsValues; + list OPs = aNode->getSetOfOutPort(); + list::iterator itOP = OPs.begin(); + for ( ; itOP!=OPs.end(); itOP++ ) + { + int aEngineNodeId = numid; + int aGuiNodeId = iGui; + if ( dynamic_cast(aNode) ) + { + Node* aChildNode = (*itOP)->getNode(); + if ( aNode != aChildNode ) + { // the event is emitted for a child node of a composed node + // (with numid corresponded to a composed node) + aGuiNodeId = aChildNode->getNumId(); + aEngineNodeId = _guiToEngineMap[aGuiNodeId]; + } + } + string aDump = _engineProc->getOutPortValue(aEngineNodeId,(*itOP)->getName().c_str()); + DEBTRACE("on status change, outport value: " << (*itOP)->getName() << " " << aDump); + /* + QString aValue(aDump); + aValue = aValue.right(aValue.length()-(aValue.find(">",aValue.find(">")+1)+1)); + aValue = aValue.left(aValue.find("<")); + if ( aValue.isEmpty() ) aValue = QString("< ? >"); + */ + QString aValue; + toString(aDump,(*itOP)->edGetType(),aValue); + DEBTRACE(aValue); + + if ( aGuiNodeId2OutPortsValues.find(aGuiNodeId) == aGuiNodeId2OutPortsValues.end() ) + { + map aPName2PValue; + aPName2PValue.insert( make_pair((*itOP)->getName(),string(aValue.latin1())) ); + aGuiNodeId2OutPortsValues.insert( make_pair( aGuiNodeId, aPName2PValue ) ); + } + else + aGuiNodeId2OutPortsValues[aGuiNodeId].insert( make_pair((*itOP)->getName(),string(aValue.latin1()) ) ); + + _guiMod->getGraph(_guiProc)->updateNodePrs(aGuiNodeId, + (*itOP)->getName(), + string(aValue.latin1())); + } + map >::iterator itMO = aGuiNodeId2OutPortsValues.begin(); + for( ; itMO!=aGuiNodeId2OutPortsValues.end(); itMO++ ) + anIP->onNotifyOutPortValues((*itMO).first,(*itMO).second); + } + myImpl->setNodeState(aName, aState); } } return true; } - MESSAGE("--- Wrong event ---"); + DEBTRACE("--- Wrong event ---"); return false; } @@ -273,7 +406,7 @@ bool Observer_i::event(QEvent *e) */ void Observer_i::notifyObserver(CORBA::Long numid, const char* event) { - //MESSAGE("Observer_i::notifyObserver " << numid << " " << event ); + DEBTRACE("Observer_i::notifyObserver " << numid << " " << event ); pair myEvent(numid, event); YACSEvent* evt = new YACSEvent(myEvent); QApplication::postEvent(this, evt); // Qt will delete it when done @@ -281,11 +414,11 @@ void Observer_i::notifyObserver(CORBA::Long numid, const char* event) void Observer_i::SetImpl(YACSGui_Observer* theImpl) { - //MESSAGE("Observer_i::SetImpl"); + DEBTRACE("Observer_i::SetImpl"); myImpl = theImpl; } -void Observer_i::SetRemoteProc(YACSGui_ORB::ProcExec_ptr engineProc) +void Observer_i::SetRemoteProc(YACS_ORB::ProcExec_ptr engineProc) { - _engineProc = YACSGui_ORB::ProcExec::_duplicate(engineProc); + _engineProc = YACS_ORB::ProcExec::_duplicate(engineProc); } diff --git a/src/gui/YACSGui_Observer.h b/src/gui/YACSGui_Observer.h index cfbca2d07..519f18a1e 100644 --- a/src/gui/YACSGui_Observer.h +++ b/src/gui/YACSGui_Observer.h @@ -65,7 +65,7 @@ class YACSGui_Observer : public YACS::ENGINE::Observer }; -class Observer_i : public POA_YACSGui_ORB::Observer, +class Observer_i : public POA_YACS_ORB::Observer, public PortableServer::RefCountServantBase, public QObject { @@ -77,7 +77,7 @@ class Observer_i : public POA_YACSGui_ORB::Observer, void notifyObserver(CORBA::Long numid, const char* event); void setConversion(); void SetImpl(YACSGui_Observer* theImpl); - void SetRemoteProc(YACSGui_ORB::ProcExec_ptr engineProc); + void SetRemoteProc(YACS_ORB::ProcExec_ptr engineProc); int getEngineId(int guiId) { return _guiToEngineMap[guiId]; }; protected: virtual bool event(QEvent *e); @@ -85,7 +85,7 @@ class Observer_i : public POA_YACSGui_ORB::Observer, YACSGui_Module* _guiMod; YACSGui_Executor* _guiExec; YACS::ENGINE::Proc* _guiProc; - YACSGui_ORB::ProcExec_var _engineProc; + YACS_ORB::ProcExec_var _engineProc; YACSGui_Observer* myImpl; std::map _guiToEngineMap; std::map _engineToGuiMap; diff --git a/src/gui/YACSGui_PlusMinusGrp.cxx b/src/gui/YACSGui_PlusMinusGrp.cxx new file mode 100644 index 000000000..933130240 --- /dev/null +++ b/src/gui/YACSGui_PlusMinusGrp.cxx @@ -0,0 +1,443 @@ +// Copyright (C) 2003 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 "YACSGui_PlusMinusGrp.h" + +#include +#include + +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + + +/* + Class : YACSGui_PlusMinusGrp + Description : Group box containing data table and "plus" "minus" and "insert" buttons +*/ + +//================================================================ +// Function : YACSGui_PlusMinusGrp +// Purpose : +//================================================================ +YACSGui_PlusMinusGrp::YACSGui_PlusMinusGrp( QWidget* theParent, + const QString& theTitle, + const int theBtns ) +: QtxGroupBox( 1, Qt::Horizontal, theTitle, theParent ), +myAddBtn( 0 ), +myInsertBtn( 0 ), +myRemoveBtn( 0 ), +myUpBtn( 0 ), +myDownBtn( 0 ), +myMinNumRow( 0 ), +myMaxNumRow( -1 ), +myAddBeforeRowNum( -1 ) +{ + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + + // cerate buttons + if ( theBtns & UpBtn ) + { + QPixmap upPix = aResMgr->loadPixmap( "YACS", tr( "ICON_UP" ) ); + myUpBtn = new QToolButton( 0 ); + myUpBtn->setIconSet( upPix ); + myUpBtn->setFixedSize( upPix.size() ); + insertTitleWidget( myUpBtn ); + } + else + myUpBtn = 0; + + if ( theBtns & DownBtn ) + { + QPixmap downPix = aResMgr->loadPixmap( "YACS", tr( "ICON_DOWN" ) ); + myDownBtn = new QToolButton( 0 ); + myDownBtn->setIconSet( downPix ); + myDownBtn->setFixedSize( downPix.size() ); + insertTitleWidget( myDownBtn ); + } + else + myDownBtn = 0; + + if ( theBtns & InsertBtn ) + { + QPixmap insertPix = aResMgr->loadPixmap( "YACS", tr( "ICON_INSERT" ) ); + myInsertBtn = new QToolButton( 0 ); + myInsertBtn->setIconSet( insertPix ); + myInsertBtn->setFixedSize( insertPix.size() ); + insertTitleWidget( myInsertBtn ); + } + else + myInsertBtn = 0; + + if ( theBtns & SelectBtn ) + { + QPixmap selectPix = aResMgr->loadPixmap( "YACS", tr( "ICON_SELECT" ) ); + mySelectBtn = new QToolButton( 0 ); + mySelectBtn->setIconSet( selectPix ); + mySelectBtn->setFixedSize( selectPix.size() ); + mySelectBtn->setToggleButton( true ); + insertTitleWidget( mySelectBtn ); + } + else + mySelectBtn = 0; + + if ( theBtns & PlusBtn ) + { + QPixmap plusPix = aResMgr->loadPixmap( "YACS", tr( "ICON_PLUS" ) ); + myAddBtn = new QToolButton( 0 ); + myAddBtn->setIconSet( plusPix ); + myAddBtn->setFixedSize( plusPix.size() ); + insertTitleWidget( myAddBtn ); + } + else + myAddBtn = 0; + + if ( theBtns & MinusBtn ) + { + QPixmap minusPix = aResMgr->loadPixmap( "YACS", tr( "ICON_MINUS" ) ); + myRemoveBtn = new QToolButton( 0 ); + myRemoveBtn->setIconSet( minusPix ); + myRemoveBtn->setFixedSize( minusPix.size() ); + insertTitleWidget( myRemoveBtn ); + } + else + myRemoveBtn = 0; + + //create table + myTable = new YACSGui_Table( 0, 0, this ); + myTable->setSelectionMode( QTable::SingleRow ); + + // connect signals and slots + if ( myUpBtn ) + connect( myUpBtn, SIGNAL( clicked() ), SLOT( onUp() ) ); + if ( myDownBtn ) + connect( myDownBtn, SIGNAL( clicked() ), SLOT( onDown() ) ); + if ( myAddBtn ) + connect( myAddBtn, SIGNAL( clicked() ), SLOT( onAdd() ) ); + if ( myInsertBtn ) + connect( myInsertBtn, SIGNAL( clicked() ), SLOT( onInsert() ) ); + if ( mySelectBtn ) + connect( mySelectBtn, SIGNAL( toggled( bool ) ), SLOT( onSelect( bool ) ) ); + if ( myRemoveBtn ) + connect( myRemoveBtn, SIGNAL( clicked() ), SLOT( onRemove() ) ); + + connect( myTable, SIGNAL( selectionChanged() ), this, SLOT( onTableSelectionChanged() ) ); + connect( myTable, SIGNAL( currentChanged( int, int ) ), this, SLOT( onTableSelectionChanged() ) ); +} + +YACSGui_PlusMinusGrp::~YACSGui_PlusMinusGrp() +{ +} + +//================================================================ +// Function : Table +// Purpose : +//================================================================ +YACSGui_Table* YACSGui_PlusMinusGrp::Table() +{ + return myTable; +} + +//================================================================ +// Function : onUp +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::onUp() +{ + int row; + row = myTable->currentRow( ); + if ( row > 0 ) + { + myTable->swapRows( row, row-1 ); + myTable->updateContents( QRect( myTable->columnPos(0), + myTable->rowPos(row-1), + myTable->contentsWidth(), + myTable->rowHeight(row)+myTable->rowHeight(row-1) ) ); + emit MovedUp( row-1 ); + } + + EnableBtn( AllBtn ); +} + +//================================================================ +// Function : onDown +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::onDown() +{ + int row; + row = myTable->currentRow( ); + if ( row >= 0 ) + { + myTable->swapRows( row, row+1 ); + myTable->updateContents( QRect( myTable->columnPos(0), + myTable->rowPos(row), + myTable->contentsWidth(), + myTable->rowHeight(row)+myTable->rowHeight(row+1) ) ); + emit MovedDown( row+1 ); + } + + EnableBtn( AllBtn ); +} + +//================================================================ +// Function : onInsert +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::onInsert() +{ + int row; + row = myTable->currentRow( ); + if ( row < 0 ) + onAdd(); + else + { + myTable->insertRows( row ); + myTable->setCurrentCell( row, myTable->currentColumn() ); + myTable->ensureCellVisible( row, myTable->currentColumn() ); + emit Inserted( row ); + } + + EnableBtn( AllBtn ); +} + +//================================================================ +// Function : onSelect +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::onSelect( bool on ) +{ + DEBTRACE(">> YACSGui_PlusMinusGrp::onSelect : on = " << on); + if ( on ) + { + int row = myTable->currentRow(); + int col = myTable->currentColumn(); + DEBTRACE(">> row = " << row << " col = " << col); + if ( row >= 0 && col >= 0 ) + { + emit initSelection( row, col ); + } + + EnableBtn( AllBtn ); + } + else + { + // do nothing (i.e. rollback the selection) + } +} + +//================================================================ +// Function : onAdd +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::onAdd() +{ + if ( myAddBeforeRowNum >= 0 ) + { + myTable->insertRows( myAddBeforeRowNum ); + myTable->ensureCellVisible( myAddBeforeRowNum, myTable->currentColumn() ); + emit Added( myAddBeforeRowNum ); + } + else + { + myTable->setNumRows( myTable->numRows() + 1 ); + myTable->ensureCellVisible( myTable->numRows() - 1, myTable->currentColumn() ); + emit Added( myTable->numRows() - 1 ); + } + + EnableBtn( AllBtn ); +} + +//================================================================ +// Function : onRemove +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::onRemove() +{ + DEBTRACE("YACSGui_PlusMinusGrp::onRemove()"); + int row; + row = myTable->currentRow( ); + if ( row >= 0 ) + { + emit Removed( row ); + myTable->removeRow( row ); + myTable->ensureCellVisible( row-1, myTable->currentColumn() ); + } + + EnableBtn( AllBtn ); +} + +//================================================================ +// Function : onTableSelectionChanged +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::onTableSelectionChanged() +{ + DEBTRACE("YACSGui_PlusMinusGrp::onTableSelectionChanged"); + if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() ) + if ( aTable == myTable && aTable->currentSelection() != -1 ) // the current selection is not empty + { + EnableBtn( AllBtn ); + EnableBtn( SelectBtn, true ); + } +} + +//================================================================ +// Function : ShowBtn +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::ShowBtn( const int theBtns ) +{ + if ( ( theBtns & UpBtn ) && myUpBtn != 0 ) + myUpBtn->show(); + if ( ( theBtns & DownBtn ) && myDownBtn != 0 ) + myDownBtn->show(); + if ( ( theBtns & InsertBtn ) && myInsertBtn != 0 ) + myInsertBtn->show(); + if ( ( theBtns & SelectBtn ) && mySelectBtn != 0 ) + mySelectBtn->show(); + if ( ( theBtns & PlusBtn ) && myAddBtn != 0 ) + myAddBtn->show(); + if ( ( theBtns & MinusBtn ) && myRemoveBtn != 0 ) + myRemoveBtn->show(); +} + +//================================================================ +// Function : HideBtn +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::HideBtn( const int theBtns ) +{ + if ( ( theBtns & UpBtn ) && myUpBtn != 0 ) + myUpBtn->hide(); + if ( ( theBtns & DownBtn ) && myDownBtn != 0 ) + myDownBtn->hide(); + if ( ( theBtns & InsertBtn ) && myInsertBtn != 0 ) + myInsertBtn->hide(); + if ( ( theBtns & SelectBtn ) && mySelectBtn != 0 ) + mySelectBtn->hide(); + if ( ( theBtns & PlusBtn ) && myAddBtn != 0 ) + myAddBtn->hide(); + if ( ( theBtns & MinusBtn ) && myRemoveBtn != 0 ) + myRemoveBtn->hide(); +} + +//================================================================ +// Function : EnableBtn +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::EnableBtn( const int theBtns ) +{ + if ( myTable->numRows() == 0 ) // an empty table + { + EnableBtn( UpBtn | DownBtn | MinusBtn, false ); + return; + } + + bool theEnable = true; + + if( myMaxNumRow <= myTable->numRows() && myMaxNumRow != -1 ) + { + theEnable = false; + } + + EnableBtn( InsertBtn, theEnable ); + EnableBtn( PlusBtn, theEnable ); + + if ( ( theBtns & MinusBtn ) && myRemoveBtn != 0 ) + { + theEnable = true; + if( myMinNumRow >= myTable->numRows() && myMinNumRow != 0 ) + theEnable = false; + myRemoveBtn->setEnabled( theEnable ); + } + + if ( myTable->numRows() == 1 ) + EnableBtn( UpBtn | DownBtn, false ); + else if ( myTable->currentRow() == 0 ) + { + EnableBtn( UpBtn, false ); + EnableBtn( DownBtn, true ); + } + else if ( myTable->currentRow() == myTable->numRows()-1 ) + { + EnableBtn( UpBtn, true ); + EnableBtn( DownBtn, false ); + } + else if ( myTable->currentRow() > 0 ) + EnableBtn( UpBtn | DownBtn, true ); +} + +//================================================================ +// Function : EnableBtn +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::EnableBtn( const int theBtns, bool theEnable ) +{ + if ( ( theBtns & UpBtn ) && myUpBtn != 0 ) + myUpBtn->setEnabled( theEnable ); + if ( ( theBtns & DownBtn ) && myDownBtn != 0 ) + myDownBtn->setEnabled( theEnable ); + if ( ( theBtns & InsertBtn ) && myInsertBtn != 0 ) + myInsertBtn->setEnabled( theEnable ); + if ( ( theBtns & SelectBtn ) && mySelectBtn != 0 ) + mySelectBtn->setEnabled( theEnable ); + if ( ( theBtns & PlusBtn ) && myAddBtn != 0 ) + myAddBtn->setEnabled( theEnable ); + if ( ( theBtns & MinusBtn ) && myRemoveBtn != 0 ) + myRemoveBtn->setEnabled( theEnable ); +} + +//================================================================ +// Function : Btn +// Purpose : +//================================================================ +QToolButton* YACSGui_PlusMinusGrp::Btn( const int theBtn ) const +{ + QToolButton* aRet = 0; + + if ( theBtn == UpBtn && myUpBtn != 0 ) + aRet = myUpBtn; + else if ( theBtn == DownBtn && myDownBtn != 0 ) + aRet = myDownBtn; + else if ( theBtn == InsertBtn && myInsertBtn != 0 ) + aRet = myInsertBtn; + else if ( theBtn == SelectBtn && mySelectBtn != 0 ) + aRet = mySelectBtn; + else if ( theBtn == PlusBtn && myAddBtn != 0 ) + aRet = myAddBtn; + else if ( theBtn == MinusBtn && myRemoveBtn != 0 ) + aRet = myRemoveBtn; + + return aRet; +} + +//================================================================ +// Function : setOffSelect +// Purpose : +//================================================================ +void YACSGui_PlusMinusGrp::setOffSelect() +{ + if ( mySelectBtn && mySelectBtn->isOn() ) + mySelectBtn->setOn(false); +} diff --git a/src/gui/YACSGui_PlusMinusGrp.h b/src/gui/YACSGui_PlusMinusGrp.h new file mode 100644 index 000000000..8ee379c21 --- /dev/null +++ b/src/gui/YACSGui_PlusMinusGrp.h @@ -0,0 +1,162 @@ +// Copyright (C) 2003 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 YACSGui_PlusMinusGrp_H +#define YACSGui_PlusMinusGrp_H + +#include "QtxGroupBox.h" +#include + +class YACSGui_Table; +class QToolButton; + +/*! + Class : YACSGui_PlusMinusGrp + Description : Group box containing data table and "plus" "minus" "insert" "up" and "down" buttons +*/ + + +class YACSGui_PlusMinusGrp : public QtxGroupBox +{ + Q_OBJECT + +public: + + enum { PlusBtn = 0x1, MinusBtn = 0x2, InsertBtn = 0x4, UpBtn = 0x8, DownBtn = 0x10, SelectBtn = 0x20, + AllBtn = PlusBtn | MinusBtn | InsertBtn | UpBtn | DownBtn | SelectBtn }; + +public: + YACSGui_PlusMinusGrp( QWidget* theParent, const QString& theTitle, const int theBtns = AllBtn ); + virtual ~YACSGui_PlusMinusGrp(); + + YACSGui_Table* Table(); + void ShowBtn( const int = AllBtn ); + void HideBtn( const int = AllBtn ); + + /*! buttons become enabled or disabled depending on number of rows at a table + and max allowed number of rows for this table + parameter: defines which buttons will be enabled/disabled + */ + void EnableBtn( const int = AllBtn ); + void EnableBtn( const int, bool theEnable ); + + /*! Returns the tool button with given id + parameter: defines tool buttons' id + */ + QToolButton* Btn( const int ) const; + + /*! Set min allowed number of rows at the table. + It is 0 by default. + */ + inline void SetMinNumRow( const int theMinRow ) { myMinNumRow = theMinRow; }; + + /*! + returns min allowed number of strings for table or 0 + */ + inline int MinNumRow() { return myMinNumRow; } + + /*! Set max allowed number of rows at the table. + It is -1 by default. That means that number of rows is not limited + */ + inline void SetMaxNumRow( const int theMaxRow ) { myMaxNumRow = theMaxRow; }; + + /*! + returns max allowed number of strings for table or -1 + */ + inline int MaxNumRow() { return myMaxNumRow; } + + /*! Set the row number before which a new row will be added in case of "Plus" button + or "Insert" button with empty rows selection in the table. + It is -1 by default. That means that row is added to the end of the table + */ + inline void SetAddBeforeRowNum( const int theAddBeforeRowNum ) { myAddBeforeRowNum = theAddBeforeRowNum; }; + + /*! + returns the row number before which a new row will be added or -1 + */ + inline int AddBeforeRowNum() { return myAddBeforeRowNum; } + + /*! + untoggled the selection button + */ + void setOffSelect(); + +signals: + void MovedUp( const int theUpRowId ); + void MovedDown( const int theDownRowId ); + void Inserted( const int theInsRowId ); + void initSelection( const int theRowId, const int theColId ); + void Added( const int theRowId ); + void Removed( const int theRowId ); + +private slots: + + /*! SLOT which called when button Up is pressed. + Moves up the selected row by one row. + */ + void onUp(); + + /*! SLOT which called when button Down is pressed. + Moves down the selected row by one row. + */ + void onDown(); + + /*! SLOT which called when button Insert is pressed. + Adds new row before selected. + */ + void onInsert(); + + /*! SLOT which called when button Select is pressed. + Emits the signal to start the selection in the tree. + The selected object have to be put into the current cell. + */ + void onSelect( bool ); + + /*! SLOT which called when button Add is pressed. + Adds new string at table's bottom. + */ + void onAdd(); + + /*! SLOT which called when button Remove is pressed. + Removed selected row from table. + */ + void onRemove(); + + /*! SLOT which called whenever a selection in the table changes + or the current cell has changed. + Apdated the enable/disable states of the tool buttons. + */ + void onTableSelectionChanged(); + +private: + int myMinNumRow; + int myMaxNumRow; + int myAddBeforeRowNum; + + YACSGui_Table* myTable; + QToolButton* myAddBtn; + QToolButton* myInsertBtn; + QToolButton* myRemoveBtn; + QToolButton* myUpBtn; + QToolButton* myDownBtn; + QToolButton* mySelectBtn; +}; + +#endif diff --git a/src/gui/YACSGui_PropertyPage.cxx b/src/gui/YACSGui_PropertyPage.cxx new file mode 100644 index 000000000..8d7e52350 --- /dev/null +++ b/src/gui/YACSGui_PropertyPage.cxx @@ -0,0 +1,128 @@ +// Copyright (C) 2003 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 +// #include + +// #include +// #include + +#include +#include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// #include + +// #include + +// #include +// #include +// #include +// #include +// #include +// #include + +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +#include + +// #include + +// #define SPACING 5 +// #define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_PropertyPage_InputPage + Description : This class is used for parameters of input panel. + All pages of input panel must be derived from it +*/ + +YACSGui_PropertyPage::YACSGui_PropertyPage( QWidget* theParent, YACSGui_Module* theModule ) + : QFrame( theParent ), + myModule(theModule), + myView(0) +{ + setLineWidth(2); + setFrameStyle(QFrame::StyledPanel|QFrame::Raised); +} + +YACSGui_PropertyPage::~YACSGui_PropertyPage() +{ +} + +void YACSGui_PropertyPage::onApply() +{ +} + diff --git a/src/gui/YACSGui_RunMode.cxx b/src/gui/YACSGui_RunMode.cxx index af72d2bb2..06b5e031d 100644 --- a/src/gui/YACSGui_RunMode.cxx +++ b/src/gui/YACSGui_RunMode.cxx @@ -1,5 +1,6 @@ #include "YACSGui_RunMode.h" +#include "YACSGui_TreeViewItem.h" #include "YACSGui_Executor.h" #include "Executor.hxx" #include "Proc.hxx" @@ -15,118 +16,12 @@ #include #include "utilities.h" +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace std; using namespace YACS::ENGINE; - - -ComposedNodeViewItem::ComposedNodeViewItem(QListView *parent, QString label) - : QListViewItem(parent, label) -{ - _cf = Qt::black; -} - -ComposedNodeViewItem::ComposedNodeViewItem(QListViewItem *parent, QString label) - : QListViewItem(parent, label) -{ - _cf = Qt::black; -} - -void ComposedNodeViewItem::paintCell( QPainter *p, const QColorGroup &cg, - int column, int width, int alignment ) -{ - //MESSAGE("ComposedNodeViewItem::paintCell " << column); - QColorGroup _cg( cg ); - QColor c = _cg.text(); - if (column == 1) _cg.setColor( QColorGroup::Text, _cf ); - QListViewItem::paintCell( p, _cg, column, width, alignment ); - if (column == 1) _cg.setColor( QColorGroup::Text, c ); -} - -void ComposedNodeViewItem::setState(int state) -{ - //MESSAGE("ComposedNodeViewItem::setState"); - _state = state; - switch (_state) - { - case YACS::UNDEFINED: _cf=Qt::lightGray; setText(1,"UNDEFINED"); repaint(); break; - case YACS::INITED: _cf=Qt::gray; setText(1,"INITED"); repaint(); break; - case YACS::TOLOAD: _cf=Qt::darkYellow; setText(1,"TOLOAD"); repaint(); break; - case YACS::LOADED: _cf=Qt::darkMagenta; setText(1,"LOADED"); repaint(); break; - case YACS::TOACTIVATE: _cf=Qt::darkCyan; setText(1,"TOACTIVATE"); repaint(); break; - case YACS::ACTIVATED: _cf=Qt::darkBlue; setText(1,"ACTIVATED"); repaint(); break; - case YACS::DESACTIVATED: _cf=Qt::gray; setText(1,"DESACTIVATED"); repaint(); break; - case YACS::DONE: _cf=Qt::darkGreen; setText(1,"DONE"); repaint(); break; - case YACS::SUSPENDED: _cf=Qt::gray; setText(1,"SUSPENDED"); repaint(); break; - case YACS::LOADFAILED: _cf.setHsv(320,255,255); setText(1,"LOADFAILED"); repaint(); break; - case YACS::EXECFAILED: _cf.setHsv( 20,255,255); setText(1,"EXECFAILED"); repaint(); break; - case YACS::PAUSE: _cf.setHsv(180,255,255); setText(1,"PAUSE"); repaint(); break; - case YACS::INTERNALERR: _cf.setHsv(340,255,255); setText(1,"INTERNALERR"); repaint(); break; - case YACS::DISABLED: _cf.setHsv( 40,255,255); setText(1,"DISABLED"); repaint(); break; - case YACS::FAILED: _cf.setHsv( 20,255,255); setText(1,"FAILED"); repaint(); break; - case YACS::ERROR: _cf.setHsv( 0,255,255); setText(1,"ERROR"); repaint(); break; - default: _cf=Qt::lightGray; repaint(); - } -} - - -NodeViewItem::NodeViewItem(QListView *parent, - const QString &text, - Type tt, - YACS::ENGINE::ElementaryNode *node) - : QCheckListItem(parent, text, tt) -{ - _cf = Qt::green; - _node = node; -} - -NodeViewItem::NodeViewItem(QListViewItem *parent, - const QString &text, - Type tt, - YACS::ENGINE::ElementaryNode *node) - : QCheckListItem(parent, text, tt) -{ - _cf = Qt::green; - _node = node; -} - -void NodeViewItem::paintCell( QPainter *p, const QColorGroup &cg, - int column, int width, int alignment ) -{ - QColorGroup _cg( cg ); - QColor c = _cg.text(); - if (column == 1) _cg.setColor( QColorGroup::Text, _cf ); - QCheckListItem::paintCell( p, _cg, column, width, alignment ); - if (column == 1) _cg.setColor( QColorGroup::Text, c ); -} - -void NodeViewItem::setState(int state) -{ - //MESSAGE("NodeViewItem::setState"); - _state = state; - switch (_state) - { - case YACS::UNDEFINED: _cf=Qt::lightGray; setText(1,"UNDEFINED"); repaint(); break; - case YACS::INITED: _cf=Qt::gray; setText(1,"INITED"); repaint(); break; - case YACS::TOLOAD: _cf=Qt::darkYellow; setText(1,"TOLOAD"); repaint(); break; - case YACS::LOADED: _cf=Qt::darkMagenta; setText(1,"LOADED"); repaint(); break; - case YACS::TOACTIVATE: _cf=Qt::darkCyan; setText(1,"TOACTIVATE"); repaint(); break; - case YACS::ACTIVATED: _cf=Qt::darkBlue; setText(1,"ACTIVATED"); repaint(); break; - case YACS::DESACTIVATED: _cf=Qt::gray; setText(1,"DESACTIVATED"); repaint(); break; - case YACS::DONE: _cf=Qt::darkGreen; setText(1,"DONE"); repaint(); break; - case YACS::SUSPENDED: _cf=Qt::gray; setText(1,"SUSPENDED"); repaint(); break; - case YACS::LOADFAILED: _cf.setHsv(320,255,255); setText(1,"LOADFAILED"); repaint(); break; - case YACS::EXECFAILED: _cf.setHsv( 20,255,255); setText(1,"EXECFAILED"); repaint(); break; - case YACS::PAUSE: _cf.setHsv(180,255,255); setText(1,"PAUSE"); repaint(); break; - case YACS::INTERNALERR: _cf.setHsv(340,255,255); setText(1,"INTERNALERR"); repaint(); break; - case YACS::DISABLED: _cf.setHsv( 40,255,255); setText(1,"DISABLED"); repaint(); break; - case YACS::FAILED: _cf.setHsv( 20,255,255); setText(1,"FAILED"); repaint(); break; - case YACS::ERROR: _cf.setHsv( 0,255,255); setText(1,"ERROR"); repaint(); break; - default: _cf=Qt::lightGray; repaint(); - } -} - - YACSGui_RunMode::YACSGui_RunMode( YACSGui_Executor* guiExec, QWidget* parent, const char* name, @@ -143,7 +38,7 @@ YACSGui_RunMode::YACSGui_RunMode( YACSGui_Executor* guiExec, void YACSGui_RunMode::resetTreeNode() { - //MESSAGE("YACSGui_RunMode::resetTreeNode"); + //DEBTRACE("YACSGui_RunMode::resetTreeNode"); _proc = _guiExec->getProc(); assert(_proc); @@ -153,8 +48,8 @@ void YACSGui_RunMode::resetTreeNode() rb_modeContinue->setChecked(true); - ComposedNodeViewItem* item = new ComposedNodeViewItem(listView_breakpoints, - "root" ); + YACSGui_ComposedNodeViewItem* item = new YACSGui_ComposedNodeViewItem(listView_breakpoints, + "root" ); _mapListViewItem[_proc->getNumId()] = item; addTreeNode(item, (ComposedNode*)(_proc)); listView_breakpoints->setOpen(item, true); @@ -167,24 +62,26 @@ YACSGui_RunMode::~YACSGui_RunMode() qWarning("YACSGui_RunMode::~YACSGui_RunMode"); } -void YACSGui_RunMode::addTreeNode(ComposedNodeViewItem *parent, +void YACSGui_RunMode::addTreeNode(YACSGui_ComposedNodeViewItem *parent, YACS::ENGINE::ComposedNode* father) { - set setOfNode= father->edGetDirectDescendants(); - for(set::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + list setOfNode= father->edGetDirectDescendants(); + for(list::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) { if (ElementaryNode* elemNode = dynamic_cast (*iter) ) { - NodeViewItem* item = new NodeViewItem(parent, - (*iter)->getQualifiedName(), - NodeViewItem::CheckBox, - elemNode); + YACSGui_ElementaryNodeViewItem* item = + new YACSGui_ElementaryNodeViewItem(parent, + (*iter)->getQualifiedName(), + YACSGui_ElementaryNodeViewItem::CheckBox, + elemNode); _mapListViewItem[(*iter)->getNumId()] = item; } else { - ComposedNodeViewItem* item = new ComposedNodeViewItem(parent, - (*iter)->getQualifiedName()); + YACSGui_ComposedNodeViewItem* item = + new YACSGui_ComposedNodeViewItem(parent, + (*iter)->getQualifiedName()); _mapListViewItem[(*iter)->getNumId()] = item; addTreeNode(item, (ComposedNode*)(*iter)); } @@ -194,13 +91,20 @@ void YACSGui_RunMode::addTreeNode(ComposedNodeViewItem *parent, void YACSGui_RunMode::onResume() { qWarning("YACSGui_RunMode::onResume"); + DEBTRACE(">> ::onResume begin -->"); if (_guiExec->checkEndOfDataFlow(false)) // --- finished or not started { + DEBTRACE(">> before run"); //resetTreeNode(); _guiExec->runDataflow(true); // --- remote run only + DEBTRACE(">> after run"); } - else // --- in progress (suspended or running) + else { // --- in progress (suspended or running) + DEBTRACE(">> before resume"); _guiExec->resumeDataflow(); + DEBTRACE(">> after resume"); + } + DEBTRACE(">> ::onResume end <--"); } void YACSGui_RunMode::onPause() @@ -223,7 +127,7 @@ void YACSGui_RunMode::onModeContinue() _guiExec->setContinueMode(); // QListViewItemIterator it( listView_breakpoints ); // for ( ; it.current(); ++it ) -// if (NodeViewItem* nodeit = dynamic_cast (*it)) +// if (YACSGui_ElementaryNodeViewItem* nodeit = dynamic_cast (*it)) // nodeit->setEnabled(false); } @@ -267,7 +171,7 @@ void YACSGui_RunMode::onAllNextToRun() { ((QCheckListItem*)it.current())->setOn(true); string nodeName = it.current()->text(0); - MESSAGE(nodeName); + DEBTRACE(nodeName); nextStepList.push_back(nodeName); ++it; } @@ -290,10 +194,10 @@ void YACSGui_RunMode::onRemoveAllNextToRun() void YACSGui_RunMode::onBreakpointClicked(QListViewItem *item) { qWarning("YACSGui_RunMode::onBreakpointClicked"); - NodeViewItem* elemNodeItem = dynamic_cast(item); + YACSGui_ElementaryNodeViewItem* elemNodeItem = dynamic_cast(item); if (elemNodeItem) { - MESSAGE("click on node " << elemNodeItem->getNode()->getQualifiedName()); + DEBTRACE("click on node " << elemNodeItem->getNode()->getQualifiedName()); if (elemNodeItem->isOn()) { if (rb_modeContinue->isChecked()) @@ -308,8 +212,8 @@ void YACSGui_RunMode::onBreakpointClicked(QListViewItem *item) list breakpointList; for (set::iterator pos = _breakpointSet.begin(); pos != _breakpointSet.end(); ++pos) { - string nodeName =_proc->getChildName(((NodeViewItem*)(_mapListViewItem[*pos]))->getNode()); - MESSAGE(nodeName); + string nodeName =_proc->getChildName(((YACSGui_ElementaryNodeViewItem*)(_mapListViewItem[*pos]))->getNode()); + DEBTRACE(nodeName); breakpointList.push_back(nodeName); } _guiExec->setBreakpointList(breakpointList); @@ -320,13 +224,13 @@ void YACSGui_RunMode::onNextStepClicked(QListViewItem *item) { qWarning("YACSGui_RunMode::onNextStepClicked"); list nextStepList; - MESSAGE("click on node " << item->text(0)); + DEBTRACE("click on node " << item->text(0)); QListViewItemIterator it(listView_nextSteps); for ( ; it.current(); ++it ) if (((QCheckListItem*)it.current())->isOn()) { string nodeName = it.current()->text(0); - MESSAGE(nodeName); + DEBTRACE(nodeName); nextStepList.push_back(nodeName); } _guiExec->setNextStepList(nextStepList); @@ -370,16 +274,16 @@ void YACSGui_RunMode::onNotifyNextSteps(std::list nextSteps) void YACSGui_RunMode::onNotifyNodeStatus(int nodeId, int status) { - //MESSAGE("YACSGui_RunMode::onNotifyNodeStatus " << nodeId << " " << status ); + //DEBTRACE("YACSGui_RunMode::onNotifyNodeStatus " << nodeId << " " << status ); QListViewItem* it = _mapListViewItem[nodeId]; if (!it) return; - NodeViewItem* itn = dynamic_cast(it); + YACSGui_ElementaryNodeViewItem* itn = dynamic_cast(it); if (itn) { itn->setState(status); return; } - ComposedNodeViewItem* itc = dynamic_cast(it); + YACSGui_ComposedNodeViewItem* itc = dynamic_cast(it); if (itc) { itc->setState(status); diff --git a/src/gui/YACSGui_RunMode.h b/src/gui/YACSGui_RunMode.h index 0c255f940..e5aa6b17f 100644 --- a/src/gui/YACSGui_RunMode.h +++ b/src/gui/YACSGui_RunMode.h @@ -11,44 +11,9 @@ #include #include -class YACSGui_Executor; -class YACS::ENGINE::ElementaryNode; - -class ComposedNodeViewItem: public QListViewItem -{ - public: - ComposedNodeViewItem(QListView *parent, QString label); - ComposedNodeViewItem(QListViewItem *parent, QString label); - void setState(int state); - virtual void paintCell( QPainter *p, const QColorGroup &cg, - int column, int width, int alignment ); - - protected: - int _state; - QColor _cf; -}; +class YACSGui_ComposedNodeViewItem; -class NodeViewItem: public QCheckListItem -{ - public: - NodeViewItem(QListView *parent, - const QString &text, - Type tt = RadioButtonController, - YACS::ENGINE::ElementaryNode *node = 0); - NodeViewItem(QListViewItem *parent, - const QString &text, - Type tt = RadioButtonController, - YACS::ENGINE::ElementaryNode *node = 0); - void setState(int state); - virtual void paintCell( QPainter *p, const QColorGroup &cg, - int column, int width, int alignment ); - YACS::ENGINE::ElementaryNode* getNode() { return _node;}; - - protected: - int _state; - QColor _cf; - YACS::ENGINE::ElementaryNode *_node; -}; +class YACSGui_Executor; class YACSGui_RunMode : public runMode { @@ -83,7 +48,7 @@ public: protected: void resetTreeNode(); - void addTreeNode(ComposedNodeViewItem *parent, + void addTreeNode(YACSGui_ComposedNodeViewItem *parent, YACS::ENGINE::ComposedNode* father); YACSGui_Executor* _guiExec; diff --git a/src/gui/YACSGui_SchemaPage.cxx b/src/gui/YACSGui_SchemaPage.cxx new file mode 100644 index 000000000..56ce5b055 --- /dev/null +++ b/src/gui/YACSGui_SchemaPage.cxx @@ -0,0 +1,449 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_SchemaPage + Description : Page for schema properties +*/ + +YACSGui_SchemaPage::YACSGui_SchemaPage( QWidget* theParent, const char* theName, WFlags theFlags ) + : SchemaPage( theParent, theName, theFlags ), + GuiObserver(), + mySProc( 0 ), + myMode( YACSGui_InputPanel::EditMode ) +{ + DEBTRACE("YACSGui_SchemaPage::YACSGui_SchemaPage"); + myErrorLog->setReadOnly(true); + // temporary disabled, because of data flow and data stream views are not yet implemented + myDataFlowMode_2->setEnabled(false); + myDataStreamMode_2->setEnabled(false); + + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( anApp ) + { + anApp->lcc()->preSet(myParams); + } + else + { + myParams.OS = ""; + myParams.mem_mb = 0; + myParams.cpu_clock = 0; + myParams.nb_proc_per_node = 0; + myParams.nb_node = 0; + myParams.isMPI = false; + myParams.parallelLib = ""; + myParams.nb_component_nodes = 0; + } + myParams.container_name = "YACSServer"; + myParams.hostname = "localhost"; + myExecutionName->setText(QString(myParams.container_name)); + myHostName->setCurrentText(QString(myParams.hostname)); + + fillHostNames(); +} + +YACSGui_SchemaPage::~YACSGui_SchemaPage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); + + if ( mySProc ) mySProc->detach(this); +} + +void YACSGui_SchemaPage::select( bool isSelected ) +{ + DEBTRACE("YACSGui_SchemaPage::select"); +} + +void YACSGui_SchemaPage::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE("YACSGui_SchemaPage::update"); +} + +void YACSGui_SchemaPage::setSProc( YACS::HMI::SubjectProc* theSProc ) +{ + if ( theSProc && mySProc != theSProc ) + { + if ( mySProc ) mySProc->detach(this); //detach from old schema + mySProc = theSProc; + mySProc->attach(this); // attach to new schema + updateState(); + } +} + +YACS::ENGINE::Proc* YACSGui_SchemaPage::getProc() const +{ + return ( mySProc ? dynamic_cast(mySProc->getNode()) : 0 ); +} + +QString YACSGui_SchemaPage::getSchemaName() const +{ + return ( mySProc ? QString( mySProc->getName() ) : QString("") ); +} + +void YACSGui_SchemaPage::setSchemaName( const QString& theName ) +{ + if ( mySProc && myMode == YACSGui_InputPanel::EditMode ) { + mySProc->getNode()->setName( theName.latin1() ); + mySProc->update( RENAME, 0, mySProc ); + + if(getInputPanel()) + getInputPanel()->getModule()->getDataModel()->updateItem( getProc(), true ); + } +} + +void YACSGui_SchemaPage::onApply() +{ + DEBTRACE("YACSGui_SchemaPage::onApply"); + // Rename a schema + if ( mySchemaName ) setSchemaName( mySchemaName->text() ); + + // set container parameters for YACS Engine + if ( myMode == YACSGui_InputPanel::RunMode ) + if (GuiContext *context = GuiContext::getCurrent()) + { + pair yc(myExecutionName->text().latin1(), myHostName->currentText().latin1()); + context->setYACSContainer(yc); + myParams.container_name = myExecutionName->text().latin1(); + myParams.hostname = myHostName->currentText().latin1(); + } + + // Change a view mode of a schema + QButton* aSelBtn = ViewModeButtonGroup->selected(); + if ( aSelBtn && getInputPanel() ) + if ( aSelBtn == myFullMode_2 ) + getInputPanel()->getModule()->onFullView(); + else if ( aSelBtn == myControlMode_2 ) + getInputPanel()->getModule()->onControlView(); + //else if ( aSelBtn == myDataFlowMode_2 ) + //else if ( aSelBtn == myDataStreamMode_2 ) +} + +YACSGui_InputPanel* YACSGui_SchemaPage::getInputPanel() const +{ + DEBTRACE("YACSGui_SchemaPage::getInputPanel"); + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( !anApp ) + return 0; + + YACSGui_Module* aModule = dynamic_cast( anApp->activeModule() ); + if( !aModule ) + return 0; + + return aModule->getInputPanel(); +} + +void YACSGui_SchemaPage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + DEBTRACE("YACSGui_SchemaPage::setMode"); + myMode = theMode; + + if ( !ViewModeButtonGroup || !NextToRunGroupBox || !mySchemaName ) return; + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + ViewModeButtonGroup->show(); + ContainerGroupBox->hide(); + NextToRunGroupBox->hide(); + mySchemaName->setReadOnly(false); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + ViewModeButtonGroup->hide(); + ContainerGroupBox->show(); + NextToRunGroupBox->show(); + mySchemaName->setReadOnly(true); + // --- when YACS engine created, its parameters are not modifiable + if (getInputPanel()->getModule()->lookForExecutor()) + { + myExecutionName->setReadOnly(true); + myHostName->setEnabled(false); + } + else + { + myExecutionName->setReadOnly(false); + myHostName->setEnabled(true); + } + } + + if ( mySchemaName ) mySchemaName->setText( getSchemaName() ); +} + +void YACSGui_SchemaPage::checkModifications() +{ + DEBTRACE("YACSGui_SchemaPage::checkModifications"); + if ( !getProc() ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + + if ( myMode == YACSGui_InputPanel::RunMode ) + { + if (GuiContext *context = GuiContext::getCurrent()) + { + DEBTRACE(isModified); + QString contname(myParams.container_name); + QString hostname(myParams.hostname); + if (myExecutionName->text().compare(contname) != 0 ) isModified = true; + if (myHostName->currentText().compare(hostname) != 0 ) isModified = true; + DEBTRACE(isModified); + } + } + else + { + if ( mySchemaName->text().compare(getSchemaName()) != 0 ) isModified = true; + + if ( !isModified ) + if ( mySProc && getInputPanel() ) + if ( Proc* aProc = getProc() ) + { + // get gui graph + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph(aProc); + if ( !aGraph ) return; + + int aViewMode = aGraph->getDMode(); + if ( myFullMode_2->isOn() && aViewMode != YACSGui_Graph::FullId + || + myControlMode_2->isOn() && aViewMode != YACSGui_Graph::ControlId + || + myDataFlowMode_2->isOn() && aViewMode != YACSGui_Graph::DataflowId + || + myDataStreamMode_2->isOn() && aViewMode != YACSGui_Graph::DataStreamId ) isModified = true; + } + } + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::SchemaId); + } + else updateState(); +} + +void YACSGui_SchemaPage::onAddAllNextToRun() +{ + list nextStepList; + QListViewItemIterator it(myNextStepsListView); + while(it.current()) + { + ((QCheckListItem*)it.current())->setOn(true); + nextStepList.push_back(it.current()->text(0)); + ++it; + } + if ( YACSGui_Executor* anExecutor = getInputPanel()->getModule()->lookForExecutor() ) + anExecutor->setNextStepList(nextStepList); +} + +void YACSGui_SchemaPage::onRemoveAllNextToRun() +{ + list nextStepList; + QListViewItemIterator it(myNextStepsListView); + while(it.current()) + { + ((QCheckListItem*)it.current())->setOn(false); + ++it; + } + if ( YACSGui_Executor* anExecutor = getInputPanel()->getModule()->lookForExecutor() ) + anExecutor->setNextStepList(nextStepList); +} + +void YACSGui_SchemaPage::onNextStepClicked( QListViewItem* theItem ) +{ + list nextStepList; + QListViewItemIterator it(myNextStepsListView); + for ( ; it.current(); ++it ) + if (((QCheckListItem*)it.current())->isOn()) + nextStepList.push_back(it.current()->text(0)); + if ( YACSGui_Executor* anExecutor = getInputPanel()->getModule()->lookForExecutor() ) + anExecutor->setNextStepList(nextStepList); +} + +void YACSGui_SchemaPage::onNotifyNextSteps( std::list theNextSteps ) +{ + myNextStepsListView->clear(); + myMapNextSteps.clear(); + myNextStepsListView->setRootIsDecorated(true); + while (! theNextSteps.empty()) + { + QCheckListItem *item = new QCheckListItem(myNextStepsListView, + theNextSteps.front().c_str(), + QCheckListItem::CheckBox ); + myMapNextSteps[item] = theNextSteps.front(); + item->setOn(true); + theNextSteps.pop_front(); + } +} + +void YACSGui_SchemaPage::updateState() +{ + DEBTRACE("YACSGui_SchemaPage::updateState"); + // Set schema name + if ( mySchemaName ) mySchemaName->setText( getSchemaName() ); + + if ( myMode == YACSGui_InputPanel::RunMode ) + if (GuiContext *context = GuiContext::getCurrent()) + { + myParams.container_name = context->getYACSCont().first.c_str(); + myParams.hostname = context->getYACSCont().second.c_str(); + myExecutionName->setText(QString(myParams.container_name)); + myHostName->setCurrentText(QString(myParams.hostname)); + } + + if ( myMode == YACSGui_InputPanel::RunMode && myNextStepsListView ) + myNextStepsListView->clear(); + + // Set view mode of the given schema + if ( mySProc ) + if ( Proc* aProc = getProc() ) + { + // get gui graph + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph(aProc); + if ( !aGraph ) return; + + int aViewMode = aGraph->getDMode(); + if ( aViewMode == YACSGui_Graph::FullId && !myFullMode_2->isOn() ) + myFullMode_2->toggle(); + else if ( aViewMode == YACSGui_Graph::ControlId && !myControlMode_2->isOn() ) + myControlMode_2->toggle(); + else if ( aViewMode == YACSGui_Graph::DataflowId && !myDataFlowMode_2->isOn() ) + myDataFlowMode_2->toggle(); + else if ( aViewMode == YACSGui_Graph::DataStreamId && !myDataStreamMode_2->isOn() ) + myDataStreamMode_2->toggle(); + } +} + +void YACSGui_SchemaPage::fillHostNames() const +{ + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if ( !anApp ) return; + + SALOME_NamingService* namingService = anApp->namingService(); + + CORBA::Object_var obj = namingService->Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS); + if ( !CORBA::is_nil(obj) ) + if ( Engines::ResourcesManager_var aResManager=Engines::ResourcesManager::_narrow(obj) ) + { + Engines::CompoList aCompoList ; + Engines::MachineParameters params; + anApp->lcc()->preSet(params); + + Engines::MachineList* aMachineList = aResManager->GetFittingResources( params, aCompoList ); + + myHostName->clear(); + myHostName->insertItem( QString("localhost") ); + for ( unsigned int i = 0; i < aMachineList->length(); i++ ) + { + const char* aMachine = (*aMachineList)[i]; + myHostName->insertItem( QString(aMachine) ); + } + } +} + diff --git a/src/gui/YACSGui_Selection.cxx b/src/gui/YACSGui_Selection.cxx new file mode 100644 index 000000000..27309c179 --- /dev/null +++ b/src/gui/YACSGui_Selection.cxx @@ -0,0 +1,100 @@ +// Copyright (C) 2003 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 +// + +// File : YACSGui_Selection.cxx +// Author : Alexander BORODIN +// Module : YACS + + +#include +#include +#include + +#include +#include +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +//!Constructor. +/*! + */ + +YACSGui_Selection::YACSGui_Selection () + :LightApp_Selection() +{ +} + +//!Destructor +/*! + */ +YACSGui_Selection::~YACSGui_Selection () +{ +} + +//!redefined method param +/*! + */ +QtxValue YACSGui_Selection::param( const int k, const QString& name) const +{ + DEBTRACE("YACSGui_Selection::param name = " << name.latin1()); + QtxValue v; + + if ( name == "ObjectType" ) + { + DEBTRACE("ObjectType= " << myCurrentObjectType.latin1()); + v = myCurrentObjectType; + return v; + } + + return LightApp_Selection::param( k, name ); +} + +//!detection of type of current selected object +/*! + */ +void YACSGui_Selection::init( const QString& client, LightApp_SelectionMgr* mgr) +{ + LightApp_Selection::init(client, mgr); + + myCurrentObjectType = ""; + + YACSGui_Module* module = dynamic_cast( mgr->application()->activeModule() ); + SalomeApp_Study* study = dynamic_cast( mgr->application()->activeStudy() ); + if ( study && module ) + { + _PTR(Study) studyDS = study->studyDS(); + if ( studyDS ) + { + SALOME_ListIO selObjects; + mgr->selectedObjects( selObjects, false ); + + //consider only single selection + if ( selObjects.Extent() == 1 ) + { + Handle(SALOME_InteractiveObject) io = selObjects.First(); + YACSGui_DataModel::ObjectType type = ((YACSGui_DataModel*)module->dataModel())->objectType( io->getEntry() ); + myCurrentObjectType = YACSGui_DataModel::Type2Str( type ); + } + } + } +} diff --git a/src/gui/YACSGui_Selection.h b/src/gui/YACSGui_Selection.h new file mode 100644 index 000000000..b9140bf81 --- /dev/null +++ b/src/gui/YACSGui_Selection.h @@ -0,0 +1,45 @@ +// Copyright (C) 2003 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 +// + +// File : YACSGui_Selection.h +// Author : Alexander BORODIN +// Module : YACS + +#ifndef YACSGui_Selection_HeaderFile +#define YACSGui_Selection_HeaderFile + +#include +#include +#include CORBA_CLIENT_HEADER(yacsgui) + +class YACSGui_Selection : public LightApp_Selection +{ + public: + YACSGui_Selection(); + virtual ~YACSGui_Selection(); + + virtual QtxValue param( const int, const QString& ) const; + virtual void init( const QString&, LightApp_SelectionMgr* ); + + private: + QString myCurrentObjectType; +}; + +#endif diff --git a/src/gui/YACSGui_ServiceNodePage.cxx b/src/gui/YACSGui_ServiceNodePage.cxx new file mode 100644 index 000000000..b3d0d8c20 --- /dev/null +++ b/src/gui/YACSGui_ServiceNodePage.cxx @@ -0,0 +1,1700 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_ServiceNodePage + Description : Page for SALOME and CORBA service nodes properties +*/ + +YACSGui_ServiceNodePage::YACSGui_ServiceNodePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : ServiceNodePage( theParent, theName, theFlags ), + YACSGui_NodePage(), + myComponent( 0 ), + mySCNode( 0 ) +{ + // the possibility to search is hided according to the Num. 14 from NEWS file + Search->hide(); + mySearch->hide(); + + //#undef HAVE_QEXTSCINTILLA_H +#ifdef HAVE_QEXTSCINTILLA_H + _myTextEdit = new QextScintilla( InPythonEditorGroupBox, "Python Editor" ); + _myTextEdit->setMinimumHeight(150); + InPythonEditorGroupBoxLayout->insertWidget(InPythonEditorGroupBoxLayout->findWidget(myTextEdit), + _myTextEdit ); + InPythonEditorGroupBoxLayout->remove(myTextEdit); + delete myTextEdit; + _myTextEdit->setUtf8(1); + QextScintillaLexerPython *lex = new QextScintillaLexerPython(_myTextEdit); + _myTextEdit->setLexer(lex); + _myTextEdit->setBraceMatching(QextScintilla::SloppyBraceMatch); + _myTextEdit->setAutoIndent(1); + _myTextEdit->setIndentationWidth(4); + _myTextEdit->setIndentationGuides(1); + _myTextEdit->setIndentationsUseTabs(0); + _myTextEdit->setAutoCompletionThreshold(2); +#endif + + if ( !myInputPortsGroupBox || !myOutputPortsGroupBox ) return; + + QString aPortTypes = QString("Data Flow;Data Stream (BASIC);Data Stream (CALCIUM);Data Stream (PALM)"); + QString aValueTypes = QString("Double;Int;String;Bool;Objref;Sequence;Array;Struct"); + + // Input Ports table + myInputPortsGroupBox->setTitle( tr("Input Ports") ); + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + //aTable->setFixedHeight( 100 ); + aTable->setNumCols( 4 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) ); + aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) ); + aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) ); + aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) ); + aTable->setColumnWidth(0,58); + aTable->setColumnWidth(1,84); + aTable->setColumnWidth(2,80); + aTable->setCellType( -1, 0, YACSGui_Table::String ); + aTable->setCellType( -1, 1, YACSGui_Table::Combo ); + aTable->setCellType( -1, 2, YACSGui_Table::Combo ); + //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column + + aTable->setParams( 0, 1, aPortTypes ); + aTable->setParams( 0, 2, aValueTypes ); + + aTable->setEditorSync(true); + + connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) ); + + myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn | + YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn ); + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + myInputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + // Output Ports table + myOutputPortsGroupBox->setTitle( tr("Output Ports") ); + aTable = myOutputPortsGroupBox->Table(); + //aTable->setFixedHeight( 100 ); + aTable->setNumCols( 5 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Name" ) ); + aTable->horizontalHeader()->setLabel( 1, tr( "Class" ) ); + aTable->horizontalHeader()->setLabel( 2, tr( "Type" ) ); + aTable->horizontalHeader()->setLabel( 3, tr( "Value" ) ); + aTable->horizontalHeader()->setLabel( 4, tr( "Is in study" ) ); + aTable->setColumnWidth(0,58); + aTable->setColumnWidth(1,84); + aTable->setColumnWidth(2,80); + + aTable->setCellType( -1, 0, YACSGui_Table::String ); + aTable->setCellType( -1, 1, YACSGui_Table::Combo ); + aTable->setCellType( -1, 2, YACSGui_Table::Combo ); + //aTable->setCellType( -1, 3, YACSGui_Table::??? ); depends on combo box item choosen in the "Value type" column + aTable->setCellType( -1, 4, YACSGui_Table::Combo ); + + aTable->setParams( 0, 1, aPortTypes ); + aTable->setParams( 0, 2, aValueTypes ); + aTable->setParams( 0, 4, QString("Yes;No") ); + aTable->setDefValue( 0, 4, QString("Yes") ); + + aTable->setEditorSync(true); + + myPara = 0; + myIndex = 0; + + connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) ); + + myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn | + YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn ); + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + myOutputPortsGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + myProcName = ""; + myProcRadioButton->setEnabled(false); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); + connect( myInstanceName, SIGNAL(activated( const QString& )), this, SLOT(onInstanceNameChanged( const QString& ) ) ); + connect( myBrowseButton, SIGNAL(clicked( )), this, SLOT(onBrowse( )) ); + connect( this, SIGNAL( enableApply( bool ) ), getInputPanel(), SLOT( onApplyEnabled( bool ) ) ); + connect( CatalogTree, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( onCatalogMethodClicked( QListViewItem* ) ) ); + connect( mySessionRadioButton, SIGNAL( stateChanged( int ) ), this, SLOT( onCatalogChanged( int ) ) ); + connect( myProcRadioButton, SIGNAL( stateChanged( int ) ), this, SLOT( onCatalogChanged( int ) ) ); + + //connect( this, SIGNAL(visibilityChanged( bool )), this, SLOT(onVisibilityChanged( bool )) ); +} + +YACSGui_ServiceNodePage::~YACSGui_ServiceNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); +} + +void YACSGui_ServiceNodePage::setSCNode( YACS::HMI::SubjectComposedNode* theSCNode ) +{ + DEBTRACE("YACSGui_ServiceNodePage::setSCNode"); + if ( theSCNode && mySCNode != theSCNode ) + mySCNode = theSCNode; +} + +void YACSGui_ServiceNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( YACS::ENGINE::ServiceNode* aServiceNode = dynamic_cast( theSNode->getNode() ) ) + { + myComponentName = QString::null; + myComponent = aServiceNode->getComponent(); + YACSGui_NodePage::setSNode( theSNode ); + } +} + +void YACSGui_ServiceNodePage::setComponent( YACS::ENGINE::ComponentInstance* theComponent ) +{ + DEBTRACE("YACSGui_ServiceNodePage::setComponent"); + if (!theComponent) return; + ServiceNode* aServiceNode = dynamic_cast(getNode()); + if (!aServiceNode) return; + ComponentInstance* compo = aServiceNode->getComponent(); + if (!compo) return; + + std::string currentInstName = compo->getInstanceName(); + std::string anInstanceName = theComponent->getInstanceName(); + + if( currentInstName != anInstanceName ) + { + myComponentName = theComponent->getCompoName(); + myInstanceName->setCurrentText(theComponent->getInstanceName()); + myComponent = theComponent; + updateState(); + + YACSGui_ComponentPage* aCompPage = + dynamic_cast( getInputPanel()->getPage( YACSGui_InputPanel::ComponentId ) ); + if ( aCompPage ) + aCompPage->setSComponent( GuiContext::getCurrent()->_mapOfSubjectComponent[theComponent], false ); + } +} + +void YACSGui_ServiceNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + DEBTRACE("YACSGui_ServiceNodePage::setMode"); + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::NewMode ) + { + DEBTRACE("new mode"); + CatalogGroupBox->show(); + PortListGroupBox->hide(); + InPythonEditorGroupBox->hide(); + NameGroupBox->hide(); +// ComponentDefinitionLabel->hide(); +// myComponentDefinition->hide(); +// MethodName->hide(); +// myMethodName->hide(); + ExecutionGroupBox->hide(); + stringstream aName; + string aType = getInputPanel()->getModule()->getNodeType(SALOMENODE); + aName << aType << GuiContext::getCurrent()->getNewId(SALOMENODE); + myNodeName->setText(aName.str()); + myNodeFullName->setText(aName.str()); + getInputPanel()->onApplyEnabled(false); + mySNode = 0; + updateState(); + } + else + { + DEBTRACE("not new mode"); + CatalogGroupBox->hide(); + PortListGroupBox->show(); + NameGroupBox->show(); +// ComponentDefinitionLabel->show(); +// myComponentDefinition->show(); +// MethodName->show(); +// myMethodName->show(); + getInputPanel()->onApplyEnabled(true); + } + + myMethodName->setReadOnly(true); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + DEBTRACE("edit mode"); + myNodeName->setReadOnly(false); + ExecutionGroupBox->hide(); + + myInputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + myOutputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + DEBTRACE("run mode"); + myNodeName->setReadOnly(true); + ExecutionGroupBox->show(); + + myInputPortsGroupBox->HideBtn(); + myOutputPortsGroupBox->HideBtn(); + } +} + +void YACSGui_ServiceNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_ServiceNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + if (!getNode()) return; + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_ServiceNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + DEBTRACE("YACSGui_ServiceNodePage::notifyInPortValues"); + QStringList aValues; + + QStringList aPortNames; + myInputPortsGroupBox->Table()->strings( 0, aPortNames ); + + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + map::iterator it1 = theInPortName2Value.find( (*it).latin1() ); + if ( it1 != theInPortName2Value.end() ) + aValues.append( QString((*it1).second.c_str()) ); + } + + if ( aPortNames.count() == aValues.count() ) + myInputPortsGroupBox->Table()->setStrings( 3, aValues ); +} + +void YACSGui_ServiceNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + DEBTRACE("YACSGui_ServiceNodePage::notifyOutPortValues"); + QStringList aValues; + + QStringList aPortNames; + myOutputPortsGroupBox->Table()->strings( 0, aPortNames ); + + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + map::iterator it1 = theOutPortName2Value.find( (*it).latin1() ); + if ( it1 != theOutPortName2Value.end() ) + aValues.append( QString((*it1).second.c_str()) ); + } + + if ( aPortNames.count() == aValues.count() ) + myOutputPortsGroupBox->Table()->setStrings( 3, aValues ); +} + +void YACSGui_ServiceNodePage::checkModifications( bool& theWarnToShow, bool& theToApply ) +{ + DEBTRACE("YACSGui_ServiceNodePage::checkModifications " << theWarnToShow <<","<( getNode() ); + if ( !aServiceNode ) return; + + if ( myNodeName->text().compare(getNodeName()) != 0) isModified = true; + + if ( !isModified ) + { + if (aServiceNode->getComponent()) + if(QString::compare(myInstanceName->currentText(),aServiceNode->getComponent()->getInstanceName()) != 0) + isModified = true; + } + + if ( !isModified ) + { + // read input data and input data stream ports values from the table + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + aTable->stopEdit(true); + + QStringList aPortNames; + QStringList aValues; + + aTable->strings( 0, aPortNames ); + aTable->strings( 3, aValues ); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + InPort* anInPort = aServiceNode->getInPort(*it); + QString value=aValues[aRowId]; + if(value.isNull()) + value="< ? >"; + DEBTRACE(getPortValue( anInPort ) << "," <( getNode() ) ) aScript = QString(aSIN->getScript()); + else if ( XmlNode* aXN = dynamic_cast( getNode() ) ) aScript = QString(aXN->getScript()); + +#ifdef HAVE_QEXTSCINTILLA_H + QString theText = _myTextEdit->text(); +#else + QString theText = myTextEdit->text(); +#endif + if ( theText.compare(aScript) != 0 ) isModified = true; + } + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( theWarnToShow ) + { + theWarnToShow = false; + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + theToApply = true; + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ServiceNodeId); + } + else + theToApply = false; + } + else if ( theToApply ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::ServiceNodeId); + } +} + +void YACSGui_ServiceNodePage::onCatalogChanged( int ) +{ + DEBTRACE("YACSGui_ServiceNodePage::onCatalogChanged"); + getInputPanel()->onApplyEnabled(false); + + // generate name of node if session catalog is active one. Name for proc catalog + // is generated when node is selected in catalog view + /*if ( !myProcRadioButton->isChecked() ) + { + stringstream aName; + string aType = getInputPanel()->getModule()->getNodeType( SALOMENODE ); + aName << aType << GuiContext::getCurrent()->getNewId( SALOMENODE ); + myNodeName->setText(aName.str()); + }*/ + + updateState(); +} + +void YACSGui_ServiceNodePage::onCatalogMethodClicked( QListViewItem* it ) +{ + if ( it ) + { + if ( !myProcRadioButton->isChecked() ) + { + // session catalog is used + std::pair compoServ = myServiceMap[it]; + getInputPanel()->onApplyEnabled(!compoServ.first.empty() && !compoServ.second.empty()); + } + else + { + // This block of code is commented because service nodes can be creatwed here only + + // proc catalog is used. Apply button should be enabled if selected item is not + // "Nodes" or "Composed nodes" one. + QListViewItem* aParent = it->parent(); + getInputPanel()->onApplyEnabled( aParent != 0 ); + + // At the time service nodes can be created only so there is no point in + // regenerating default node name in accordance with its type + // Update name + if ( myProcNodesMap.count( it ) ) + { + YACS::ENGINE::Node* aNode = myProcNodesMap[ it ]; + if ( aNode ) + { + YACS::HMI::TypeOfElem aTypeId = ProcInvoc::getTypeOfNode( aNode ); + stringstream aName; + string aType = getInputPanel()->getModule()->getNodeType( aTypeId ); + aName << aType << GuiContext::getCurrent()->getNewId( aTypeId ); + myNodeName->setText( aName.str() ); + myNodeFullName->setText( aName.str() ); + myNodeType->setText( aType.c_str() ); + } + } + } + } +} + +void YACSGui_ServiceNodePage::onBrowse() +{ + DEBTRACE("YACSGui_ServiceNodePage::onBrowse"); + QString fn = QFileDialog::getOpenFileName( QString::null, + tr( "XML-Files (*.xml);;All Files (*)" ), + this, + "load YACS scheme file dialog as catalog", + "Choose a filename to load" ); + if ( fn.isEmpty() ) + return; + + myProcName = fn.latin1(); + + myProcRadioButton->setEnabled(true); + myProcRadioButton->setChecked(true); + + getInputPanel()->onApplyEnabled(false); + updateState(); +} + +void YACSGui_ServiceNodePage::onApply() +{ + DEBTRACE("YACSGui_ServiceNodePage::onApply"); + if ( myMode == YACSGui_InputPanel::NewMode ) + { + // --- NewMode: import a node or composed node of any type from catalog --------- + + GuiContext* aContext = GuiContext::getCurrent(); + if ( !aContext ) return; + + YACSGui_Module* aModule = getInputPanel()->getModule(); + if ( !aModule ) return; + + YACSGui_EditionTreeView * aETV = dynamic_cast(aModule->activeTreeView()); + if ( !aETV ) return; + + SubjectProc* aSchema = aContext->getSubjectProc(); + DEBTRACE("YACSGui_ServiceNodePage::onApply: "<< aSchema); + + YACS::ENGINE::Catalog* aCatalog = 0; + if ( myProcRadioButton->isChecked() ) + { + aCatalog = YACS::ENGINE::getSALOMERuntime()->loadCatalog( "proc", myProcName.c_str() ); + std::string errors=aCatalog->getErrors(); + if(errors != "") + { + + std::string msg="The imported file "; + msg=msg+myProcName+" has errors. Some nodes can be uncompletely built\n"; + LogViewer* log=new LogViewer(msg+errors,getInputPanel()->getModule()->getApp()->desktop(),"dialog",WDestructiveClose); + log->show(); + getInputPanel()->getModule()->getApp()->logWindow()->putMessage(msg+errors ); + } + } + else + aCatalog = aModule->getCatalog(); + + QListViewItem* anItem = CatalogTree->selectedItem(); + + SubjectServiceNode* aNewSNode = 0; + if ( aSchema && aCatalog && anItem && mySCNode ) + { + string compo; + string service; + YACS::HMI::TypeOfElem aTypeId = UNKNOWN; + if ( !myProcRadioButton->isChecked() ) + { + if ( myServiceMap.find( anItem ) == myServiceMap.end() ) + return; + + pair compoServ = myServiceMap[anItem]; + compo = compoServ.first; + service = compoServ.second; + aTypeId = SALOMENODE; + } + else + { + if ( anItem->text( 0 ).isNull() ) + return; + + compo = ""; + service = anItem->text( 0 ).latin1(); + + if ( !myProcNodesMap.count( anItem ) ) + return; // nonsense + + YACS::ENGINE::Node* aNode = myProcNodesMap[ anItem ]; + + // Add node in catalog map if necessary. In the other case it will not be + // found in CommandAddNodeFromCatalog method + if ( !aCatalog->_nodeMap.count( service ) && + !aCatalog->_composednodeMap.count( service ) ) + { + aCatalog->_nodeMap[ service ] = aNode; + } + + YACS::ENGINE::ServiceNode* aServiceNode = + dynamic_cast< YACS::ENGINE::ServiceNode* >( aNode ); + if ( aServiceNode ) + aServiceNode->setComponent( 0 ); + + aTypeId = ProcInvoc::getTypeOfNode( aNode ); + } + + myComponentName = compo; + myMethodName->setText( service ); + + Proc* aProc = aContext->getProc(); + DEBTRACE("YACSGui_ServiceNodePage::onApply: " << aProc); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = aModule->getGraph( aProc ); + if ( !aGraph ) return; + + stringstream aName; + string aType = aModule->getNodeType( aTypeId ); + aName << aType << aContext->getNewId( aTypeId ); + + // ---> block for correct node (engine - subject - presentation) creation + SubjectNode* aCreatedSNode = 0; + if ( mySCNode ) + { + if ( SubjectSwitch* aSwitch = dynamic_cast(mySCNode) ) + { + map bodyMap = aSwitch->getBodyMap(); + int aSwCase = 0; + if (bodyMap.empty()) aSwCase = 1; + else + { + map::reverse_iterator rit = bodyMap.rbegin(); + aSwCase = (*rit).first + 1; + } + aCreatedSNode = aSwitch->addNode( aCatalog, compo, service, aName.str(), aSwCase); + } + else if ( SubjectForLoop* aForLoop = dynamic_cast(mySCNode) ) + { + aCreatedSNode = aModule->createBody( SALOMENODE, mySCNode, aCatalog, compo, service ); + } + else if ( SubjectForEachLoop* aForEachLoop = dynamic_cast(mySCNode) ) + { + aCreatedSNode = aModule->createBody( SALOMENODE, mySCNode, aCatalog, compo, service ); + } + else if ( SubjectWhileLoop* aWhileLoop = dynamic_cast(mySCNode) ) + { + aCreatedSNode = aModule->createBody( SALOMENODE, mySCNode, aCatalog, compo, service ); + } + else if ( SubjectProc* aSchema = dynamic_cast(mySCNode) ) + { + DEBTRACE("YACSGui_ServiceNodePage::onApply: " << aSchema); + aCreatedSNode = aSchema->addNode( aCatalog, compo, service, aName.str() ); + } + else if ( SubjectBloc* aBloc = dynamic_cast(mySCNode) ) + { + aCreatedSNode = aBloc->addNode( aCatalog, compo, service, aName.str() ); + if( SubjectComposedNode* aParent = dynamic_cast(aBloc->getParent()) ) + aGraph->update(aBloc->getNode(), aParent); + } + } + else + { + aCreatedSNode = aSchema->addNode( aCatalog, compo, service, aName.str() ); + } + // <--- + + if ( SubjectBloc* aSB = dynamic_cast(mySCNode) ) + aSB->update( EDIT, 0, aSB ); + + aNewSNode = dynamic_cast(aCreatedSNode); + ServiceNode* aNewNode =0; + if ( aNewSNode ) + aNewNode = dynamic_cast(aNewSNode->getNode()); + ComponentInstance* aComp = 0; + if ( aNewNode ) + aComp = aNewNode->getComponent(); + SubjectComponent* aSComp = 0; + if ( aComp ) // find the component subject in the current GuiContext + if ( aContext->_mapOfSubjectComponent.find(aComp) != aContext->_mapOfSubjectComponent.end() ) + aSComp = aContext->_mapOfSubjectComponent[aComp]; + + if ( aSComp ) + { + SubjectContainer* aSCont = 0; + SalomeContainer* aCont = dynamic_cast(aComp->getContainer()); + if ( !aCont ) + { // container is not found + // 1) try to find the first container with the suitable type (i.e. Salome container) + // in the current GuiContext + map::iterator itCont = aContext->_mapOfSubjectContainer.begin(); + for ( ; itCont!=aContext->_mapOfSubjectContainer.end(); itCont++ ) + { + SalomeContainer* aSalomeCont = dynamic_cast( (*itCont).first ); + if ( aSalomeCont ) + { + aSCont = (*itCont).second; + aCont = aSalomeCont; + break; + } + } + + if ( !aSCont ) + { + // 2) create a new default Salome container and subject for it + string aDefContainer = "DefaultContainer"; + if ( !aProc->containerMap.count(aDefContainer) ) + { + aSCont = aSchema->addContainer(aDefContainer); + aCont = dynamic_cast(aSCont->getContainer()); + } + } + } + else + { //container is found => try to get its subject from the current GuiContext + if ( aContext->_mapOfSubjectContainer.find(aCont) != aContext->_mapOfSubjectContainer.end() ) + aSCont = aContext->_mapOfSubjectContainer[aCont]; + } + + if ( aSCont ) + { + YACSGui_ContainerViewItem* aContainerItem = 0; + + // get the "Containers" label view item + YACSGui_LabelViewItem* aContainersL = + dynamic_cast(aETV->firstChild()->firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContainersL || aContainersL->text(0).compare(QString("Containers")) ) return; + + YACSGui_ContainerViewItem* anAfter = 0; + if ( QListViewItem* aChild = aContainersL->firstChild() ) + { + while( aChild ) + { + if ( anAfter = dynamic_cast(aChild) ) + if ( anAfter->getContainer() == aCont ) + { + aContainerItem = anAfter; + break; + } + aChild = aChild->nextSibling(); + } + } + + if ( aContainerItem ) + { + aContainerItem->addComponentItem(aSComp); + aSComp->associateToContainer( aSCont ); + aNewSNode->associateToComponent(aSComp); + } + } + } + + aModule->temporaryExport(); + } + + // --- commented to avoid to close the NewMode panel +// aModule->setGuiMode(YACSGui_Module::EditMode); +// setMode(YACSGui_InputPanel::EditMode); + if ( aNewSNode ) setSNode(aNewSNode); + + if ( aModule->activeTreeView() ) + aModule->activeTreeView()->syncPageTypeWithSelection(); + + return; + } + + // --- not NewMode: edition of an existing Service Node ----------- + + // Rename a node + if ( myNodeName ) + setNodeName( myNodeName->text() ); + + if ( ServiceNode* aServiceNode = dynamic_cast( getNode() ) ) + { + SubjectServiceNode* aSSNode = dynamic_cast(mySNode); + // change component + if (ComponentInstance* aPrevComponent = aServiceNode->getComponent()) + { + SubjectComponent* aPrevSComponent = GuiContext::getCurrent()->_mapOfSubjectComponent[aPrevComponent]; + + if(QString::compare(myInstanceName->currentText(),aServiceNode->getComponent()->getInstanceName()) != 0) + { + ComponentInstance* compo = 0; + Proc* aProc = GuiContext::getCurrent()->getProc(); + if (aProc) + { + map,ComponentInstance*>::const_iterator it = aProc->componentInstanceMap.begin(); + for(; it!=aProc->componentInstanceMap.end(); ++it) + { + ComponentInstance *inst=(*it).second; + if (! QString::compare(inst->getInstanceName(), myInstanceName->currentText())) // if same instance name + { + compo = inst; + break; + } + } + } + if (compo) + { + SubjectComponent* aSComp = GuiContext::getCurrent()->_mapOfSubjectComponent[compo]; + if ( aSSNode && aSComp ) aSSNode->associateToComponent(aSComp); + setComponent(compo); + } + } + } + else + { + SubjectComponent* aSComp = GuiContext::getCurrent()->_mapOfSubjectComponent[myComponent]; + if ( aSSNode && aSComp ) aSSNode->associateToComponent(aSComp); + } + } + + // Reset the list of input ports + setInputPorts(); + + // Reset the list of output ports + setOutputPorts(); + + // Reset Python function/script + string aScript = scriptText().isEmpty() ? string("") : scriptText().latin1(); + if ( ServiceInlineNode* aSIN = dynamic_cast( getNode() ) ) aSIN->setScript( aScript ); + else if ( XmlNode* aXN = dynamic_cast( getNode() ) ) aXN->setScript( aScript ); + + updateBlocSize(); +} + +void YACSGui_ServiceNodePage::buildTree( YACS::ENGINE::Node* theNode, + QListViewItem* nodeLabel, + QListViewItem* compoNodeLabel ) +{ + if ( !theNode ) + return; + + // --- Create item corresponding to the node + QString aName( theNode->getName().c_str() ); + if ( aName.isNull()) + return; + + QListViewItem* theParent = nodeLabel; + if (YACS::ENGINE::ComposedNode* aCompNode = dynamic_cast(theNode)) + { + theParent = compoNodeLabel; + std::list aNodes = aCompNode->edGetDirectDescendants(); + std::list::iterator anIter; + for ( anIter = aNodes.begin(); anIter != aNodes.end(); ++anIter ) + buildTree( *anIter, nodeLabel, compoNodeLabel ); + } + + QListViewItem* anItem = new QListViewItem( theParent, aName ); + anItem->setPixmap( 0, YACSGui_NodeViewItem::icon( theNode ) ); + myProcNodesMap[ anItem ] = theNode; +} + + +void YACSGui_ServiceNodePage::updateState() +{ + DEBTRACE("YACSGui_ServiceNodePage::updateState"); + if ( myMode == YACSGui_InputPanel::NewMode ) + { + //DEBTRACE("New mode"); + //myNodeType->setText( tr( "SALOME_SERVICE_NODE" ) ); // SALOME service node + CatalogTree->clear(); + CatalogTree->setRootIsDecorated( TRUE ); + + YACS::ENGINE::Catalog *_currentCatalog =0; + if ( myProcRadioButton->isChecked() ) + { + _currentCatalog = YACS::ENGINE::getSALOMERuntime()->loadCatalog( "proc", myProcName.c_str() ); + std::string errors=_currentCatalog->getErrors(); + if(errors != "") + { + std::string msg="The imported file "; + msg=msg+myProcName+" has errors. Some nodes can be uncompletely built\n"; + LogViewer* log=new LogViewer(msg+errors,getInputPanel()->getModule()->getApp()->desktop(),"dialog",WDestructiveClose); + log->show(); + getInputPanel()->getModule()->getApp()->logWindow()->putMessage(msg+errors ); + } + } + else + _currentCatalog = getInputPanel()->getModule()->getCatalog(); + + if ( _currentCatalog ) + { + myProcNodesMap.clear(); + + // --- nodes and composed nodes + std::map< std::string, Node* >& aNodeMap = _currentCatalog->_nodeMap; + std::map< std::string, ComposedNode* >& aCompMap = _currentCatalog->_composednodeMap; + QListViewItem* aNodeRoot = new QListViewItem( CatalogTree, tr( "NODES" ) ); + QListViewItem* aCompRoot = new QListViewItem( CatalogTree, tr( "COMPOSED_NODES" ) ); + + if ( aCompMap.size() ) + { + std::map< std::string, ComposedNode* >::iterator cIter; + for ( cIter = aCompMap.begin(); cIter != aCompMap.end(); ++cIter ) + { + YACS::ENGINE::Node* aNode = cIter->second; + buildTree( aNode, aNodeRoot, aCompRoot ); + } + } + if ( aNodeMap.size() ) + { + std::map< std::string, Node* >::iterator nIter; + for ( nIter = aNodeMap.begin(); nIter != aNodeMap.end(); ++nIter ) + { + YACS::ENGINE::Node* aNode = nIter->second; + buildTree( aNode, aNodeRoot, aCompRoot ); + } + } + + // --- composed nodes + + // --- component and services + map::const_iterator itComp; + for (itComp = _currentCatalog->_componentMap.begin(); + itComp != _currentCatalog->_componentMap.end(); + ++itComp) + { + string compoName = (*itComp).first; + YACS::ENGINE::ComponentDefinition* compo = (*itComp).second; + QListViewItem *item = new QListViewItem(CatalogTree, compoName.c_str()); + myServiceMap[item] = pair(compoName,""); + map::iterator itServ; + for (itServ = compo->_serviceMap.begin(); itServ != compo->_serviceMap.end(); ++itServ) + { + string serviceName = (*itServ).first; + YACS::ENGINE::ServiceNode* service = (*itServ).second; + QListViewItem *sitem = new QListViewItem(item, serviceName.c_str()); + myServiceMap[sitem] = pair(compoName,serviceName); + } + } + } + return; + } + //DEBTRACE("not new mode"); + + if ( myType != SALOMEService ) + { + //DEBTRACE("myType != SALOMEService"); + myInputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::AllBtn ); + myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn | + YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn | + YACSGui_PlusMinusGrp::InsertBtn ); + + myOutputPortsGroupBox->ShowBtn( YACSGui_PlusMinusGrp::AllBtn ); + myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::SelectBtn ); + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn | + YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn | + YACSGui_PlusMinusGrp::InsertBtn ); + } + else + { + //DEBTRACE("myType == SALOMEService"); + myInputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn | + YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn ); + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + + myOutputPortsGroupBox->HideBtn( YACSGui_PlusMinusGrp::PlusBtn | YACSGui_PlusMinusGrp::MinusBtn | + YACSGui_PlusMinusGrp::InsertBtn | YACSGui_PlusMinusGrp::SelectBtn ); + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + } + + if ( (myType == ServiceInline || myType == XMLNode) && InPythonEditorGroupBox ) + { + // show built-in Python code editor + InPythonEditorGroupBox->show(); + connect( mySearch, SIGNAL(returnPressed()), this, SLOT(onSearch()) ); + } + else if ( InPythonEditorGroupBox ) + { + // hide built-in Python code editor + InPythonEditorGroupBox->hide(); + disconnect( mySearch, SIGNAL(returnPressed()), this, SLOT(onSearch()) ); + } + + // Clear input ports table and output ports tables, if they are not empty + if ( myInputPortsGroupBox ) + { + myInputPortsGroupBox->Table()->setNumRows( 0 ); + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + } + if ( myOutputPortsGroupBox ) + { + myOutputPortsGroupBox->Table()->setNumRows( 0 ); + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + } + + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Set node type: SALOME or CORBA service + switch (myType) + { + case SALOMEService: + myNodeType->setText( tr( "SALOME_SERVICE_NODE" ) ); break; + case CORBAService: + myNodeType->setText( tr( "CORBA_SERVICE_NODE" ) ); break; + case CPPNode: + myNodeType->setText( tr( "CPP_NODE" ) ); break; + case ServiceInline: + myNodeType->setText( tr( "SERVICE_INLINE_NODE" ) ); break; + case XMLNode: + myNodeType->setText( tr( "XML_NODE" ) ); break; + default: break; + } + + // Set component instance and services + if( myComponentDefinition && myMethodName ) + updateServices(); + + // --- always fill the table seems safer (salome nodes) + // if ( myType == CORBAService || myType == CPPNode /*|| myType == ServiceInline || myType == XMLNode*/ ) + { + // Fill the table of input ports of the node + fillInputPortsTable( getNode() ); + + // Fill the table of output ports of the node + fillOutputPortsTable( getNode() ); + } +} + +void YACSGui_ServiceNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + +void YACSGui_ServiceNodePage::onInstanceNameChanged( const QString& theInstanceName ) +{ + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( !aProc ) return; + + ComponentInstance* compo = 0; + map,ComponentInstance*>::const_iterator it = aProc->componentInstanceMap.begin(); + for(; it!=aProc->componentInstanceMap.end(); ++it) + { + ComponentInstance *inst=(*it).second; + if (! QString::compare(inst->getInstanceName(), theInstanceName)) // if same instance name + { + compo = inst; + break; + } + } + if (!compo) return; + + YACSGui_ComponentPage* aCompPage = + dynamic_cast( getInputPanel()->getPage( YACSGui_InputPanel::ComponentId ) ); + if ( aCompPage ) + aCompPage->setSComponent( GuiContext::getCurrent()->_mapOfSubjectComponent[compo], false ); +} + +void YACSGui_ServiceNodePage::onValueChanged( int theRow, int theCol ) +{ + DEBTRACE("YACSGui_ServiceNodePage::onValueChanged " << theRow << "," << theCol); + if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() ) + if ( theCol == 2 ) // the value type of the port was changed + setValueCellValidator( aTable, theRow ); +} + +void YACSGui_ServiceNodePage::hideEvent( QHideEvent* ) +{ + myPara = 0; + myIndex = 0; +#ifdef HAVE_QEXTSCINTILLA_H +// _myTextEdit->removeSelection(); // --- see if replacement ? +#else + myTextEdit->removeSelection(); +#endif +} + +void YACSGui_ServiceNodePage::onSearch() +{ +#ifdef HAVE_QEXTSCINTILLA_H + if ( _myTextEdit && mySearch ) + { + if ( _myTextEdit->findFirst( mySearch->text(), true, false, true, &myPara, &myIndex ) ) + { + _myTextEdit->setSelection( myPara, myIndex, myPara, myIndex + mySearch->text().length() ); + myIndex += mySearch->text().length(); + } else { + myPara = 0; + myIndex = 0; + } + } +#else + if ( myTextEdit && mySearch ) + { + if ( myTextEdit->find( mySearch->text(), true, false, true, &myPara, &myIndex ) ) + { + myTextEdit->setSelection( myPara, myIndex, myPara, myIndex + mySearch->text().length() ); + myIndex += mySearch->text().length(); + } else { + myPara = 0; + myIndex = 0; + } + } +#endif +} + +void YACSGui_ServiceNodePage::updateServices() +{ + if ( !myComponent ) + { + if ( myComponentDefinition ) myComponentDefinition->clear(); + if ( myMethodName ) myMethodName->clear(); + return; + } + + YACS::ENGINE::ServiceNode* aServiceNode = dynamic_cast( getNode() ); + if( !aServiceNode ) return; + + if( myComponentName.isNull() ) + myComponentName = aServiceNode->getComponent()->getCompoName(); + + myComponentDefinition->setText( myComponentName ); + myMethodName->setText( aServiceNode->getMethod() ); + fillInstanceNames(); + myInstanceName->setCurrentText( aServiceNode->getComponent()->getInstanceName() ); + + fillInputPortsTable( aServiceNode ); + fillOutputPortsTable( aServiceNode ); +} + +void YACSGui_ServiceNodePage::fillInstanceNames() +{ + myInstanceName->clear(); + YACS::ENGINE::ServiceNode* aServiceNode = dynamic_cast( getNode() ); + if( !aServiceNode ) return; + ComponentInstance* compo = aServiceNode->getComponent(); + if (!compo) return; + + if (compo->getKind() == "Salome") + myInstanceName->setEnabled(true); + else + myInstanceName->setEnabled(false); + + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( !aProc ) return; + + map,ComponentInstance*>::const_iterator it = aProc->componentInstanceMap.begin(); + for(; it!=aProc->componentInstanceMap.end(); ++it) + { + ComponentInstance *inst=(*it).second; + QString aComponentName = inst->getCompoName(); + if (! QString::compare(compo->getCompoName(), aComponentName)) // if same component name + myInstanceName->insertItem( QString(inst->getInstanceName())); + } +} + +void YACSGui_ServiceNodePage::fillInputPortsTable( YACS::ENGINE::Node* theNode ) +{ + DEBTRACE("YACSGui_ServiceNodePage::fillInputPortsTable"); + if( !theNode ) + return; + + QStringList aPortNames; + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + + QValueList aReadOnlyFlags; + + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + QStringList aPTCB = aTable->Params( 0, 1 ); + + list anInPortsEngine = theNode->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + { + InPort* anInPort = *anInPortsIter; + + // Collect port names in the list + aPortNames.append( anInPort->getName() ); + + // Port type + if ( InputPort* anInputP = dynamic_cast(anInPort) ) + { + aPortTypes.append( aPTCB[0] ); + + int nbLinks = anInPort->edGetNumberOfLinks(); + aReadOnlyFlags.append( nbLinks > 0 ); + } + //else if ( InputBasicStreamPort* aBasicStreamP = dynamic_cast(anInPort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[1] ); + //} + else if ( InputCalStreamPort* aCalStreamP = dynamic_cast(anInPort) ) + { + aPortTypes.append( aPTCB[2] ); + aReadOnlyFlags.append( true ); + } + //else if ( InputPalmStreamPort* aPalmStreamP = dynamic_cast(anInPort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[3] ); + //} + else if ( InputDataStreamPort* aCalStreamP = dynamic_cast(anInPort) ) + { + aPortTypes.append( aPTCB[2] ); + aReadOnlyFlags.append( true ); + } + else + { // take default value from combo box + aPortTypes.append( aPTCB[0] ); + aReadOnlyFlags.append( true ); + } + + // Value type + aValueTypes.append( getPortType( anInPort ) ); + + // Value + aValues.append( getPortValue( anInPort ) ); + } + + // Fill "Port name" column + aTable->setStrings( 0, aPortNames, true ); + + // Fill "Port type" column + aTable->setStrings( 1, aPortTypes, true ); + + // Fill "Value type" column + aTable->setStrings( 2, aValueTypes, true ); + + if ( myType == SALOMEService ) + // Set the valid cell type for the input ports values + for ( int i=0; inumRows(); i++ ) + setValueCellValidator( aTable, i ); + + // Fill "Value" column + aTable->setStrings( 3, aValues, true ); + + if ( myType == SALOMEService ) + { + // Set all columns read only (except "Value" column) + aTable->setReadOnly( -1, 0, true ); + aTable->setReadOnly( -1, 1, true ); + aTable->setReadOnly( -1, 2, true ); + } + + // Set "Value" column read only (for linked ports) + for ( int i = 0, n = aTable->numRows(); i < n; i++ ) + { + aTable->setDefValue( i, 2, aValueTypes[i] ); + aTable->setReadOnly( i, 3, aReadOnlyFlags[ i ] ); + } + + if ( aPortNames.count() > 1 ) + myInputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); + +} + +void YACSGui_ServiceNodePage::fillOutputPortsTable( YACS::ENGINE::Node* theNode ) +{ + if( !theNode ) + return; + + QStringList aPortNames; + QStringList aPortTypes; + QStringList aValueTypes; + QStringList aValues; + QStringList anIsInStudy; + + YACSGui_Table* aTable = myOutputPortsGroupBox->Table(); + QStringList aPTCB = aTable->Params( 0, 1 ); + + list anOutPortsEngine = theNode->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + { + OutPort* anOutPort = *anOutPortsIter; + + // Collect port names in the list + aPortNames.append( anOutPort->getName() ); + + // Port type + if ( OutputPort* anOutputP = dynamic_cast(anOutPort) ) + { + aPortTypes.append( aPTCB[0] ); + } + //else if ( OutputBasicStreamPort* aBasicStreamP = dynamic_cast(anOutPort) ) + //{ // there is no possibility to identify BASIC data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[1] ); + //} + else if ( OutputCalStreamPort* aCalStreamP = dynamic_cast(anOutPort) ) + { + aPortTypes.append( aPTCB[2] ); + } + //else if ( OutputPalmStreamPort* aPalmStreamP = dynamic_cast(anOutPort) ) + //{ // there is no possibility to identify PALM data stream port in engine now => take default value from combo box + // aPortTypes.append( aPTCB[3] ); + //} + else if ( OutputDataStreamPort* aCalStreamP = dynamic_cast(anOutPort) ) + { + aPortTypes.append( aPTCB[2] ); + } + else + { // take default value from combo box + aPortTypes.append( aPTCB[0] ); + } + + // Value type + aValueTypes.append( getPortType( anOutPort ) ); + + // Value + aValues.append( getPortValue( anOutPort ) ); + + // Is in study + // There is no a such parameter either in engine or GUI at the current moment. + // TODO: we need to implement it at GUI side. + // As a temporary solution we set the default value + anIsInStudy.append( aTable->defValue( 0, 4 ) ); + } + + // Fill "Port name" column + aTable->setStrings( 0, aPortNames, true ); + + // Fill "Port type" column + aTable->setStrings( 1, aPortTypes, true ); + + // Fill "Value type" column + aTable->setStrings( 2, aValueTypes, true ); + + // Fill "Value" column + aTable->setStrings( 3, aValues, true ); + + // Fill "Is in study" column + aTable->setStrings( 4, anIsInStudy, true ); + + if ( myType == SALOMEService ) + { + // Set all columns read only + aTable->setReadOnly( -1, 0, true ); + aTable->setReadOnly( -1, 1, true ); + aTable->setReadOnly( -1, 2, true ); + aTable->setReadOnly( -1, 3, true ); + } + + for ( int i = 0, n = aTable->numRows(); i < n; i++ ) + aTable->setDefValue( i, 2, aValueTypes[i] ); + + if ( aPortNames.count() > 1 ) + myOutputPortsGroupBox->EnableBtn( YACSGui_PlusMinusGrp::UpBtn | YACSGui_PlusMinusGrp::DownBtn ); +} + +QString YACSGui_ServiceNodePage::getPortType( YACS::ENGINE::Port* thePort ) const +{ + QString aType; + + YACSGui_Table* aTable = 0; + if ( dynamic_cast(thePort) ) + aTable = myInputPortsGroupBox->Table(); + else if ( dynamic_cast(thePort) ) + aTable = myOutputPortsGroupBox->Table(); + + if ( !aTable ) return aType; + + QStringList aVTCB = aTable->Params( 0, 2 ); + + if ( DataPort* aDataPort = dynamic_cast(thePort) ) + { + DynType aDType = aDataPort->edGetType()->kind(); + if ( aDType > NONE && aDType < Objref ) //if (aDType != NONE) + aType = aVTCB[aDType-1]; + else + aType = QString(aDataPort->edGetType()->name()); + //SCRUTE(aType); + } + + return aType; +} + +void YACSGui_ServiceNodePage::setInputPorts() +{ + DEBTRACE("YACSGui_ServiceNodePage::setInputPorts"); + if ( !myInputPortsGroupBox ) return; + + ServiceNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + + myInputPortsGroupBox->Table()->stopEdit(true); + + if ( myType != SALOMEService ) + { + // remove old ports + list anInPortsEngine = aNode->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + { + mySNode->update( REMOVE, + ( dynamic_cast(*anInPortsIter) ? INPUTPORT : INPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] ); + + //aNode->edRemovePort(*anInPortsIter); + // remove port subject (and all subject links connected to this port) + mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anInPortsIter] ); + } + + // create a set of new input ports + YACS::ENGINE::Catalog* aCatalog = getInputPanel()->getModule()->getCatalog(); + if ( aCatalog && aNode->getComponent() + && + aCatalog->_componentMap.count(aNode->getComponent()->getCompoName()) ) + { + ComponentDefinition* aCompodef = aCatalog->_componentMap[aNode->getComponent()->getCompoName()]; + if ( aCompodef && aCompodef->_serviceMap.count(aNode->getMethod()) ) + if ( ServiceNode* aNodeToClone = aCompodef->_serviceMap[aNode->getMethod()] ) + { + list anInPortsClone = aNodeToClone->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsClone.begin(); + for( ;anInPortsIter!=anInPortsClone.end();anInPortsIter++) + if ( InputPort* anIP = dynamic_cast(*anInPortsIter) ) // Data Flow port + dynamic_cast(mySNode)->addInputPort( aCatalog, + portValueType(anIP->edGetType()), + anIP->getName() ); + else if ( InputDataStreamPort* anIDSP = dynamic_cast(*anInPortsIter) ) // Data Stream port + dynamic_cast(mySNode)->addIDSPort( aCatalog, + portValueType(anIDSP->edGetType()), + anIDSP->getName() ); + } + } + } + + // read input data and input data stream ports from the table + YACSGui_Table* aTable = myInputPortsGroupBox->Table(); + + QStringList aPortNames; + QStringList aValues; + + aTable->strings( 0, aPortNames ); + aTable->strings( 3, aValues ); + + // initialize created input ports with values + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it,++aRowId ) + { + if ( (*it).isEmpty() ) continue; + + if ( aTable->intValueCombo( 1, aRowId ) == 0 ) // Data Flow port + { + InputPort* aIDP; + try { + aIDP = aNode->getInputPort(*it); + } + catch (YACS::Exception& ex) { + continue; + } + if ( !aIDP ) + continue; + + TypeCode* aTC = aIDP->edGetType(); + if ( !aTC ) + continue; + +#ifdef _DEVDEBUG_ + if(!aValues[aRowId].isNull()) + std::cerr << aValues[aRowId] << std::endl; + else + std::cerr << "Qnull" << std::endl; +#endif + + if( aValues[aRowId] == "< ? >") + continue; + + // initialize new created input data port + double d; + bool ok; + switch ( aTC->kind() ) + { + case Double: + d=aValues[aRowId].toDouble(&ok); + if(ok) + aIDP->edInit(d); + break; + case Int: + aIDP->edInit( aValues[aRowId].toInt() ); + break; + case String: + aIDP->edInit( aValues[aRowId].latin1() ); + break; + case Bool: + aIDP->edInit( aValues[aRowId].compare( aTable->Params(aRowId,3)[0] ) ? false : true ); + break; + case Objref: + //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + break; + case Sequence: + //aIDP->edInit( "" ); // TODO : create an Any* (i.e. SequenceAny*) with corresponding type and initialize with it + break; + case Array: + //aIDP->edInit( "" ); // TODO : create an Any* (i.e. ArrayAny*) with corresponding type and initialize with it + break; + case Struct: + //aIDP->edInit( "" ); // TODO : create an Any* with corresponding type and initialize with it + break; + default: + break; + } + + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aIDP]); + } + //else if ( aTable->intValueCombo( 1, aRowId ) == 1 ) // Data Stream (BASIC) port + // // TODO : set value for input data stream port + //else if ( aTable->intValueCombo( 1, aRowId ) == 2 ) // Data Stream (CALCIUM) port + // // TODO : set value for input data stream port + //else if ( aTable->intValueCombo( 1, aRowId ) == 3 ) // Data Stream (PALM) port + // // TODO : set value for input data stream port + + } +} + +void YACSGui_ServiceNodePage::setOutputPorts() +{ + DEBTRACE("YACSGui_ServiceNodePage::setOutputPorts"); + if ( !myOutputPortsGroupBox ) return; + + ServiceNode* aNode = dynamic_cast( getNode() ); + if ( !aNode ) return; + + myOutputPortsGroupBox->Table()->stopEdit(true); + + if ( myType != SALOMEService ) + { + // remove old ports + list anOutPortsEngine = aNode->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + { + mySNode->update( REMOVE, + ( dynamic_cast(*anOutPortsIter) ? OUTPUTPORT : OUTPUTDATASTREAMPORT ), + GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] ); + + //aNode->edRemovePort(*anOutPortsIter); + // remove port subject (and all subject links connected to this port) + mySNode->destroy( GuiContext::getCurrent()->_mapOfSubjectDataPort[*anOutPortsIter] ); + } + + // create a set of new input ports + YACS::ENGINE::Catalog* aCatalog = getInputPanel()->getModule()->getCatalog(); + if ( aCatalog && aNode->getComponent() + && + aCatalog->_componentMap.count(aNode->getComponent()->getCompoName()) ) + { + ComponentDefinition* aCompodef = aCatalog->_componentMap[aNode->getComponent()->getCompoName()]; + if ( aCompodef && aCompodef->_serviceMap.count(aNode->getMethod()) ) + if ( ServiceNode* aNodeToClone = aCompodef->_serviceMap[aNode->getMethod()] ) + { + list anOutPortsClone = aNodeToClone->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsClone.begin(); + for( ;anOutPortsIter!=anOutPortsClone.end();anOutPortsIter++) + if ( OutputPort* anOP = dynamic_cast(*anOutPortsIter) ) // Data Flow port + dynamic_cast(mySNode)->addOutputPort( aCatalog, + portValueType(anOP->edGetType()), + anOP->getName() ); + else if ( OutputDataStreamPort* anODSP = dynamic_cast(*anOutPortsIter) ) // Data Stream port + dynamic_cast(mySNode)->addODSPort( aCatalog, + portValueType(anODSP->edGetType()), + anODSP->getName() ); + } + } + } + + // read output data and output data stream ports from the table + YACSGui_Table* aTable = myOutputPortsGroupBox->Table(); + + QStringList aPortNames; + aTable->strings( 0, aPortNames ); + + int aRowId = 0; + for ( QStringList::Iterator it = aPortNames.begin(); it != aPortNames.end(); ++it ) + { + if ( (*it).isEmpty() ) continue; + + // TODO : Remember "Is in study" flag for output port + // ... + + aRowId++; + } +} + +YACS::ENGINE::TypeCode* YACSGui_ServiceNodePage::createTypeCode( YACS::ENGINE::DynType theType, + YACSGui_Table* theTable, + int theRowId ) +{ + TypeCode* aTC = 0; + + switch (theType) + { + case Double: + case Int: + case String: + case Bool: + aTC = new TypeCode(theType); + break; + case Objref: + { + if ( theTable->intValueCombo( 1, theRowId ) == 2 ) // Data Stream (CALCIUM) port + aTC = new TypeCodeObjref("CALCIUM","CALCIUM"); + else if ( theTable->intValueCombo( 1, theRowId ) == 1 ) // Data Stream (BASIC) port + aTC = new TypeCodeObjref("BASIC","BASIC"); + else if ( theTable->intValueCombo( 1, theRowId ) == 3 ) // Data Stream (PALM) port + aTC = new TypeCodeObjref("PALM","PALM"); + else + aTC = new TypeCodeObjref("",""); + } + break; + case Sequence: + aTC = new TypeCodeSeq("","",(new TypeCode(Double))); + break; + case Array: + aTC = new TypeCodeArray("","",(new TypeCode(Double)),0); + break; + case Struct: + aTC = new TypeCodeStruct("",""); + break; + default: + break; + } + + return aTC; +} + +QString YACSGui_ServiceNodePage::scriptText() const +{ +#ifdef HAVE_QEXTSCINTILLA_H + return _myTextEdit->text(); +#else + return myTextEdit->text(); +#endif +} + +void YACSGui_ServiceNodePage::setScriptText( const QString& txt ) +{ +#ifdef HAVE_QEXTSCINTILLA_H + _myTextEdit->setText( txt ); +#else + myTextEdit->setText( txt ); +#endif +} diff --git a/src/gui/YACSGui_Swig.cxx b/src/gui/YACSGui_Swig.cxx index 358cb7a6e..e8b5b1562 100644 --- a/src/gui/YACSGui_Swig.cxx +++ b/src/gui/YACSGui_Swig.cxx @@ -34,7 +34,10 @@ #include "SALOME_Event.hxx" +#include + using namespace YACS::ENGINE; +using namespace YACS::HMI; YACSGui_Swig::YACSGui_Swig() { @@ -64,7 +67,7 @@ void YACSGui_Swig::createGraphPresentation( YACS::ENGINE::Proc* theProc ) { // get YACSGui module CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication()); - YACSGui_Module* aModule = dynamic_cast( anApp->module( anApp->moduleTitle( "YACSGui" ) ) ); + YACSGui_Module* aModule = dynamic_cast( anApp->module( anApp->moduleTitle( "YACS" ) ) ); if ( !aModule ) return; // create view window for presentation of theProc @@ -75,9 +78,11 @@ void YACSGui_Swig::createGraphPresentation( YACS::ENGINE::Proc* theProc ) if ( aVW ) aVW->setCaption(theProc->getName().c_str()); // add theProc to data model as not editable graph - YACSGui_DataModel* aModel = aModule->getDataModel(); + + /*abd + YACSGui_DataModel* aModel = aModule->getDataModel(); if (aModel) - aModel->add(theProc, false); + aModel->add(theProc, false);*/ // create presentation for theProc (i.e. YACSGui_Graph, presentations of graph's nodes ...) and display it if ( aVW ) @@ -85,6 +90,12 @@ void YACSGui_Swig::createGraphPresentation( YACS::ENGINE::Proc* theProc ) YACSGui_Loader::PrsDataMap aPrsData; YACSGui_Loader::PortLinkDataMap aPortLinkData; YACSGui_Loader::LabelLinkDataMap aLabelLinkData; - aModule->displayGraph( theProc, aPrsData, aPortLinkData, aLabelLinkData ); + + // create GuiContext for Proc* + GuiContext* aCProc = new GuiContext(); + GuiContext::setCurrent( aCProc ); + aCProc->setProc( theProc ); + + aModule->displayGraph( aCProc, aPrsData, aPortLinkData, aLabelLinkData ); } } diff --git a/src/gui/YACSGui_SwitchNodePage.cxx b/src/gui/YACSGui_SwitchNodePage.cxx new file mode 100644 index 000000000..ce71a9a0e --- /dev/null +++ b/src/gui/YACSGui_SwitchNodePage.cxx @@ -0,0 +1,984 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_SwitchNodePage + Description : Page for SWITCH node properties +*/ + +YACSGui_SwitchNodePage::YACSGui_SwitchNodePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : SwitchNodePage( theParent, theName, theFlags ), + YACSGui_NodePage(), + myIsSelectChild(false) +{ + if ( mySwitchCasesGroupBox ) + { + mySwitchCasesGroupBox->setTitle( tr("SWITCH Cases") ); + mySwitchCasesGroupBox->HideBtn( YACSGui_PlusMinusGrp::InsertBtn | + YACSGui_PlusMinusGrp::UpBtn | + YACSGui_PlusMinusGrp::DownBtn ); + mySwitchCasesGroupBox->EnableBtn( YACSGui_PlusMinusGrp::SelectBtn, false ); + YACSGui_Table* aTable = mySwitchCasesGroupBox->Table(); + aTable->setFixedHeight( 100 ); + aTable->setNumCols( 2 ); + aTable->horizontalHeader()->setLabel( 0, tr( "Case id" ) ); + aTable->horizontalHeader()->setLabel( 1, tr( "Node name" ) ); + aTable->setCellType( -1, 0, YACSGui_Table::String ); + aTable->setCellType( -1, 1, YACSGui_Table::String ); + + connect( aTable, SIGNAL(valueChanged( int, int )), this, SLOT(onValueChanged( int, int )) ); + + mySwitchCasesGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + mySwitchCasesGroupBox->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); + + mySwitchCasesGroupBox->Btn(YACSGui_PlusMinusGrp::SelectBtn)->setTextLabel(tr("SELECT_BTN_TOOLTIP"),true); + mySwitchCasesGroupBox->Btn(YACSGui_PlusMinusGrp::PlusBtn)->setTextLabel(tr("PLUS_BTN_TOOLTIP"),true); + mySwitchCasesGroupBox->Btn(YACSGui_PlusMinusGrp::MinusBtn)->setTextLabel(tr("MINUS_BTN_TOOLTIP"),true); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); + connect( mySwitchCasesGroupBox, SIGNAL(initSelection( const int, const int )), + this, SLOT(onInitSelection( const int, const int )) ); + connect( mySwitchCasesGroupBox->Table(), SIGNAL(itemCreated( const int, const int )), + this, SLOT(onNewItem( const int, const int )) ); + + connect( mySwitchCasesGroupBox, SIGNAL(Added( const int )), this, SLOT(onAdded( const int )) ); + connect( mySwitchCasesGroupBox, SIGNAL(Inserted( const int )), this, SLOT(onInserted( const int )) ); + connect( mySwitchCasesGroupBox, SIGNAL(MovedUp( const int )), this, SLOT(onMovedUp( const int )) ); + connect( mySwitchCasesGroupBox, SIGNAL(MovedDown( const int )), this, SLOT(onMovedDown( const int )) ); + connect( mySwitchCasesGroupBox, SIGNAL(Removed( const int )), this, SLOT(onRemoved( const int )) ); + } + + // TODO: implement presentation of the switch node in collapsed mode + // temporary solution : + myCollapsedRadioButton->setEnabled(false ); +} + +YACSGui_SwitchNodePage::~YACSGui_SwitchNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); + + myRow2ChildMap.clear(); + myRowsOfSelectedChildren.clear(); +} + +void YACSGui_SwitchNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( dynamic_cast( theSNode->getNode() ) ) + YACSGui_NodePage::setSNode( theSNode ); +} + +void YACSGui_SwitchNodePage::setChild( YACS::HMI::SubjectNode* theChildNode ) +{ + if ( !theChildNode ) return; + + if ( !mySwitchCasesGroupBox ) return; + YACSGui_Table* aTable = mySwitchCasesGroupBox->Table(); + + myIsSelectChild = false; + mySwitchCasesGroupBox->setOffSelect(); + mySwitchCasesGroupBox->EnableBtn( YACSGui_PlusMinusGrp::SelectBtn, false ); + + // sets the child node name into table's cell + QStringList aChildNames; + aTable->strings( 1, aChildNames ); + aChildNames[aTable->currentRow()] = theChildNode->getNode()->getName(); + aTable->setStrings( 1, aChildNames ); + + // add theChildNode into the map of children of this switch node + if ( myRow2ChildMap.find(aTable->currentRow()) == myRow2ChildMap.end() ) + myRow2ChildMap.insert( std::make_pair( aTable->currentRow(), theChildNode ) ); + else + myRow2ChildMap[aTable->currentRow()] = theChildNode; + + bool anExist = false; + std::list::iterator it = myRowsOfSelectedChildren.begin(); + for ( ; it != myRowsOfSelectedChildren.end(); it++ ) + if ( *it == aTable->currentRow() ) + { + anExist = true; + break; + } + if ( !anExist ) + myRowsOfSelectedChildren.push_back( aTable->currentRow() ); +} + +bool YACSGui_SwitchNodePage::isSelectChild() const +{ + return myIsSelectChild; +} + +void YACSGui_SwitchNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + myNodeName->setReadOnly(false); + + mySwitchCasesGroupBox->ShowBtn( YACSGui_PlusMinusGrp::SelectBtn | + YACSGui_PlusMinusGrp::PlusBtn | + YACSGui_PlusMinusGrp::MinusBtn ); + YACSGui_Table* aTable = mySwitchCasesGroupBox->Table(); + aTable->setReadOnly( -1, 0, false ); + + ViewModeButtonGroup->show(); + + ExecutionGroupBox->hide(); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + myNodeName->setReadOnly(true); + + mySwitchCasesGroupBox->HideBtn(); + YACSGui_Table* aTable = mySwitchCasesGroupBox->Table(); + aTable->setReadOnly( -1, 0, true ); + + ViewModeButtonGroup->hide(); + + ExecutionGroupBox->show(); + } +} + +void YACSGui_SwitchNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_SwitchNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_SwitchNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + //printf("==> SwitchNodePage : Size of theInPortName2Value : %d\n",theInPortName2Value.size()); + + Switch* aSwitchNode = dynamic_cast( getNode() ); + if ( !aSwitchNode ) return; + + if ( theInPortName2Value.size() == 1 ) + { + // select port + QString aName(aSwitchNode->edGetConditionPort()->getName()); + map::iterator it = theInPortName2Value.begin(); + QString aGivenName( (*it).first ); + if ( !aGivenName.compare(aName) && mySelectInputPortValue ) + { + QString aValue( (*it).second ); + if ( !aValue.compare(QString("< ? >")) ) + mySelectInputPortValue->setValue( 0 ); + else + mySelectInputPortValue->setValue( aValue.toInt() ); + } + } +} + +void YACSGui_SwitchNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + //printf("==> SwitchNodePage : Size of theOutPortName2Value : %d\n",theOutPortName2Value.size()); +} + +void YACSGui_SwitchNodePage::notifyNodeCreateNode( YACS::HMI::Subject* theSubject ) +{ + updateState(); +} + +void YACSGui_SwitchNodePage::checkModifications() +{ + if ( !getNode() ) return; + + Switch* aSwitch = dynamic_cast(getNode()); + if ( !aSwitch ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + + if ( myNodeName->text().compare(getNodeName()) != 0 ) isModified = true; + else if( YACS::ENGINE::InputPort* aPort = aSwitch->edGetConditionPort() ) + { + bool ok; + int aValue = getPortValue( aPort ).toInt( &ok ); + if( ok && mySelectInputPortValue->value() != aValue ) isModified = true; + } + + if ( !isModified ) + { + // check switch cases nodes + YACSGui_Table* aTable = mySwitchCasesGroupBox->Table(); + if ( !aTable ) return; + + QStringList aChildIds, aChildNames; + aTable->strings( 0, aChildIds ); + aTable->strings( 1, aChildNames ); + + std::list aCaseNodes = aSwitch->edGetDirectDescendants(); + if ( aChildIds.count() != aCaseNodes.size() ) isModified = true; + else + { + std::list::iterator anIter; + std::map aCase2Node; + for ( anIter = aCaseNodes.begin(); anIter != aCaseNodes.end(); ++anIter ) + aCase2Node.insert(make_pair(aSwitch->getRankOfNode(*anIter),(*anIter))); + + int aRowId = 0; + for ( QStringList::Iterator it = aChildIds.begin(); it != aChildIds.end(); ++it ) + { + int aCaseId; + if( (*it).compare(Switch::DEFAULT_NODE_NAME) == 0 ) + aCaseId = Switch::ID_FOR_DEFAULT_NODE; + else + aCaseId = (*it).toInt(); + + map::iterator iter = aCase2Node.find(aCaseId); + if ( iter == aCase2Node.end() ) + { + isModified = true; + break; + } + else + { + Node* aChild = 0; + if ( SubjectNode* aSChild = myRow2ChildMap[aRowId] ) + aChild = aSChild->getNode(); + + if ( (*iter).second != aChild ) + { + isModified = true; + break; + } + } + + aRowId++; + } + } + } + + //if ( !isModified ) + // TODO: compare view mode: expanded or collapsed (not yet in use) + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::InlineNodeId); + } +} + +void YACSGui_SwitchNodePage::onApply() +{ + // Rename a node + if ( myNodeName && getNode() ) + getNode()->setName( myNodeName->text().latin1() ); + + // Reset select input port value + if ( YACS::ENGINE::Switch* aSwitchNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aPort = aSwitchNode->edGetConditionPort() ) + { + int aValue = mySelectInputPortValue->value(); + aPort->edInit( aValue ); + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aPort] ); + } + } + + // To remove a new child nodes from its old places in the tree view + std::list::iterator it = myRowsOfSelectedChildren.begin(); + for ( ; it != myRowsOfSelectedChildren.end(); it++ ) + { + SubjectNode* aNewSelectedChild = myRow2ChildMap[*it]; + Node* aNode = aNewSelectedChild->getNode(); + + if( SubjectSwitch* aSSwitch = dynamic_cast( aNewSelectedChild->getParent() ) ) + { + Switch* aSwitch = dynamic_cast( aSSwitch->getNode() ); + + Node* aDefaultNode = 0; + try { + aDefaultNode = aSwitch->getChildByShortName(Switch::DEFAULT_NODE_NAME); + } + catch (YACS::Exception& ex) {} + + if( aDefaultNode && aDefaultNode == aNode ) + continue; // do not remove a default node - keep it for copying + } + + try { + getNode()->getChildByName( aNode->getName() ); + } + catch (YACS::Exception& ex) { + // switch is not contain nodes with the same name as aNode + // get schema engine object + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( !aProc ) return; + // get gui graph + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + aNewSelectedChild->getParent()->detach(aGraph); // to remove only a node view item in the tree, node presentation is still alive + + aNewSelectedChild->getParent()->update( REMOVE, + ProcInvoc::getTypeOfNode( aNewSelectedChild->getNode() ), + aNewSelectedChild ); + + aNewSelectedChild->getParent()->attach(aGraph); // to remove only a node view item in the tree, node presentation is still alive + } + } + + // Reset the list of switch cases + setSwitchCases(); + + // Reset the view mode + // ... + + mySNode->update( EDIT, 0, mySNode ); + + updateLabelPorts(); + + // clear for next selections + myRowsOfSelectedChildren.clear(); + + updateBlocSize(); +} + +void YACSGui_SwitchNodePage::updateState() +{ + myRow2ChildMap.clear(); + myRowsOfSelectedChildren.clear(); + + // Clear input ports table and output ports tables, if they are not empty + if ( mySwitchCasesGroupBox ) { + mySwitchCasesGroupBox->Table()->setNumRows( 0 ); + mySwitchCasesGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Fill the table of child nodes of the switch + SubjectSwitch* aSNode = dynamic_cast(mySNode); + if ( aSNode && mySwitchCasesGroupBox ) + { + if( Switch* aSwitch = dynamic_cast(getNode()) ) + { + if( YACS::ENGINE::InputPort* aPort = aSwitch->edGetConditionPort() ) + { + bool ok; + int aValue = getPortValue( aPort ).toInt( &ok ); + if( ok ) + mySelectInputPortValue->setValue( aValue ); + } + + list aChildren = dynamic_cast(getNode())->edGetDirectDescendants(); + if ( !aChildren.empty() ) + { + list::iterator aChildIt = aChildren.begin(); + + Node* aDefaultNode = 0; + try { + aDefaultNode = aSwitch->getChildByShortName(Switch::DEFAULT_NODE_NAME); + } + catch (YACS::Exception& ex) { + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString("Switch has no a default node!"), + tr("BUT_OK")); + } + + int aMinCaseId, aMaxCaseId; + aMinCaseId = aMaxCaseId = aSwitch->getRankOfNode(*aChildIt); + + list aCaseNodes; + + for( ; aChildIt != aChildren.end(); aChildIt++ ) + { + Node* aNode = *aChildIt; + if( aNode == aDefaultNode ) + continue; + + int aRank = aSwitch->getRankOfNode( aNode ); + if( aMinCaseId >= aRank ) + { + aCaseNodes.push_front( aNode ); + aMinCaseId = aRank; + } + else if( aMinCaseId < aRank && aMaxCaseId > aRank ) + { + list::iterator aCaseNodesIt = aCaseNodes.begin(); + for( list::iterator anIt = aCaseNodesIt; + anIt++ != aCaseNodes.end(); + aCaseNodesIt++, anIt = aCaseNodesIt ) + { + if ( aRank >= aSwitch->getRankOfNode( *aCaseNodesIt ) && + aSwitch->getRankOfNode( aNode ) <= aSwitch->getRankOfNode( *anIt ) ) + { + aCaseNodes.insert( anIt, aNode ); + break; + } + } + } + else if( aMaxCaseId <= aRank ) + { + aCaseNodes.push_back( aNode ); + aMaxCaseId = aRank; + } + } + aCaseNodes.push_back( aDefaultNode ); + + QStringList aChildIds; + QStringList aChildNames; + + list::iterator anIt = aCaseNodes.begin(); + list::iterator anItEnd = aCaseNodes.end(); + for( int aRow = 0; anIt != anItEnd; anIt++, aRow++ ) + { + QString anId, aName; + Node* aNode = *anIt; + + if ( !aNode ) continue; + + if( aNode == aDefaultNode ) + anId = Switch::DEFAULT_NODE_NAME; + else + anId = QString::number( aSwitch->getRankOfNode( aNode ) ); + aChildIds.append( anId ); + + // Collect child names in the list + aName = aNode->getName(); + aChildNames.append( aName ); + + if ( myRow2ChildMap.find(aRow) == myRow2ChildMap.end() ) + myRow2ChildMap.insert( std::make_pair( aRow, aSNode->getChild(aNode) ) ); + else + myRow2ChildMap[aRow] = aSNode->getChild(aNode); + } + + // Fill "Node name" column + mySwitchCasesGroupBox->Table()->setStrings( 0, aChildIds, true ); + mySwitchCasesGroupBox->Table()->setStrings( 1, aChildNames, true ); + + if ( !aChildNames.empty() ) mySwitchCasesGroupBox->EnableBtn( YACSGui_PlusMinusGrp::AllBtn ); + } + } + } + + // Set view mode of the given switch node + // the following method can be used if its needed: + // YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( myProc ); + // ... +} + +void YACSGui_SwitchNodePage::updateLabelPorts() +{ + if( Proc* aProc = dynamic_cast(getNode()->getRootNode()) ) + { + if( YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ) ) + { + if ( YACSPrs_ElementaryNode* aNodePrs = aGraph->getItem( getNode() ) ) + { + QPtrList aPorts = aNodePrs->getPortList(); + for (YACSPrs_Port* aPort = aPorts.first(); aPort; aPort = aPorts.next()) + { + if ( YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ) ) + aGraph->update( aLabelPort ); + } + } + aGraph->getCanvas()->update(); + } + } +} + +void YACSGui_SwitchNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + +void YACSGui_SwitchNodePage::onValueChanged( int theRow, int theCol ) +{ + if ( YACSGui_Table* aTable = ( YACSGui_Table* )sender() ) + { + if ( theCol == 0 ) + { + QString anId = aTable->item( theRow, theCol )->text(); + QStringList anIds; + aTable->strings( 0, anIds ); + if( anIds.contains( anId ) > 1 ) + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString("Switch is already contains a node with such id."), + tr("BUT_OK")); + } + } +} + +void YACSGui_SwitchNodePage::onInitSelection( const int theRow, const int theCol ) +{ + myIsSelectChild = true; +} + +void YACSGui_SwitchNodePage::onNewItem( const int theRow, const int theCol ) +{ + if ( mySwitchCasesGroupBox && theCol == 1 ) // set "node name" column read only + mySwitchCasesGroupBox->Table()->setReadOnly( theRow, theCol, true ); +} + +void YACSGui_SwitchNodePage::onAdded( const int theRow ) +{ + SubjectNode* aNode = 0; + myRow2ChildMap.insert( std::make_pair( theRow, aNode ) ); +} + +void YACSGui_SwitchNodePage::onInserted( const int theRow ) +{ + SubjectNode* aNode = 0; + + if ( myRow2ChildMap.find(theRow) == myRow2ChildMap.end() ) + myRow2ChildMap.insert( std::make_pair( theRow, aNode ) ); + else + { + SubjectNode* aStartNodeToMoveDown = myRow2ChildMap[theRow]; + myRow2ChildMap[theRow] = aNode; + + for ( int aRow = myRow2ChildMap.size()-1; aRow > theRow+1; aRow-- ) + myRow2ChildMap[aRow] = myRow2ChildMap[aRow-1]; + + myRow2ChildMap[theRow+1] = aStartNodeToMoveDown; + } +} + +void YACSGui_SwitchNodePage::onMovedUp( const int theUpRow ) +{ + SubjectNode* aNodeToMoveDown = myRow2ChildMap[theUpRow]; + SubjectNode* aNodeToMoveUp = myRow2ChildMap[theUpRow+1]; + + myRow2ChildMap[theUpRow] = aNodeToMoveUp; + myRow2ChildMap[theUpRow+1] = aNodeToMoveDown; + +} + +void YACSGui_SwitchNodePage::onMovedDown( const int theDownRow ) +{ + SubjectNode* aNodeToMoveUp = myRow2ChildMap[theDownRow]; + SubjectNode* aNodeToMoveDown = myRow2ChildMap[theDownRow-1]; + + myRow2ChildMap[theDownRow] = aNodeToMoveDown; + myRow2ChildMap[theDownRow-1] = aNodeToMoveUp; +} + +void YACSGui_SwitchNodePage::onRemoved( const int theRow ) +{ + /* + SubjectNode* aSNodeToRaise = myRow2ChildMap[theRow]; + Node* aNodeToRaise = aSNodeToRaise->getNode(); + + Bloc* aBloc = dynamic_cast( getNode() ); + if ( !aBloc ) return; + + // remove aNodeToRaise node from the children list (if it is present in it) + set aChildren = aBloc->edGetDirectDescendants(); + set::iterator aChildIter = aChildren.begin(); + for( ;aChildIter!=aChildren.end();aChildIter++) + { + if ( *aChildIter == aNodeToRaise ) + { + // get schema engine object + Proc* aProc = dynamic_cast(aBloc->getRootNode()); + if ( !aProc ) return; + + // get schema subject + //YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + //if ( !aGraph ) return; + //SubjectProc* aSProc = aGraph->getContext()->getSubjectProc(); + SubjectProc* aSProc = GuiContext::getCurrent()->getSubjectProc() + if ( !aSProc ) return; + + aBloc->edRemoveChild(aNodeToRaise); + + try { + aProc->edAddChild(aNodeToRaise); // raise the removed child to the Proc level + aSNodeToRaise->reparent(aSProc); + } + catch (YACS::Exception& ex) { + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString(ex.what())+QString("\nThe child node will be deleted. Do you want to continue?"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 1) == 0 ) + { + // delete the old child node + if ( YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ) ) + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(aNodeToRaise) ) + { + anItem->hide(); + aGraph->removeItem(anItem); + delete anItem; + } + //aNodeToRaise = 0; + delete aNodeToRaise; + } + else + { + aBloc->edAddChild(aNodeToRaise); + return; + } + } + break; + } + } + */ + + if ( theRow == myRow2ChildMap.size()-1 ) + myRow2ChildMap.erase(theRow); + else + { + for ( int aRow = theRow; aRow < myRow2ChildMap.size()-1; aRow++ ) + myRow2ChildMap[aRow] = myRow2ChildMap[aRow+1]; + myRow2ChildMap.erase(myRow2ChildMap.size()-1); + } +} + +void YACSGui_SwitchNodePage::setSwitchCases() +{ + if ( !mySwitchCasesGroupBox ) return; + + SubjectSwitch* aSNode = dynamic_cast(mySNode); + if ( !aSNode ) return; + + Switch* aSwitch = dynamic_cast( getNode() ); + if ( !aSwitch ) return; + + // get schema engine object + Proc* aProc = dynamic_cast(aSwitch->getRootNode()); + if ( !aProc ) return; + + // get schema subject + SubjectProc* aSProc = GuiContext::getCurrent()->getSubjectProc(); + if ( !aSProc ) return; + + // get gui graph + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + //printf("myRow2ChildMap:\n"); + //for( map::iterator aChildIt = myRow2ChildMap.begin(); aChildIt != myRow2ChildMap.end(); aChildIt++ ) + // printf( "%d - %s\n", (*aChildIt).first, ((*aChildIt).second)->getNode()->getName().c_str() ); + + // remove old children + Node* aRemovedOldChild; + list aChildren = aSwitch->edGetDirectDescendants(); + list::iterator aChildIter = aChildren.begin(); + for( ;aChildIter!=aChildren.end();aChildIter++) + { + bool isNeedToRemove = true; + map::iterator aChildIt = myRow2ChildMap.begin(); + for( ;aChildIt!=myRow2ChildMap.end();aChildIt++) + if ( (*aChildIt).second->getNode() == (*aChildIter) ) + { + isNeedToRemove = false; + break; + } + if ( !isNeedToRemove ) continue; + + int anId; + Node* aDefaultNode = 0; + try { + aDefaultNode = aSwitch->getChildByShortName(Switch::DEFAULT_NODE_NAME); + } + catch (YACS::Exception& ex) { + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString("Switch has no a default node!"), + tr("BUT_OK")); + } + if( aDefaultNode && (*aChildIter) == aDefaultNode ) + anId = Switch::ID_FOR_DEFAULT_NODE; + else + anId = aSwitch->getRankOfNode( *aChildIter ); + + //aSwitch->edRemoveChild(*aChildIter); // the _father of the removed node will be 0 + aSwitch->edReleaseCase( anId ); + aRemovedOldChild = *aChildIter; + SubjectNode* aSChild = aSNode->getChild(*aChildIter); + + try { + aProc->edAddChild(*aChildIter); // raise the removed child to the Proc level + aSChild->reparent(aSProc); + } + catch (YACS::Exception& ex) + { + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString(ex.what())+QString("\nThe child node will be deleted. Do you want to continue?"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 1) == 0 ) + { + // delete the old child node + // 1) delete corresponding tree view item + aSNode->update(REMOVE, ProcInvoc::getTypeOfNode( aSChild->getNode() ), aSChild); + // 2) delete 2D presentation + aGraph->removeNode( aSChild->getNode() ); + // 3) delete corresponding subject + aSNode->destroy(aSChild); + } + else + { + //aSwitch->edAddChild(aRemovedOldChild); + updateState(); + return; + } + } + } + + // read new children nodes from the table + YACSGui_Table* aTable = mySwitchCasesGroupBox->Table(); + + QStringList aChildIds, aChildNames; + aTable->strings( 0, aChildIds ); + aTable->strings( 1, aChildNames ); + + bool isNeedToUpdate = false; + map::iterator aChildIt = myRow2ChildMap.begin(); + for( ;aChildIt!=myRow2ChildMap.end();aChildIt++) + { + SubjectNode* aSChild = (*aChildIt).second; + Node* aChild = aSChild->getNode(); + if( aChild->getFather() == aSwitch ) + continue; + + int aRow = aChildNames.findIndex( QString(aChild->getName()) ); + if ( aRow != -1 ) + { + int aNewId; + QString aStr = aChildIds[ aRow ]; + if( aStr == Switch::DEFAULT_NODE_NAME ) + aNewId = Switch::ID_FOR_DEFAULT_NODE; + else + aNewId = aStr.toInt(); + + if ( Switch* aFather = dynamic_cast(aChild->getFather()) ) + { + int anId; + Node* aFatherDefaultNode = 0; + try { + aFatherDefaultNode = aFather->getChildByShortName(Switch::DEFAULT_NODE_NAME); + } + catch (YACS::Exception& ex) {} + + if( aFatherDefaultNode && aChild == aFatherDefaultNode ) + { + anId = Switch::ID_FOR_DEFAULT_NODE; + + // If the child is a default node of the another switch - just copy it to the current switch + YACS::ENGINE::Catalog* catalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + + std::string compo; + std::string type; + if( YACS::ENGINE::ServiceNode* aServiceNode = dynamic_cast( aChild ) ) + { + if ( aServiceNode->getComponent() ) + compo = aServiceNode->getComponent()->getCompoName(); + type = aServiceNode->getMethod(); + } + else + type = getInputPanel()->getModule()->getNodeType( ProcInvoc::getTypeOfNode(aChild) ); + + std::string name = aChild->getName(); + if( aSNode->addNode( catalog, compo, type, name, aNewId, true ) ) + { + Node* aNewChild; + list aNewChildren = aSwitch->edGetDirectDescendants(); + list::iterator aNewChildIt = aNewChildren.begin(); + list::iterator aNewChildItEnd = aNewChildren.end(); + for( ; aNewChildIt != aNewChildItEnd; aNewChildIt++ ) + if( (*aNewChildIt)->getName() == name ) + { + aNewChild = (*aNewChildIt); + break; + } + + aGraph->update( aNewChild, dynamic_cast( getSNode() ) ); + aGraph->show(); + } + } + else + anId = aFather->getRankOfNode( aChild ); + + if( anId == Switch::ID_FOR_DEFAULT_NODE ) + continue; + + aFather->edReleaseCase( anId ); + + try { + aSwitch->edSetNode(aNewId, aChild); + aSChild->reparent(mySNode); + } + catch (YACS::Exception& ex) + { + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString(ex.what())+QString("\nRename, please, a new child node and try to add it into the switch once more."), + tr("BUT_OK")); + + aFather->edSetNode(anId, aChild); + isNeedToUpdate = true; + } + } + else if ( Bloc* aFather = dynamic_cast(aChild->getFather()) ) + { + aFather->edRemoveChild(aChild); + + try { + aSwitch->edSetNode(aNewId, aChild); + aSChild->reparent(mySNode); + } + catch (YACS::Exception& ex) + { + SUIT_MessageBox::warn1(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + QString(ex.what())+QString("\nRename, please, a new child node and try to add it into the switch once more."), + tr("BUT_OK")); + + aFather->edAddChild(aChild); + isNeedToUpdate = true; + } + } + } + } + + if ( isNeedToUpdate ) updateState(); + + // update the block node presentation + aGraph->update( aSwitch, dynamic_cast( getSNode()->getParent() ) ); +} + diff --git a/src/gui/YACSGui_Table.cxx b/src/gui/YACSGui_Table.cxx new file mode 100644 index 000000000..34d97d831 --- /dev/null +++ b/src/gui/YACSGui_Table.cxx @@ -0,0 +1,1122 @@ +// Copyright (C) 2003 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 + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utilities.h" + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +/*! constructor + */ +YACSGui_TableItem::YACSGui_TableItem( QTable* tab, YACSGui_Table::CellType t ) +: QTableItem( tab, QTableItem::WhenCurrent ), + myIsReadOnly( false ), + myType( t ) +{ + //DEBTRACE(myType); +} + +/*! Destructor + */ +YACSGui_TableItem::~YACSGui_TableItem() +{ +} + +/*! Function: setText + */ +void YACSGui_TableItem::setText( const QString& txt ) +{ + QTableItem::setText( txt ); + table()->updateCell( row(), col() ); +} + +/*! Function: readOnly + */ +bool YACSGui_TableItem::readOnly() const +{ + return myIsReadOnly; +} + +/*! Function: setReadOnly + */ +void YACSGui_TableItem::setReadOnly( const bool theReadOnly ) +{ + myIsReadOnly = theReadOnly; +} + +/*! Function: type + */ +YACSGui_Table::CellType YACSGui_TableItem::type() const +{ + return myType; +} + +/*! Function: createEditor + */ +QWidget* YACSGui_TableItem::createEditor() const +{ + if( myIsReadOnly ) + return 0; + + QWidget* res = 0; + YACSGui_Table* tab = dynamic_cast( table() ); + if( !tab ) + return 0; + + switch( type() ) + { + case YACSGui_Table::String: + res = new QLineEdit( text(), 0 ); + break; + + case YACSGui_Table::Int: + { + QtxIntSpinBox* sb = new QtxIntSpinBox( 0 ); + bool ok = false; + sb->setMinValue(LONG_MIN); + sb->setMaxValue(LONG_MAX); + int d = text().toInt( &ok ); + sb->setValue( ok ? d : 0 ); + res = sb; + } + break; + + case YACSGui_Table::Double: + { + QtxDblSpinBox* sb = new QtxDblSpinBox( 0 ); + bool ok = false; + double d = text().toDouble( &ok ); + sb->setValue( ok ? d : 0.0 ); + res = sb; + } + break; + case YACSGui_Table::Combo: + { + QComboBox* cb = new QComboBox( (QWidget*)0 ); + QStringList aL = tab->Params( row(), col() ); + if( !aL.empty() ) + { + QString aDefVal; + if ( YACSGui_Table* aTable = dynamic_cast(table()) ) + aDefVal = aTable->defValue(row(), col()); + int anIndex = 0; + + int id = 0; + for( QStringList::Iterator it = aL.begin(); it != aL.end(); it++ ) + { + cb->insertItem( *it ); + if ( !aDefVal.isEmpty() && aDefVal.compare(*it) == 0 ) anIndex = id; + id++; + } + cb->setCurrentItem( anIndex ); + } + res = cb; + } + break; + default: + break; + } + + if( res && tab->isEditorSync() ) + { + QString sign; + switch( type() ) + { + case YACSGui_Table::String: + sign = SIGNAL( textChanged( const QString& ) ); + break; + + case YACSGui_Table::Int: + sign = SIGNAL( valueChanged( int ) ); + break; + + case YACSGui_Table::Double: + sign = SIGNAL( valueChanged( double ) ); + break; + + case YACSGui_Table::Combo: + sign = SIGNAL( activated( const QString& ) ); + break; + + default: + break; + } + if( !sign.isEmpty() ) + QObject::connect( res, sign, tab, SLOT( onSync() ) ); + } + + return res; +} + +/*! Function: setContentFromEditor + */ +void YACSGui_TableItem::setContentFromEditor( QWidget* w ) +{ + QString res; + switch( type() ) + { + case YACSGui_Table::String: + { + QLineEdit* le = dynamic_cast( w ); + if( le ) + res = le->text(); + } + break; + + case YACSGui_Table::Int: + { + QtxIntSpinBox* sb = dynamic_cast( w ); + if( sb ) + res = QString::number( sb->value() ); + } + break; + + case YACSGui_Table::Double: + { + QtxDblSpinBox* sb = dynamic_cast( w ); + if( sb ) + res = QString::number( sb->value() ); + } + break; + + case YACSGui_Table::Combo: + { + QComboBox* cb = dynamic_cast( w ); + if( cb ) + res = cb->currentText(); + } + break; + + default: + break; + } + + setText( res ); +} + + +/*! constructor + */ +YACSGui_TableComboSelectItem::YACSGui_TableComboSelectItem( QTable* theTable, bool theEditable ) + : YACSGui_TableItem( theTable, YACSGui_Table::ComboSelect ), + mySelectBtn( 0 ), + myEditable( theEditable ) +{ + createSelectButton(); +} + +/*! Destructor + */ +YACSGui_TableComboSelectItem::~YACSGui_TableComboSelectItem() +{ +} + +/*! Function: setText + */ +void YACSGui_TableComboSelectItem::setText( const QString& txt ) +{ + YACSGui_TableItem::setText( txt ); +} + +/*! Function: createEditor + */ +QWidget* YACSGui_TableComboSelectItem::createEditor() const +{ + if( myIsReadOnly ) return 0; + + YACSGui_Table* tab = dynamic_cast( table() ); + if( !tab ) return 0; + + QComboBox* cb = new QComboBox( table()->viewport() ); + QStringList aL = tab->Params( row(), col() ); + if( !aL.empty() ) + { + QString aDefVal; + if ( YACSGui_Table* aTable = dynamic_cast(table()) ) + aDefVal = aTable->defValue(row(), col()); + int anIndex = -1; + + int id = 0; + for( QStringList::Iterator it = aL.begin(); it != aL.end(); it++ ) + { + cb->insertItem( *it ); + if ( !aDefVal.isEmpty() && aDefVal.compare(*it) == 0 ) anIndex = id; + id++; + } + + if ( anIndex >= 0 ) + cb->setCurrentItem( anIndex ); + else + { + cb->setEditable(myEditable); + cb->setEditText(aDefVal); + } + } + + if ( mySelectBtn ) + { + QRect r = table()->cellGeometry( row(), col() ); + if ( !r.size().isValid() ) { + table()->ensureCellVisible( row(), col() ); + r = table()->cellGeometry( row(), col() ); + } + r.setWidth( r.width() - mySelectBtn->width() ); + + mySelectBtn->parentWidget()->resize( mySelectBtn->width(), r.height() ); + table()->moveChild( mySelectBtn->parentWidget(), r.x() + r.width(), r.y() ); + mySelectBtn->setFixedHeight( QMAX( 0, r.height() - 3 ) ); + + mySelectBtn->parentWidget()->show(); + } + + QWidget* res = cb; + if( res && tab->isEditorSync() ) + { + QString sign = SIGNAL( activated( const QString& ) ); + + if( !sign.isEmpty() ) + QObject::connect( res, sign, tab, SLOT( onSync() ) ); + } + + return res; +} + +/*! Function: setContentFromEditor + */ +void YACSGui_TableComboSelectItem::setContentFromEditor( QWidget* w ) +{ + QString res; + + QComboBox* cb = dynamic_cast( w ); + if( cb ) + res = cb->currentText(); + + setText( res ); +} + +void YACSGui_TableComboSelectItem::showEditor( bool theIsEditing ) +{ + createSelectButton(); + + placeEditor(theIsEditing); + mySelectBtn->parentWidget()->raise(); + mySelectBtn->parentWidget()->show(); + //table()->cellWidget(row(),col())->show(); +} + +void YACSGui_TableComboSelectItem::hideEditor() +{ + createSelectButton(); + + mySelectBtn->parentWidget()->hide(); + table()->cellWidget(row(),col())->hide(); +} + +/*! Call this to place/resize the item editor correctly (normally + call it from showEditor()) +*/ +void YACSGui_TableComboSelectItem::placeEditor( bool theIsEditing ) +{ + createSelectButton(); + + QRect r = table()->cellGeometry( row(), col() ); + if ( !r.size().isValid() ) { + table()->ensureCellVisible( row(), col() ); + r = table()->cellGeometry( row(), col() ); + } + + if ( !theIsEditing ) r.setWidth( r.width() - mySelectBtn->width() ); + + mySelectBtn->parentWidget()->resize( mySelectBtn->width(), r.height() ); + table()->moveChild( mySelectBtn->parentWidget(), r.x() + r.width(), r.y() ); + mySelectBtn->setFixedHeight( QMAX( 0, r.height() - 3 ) ); +} + +void YACSGui_TableComboSelectItem::createSelectButton() +{ + if ( mySelectBtn ) return; + + QHBox* hbox = new QHBox( table()->viewport() ); + hbox->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); + hbox->setLineWidth( 1 ); + + mySelectBtn = new QToolButton( hbox ); + + QPixmap selectPix = SUIT_Session::session()->resourceMgr()->loadPixmap( "YACS", QObject::tr( "ICON_SELECT" ) ); + mySelectBtn->setIconSet( selectPix ); + + mySelectBtn->setFixedWidth( selectPix.width() ); + + mySelectBtn->setToggleButton( true ); + + hbox->layout()->setAlignment( Qt::AlignRight ); + table()->addChild( hbox ); + hbox->hide(); + + if ( YACSGui_Table* aTable = dynamic_cast(table()) ) + QObject::connect( mySelectBtn, SIGNAL( clicked() ), aTable, SLOT( onSelectButton() ) ); + + QToolTip::add( mySelectBtn, QObject::tr( "Select data type in the tree view" ) ); + QWhatsThis::add( mySelectBtn, QObject::tr( "Click this button to select data type in the tree view" ) ); +} + +void YACSGui_TableComboSelectItem::showText( QString theText ) +{ + if ( myEditable ) + if ( QComboBox* aCB = dynamic_cast(table()->cellWidget( row(), col() )) ) + { + aCB->setEditable(myEditable); + aCB->setEditText(theText); + } +} + +/*! constructor + */ +YACSGui_Table::YACSGui_Table( const int numRows, const int numCols, QWidget* parent, CellType defType ) +: QtxTable( numRows, numCols, parent ), + myDefType( defType ), + myIsSync( false ), + myColTypes( numCols, defType ) +{ + for ( int i = 0; i < numCols; i++ ) + { + QMap aRTypes; + for ( int j = 0; j < numRows; j++ ) + aRTypes.insert( j, defType ); + myCellTypes.insert( i, aRTypes ); + } + + /* no slot onPressed, onClicked ??? + connect( this, SIGNAL( pressed( int, int, int, const QPoint& )), + this, SLOT( onPressed( int, int, int, const QPoint& )) ); + connect( this, SIGNAL( clicked( int, int, int, const QPoint& )), + this, SLOT( onClicked( int, int, int, const QPoint& )) ); + */ +} + +/*! Destructor + */ +YACSGui_Table::~YACSGui_Table() +{ +} + +/*! Function: defCellType + */ +YACSGui_Table::CellType YACSGui_Table::defCellType() const +{ + return myDefType; +} + +/*! Function: setDefCellType + */ +void YACSGui_Table::setDefCellType( CellType t ) +{ + myDefType = t; +} + +/*! Function: cellType + */ +YACSGui_Table::CellType YACSGui_Table::cellType( const int indR, const int indC, bool& ok ) const +{ + ok = false; + + if ( indR < 0 ) // i.e. row is not defined + { + for( int i=0; i numCols() ) + { + for( int i=numCols(); i aRTypes; + for ( int j=0; j numRows() ) + { + for( int j=numRows(); j 0 && myRCComboBoxParam.contains(j) ) myRCComboBoxParam.remove(j); + if ( i == 0 && j > 0 && myRCDefValues.contains(j) ) myRCDefValues.remove(j); + } + } + + // 2.) increase the row list + if ( anOldNumRows < numRows() ) + { + CellType aT; + if ( i < myColTypes.size() ) aT = myColTypes[i]; + else aT = defCellType(); + + for( int j=anOldNumRows; j 0 && myRCComboBoxParam.contains(j-1) ) + myRCComboBoxParam.insert( j, myRCComboBoxParam[j-1] ); // the previous line + + if ( j > 0 && myRCDefValues.contains(j-1) ) + myRCDefValues.insert( j, myRCDefValues[j-1] ); // the previous line + } + } + } + } + + update(); +} + +/*! Function: insertColumns + */ +void YACSGui_Table::insertColumns( int col, int count ) +{ + QtxTable::insertColumns( col, count ); + update(); +} + +/*! Function: insertRows + */ +void YACSGui_Table::insertRows( int row, int count ) +{ + QtxTable::insertRows( row, count ); + update(); +} + +/*! Function: insertRows + */ +void YACSGui_Table::setCurrentCell( int row, int col ) +{ + int aRow = currentRow(); + int aCol = currentColumn(); + if ( aRow != row || aCol != col ) + { + bool ok; + if ( cellType( aRow, aCol, ok ) == ComboSelect ) + if ( YACSGui_TableComboSelectItem* anIt = dynamic_cast(item(currEditRow(),currEditCol())) ) + anIt->hideEditor(); + } + + QTable::setCurrentCell ( row, col ); +} + +/*! Function: onSelectButton + */ +void YACSGui_Table::onSelectButton() +{ + emit selectButtonClicked(currEditRow(),currEditCol()); +} + +/*! Function: createItem + */ +QTableItem* YACSGui_Table::createItem( const int row, const int col, CellType t ) const +{ + DEBTRACE("YACSGui_Table::createItem " << row << " " << col); + YACSGui_TableItem* it; + if ( t == ComboSelect ) + it = new YACSGui_TableComboSelectItem( ( QTable* )this, true ); + else + it = new YACSGui_TableItem( ( QTable* )this, t ); + + it->setText( defValue( row, col ) ); + return it; +} + +/*! Function: update + */ +void YACSGui_Table::update() +{ + bool ok; + for( int i=0; i( i ); + + return it->type(); +} + +/*! Function: endEdit + */ +void YACSGui_Table::endEdit( int row, int col, bool accept, bool replace ) +{ + bool ok; + if ( cellType( currEditRow(), currEditCol(), ok ) == ComboSelect ) + if ( YACSGui_TableComboSelectItem* anIt = dynamic_cast(item(currEditRow(),currEditCol())) ) + anIt->hideEditor(); + + QTable::endEdit( row, col, accept, replace ); +} + +/*! Function: columnWidthChanged + */ +void YACSGui_Table::columnWidthChanged( int col ) +{ + QTable::columnWidthChanged(col); + + if ( col <= currEditCol() ) + { + bool ok; + if ( cellType( currEditRow(), currEditCol(), ok ) == ComboSelect ) + if ( YACSGui_TableComboSelectItem* anIt = dynamic_cast(item(currEditRow(),currEditCol())) ) + anIt->showEditor( true ); + } +} + +/*! Function: rowHeightChanged + */ +void YACSGui_Table::rowHeightChanged( int row ) +{ + QTable::rowHeightChanged(row); + + if ( row <= currEditRow() ) + { + bool ok; + if ( cellType( currEditRow(), currEditCol(), ok ) == ComboSelect ) + if ( YACSGui_TableComboSelectItem* anIt = dynamic_cast(item(currEditRow(),currEditCol())) ) + anIt->showEditor( true ); + } +} + +/*! Function: doubles + */ +DoubleListVal YACSGui_Table::doubles( const int col, const int except, bool* ok ) const +{ + if( ok ) + *ok = true; + + DoubleListVal aDoubleList; + if( numRows()-except<1 ) + return aDoubleList; + + double val; + bool isOk; + for( int i=0; itext().toDouble( &isOk ); + aDoubleList.push_back( isOk ? val : 0.0 ); + if( ok ) + *ok = *ok && isOk; + } + return aDoubleList; +} + +/*! Function: integers + */ +IntListVal YACSGui_Table::integers( const int col, bool* ok ) const +{ + if( ok ) + *ok = true; + IntListVal aIntList; + if( numRows()<1 ) + return aIntList; + + int val; + bool isOk; + for( int i=0; itext().toInt( &isOk ); + aIntList.push_back( isOk ? val : 0 ); + if( ok ) + *ok = *ok && isOk; + } + + return aIntList; +} + +/*! Function: strings + */ +void YACSGui_Table::strings( const int col, QStringList& mat ) const +{ + DEBTRACE("YACSGui_Table::strings " << col << " " << numRows()); + mat.clear(); + for( int i=0; iendEdit( i, col, false, false ); + QTableItem* it = item( i, col ); + QString val=it ? it->text() : QString::null; +#ifdef _DEVDEBUG_ + if(!val.isNull()) + std::cerr << val << std::endl; + else + std::cerr << "Qnull" << std::endl; +#endif + mat.append(val); + } +} + +/*! Function: updateSize + */ +int YACSGui_Table::updateSize( const int count, const bool resize ) +{ + int size = -1; + if( resize ) + { + setNumRows( count ); + size = count; + } + else + size = QMIN( numRows(), count ); + return size; +} + +/*! Function: setDoubles + */ +void YACSGui_Table::setDoubles( const int col, const DoubleListVal& arr, const double def, const bool resize ) +{ + if( col<0 || col>=numCols() ) + return; + + int size = updateSize( arr.empty() ? 0 : arr.size(), resize ); + DoubleListVal::const_iterator it = arr.begin(); + for( int i=0; isetText( QString::number( i=numCols() ) + return; + + int size = updateSize( arr.empty() ? 0 : arr.size(), resize ); + IntListVal::const_iterator it = arr.begin(); + for( int i=0; isetText( QString::number( num ) ); + } +} + +/*! Function: setStrings + */ +void YACSGui_Table::setStrings( const int col, const QStringList& mat, const bool resize ) +{ + //DEBTRACE("col="<setText( iinherits( "QWidget" ) ) + { + it->setContentFromEditor( ( QWidget* )sender() ); + setDefValue(it->row(), it->col(), it->text()); + emit valueChanged( currEditRow(), currEditCol() ); + } +} + +/*! Function: readOnly + */ +bool YACSGui_Table::readOnly( const int row, const int col ) const +{ + YACSGui_TableItem* it = dynamic_cast( item( row, col ) ); + return it ? it->readOnly() : false; +} + +/*! Function: setReadOnly + */ +void YACSGui_Table::setReadOnly( const int row, const int col, const bool ro ) +{ + // if row is not defined - set the read only flag for all rows in the given column + int r1 = row >= 0 ? row : 0; + int r2 = row >= 0 ? row : numRows()-1; + + for( int r = r1; r <= r2; r++ ) + { + YACSGui_TableItem* it = dynamic_cast( item( r, col ) ); + if( it ) + { + endEdit( r, col, false, false ); + it->setReadOnly( ro ); + if( ro && !defValue( r, col ).isEmpty() ) + it->setText( defValue( r, col ) ); + } + } + update(); +} + +/*! Function: defValue + */ +QString YACSGui_Table::defValue( CellType t ) const +{ + QString res; + if( myTDefValues.contains( t ) ) + res = myTDefValues[t]; + return res; +} + +/*! Function: setDefValue + */ +void YACSGui_Table::setDefValue( CellType t, const QString& txt ) +{ + myTDefValues.insert( t, txt ); +} + +/*! Function: defValue + */ +QString YACSGui_Table::defValue( const int indR, const int indC ) const +{ + if( myRCDefValues.contains( indR ) && myRCDefValues[indR].contains( indC ) ) + return myRCDefValues[indR][indC]; + else + { + bool ok; + return defValue( cellType( indR, indC, ok ) ); + } +} + +/*! Function: setDefValue + */ +void YACSGui_Table::setDefValue( const int indR, const int indC, const QString& txt ) +{ + myRCDefValues[indR][indC] = txt; //.insert( ind, txt ); +} + +/*! Function: stopEdit + */ +void YACSGui_Table::stopEdit( const bool accept ) +{ + endEdit( currEditRow(), currEditCol(), accept, accept ); +} + +/*! Function: setParams + */ +void YACSGui_Table::setParams( const int idR, const int idC, const QString& text ) +{ + QStringList aL; + if( !text.isEmpty() ) + { + int length = text.length(); + int start = 0; + int idx = 0; + do + { + idx = text.find( ';', start ); + if( idx== -1 ) { + idx = length; + } + aL.append( text.mid( start, idx-start ) ); + start = idx+1; + } while( start < length ); + } + + if ( idR < 0 ) // i.e. row is not defined + { // set the same parameters for all rows in the given column + for( int i=0; i() ); + myRCComboBoxParam[i].insert( idC, aL ); + } + } + else + { + if ( !myRCComboBoxParam.contains( idR ) ) + myRCComboBoxParam.insert( idR, QMap() ); + myRCComboBoxParam[idR].insert( idC, aL ); + } +} + +/*! Function: Params + */ +QStringList YACSGui_Table::Params( const int idR, const int idC ) const +{ + if( myRCComboBoxParam.contains( idR ) && myRCComboBoxParam[idR].contains( idC ) ) + return myRCComboBoxParam[idR][idC]; + else + return 0; +} + +/*! Function: valueComboBox + */ +IntListVal YACSGui_Table::valueComboBox( const int col ) const +{ + IntListVal aIntList; + if( numRows()<1 ) + return aIntList; + + QString val; int idx; + for( int i=0; itext(); + idx = aL.findIndex( val ); + aIntList.push_back( idx != -1 ? idx : 0 ); + } + return aIntList; +} + +/*! Function: intValue + */ +int YACSGui_Table::intValue( const int col, const int row, bool* ok ) const +{ + if( ok ) + *ok = true; + if( numRows() < row || numCols() < col ) + return -1; + + int val = 0; + + QTableItem* it = item( row, col ); + if( it ) + val = it->text().toInt( ok ); + + return val; +} + +/*! Function: doubleValue + */ +double YACSGui_Table::doubleValue( const int col, const int row, bool* ok ) const +{ + if( ok ) + *ok = true; + if( numRows() < row || numCols() < col ) + return -1.; + + double val = 0.; + + QTableItem* it = item( row, col ); + if( it ) + val = it->text().toDouble( ok ); + + return val; +} + +/*! Function: intValueCombo + */ +int YACSGui_Table::intValueCombo( const int col, const int row ) const +{ + if( numRows() < row || numCols() < col ) + return -1; + + QString text; + int idx, val; + QStringList aL = Params( row, col ); + + QTableItem* it = item( row, col ); + if( it ) + text = it->text(); + idx = aL.findIndex( text ); + val = (idx != -1 ? idx : 0); + + return val; +} + +/*! Function: selectedRow + */ +int YACSGui_Table::selectedRow() const +{ + QTableSelection sel = selection( currentSelection() ); + if ( sel.isActive() ) + return sel.topRow(); + return -1; +} + +QRect YACSGui_Table::cellGeometry ( int row, int col ) const +{ + QRect aRect = QTable::cellGeometry( row, col ); + if ( row == currEditRow() && col == currEditCol() ) + { + bool ok; + if ( cellType( row, col, ok ) == ComboSelect ) + if ( YACSGui_TableComboSelectItem* anIt = dynamic_cast(item(row,col)) ) + aRect.setWidth( aRect.width() - anIt->selectButton()->width() ); + } + + return aRect; +} diff --git a/src/gui/YACSGui_Table.h b/src/gui/YACSGui_Table.h new file mode 100644 index 000000000..89507abc3 --- /dev/null +++ b/src/gui/YACSGui_Table.h @@ -0,0 +1,418 @@ +// Copyright (C) 2003 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 YACSGui_TABLE_HEADER +#define YACSGui_TABLE_HEADER + +#include +#include +#include + +#include + +typedef std::list IntListVal; +typedef std::list DoubleListVal; + +/*! + * Class, intended to create table with different types of values entered to columns. + * The following types are possible: int, double (created as spinboxes), + * string (created as lineedit) and it's possible to specify combobox. + */ +class YACSGui_Table : public QtxTable +{ + Q_OBJECT + +public: + /*enum, defines types of columns + */ + typedef enum { String, Int, Double, Combo, ComboSelect } CellType; + +public: + YACSGui_Table( const int numRows, const int numCols, QWidget*, CellType = Int ); + virtual ~YACSGui_Table(); + + /*! + * Returns type assigned to all cells of the table by default + */ + CellType defCellType() const; + + /*! + * Set type of cells, which will be set to table by default + */ + void setDefCellType( CellType ); + + /*! + * Returns type of given cell, if cell type is not set + * evidently then returns type of cell which is set by default. + * Parameters: int - row number + * int - column number + * bool - returns true if it is possible to determine column type, otherwise - false + */ + CellType cellType( const int, const int, bool& ) const; + + /*! + * Set type for cell at the table + * Parameters: int - row number, if row < 0 ( i.e. row is not defined), + * set the same types for all rows in the given column + * int - column number + * CellType - cell type + */ + void setCellType( const int, const int, CellType ); + + + /*! + * Returns value by default for given type + */ + QString defValue( CellType ) const; + + /*! + * Sets value by default for given type + */ + void setDefValue( CellType, const QString& ); + + /*! + * Returns value by default for given row and column (i.e. cell) + */ + QString defValue( const int, const int ) const; + + /*! + * Sets value by default for given row and column (i.e. cell) + */ + void setDefValue( const int, const int, const QString& ); + + + /*! + * This method finishes ediitng the cell contents in a cell specified by currEditRow() and currEditCol(). + * Modifications are accepted or rejected depending on parameter value + */ + void stopEdit( const bool ); + + + /*! + * Returns list of double values for given column. If value is not defined + * in row of the table then 0 will be added to the list + * and parameter bool will return false + * Paramrters: first int - column number + * second int - It is an index of string starting from which + * all following strings are ignored, i.e. their + * values are not added to the list + * ok - returns true if all values from the strings + * had been sucessfully casted to double. + */ + DoubleListVal doubles( const int, const int = 0, bool* ok = 0 ) const; + + /*! + * Fill given column with values, given at list. If size of list is lesser that number + * of rows in the table then the rest rows are filled by values set by parameter def. + * Parameters: col - column number + * DoubleListVal- list of values + * def- value for rows which are not given at list + * Resize - determines if need to change number of rows in the table + * according to given list size + */ + void setDoubles( const int, const DoubleListVal&, const double, const bool = false ); + + /*! + * Returns list of integer values for given column. If value is not defined + * in row of the table then 0 will be added to the list + * and parameter bool will return false + * Paramrters: first int - column number + * ok - returns true if all values from the strings + * had been sucessfully casted to double. + */ + IntListVal integers( const int, bool* ok = 0 ) const; + + /*! + * Fill given column with values, given at list. If size of list is lesser that number + * of rows in the table then the rest rows are filled by values set by parameter def. + * Parameters: col - column number + * DoubleListVal- list of values + * def- value for string which are not given at list + * Resize - determines if need to change number of rows in the table + * according to given list size + */ + void setIntegers( const int, const IntListVal&, const int, const bool = false ); + + /*! + * Returns list of string values for given column into QStringList. If value is not defined + * in row of the table then QString::null will be added to the list + * Paramrters: first int - column number + * QStringList - list of string values + */ + void strings( const int, QStringList& ) const; + + /*! + * Fill given column with values, given at list. + * Parameters: col - column number + * DoubleListVal- list of values + * Resize - determines if need to change number of rows in the table + * according to given list size + */ + void setStrings( const int, const QStringList&, const bool = false ); + + /*! + * Returns list of integer values for given column. If value is not defined + * in row of the table then -1 will be added to the list + * Paramrters: int - column number + */ + IntListVal valueComboBox( const int ) const; + + /*! + * Returns values of integer of item for given row and column + */ + int intValue( const int, const int, bool* ok = 0 ) const; + + /*! + * Returns values of double of item for given row and column + */ + double doubleValue( const int, const int, bool* ok = 0 ) const; + + /*! + * Returns values of integer of item for given row and column + */ + int intValueCombo( const int, const int ) const; + + /*! + * Allow getting value of special table field: when this field is true, + * the contents of the cell being edited are synchroinized with the contents of + * the cell editor widget, and valueChanged() signal is emitted each time the + * editor contents change - for instance, each time the user types a character + * in a line edit that is used as a cell editor. + */ + bool isEditorSync() const; + + /*! + * Allow setting value of special table field: when this field is true, + * the contents of the cell being edited are synchroinized with the contents of + * the cell editor widget, and valueChanged() signal is emitted each time the + * eidtor contents change - for instance, eahc time the user types a character + * in a line edit that is used as a cell editor. + */ + void setEditorSync( const bool ); + + /*! + * Returns values(true/false) of item for given row and column + * Parameters: first int - row - row number + * second int - col - column number + */ + bool readOnly( const int, const int ) const; + + /*! + * Sets flag read only for given row and column. + * Parameters: first int - row - row number, if row < 0 ( i.e. row is not defined), + * set the read only flag for all rows in the given column + * second int - col - column number + */ + void setReadOnly( const int, const int, const bool ); + + /*! + * Rebuilds table items if necessary, for instance when the number of rows + * or columns changes. + */ + void update(); + + /*! + * Generates list of strings for given row and column (i.e. cell) which will be used at combobox + * Parameters: int - row - row number, if row < 0 ( i.e. row is not defined), + * set the same parameters for all rows in the given column + * int - col - column number + * Text - values for combobox for given column separated by ";" + */ + void setParams( const int, const int, const QString& ); + + /*! + * Returns list of strings for indexes of row and column (i.e. cell) which defines it's combobox contents + * Parameters: int - row - row number + * int - col - column number + */ + QStringList Params( int, int ) const; + + /*! + * Returns number of selected row + */ + int selectedRow() const; + + virtual QRect cellGeometry ( int row, int col ) const; + +signals: + void itemCreated( const int, const int ); + void selectButtonClicked( const int, const int ); + +public slots: + /*! + * Sets the number of the columns at the table. called method update() + */ + virtual void setNumCols( int c ); + + /*! + * Sets the number of the rows at the table. called method update() + */ + virtual void setNumRows( int r ); + + /*! + * Inserts "count" empty rows at row "row" + */ + virtual void insertRows( int row, int count = 1 ); + + /*! + * Inserts "count" empty columns at column "col" + */ + virtual void insertColumns( int col, int count = 1 ); + + /*! + * Redefine this slot to show/hide the cell's selection control + */ + virtual void setCurrentCell ( int row, int col ); + + void onSelectButton(); + +protected: + /*! + * creates new item for tables with type, + * defined by CellType and by value, defined by default at row row and column col + */ + virtual QTableItem* createItem( const int, const int, CellType ) const; + /*! + * Returns type of the table item + */ + virtual CellType itemType( QTableItem* ) const; + + virtual void endEdit( int row, int col, bool accept, bool replace ); + +protected slots: + virtual void columnWidthChanged( int col ); + + virtual void rowHeightChanged( int row ); + +private slots: + /*! + * slot which is called when syncronization is enabled - it + * receives new value from editor and saves it ro cell and emits valueChanged() + */ + void onSync(); + +private: + /*! + * change number of strings according to count when resize == true, + * otherwise retur miniman value from count or numRows + */ + int updateSize( const int, const bool ); + +private: + CellType myDefType; + bool myIsSync; + QMap myTDefValues; + + QMap > myRCDefValues; // row <-> ( column <-> DefValue ) + + QMap > myRCComboBoxParam; // row <-> ( column <-> Params ) + + QValueVector myColTypes; + QMap > myCellTypes; //column <-> ( row <-> cellType ) + +}; + +/*! + * The YACSGui_TableItem class provides the cell content for YACSGui_Table cells. + */ +class YACSGui_TableItem : public QTableItem +{ +public: + YACSGui_TableItem( QTable*, YACSGui_Table::CellType ); + virtual ~YACSGui_TableItem(); + + /*! + * Returns type of item + */ + YACSGui_Table::CellType type() const; + + /*! + * Sets text for current item + */ + virtual void setText( const QString& ); + + /*! + * This virtual function creates an editor which the user can interact with to edit the cell's contents. + */ + virtual QWidget* createEditor() const; + + /*! + * Updates cell contents after cell editing has been finished. Retrieves values from the editor widget. + */ + virtual void setContentFromEditor( QWidget* ); + + /*! + * Returns flag read only for item. + */ + bool readOnly() const; + + /*! + * Sets flag read only for item. + */ + void setReadOnly( const bool ); + +protected: + bool myIsReadOnly; + YACSGui_Table::CellType myType; + +private: +}; + +/*! + * The YACSGui_TableComboSelectItem class provides the cell content with combo box and selection control for YACSGui_Table cells. + */ +class YACSGui_TableComboSelectItem : public YACSGui_TableItem +{ +public: + YACSGui_TableComboSelectItem( QTable*, bool ); + virtual ~YACSGui_TableComboSelectItem(); + + /*! + * Sets text for current item + */ + virtual void setText( const QString& ); + + /*! + * This virtual function creates an editor which the user can interact with to edit the cell's contents. + */ + virtual QWidget* createEditor() const; + + /*! + * Updates cell contents after cell editing has been finished. Retrieves values from the editor widget. + */ + virtual void setContentFromEditor( QWidget* ); + + virtual void showEditor( bool theIsEditing = false ); + virtual void hideEditor(); + + QToolButton* selectButton() const { return mySelectBtn; } + + void showText( QString theText ); + +private: + void createSelectButton(); + void placeEditor( bool theIsEditing ); + void updateSelectButtonState(); + + QToolButton* mySelectBtn; + bool myEditable; +}; + +#endif diff --git a/src/gui/YACSGui_TreeView.cxx b/src/gui/YACSGui_TreeView.cxx new file mode 100644 index 000000000..42241c961 --- /dev/null +++ b/src/gui/YACSGui_TreeView.cxx @@ -0,0 +1,2599 @@ +// Copyright (C) 2003 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 + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Logger.hxx" +#include "LinkInfo.hxx" + +#include +#include + +#include +#include + +#include //for debug only + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; +using namespace YACS::HMI; + +using namespace std; + +/*! + Method returns vector of the internal control links for the given composed node +*/ +std::vector< std::pair< OutGate*,InGate* > > getInternalControlLinks( ComposedNode* theNode ) +{ + vector< pair< OutGate*,InGate* > > anInternalGateLinks; + + if (theNode) + { + list constituents = theNode->edGetDirectDescendants(); + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) + { + // fill control links: check links going from output gate port of each direct child node + OutGate* anOutGate = ( *iter )->getOutGate(); + if (anOutGate) { + set anInGates = anOutGate->edSetInGate(); + set::iterator anInGatesIter = anInGates.begin(); + for(; anInGatesIter!=anInGates.end(); anInGatesIter++) { + InGate* aCurInGate = *anInGatesIter; + if ( find(constituents.begin(),constituents.end(),aCurInGate->getNode()) != constituents.end() ) + anInternalGateLinks.push_back(pair(anOutGate,aCurInGate)); + } + } + } + } + + return anInternalGateLinks; +} + +/*! + Method returns vector of the internal data and stream links for the given composed node +*/ +std::vector< std::pair< OutPort*,InPort* > > getInternalLinks( ComposedNode* theNode ) +{ + vector< pair< OutPort*,InPort* > > anInternalLinks; + + if (theNode) + { + list constituents = theNode->edGetDirectDescendants(); + list temp; + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) + { + if ( !dynamic_cast( *iter ) ) + { // not cross link + list currentsPorts=(*iter)->getSetOfOutputPort(); // only data links! + temp.insert(temp.end(),currentsPorts.begin(),currentsPorts.end()); + + list currentsDataStreamPorts=(*iter)->getSetOfOutputDataStreamPort(); // only data stream links! + temp.insert(temp.end(),currentsDataStreamPorts.begin(),currentsDataStreamPorts.end()); + } + else + { // cross links + vector< pair > aCrossLinks = + dynamic_cast( *iter )->getSetOfLinksLeavingCurrentScope(); // data links and data stream links + vector< pair< OutPort*,InPort* > >::iterator aCrossLinksIter = aCrossLinks.begin(); + for ( ; aCrossLinksIter != aCrossLinks.end(); aCrossLinksIter++ ) { + InPort* aCurInPort = (*aCrossLinksIter).second; + if ( find(constituents.begin(),constituents.end(),aCurInPort->getNode()) != constituents.end() ) + temp.insert(temp.end(),(*aCrossLinksIter).first); + } + } + } + + // fill data and stream links + for(list::iterator iter2=temp.begin();iter2!=temp.end();iter2++) + { + set temp2=(*iter2)->edSetInPort(); + for(set::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++) + if(theNode->isInMyDescendance((*iter3)->getNode())) + anInternalLinks.push_back(pair((*iter2),(*iter3))); + } + } + + return anInternalLinks; +} + +/*! + Method returns vectors of all internal links for the given composed node +*/ +void getAllInternalLinks( ComposedNode* theNode, + std::set< std::pair< OutGate*,InGate* > >& theInternalGateLinks, + std::set< std::pair< OutPort*,InPort* > >& theInternalLinks ) +{ + if (theNode) + { + list constituents = theNode->edGetDirectDescendants(); + list temp; + for(list::iterator iter=constituents.begin();iter!=constituents.end();iter++) + { + if ( !dynamic_cast( *iter ) ) + { // not cross link + + list currentsPorts=(*iter)->getSetOfOutputPort(); // only data links! + temp.insert(temp.end(),currentsPorts.begin(),currentsPorts.end()); + + list currentsDataStreamPorts=(*iter)->getSetOfOutputDataStreamPort(); // only data stream links! + temp.insert(temp.end(),currentsDataStreamPorts.begin(),currentsDataStreamPorts.end()); + } + else + { // cross links + vector< pair > aCrossLinks = + dynamic_cast( *iter )->getSetOfLinksLeavingCurrentScope(); // data links and data stream links + vector< pair< OutPort*,InPort* > >::iterator aCrossLinksIter = aCrossLinks.begin(); + for ( ; aCrossLinksIter != aCrossLinks.end(); aCrossLinksIter++ ) { + InPort* aCurInPort = (*aCrossLinksIter).second; + if ( find(constituents.begin(),constituents.end(),aCurInPort->getNode()) != constituents.end() ) + temp.insert(temp.end(),(*aCrossLinksIter).first); + } + } + + // fill control links: check links going from output gate port of each direct child node + OutGate* anOutGate = ( *iter )->getOutGate(); + if (anOutGate) { + set anInGates = anOutGate->edSetInGate(); + set::iterator anInGatesIter = anInGates.begin(); + for(; anInGatesIter!=anInGates.end(); anInGatesIter++) { + InGate* aCurInGate = *anInGatesIter; + if ( find(constituents.begin(),constituents.end(),aCurInGate->getNode()) != constituents.end() ) + theInternalGateLinks.insert(pair(anOutGate,aCurInGate)); + } + } + } + + // fill data and stream links + for(list::iterator iter2=temp.begin();iter2!=temp.end();iter2++) + { + set temp2=(*iter2)->edSetInPort(); + for(set::iterator iter3=temp2.begin();iter3!=temp2.end();iter3++) + if(theNode->isInMyDescendance((*iter3)->getNode())) + theInternalLinks.insert(pair((*iter2),(*iter3))); + } + } +} + + +//! Constructor. +/*! + */ +YACSGui_TreeView::YACSGui_TreeView( YACSGui_Module* theModule, YACS::HMI::SubjectProc* theSProc, + QWidget* theParent, const char* theName, WFlags theFlags ) + : QListView( theParent, theName, theFlags ), + myModule( theModule ), + mySProc( theSProc ) +{ + setSorting( -1 ); + setRootIsDecorated( true ); + setSelectionMode( QListView::Extended ); + //viewport()->installEventFilter( this ); + + connect( this, SIGNAL( contextMenuRequested( QListViewItem*, const QPoint&, int ) ), + this, SLOT ( onContextMenuRequested( QListViewItem*, const QPoint& ) ) ); +} + +//! Destructor. +/*! + */ +YACSGui_TreeView::~YACSGui_TreeView() +{ +} + +//! Gets the list of selected objects +/*! + */ +std::list YACSGui_TreeView::getSelected() +{ + list aSelList; + for ( QListViewItemIterator it( this ); it.current(); ++it ) + if ( it.current()->isSelected() ) + aSelList.push_back( it.current() ); + return aSelList; +} + +//! Gets the engine Proc* object from the subject proc +/*! + */ +YACS::ENGINE::Proc* YACSGui_TreeView::getProc() const +{ + return ( mySProc ? dynamic_cast(mySProc->getNode()) : 0 ); +} + +//! Builds the tree view according to the schema content. Schema is used as the root object. +/*! + */ +void YACSGui_TreeView::build() +{ + +} + +//! Udates the tree view starting from the given item. +/*! + * \param theItem - the item, which subtree have to be updated. + * \param theIsRecursive - the flag for recursive or not recursive update. + * By default theIsRecursive = false. + */ +void YACSGui_TreeView::update( QListViewItem* theItem, const bool theIsRecursive ) +{ +} + +//! Constructor. +/*! + */ +YACSGui_EditionTreeView::YACSGui_EditionTreeView( YACSGui_Module* theModule, YACS::HMI::SubjectProc* theSProc, + QWidget* theParent, const char* theName, WFlags theFlags ) + : YACSGui_TreeView( theModule, theSProc, theParent, theName, theFlags ) +{ + if ( getProc() ) + { + setCaption( tr( "EDIT_TREE_VIEW" ) + QString( " of " ) + QString( getProc()->getName() ) ); + + addColumn( "Object", 250 ); + + fillContainerData(mySProc); + build(); + + myPreviousSelected = 0; + mySelectedSubjectOutPort = 0; + mySelectedSubjectOutNode = 0; + + connect( this, SIGNAL( doubleClicked( QListViewItem* ) ), this, SLOT( onDblClick( QListViewItem* ) ) ); + connect( this, SIGNAL( selectionChanged() ), this, SLOT( onSelectionChanged() ) ); + } +} + +//! Destructor. +/*! + */ +YACSGui_EditionTreeView::~YACSGui_EditionTreeView() +{ +} + +//! Udates the tree view starting from the given item. +/*! + * \param theItem - the item, which subtree have to be updated. + * \param theIsRecursive - the flag for recursive or not recursive update. + * By default theIsRecursive = false. + */ +void YACSGui_EditionTreeView::update( QListViewItem* theItem, const bool theIsRecursive ) +{ + YACSGui_ViewItem* anItem = dynamic_cast( theItem ); + + if ( !anItem ) + anItem = dynamic_cast( firstChild() ); // get a root item + + if ( anItem && anItem->listView() == this ) + { + anItem->update( theIsRecursive ); + //triggerUpdate(); + } +} + +/*! + Method for displaying the node with all its subnodes in the tree view +*/ +YACSGui_NodeViewItem* YACSGui_EditionTreeView::displayNodeWithPorts( QListViewItem* theRoot, + YACSGui_NodeViewItem* theAfter, + SubjectNode* theSNode ) +{ + YACSGui_NodeViewItem* aNodeItem = 0; + + if ( !theSNode ) return aNodeItem; + + // Display the given node + aNodeItem = new YACSGui_NodeViewItem( theRoot, theAfter, theSNode ); + + displayChildren( aNodeItem ); + + return aNodeItem; +} + +/*! + Method for displaying all nodes ports and subnodes in the tree view +*/ +void YACSGui_EditionTreeView::displayChildren( YACSGui_NodeViewItem* theNodeItem ) +{ + if ( !theNodeItem ) return; + + SubjectComposedNode* aSComposedNode = dynamic_cast( theNodeItem->getSNode() ); + Node* aNode = theNodeItem->getNode(); + ComposedNode* aComposedNode = dynamic_cast( aNode ); + + // Process all subnodes of a composed node + YACSGui_NodeViewItem* aSubNodeItem = 0; + if (aSComposedNode && aComposedNode) { + list aChildNodeSet = aComposedNode->edGetDirectDescendants(); + list::const_iterator aChildIter = aChildNodeSet.begin(); + for(;aChildIter!=aChildNodeSet.end();aChildIter++) + aSubNodeItem = displayNodeWithPorts( theNodeItem, aSubNodeItem, aSComposedNode->getChild(*aChildIter) ); + } + + // Display ports of a given node + + // input ports + + QListViewItem* anInPortItem = aSubNodeItem; + if (!aComposedNode) { + list anInPorts = aNode->getSetOfInPort(); + + list::iterator InPortsIter = anInPorts.begin(); + for(; InPortsIter != anInPorts.end(); InPortsIter++) + anInPortItem = new YACSGui_PortViewItem( theNodeItem, anInPortItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[*InPortsIter] ); + } + else if ( ForLoop* aForLoopNode = dynamic_cast( aNode ) ) { + InputPort* anInputPort = aForLoopNode->edGetNbOfTimesInputPort(); + if (anInputPort) + anInPortItem = new YACSGui_PortViewItem( theNodeItem, aSubNodeItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[anInputPort] ); + } + else if ( Switch* aSwitchNode = dynamic_cast( aNode ) ) { + InputPort* anInputPort = aSwitchNode->edGetConditionPort(); + if (anInputPort) + anInPortItem = new YACSGui_PortViewItem( theNodeItem, aSubNodeItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[anInputPort] ); + } + else if ( WhileLoop* aWhileLoopNode = dynamic_cast( aNode ) ) { + InputPort* anInputPort = aWhileLoopNode->edGetConditionPort(); + if (anInputPort) + anInPortItem = new YACSGui_PortViewItem( theNodeItem, aSubNodeItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[anInputPort] ); + } + else if ( ForEachLoop* aForEachLoopNode = dynamic_cast( aNode ) ) { + InputPort* anInputPort1 = aForEachLoopNode->edGetNbOfBranchesPort(); + if (anInputPort1) + anInPortItem = new YACSGui_PortViewItem( theNodeItem, aSubNodeItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[anInputPort1] ); + InputPort* anInputPort2 = aForEachLoopNode->edGetSeqOfSamplesPort(); + if (anInputPort2) + anInPortItem = new YACSGui_PortViewItem( theNodeItem, anInPortItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[anInputPort2] ); + } + + //InGate* anInGate = aNode->getInGate(); + //if (anInGate) + // anInPortItem = new YACSGui_PortViewItem( theNodeItem, anInPortItem, anInGate ); + + // output ports + + QListViewItem* anOutPortItem = anInPortItem; + if (!aComposedNode) { + list anOutPorts = aNode->getSetOfOutPort(); + + list::iterator OutPortsIter = anOutPorts.begin(); + for(; OutPortsIter != anOutPorts.end(); OutPortsIter++) + anOutPortItem = new YACSGui_PortViewItem( theNodeItem, anOutPortItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[*OutPortsIter] ); + } + else if ( ForEachLoop* aForEachLoopNode = dynamic_cast( aNode ) ) { + OutputPort* anOutputPort = aForEachLoopNode->edGetSamplePort(); + if (anOutputPort) + anOutPortItem = new YACSGui_PortViewItem( theNodeItem, anInPortItem, + GuiContext::getCurrent()->_mapOfSubjectDataPort[anOutputPort] ); + } + + //OutGate* anOutGate = aNode->getOutGate(); + //if (anOutGate) + // anOutPortItem = new YACSGui_PortViewItem( theNodeItem, anOutPortItem, anOutGate ); + + if (aComposedNode) + { + set< pair< OutGate*,InGate* > > anInternalGateLinks; + set< pair< OutPort*,InPort* > > anInternalLinks; + getAllInternalLinks( aComposedNode, anInternalGateLinks, anInternalLinks ); + + // Create internal links + + // Create "Links" label + YACSGui_LabelViewItem* aLinksItem = new YACSGui_LabelViewItem( theNodeItem, anOutPortItem, tr( "LINKS" ) ); + + // Control links + QListViewItem* aControlLinkItem = 0; + set< pair< OutGate*,InGate* > >::iterator aGateLinksIter = anInternalGateLinks.begin(); + for ( ; aGateLinksIter != anInternalGateLinks.end(); aGateLinksIter++ ) + { + pair On2IN = make_pair( (*aGateLinksIter).first->getNode(), (*aGateLinksIter).second->getNode() ); + aControlLinkItem = new YACSGui_ControlLinkViewItem( aLinksItem, aControlLinkItem, + GuiContext::getCurrent()->_mapOfSubjectControlLink[On2IN] ); + } + + // Process out ports list of the node : Data links + QListViewItem* aDataLinkItem = aControlLinkItem; + set< pair< OutPort*,InPort* > >::iterator aLinksIter = anInternalLinks.begin(); + for ( ; aLinksIter != anInternalLinks.end(); aLinksIter++ ) { + OutPort* aCurOutPort = (*aLinksIter).first; + string aClassName = aCurOutPort->getNameOfTypeOfCurrentInstance(); + + // Data links + if ( !aClassName.compare(OutputPort::NAME) ) { + OutputPort* anOutputDFPort = dynamic_cast( aCurOutPort ); + if ( anOutputDFPort ) + aDataLinkItem = new YACSGui_LinkViewItem( aLinksItem, aDataLinkItem, + GuiContext::getCurrent()->_mapOfSubjectLink[*aLinksIter] ); + } + } + + // Process out ports list of the node : Stream links + QListViewItem* aStreamLinkItem = aDataLinkItem; + aLinksIter = anInternalLinks.begin(); + for ( ; aLinksIter != anInternalLinks.end(); aLinksIter++ ) { + OutPort* aCurOutPort = (*aLinksIter).first; + string aClassName = aCurOutPort->getNameOfTypeOfCurrentInstance(); + + // Stream links + if ( !aClassName.compare(OutputDataStreamPort::NAME) || !aClassName.compare(OutputCalStreamPort::NAME) ) { + OutputDataStreamPort* anOutputDSPort = dynamic_cast( aCurOutPort ); + if ( anOutputDSPort ) + aStreamLinkItem = new YACSGui_LinkViewItem( aLinksItem, aStreamLinkItem, + GuiContext::getCurrent()->_mapOfSubjectLink[*aLinksIter] ); + } + } + } + +} + +/*! + Method returns a subject of given tree viewitem +*/ + +YACS::HMI::Subject* YACSGui_EditionTreeView::getSubject( QListViewItem* theItem ) +{ + Subject* aSub = 0; + + if ( YACSGui_ReferenceViewItem* aRefItem = dynamic_cast( theItem ) ) + aSub = aRefItem->getSReference(); + if ( YACSGui_PortViewItem* aPortItem = dynamic_cast( theItem ) ) + aSub = aPortItem->getSPort(); + else if ( YACSGui_NodeViewItem* aNodeItem = dynamic_cast( theItem ) ) + aSub = aNodeItem->getSNode(); + else if ( YACSGui_LinkViewItem* aLinkItem = dynamic_cast( theItem ) ) + aSub = aLinkItem->getSLink(); + else if ( YACSGui_ControlLinkViewItem* aCLinkItem = dynamic_cast( theItem ) ) + aSub = aCLinkItem->getSLink(); + else if ( YACSGui_SchemaViewItem* aSchemaItem = dynamic_cast( theItem ) ) + aSub = aSchemaItem->getSProc(); + else if ( YACSGui_ContainerViewItem* aContItem = dynamic_cast( theItem ) ) + aSub = aContItem->getSContainer(); + else if ( YACSGui_ComponentViewItem* aCompItem = dynamic_cast( theItem ) ) + aSub = aCompItem->getSComponent(); + + return aSub; +} + +/*! + Method returns a subject of the selected tree viewitem if the selection is a single selection or 0, otherwise +*/ +YACS::HMI::Subject* YACSGui_EditionTreeView::getSelectedSubject() +{ + std::list aSelList = getSelected(); + QListViewItem* anItem = 0; + + // check if the current selection is a single selection + if ( aSelList.size() == 1 ) anItem = aSelList.front(); + + return getSubject( anItem ); +} + +//! Public slot. Adds the selected node into the library. +/*! + */ +void YACSGui_EditionTreeView::onAddToLibrary() +{ + +} + +//! Public slot. Adds the data (flow or stream) / control link from the selected port / node to the other (selected later). +/*! + */ +void YACSGui_EditionTreeView::onAddLink() +{ + if ( Subject* aSub = getSelectedSubject() ) + { + if ( dynamic_cast(aSub) || dynamic_cast(aSub) ) + mySelectedSubjectOutPort = static_cast(aSub); + else if (dynamic_cast(aSub)) + mySelectedSubjectOutNode = static_cast(aSub); + } +} + +//! Public slot. Copies the selected item. +/*! + */ +void YACSGui_EditionTreeView::onCopyItem() +{ + +} + +//! Public slot. Pastes an item. +/*! + */ +void YACSGui_EditionTreeView::onPasteItem() +{ + +} + +//! Public slot. Deletes the selected item. +/*! + */ +void YACSGui_EditionTreeView::onDeleteItem() +{ + DEBTRACE("YACSGui_EditionTreeView::onDeleteItem"); + if ( Subject* aSub = getSelectedSubject() ) + { + clearSelection(); + + if ( SubjectLink* aSLink = dynamic_cast(aSub) ) + { + DEBTRACE("delete data link"); + SubjectNode* aNode = aSLink->getSubjectOutNode(); + aNode->update( REMOVE, DATALINK, aSLink ); + if ( !aSLink->getParent()->destroy( aSLink ) ) + { + SUIT_MessageBox::warn1(myModule->getApp()->desktop(), + tr("WARNING"), + GuiContext::getCurrent()->_lastErrorMessage, + tr("BUT_OK")); + //To do restore the link views + } + else + { + myModule->temporaryExport(); + } + } + else if ( SubjectControlLink* aSCLink = dynamic_cast(aSub) ) + { + DEBTRACE("control link"); + SubjectNode* aNode = aSCLink->getSubjectOutNode(); + aNode->update( REMOVE, CONTROLLINK, aSCLink ); + aSCLink->getParent()->destroy( aSCLink ); + + myModule->temporaryExport(); + } + else if ( SubjectDataPort* aSDPort = dynamic_cast(aSub) ) + { + DEBTRACE("port"); + Subject* aNode = aSDPort->getParent(); + aNode->update( REMOVE, ProcInvoc::getTypeOfPort(aSDPort->getPort()), aSDPort ); + aNode->destroy( aSDPort ); + + myModule->temporaryExport(); + } + else if ( SubjectNode* aSNode = dynamic_cast(aSub) ) + { + DEBTRACE("node"); + if ( !myModule ) return; + + YACSGui_Graph* aGraph = myModule->activeGraph(); + if( !aGraph ) return; + + SubjectComposedNode* aSParent = dynamic_cast(aSNode->getParent()); + if ( !aSParent ) return; + + aSParent->update( REMOVE, ProcInvoc::getTypeOfNode( aSNode->getNode() ), aSNode ); + // clear the content of the property page of deleted node + aSNode->update( REMOVE, 0, 0 ); + + aGraph->removeNode( aSNode->getNode() ); + aSParent->destroy( aSNode ); + + myModule->temporaryExport(); + + SubjectBloc* aSBloc = dynamic_cast(aSParent); + if ( aSBloc && !dynamic_cast(aSParent) ) + { + Node* aBloc = aSBloc->getNode(); + if ( !aBloc ) return; + + SubjectComposedNode* aSBlocParent = dynamic_cast( aSBloc->getParent() ); + if ( !aSBlocParent ) return; + + aGraph->update( aBloc, aSBlocParent ); + } + } + else if ( SubjectComponent* aSComp = dynamic_cast(aSub) ) + { + DEBTRACE("component"); + Subject* aProc = aSComp->getParent(); + ComponentInstance* aComp = aSComp->getComponent(); + if ( !aComp ) + { + SUIT_MessageBox::warn1(myModule->getApp()->desktop(), + tr("WARNING"), + "The component instance is null.", + tr("BUT_OK")); + aProc->update( REMOVE, COMPONENT, aSComp ); + // clear the content of the property page of deleted component + aSComp->update( REMOVE, 0, 0 ); + + myModule->temporaryExport(); + + return; + } + + if ( dynamic_cast(aComp) ) + { + aProc->update( REMOVE, COMPONENT, aSComp ); + // clear the content of the property page of deleted component + aSComp->update( REMOVE, 0, 0 ); + aProc->destroy( aSComp ); + + myModule->temporaryExport(); + + return; + } + + Container* aCont = aComp->getContainer(); + if ( !aCont ) return; + + GuiContext* aContext = GuiContext::getCurrent(); + if ( !aContext ) return; + + SubjectContainer* aSCont = 0; + if ( aContext->_mapOfSubjectContainer.find(aCont) != aContext->_mapOfSubjectContainer.end() ) + aSCont = aContext->_mapOfSubjectContainer[aCont]; + if ( !aSCont ) return; + + aSCont->update( REMOVE, COMPONENT, aSComp ); + // clear the content of the property page of deleted component + aSComp->update( REMOVE, 0, 0 ); + aProc->destroy( aSComp ); + + myModule->temporaryExport(); + } + else if ( SubjectContainer* aSCont = dynamic_cast(aSub) ) + { + DEBTRACE("container"); + SubjectProc* aProc = dynamic_cast(aSCont->getParent()); + if ( !aProc ) return; + + aProc->update( REMOVE, CONTAINER, aSCont ); + // clear the content of the property page of deleted container + aSCont->update( REMOVE, 0, 0 ); + aProc->destroy( aSCont ); + + myModule->temporaryExport(); + } + } +} + +//! Public slot. Display 2D view of the selected schema. +/*! + */ +void YACSGui_EditionTreeView::onDisplaySchema() +{ + +} + +//! Public slot. Erase 2D view of the selected schema. +/*! + */ +void YACSGui_EditionTreeView::onEraseSchema() +{ + +} + +//! Public slot. Display 2D presentation of the selected node. +/*! + */ +void YACSGui_EditionTreeView::onDisplayNode() +{ + +} + +//! Public slot. Erase 2D presentation of the selected node. +/*! + */ +void YACSGui_EditionTreeView::onEraseNode() +{ + +} + +//! Protected slot. Shows context popup menu. +/*! + */ +void YACSGui_EditionTreeView::onContextMenuRequested( QListViewItem* theItem, const QPoint& thePoint ) +{ + list aSelList = getSelected(); + if ( aSelList.size() > 1 ) + return; + + if ( YACSGui_LabelViewItem* aLIt = dynamic_cast( theItem ) ) + { + if ( !aLIt->name().compare( QString("Data Types") ) ) + showPopup( contextMenuPopup( YACSGui_EditionTreeView::DataTypeItem ), thePoint ); + if ( !aLIt->name().compare( QString("Nodes") ) ) + showPopup( contextMenuPopup( YACSGui_EditionTreeView::LabelNodesItem ), thePoint ); + if ( !aLIt->name().compare( QString("Containers") ) ) + showPopup( contextMenuPopup( YACSGui_EditionTreeView::LabelContainersItem ), thePoint ); + } + else if ( dynamic_cast( theItem ) ) + { + showPopup( contextMenuPopup( YACSGui_TreeView::SchemaItem ), thePoint ); + } + else if ( YACSGui_NodeViewItem* aNIt = dynamic_cast( theItem ) ) + { + if ( dynamic_cast( aNIt->getNode() ) ) + showPopup( contextMenuPopup( YACSGui_EditionTreeView::ServiceNodeItem ), thePoint ); + else if ( dynamic_cast( aNIt->getNode() ) || dynamic_cast( aNIt->getNode() ) ) + showPopup( contextMenuPopup( YACSGui_EditionTreeView::ComposedNodeItem ), thePoint ); + else if ( dynamic_cast( aNIt->getNode() ) || dynamic_cast( aNIt->getNode() ) ) + showPopup( contextMenuPopup( YACSGui_EditionTreeView::LoopNodeItem ), thePoint ); + else + showPopup( contextMenuPopup( YACSGui_TreeView::NodeItem ), thePoint ); + } + else if ( YACSGui_PortViewItem* aPIt = dynamic_cast( theItem ) ) + { + showPopup( contextMenuPopup( YACSGui_EditionTreeView::PortItem, aPIt->getSPort() ), thePoint ); + } + else if ( dynamic_cast( theItem ) || dynamic_cast( theItem ) ) + { + showPopup( contextMenuPopup( YACSGui_EditionTreeView::LinkItem ), thePoint ); + } + else if ( dynamic_cast( theItem ) ) + { + showPopup( contextMenuPopup( YACSGui_EditionTreeView::ContainerItem ), thePoint ); + } + else if ( YACSGui_ComponentViewItem* aCIt = dynamic_cast( theItem ) ) + { + if ( aCIt->getComponent() && aCIt->getComponent()->getKind() == CORBAComponent::KIND ) + showPopup( contextMenuPopup( YACSGui_EditionTreeView::CorbaComponentItem ), thePoint ); + else + showPopup( contextMenuPopup( YACSGui_EditionTreeView::ComponentItem ), thePoint ); + } +} + +/*! + \brief Builds tree for data types + \param theSchemaItemL schema item + \return "Data types" item + */ +YACSGui_LabelViewItem* YACSGui_EditionTreeView::buildDataTypesTree( + YACSGui_SchemaViewItem* theSchemaItem ) +{ + return theSchemaItem->buildDataTypesTree(); +} + +//! Builds the tree view according to the schema content. Schema is used as the root object. +/*! + */ +void YACSGui_EditionTreeView::build() +{ + if ( !getProc() ) return; + + // Create a schema root object + YACSGui_SchemaViewItem* aSchemaItem = new YACSGui_SchemaViewItem( this, 0, mySProc ); + + YACSGui_LabelViewItem* aDataTypesItem = buildDataTypesTree( aSchemaItem ); + if ( !aDataTypesItem ) + return; + + // Create "Nodes" label if necessary + YACSGui_LabelViewItem* aNodesItem = 0; + list aDirectNodeSet = getProc()->edGetDirectDescendants(); + //if (aDirectNodeSet.size() > 0) + aNodesItem = new YACSGui_LabelViewItem( aSchemaItem, aDataTypesItem, tr( "NODES" ) ); + + // Put all nodes under "Nodes" label + if ( aNodesItem ) + { + YACSGui_NodeViewItem* aNodeItem = 0; + for ( list::iterator it = aDirectNodeSet.begin(); it != aDirectNodeSet.end(); it++ ) + aNodeItem = displayNodeWithPorts( aNodesItem, aNodeItem, mySProc->getChild(*it) ); + } + + // Create "Links" label + YACSGui_LabelViewItem* aLinksItem = new YACSGui_LabelViewItem( aSchemaItem, + aNodesItem ? aNodesItem : aDataTypesItem, + tr( "LINKS" ) ); + + // Put all links under "Links" label + list aNodeSet = getProc()->getAllRecursiveConstituents(); + for ( list::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) { + Node* aCurNode = *it; + if (!aCurNode) continue; + + set< pair< OutGate*,InGate* > > anInternalGateLinks; + set< pair< OutPort*,InPort* > > anInternalLinks; + if ( ComposedNode* aComposedNode = aCurNode->getFather() ) + if ( !dynamic_cast( aComposedNode ) ) + getAllInternalLinks( aComposedNode, anInternalGateLinks, anInternalLinks ); + + // Control links + QListViewItem* aLinkItem = 0; + OutGate* anOutGate = aCurNode->getOutGate(); + if (anOutGate) { + set anInGates = anOutGate->edSetInGate(); + set::iterator anInGatesIter = anInGates.begin(); + for(; anInGatesIter!=anInGates.end(); anInGatesIter++) { + InGate* aCurInGate = *anInGatesIter; + + if ( anInternalGateLinks.find( make_pair< OutGate*,InGate* >(anOutGate, aCurInGate) ) == anInternalGateLinks.end() ) + { + pair On2IN = make_pair( anOutGate->getNode(), aCurInGate->getNode() ); + aLinkItem = new YACSGui_ControlLinkViewItem( aLinksItem, aLinkItem, + GuiContext::getCurrent()->_mapOfSubjectControlLink[On2IN] ); + } + } + } + + // Get list of current node out ports + list anOutPorts; + + if ( !dynamic_cast( aCurNode ) ) + anOutPorts = aCurNode->getSetOfOutPort(); + else if ( ForEachLoop* aForEachLoopNode = dynamic_cast(aCurNode) ) { + OutputPort* anOutputPort = aForEachLoopNode->edGetSamplePort(); + if (anOutputPort) + anOutPorts.push_back(anOutputPort); + } + + // Process out ports list of the node : Data links + list::iterator anOutPortsIter = anOutPorts.begin(); + QListViewItem* aDataLinkItem = aLinkItem; + for ( ; anOutPortsIter != anOutPorts.end(); anOutPortsIter++ ) { + OutPort* aCurOutPort = *anOutPortsIter; + string aClassName = aCurOutPort->getNameOfTypeOfCurrentInstance(); + + set anInPorts = aCurOutPort->edSetInPort(); + set::iterator anInPortsIter = anInPorts.begin(); + + // Data links + if ( !aClassName.compare(OutputPort::NAME) ) { + if ( OutputPort* anOutputDFPort = dynamic_cast( aCurOutPort ) ) + for ( ; anInPortsIter != anInPorts.end(); anInPortsIter++ ) { + InPort* aCurInPort = *anInPortsIter; + + pair< OutPort*,InPort* > anOIP = make_pair(anOutputDFPort, aCurInPort); + if ( anInternalLinks.find(anOIP) == anInternalLinks.end() ) + aDataLinkItem = new YACSGui_LinkViewItem( aLinksItem, aDataLinkItem, + GuiContext::getCurrent()->_mapOfSubjectLink[anOIP] ); + } + } + } // out ports of the node iteration + + // Process out ports list of the node : Stream Links + anOutPortsIter = anOutPorts.begin(); + QListViewItem* aStreamLinkItem = aDataLinkItem; + for ( ; anOutPortsIter != anOutPorts.end(); anOutPortsIter++ ) { + OutPort* aCurOutPort = *anOutPortsIter; + string aClassName = aCurOutPort->getNameOfTypeOfCurrentInstance(); + + set anInPorts = aCurOutPort->edSetInPort(); + set::iterator anInPortsIter = anInPorts.begin(); + + // Stream links + if ( !aClassName.compare(OutputDataStreamPort::NAME) || !aClassName.compare(OutputCalStreamPort::NAME) ) { + if ( OutputDataStreamPort* anOutputDSPort = dynamic_cast( aCurOutPort ) ) + for ( ; anInPortsIter != anInPorts.end(); anInPortsIter++ ) { + InPort* aCurInPort = *anInPortsIter; + pair< OutPort*,InPort* > anOIP = make_pair(anOutputDSPort, aCurInPort); + if ( anInternalLinks.find(anOIP) == anInternalLinks.end() ) + aStreamLinkItem = new YACSGui_LinkViewItem( aLinksItem, aStreamLinkItem, + GuiContext::getCurrent()->_mapOfSubjectLink[anOIP] ); + } + } + } // out ports of the node iteration + + } // nodes of the proc iteration + + // Create "Containers" label if necessary + YACSGui_LabelViewItem* aContainersItem = 0; + //if ( !mySalomeComponentData.empty() || !myCorbaComponentData.empty() ) + aContainersItem = new YACSGui_LabelViewItem( aSchemaItem, aLinksItem, "Containers" ); + + if ( aContainersItem ) + { + // Put all SALOME containers under "Containers" label + YACSGui_ContainerViewItem* aContainerItem = 0; + for (map::const_iterator itCont = getProc()->containerMap.begin(); + itCont != getProc()->containerMap.end(); ++itCont) + { + aContainerItem = new YACSGui_ContainerViewItem( aContainersItem, aContainerItem, + GuiContext::getCurrent()->_mapOfSubjectContainer[(*itCont).second] ); + + // get a list of service nodes (and therefore, components) inside this container + Component2ServiceNodesMap aComponent2ServiceNodes; + if ( mySalomeComponentData.find(dynamic_cast( (*itCont).second )) + != mySalomeComponentData.end() ) + aComponent2ServiceNodes = mySalomeComponentData[dynamic_cast( (*itCont).second )]; + + YACSGui_ComponentViewItem* aComponentItem = 0; + for (map, ComponentInstance*>::const_iterator itComp = getProc()->componentInstanceMap.begin(); + itComp != getProc()->componentInstanceMap.end(); ++itComp) + { + bool aNeedToPublish = true; + list aServiceNodes; + if ( aComponent2ServiceNodes.find((*itComp).second) != aComponent2ServiceNodes.end() ) + aServiceNodes = aComponent2ServiceNodes[(*itComp).second]; + else + // this component is not associated with any service node + // check this component have to be loaded in the current container (itCont) or not + if ( (*itComp).second->getContainer() != (*itCont).second ) + aNeedToPublish = false; + + if ( !aNeedToPublish ) continue; + + SubjectComponent* aSComp = GuiContext::getCurrent()->_mapOfSubjectComponent[(*itComp).second]; + aComponentItem = new YACSGui_ComponentViewItem( aContainerItem, aComponentItem, aSComp ); + + YACSGui_ReferenceViewItem* aRefNodeItem = 0; + for ( list::iterator itSNode = aServiceNodes.begin(); + itSNode != aServiceNodes.end(); itSNode++ ) + // Put a reference to the schemas node, which is used this component instance + aRefNodeItem = new YACSGui_ReferenceViewItem( aComponentItem, aRefNodeItem, (*itSNode)->getSubjectReference() ); + } + } + + // Put all CORBA components under "Containers" label + YACSGui_ComponentViewItem* aCComponentItem = 0; + for ( Component2ServiceNodesMap::iterator itComp = myCorbaComponentData.begin(); + itComp != myCorbaComponentData.end(); itComp++ ) + { + SubjectComponent* aSComp = GuiContext::getCurrent()->_mapOfSubjectComponent[(*itComp).first]; + aCComponentItem = new YACSGui_ComponentViewItem( aContainersItem, + aCComponentItem ? (QListViewItem*)aCComponentItem : + (QListViewItem*)aContainerItem, + aSComp ); + + YACSGui_ReferenceViewItem* aRefNodeItem = 0; + list aServiceNodes = (*itComp).second; + for ( list::iterator itSNode = aServiceNodes.begin(); + itSNode != aServiceNodes.end(); itSNode++ ) + // Put a reference to the schemas node, which is used this component instance + aRefNodeItem = new YACSGui_ReferenceViewItem( aCComponentItem, aRefNodeItem, (*itSNode)->getSubjectReference() ); + } + } +} + +void YACSGui_EditionTreeView::fillContainerData( YACS::HMI::SubjectComposedNode* theSNode ) +{ + if ( theSNode ) + if ( ComposedNode* aNode = dynamic_cast(theSNode->getNode()) ) //if ( getProc() ) + { // find containers and components, which are used by Proc* service nodes + list aNodeSet = aNode->edGetDirectDescendants(); //getProc()->getAllRecursiveConstituents(); + for ( list::iterator it = aNodeSet.begin(); it != aNodeSet.end(); it++ ) + { + if ( ServiceNode* aSNode = dynamic_cast( *it ) ) + { + if ( ComponentInstance* aComponent = aSNode->getComponent() ) + { + if ( SubjectServiceNode* aSSNode = dynamic_cast( theSNode->getChild(aSNode) ) ) + { + if ( aComponent->getKind() == CORBAComponent::KIND ) + { // CORBA component + if ( myCorbaComponentData.find( aComponent ) == myCorbaComponentData.end() ) + myCorbaComponentData.insert( make_pair( aComponent, list( 1, aSSNode ) ) ); + else if ( std::find(myCorbaComponentData[ aComponent ].begin(), + myCorbaComponentData[ aComponent ].end(), + aSSNode) == myCorbaComponentData[ aComponent ].end() ) + { + myCorbaComponentData[ aComponent ].push_back( aSSNode ); + DEBTRACE(">> CORBA ComponentInstance = "<( aComponent->getContainer() ) ) + if ( mySalomeComponentData.find( aContainer ) == mySalomeComponentData.end() ) + { + Component2ServiceNodesMap aComp2Service; + aComp2Service.insert( make_pair( aComponent, list( 1, aSSNode ) ) ); + mySalomeComponentData.insert( make_pair( aContainer, aComp2Service ) ); + } + else if ( std::find( mySalomeComponentData[ aContainer ][ aComponent ].begin(), + mySalomeComponentData[ aContainer ][ aComponent ].end(), + aSSNode ) == mySalomeComponentData[ aContainer ][ aComponent ].end() ) + mySalomeComponentData[ aContainer ][ aComponent ].push_back( aSSNode ); + } + } + } + } + else if ( ComposedNode* aCNode = dynamic_cast( *it ) ) + { + fillContainerData( dynamic_cast( theSNode->getChild(aCNode) ) ); + } + } + } +} + +QPopupMenu* YACSGui_EditionTreeView::contextMenuPopup( const int theType, YACS::HMI::Subject* theSub ) +{ + QPopupMenu* aPopup = new QPopupMenu( this ); + + int anId; + QPopupMenu* aCrNPopup = new QPopupMenu( this ); + aCrNPopup->insertItem( tr("POP_SALOME_SERVICE"), myModule, SLOT(onSalomeServiceNode()) ); +// aCrNPopup->insertItem( tr("POP_CORBA_SERVICE"), myModule, SLOT(onCorbaServiceNode()) ); + //aCrNPopup->insertItem( tr("POP_NODENODE_SERVICE"), myModule, SLOT(onNodeNodeServiceNode()) ); + aCrNPopup->insertItem( tr("POP_CPP"), myModule, SLOT(onCppNode()) ); + anId = aCrNPopup->insertItem( tr("POP_SERVICE_INLINE"), myModule, SLOT(onServiceInlineNode()) ); + aCrNPopup->setItemEnabled ( anId, false ); + anId = aCrNPopup->insertItem( tr("POP_XML"), myModule, SLOT(onXMLNode()) ); + aCrNPopup->setItemEnabled ( anId, false ); + aCrNPopup->insertItem( tr("POP_INLINE_SCRIPT"), myModule, SLOT(onInlineScriptNode()) ); + aCrNPopup->insertItem( tr("POP_INLINE_FUNCTION"), myModule, SLOT(onInlineFunctionNode()) ); + aCrNPopup->insertItem( tr("POP_IN_DATANODE"), myModule, SLOT(onInDataNode()) ); + aCrNPopup->insertItem( tr("POP_OUT_DATANODE"), myModule, SLOT(onOutDataNode()) ); + aCrNPopup->insertItem( tr("POP_IN_STUDYNODE"), myModule, SLOT(onInStudyNode()) ); + aCrNPopup->insertItem( tr("POP_OUT_STUDYNODE"), myModule, SLOT(onOutStudyNode()) ); + aCrNPopup->insertItem( tr("POP_BLOCK"), myModule, SLOT(onBlockNode()) ); + aCrNPopup->insertItem( tr("POP_FOR_LOOP"), myModule, SLOT(onFORNode()) ); + aCrNPopup->insertItem( tr("POP_FOREACH_LOOP"), myModule, SLOT(onFOREACHNode()) ); + aCrNPopup->insertItem( tr("POP_WHILE_LOOP"), myModule, SLOT(onWHILENode()) ); + aCrNPopup->insertItem( tr("POP_SWITCH"), myModule, SLOT(onSWITCHNode()) ); + //aCrNPopup->insertItem( tr("POP_FROM_LIBRARY"), myModule, SLOT(onNodeFromLibrary()) ); + + switch ( theType ) + { + case YACSGui_EditionTreeView::DataTypeItem: + { + anId = aPopup->insertItem( tr("POP_EDIT"), myModule, SLOT(onEditDataTypes()) ); + aPopup->setItemEnabled ( anId, false ); + aPopup->insertItem( tr("POP_IMPORT_DATA_TYPE"), myModule, SLOT(onImportDataType()) ); + } + break; + case YACSGui_EditionTreeView::LabelNodesItem: + { + aPopup->insertItem(tr("POP_CREATE_NODE"), aCrNPopup); + } + break; + case YACSGui_EditionTreeView::LabelContainersItem: + { + aPopup->insertItem( tr("POP_CREATE_CONTAINER_DEF"), myModule, SLOT(onNewContainer()) ); + } + break; + case YACSGui_TreeView::SchemaItem: + { + aPopup->insertItem( tr("POP_EXPORT"), myModule, SLOT(onExportSchema()) ); + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_CREATE_DATA_TYPE"), myModule, SLOT(onCreateDataType()) ); + aPopup->setItemEnabled ( anId, false ); + aPopup->insertItem( tr("POP_CREATE_CONTAINER_DEF"), myModule, SLOT(onNewContainer()) ); + aPopup->insertSeparator(); + + QPopupMenu* aCrNPopup = new QPopupMenu( this ); + aCrNPopup->insertItem( tr("POP_SALOME_SERVICE"), myModule, SLOT(onSalomeServiceNode()) ); + //aCrNPopup->insertItem( tr("POP_CORBA_SERVICE"), myModule, SLOT(onCorbaServiceNode()) ); + //aCrNPopup->insertItem( tr("POP_NODENODE_SERVICE"), myModule, SLOT(onNodeNodeServiceNode()) ); + aCrNPopup->insertItem( tr("POP_CPP"), myModule, SLOT(onCppNode()) ); + anId = aCrNPopup->insertItem( tr("POP_SERVICE_INLINE"), myModule, SLOT(onServiceInlineNode()) ); + aCrNPopup->setItemEnabled ( anId, false ); + anId = aCrNPopup->insertItem( tr("POP_XML"), myModule, SLOT(onXMLNode()) ); + aCrNPopup->setItemEnabled ( anId, false ); + aCrNPopup->insertItem( tr("POP_INLINE_SCRIPT"), myModule, SLOT(onInlineScriptNode()) ); + aCrNPopup->insertItem( tr("POP_INLINE_FUNCTION"), myModule, SLOT(onInlineFunctionNode()) ); + aCrNPopup->insertItem( tr("POP_IN_DATANODE"), myModule, SLOT(onInDataNode()) ); + aCrNPopup->insertItem( tr("POP_OUT_DATANODE"), myModule, SLOT(onOutDataNode()) ); + aCrNPopup->insertItem( tr("POP_IN_STUDYNODE"), myModule, SLOT(onInStudyNode()) ); + aCrNPopup->insertItem( tr("POP_OUT_STUDYNODE"), myModule, SLOT(onOutStudyNode()) ); + aCrNPopup->insertItem( tr("POP_BLOCK"), myModule, SLOT(onBlockNode()) ); + aCrNPopup->insertItem( tr("POP_FOR_LOOP"), myModule, SLOT(onFORNode()) ); + aCrNPopup->insertItem( tr("POP_FOREACH_LOOP"), myModule, SLOT(onFOREACHNode()) ); + aCrNPopup->insertItem( tr("POP_WHILE_LOOP"), myModule, SLOT(onWHILENode()) ); + aCrNPopup->insertItem( tr("POP_SWITCH"), myModule, SLOT(onSWITCHNode()) ); + anId = aCrNPopup->insertItem( tr("POP_FROM_LIBRARY"), myModule, SLOT(onNodeFromLibrary()) ); + aCrNPopup->setItemEnabled ( anId, false ); + + aPopup->insertItem(tr("POP_CREATE_NODE"), aCrNPopup); + aPopup->insertSeparator(); + + aPopup->insertItem( tr("POP_EXECUTE"), myModule, SLOT(onCreateExecution(/*bool theIsFromTreeView*/)) ); + // TODO: if theIsFromTreeView = true, search SObject in Object Browser by name of the selected schema item in the tree view + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_COPY"), this, SLOT(onCopyItem()) ); + aPopup->setItemEnabled ( anId, false ); + anId = aPopup->insertItem( tr("POP_PASTE"), this, SLOT(onPasteItem()) ); + aPopup->setItemEnabled ( anId, false ); + //aPopup->insertItem( tr("POP_DELETE"), this, SLOT(onDeleteItem()) ); + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_DISPLAY"), this, SLOT(onDisplaySchema()) ); + aPopup->setItemEnabled ( anId, false ); + anId = aPopup->insertItem( tr("POP_ERASE"), this, SLOT(onEraseSchema()) ); + aPopup->setItemEnabled ( anId, false ); + } + break; + case YACSGui_EditionTreeView::ContainerItem: + { + QPopupMenu* aCrCPopup = new QPopupMenu( this ); + aCrCPopup->insertItem( tr("POP_SALOME_COMPONENT"), myModule, SLOT(onNewSalomeComponent()) ); + anId = aCrCPopup->insertItem( tr("POP_PYTHON_COMPONENT"), myModule, SLOT(onNewSalomePythonComponent()) ); + aCrCPopup->setItemEnabled ( anId, false ); + + aPopup->insertItem(tr("POP_CREATE_COMPONENT"), aCrCPopup); + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_COPY"), this, SLOT(onCopyItem()) ); + aPopup->setItemEnabled ( anId, false ); + anId = aPopup->insertItem( tr("POP_PASTE"), this, SLOT(onPasteItem()) ); + aPopup->setItemEnabled ( anId, false ); + aPopup->insertItem( tr("POP_DELETE"), this, SLOT(onDeleteItem()) ); + } + break; + case YACSGui_EditionTreeView::ComponentItem: + { + QPopupMenu* aCrN2Popup = new QPopupMenu( this ); + aCrN2Popup->insertItem( tr("POP_SALOME_SERVICE"), myModule, SLOT(onSalomeServiceNode()) ); + anId = aCrN2Popup->insertItem( tr("POP_SERVICE_INLINE"), myModule, SLOT(onServiceInlineNode()) ); + aCrN2Popup->setItemEnabled ( anId, false ); + + aPopup->insertItem(tr("POP_CREATE_NODE"), aCrN2Popup); + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_COPY"), this, SLOT(onCopyItem()) ); + aPopup->setItemEnabled ( anId, false ); + aPopup->insertItem( tr("POP_DELETE"), this, SLOT(onDeleteItem()) ); + } + break; + case YACSGui_EditionTreeView::CorbaComponentItem: + { + //aPopup->insertItem( tr("POP_CREATE_CORBA_SERVICE_NODE"), myModule, SLOT(onCorbaServiceNode()) ); + //aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_COPY"), this, SLOT(onCopyItem()) ); + aPopup->setItemEnabled ( anId, false ); + aPopup->insertItem( tr("POP_DELETE"), this, SLOT(onDeleteItem()) ); + } + break; + case YACSGui_TreeView::NodeItem: + case YACSGui_EditionTreeView::ServiceNodeItem: + case YACSGui_EditionTreeView::ComposedNodeItem: + case YACSGui_EditionTreeView::LoopNodeItem: + { + //if ( theType == YACSGui_EditionTreeView::ServiceNodeItem ) + //{ + // aPopup->insertItem( tr("POP_CREATE_NODE-NODE_SERVICE_NODE"), myModule, SLOT(onNodeNodeServiceNode()) ); + // aPopup->insertSeparator(); + //} + + if ( theType == YACSGui_EditionTreeView::LoopNodeItem || + theType == YACSGui_EditionTreeView::ComposedNodeItem ) + { + // TODO: in slots we have to check what is selected: schema, + // loop node (=> from ¨Create a body¨) or + // another node (=> from ¨Create a loop¨). + if ( theType == YACSGui_EditionTreeView::LoopNodeItem ) + aPopup->insertItem(tr("POP_CREATE_BODY"), aCrNPopup); + else if ( theType == YACSGui_EditionTreeView::ComposedNodeItem ) + aPopup->insertItem(tr("POP_CREATE_NODE"), aCrNPopup); + aPopup->insertSeparator(); + } + + QPopupMenu* aCrN2Popup = new QPopupMenu( this ); + aCrN2Popup->insertItem( tr("POP_FOR_LOOP"), myModule, SLOT(onFORNode()) ); + aCrN2Popup->insertItem( tr("POP_FOREACH_LOOP"), myModule, SLOT(onFOREACHNode()) ); + aCrN2Popup->insertItem( tr("POP_WHILE_LOOP"), myModule, SLOT(onWHILENode()) ); + + aPopup->insertItem(tr("POP_CREATE_LOOP"), aCrN2Popup); + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_ADD_TO_LIBRARY"), this, SLOT(onAddToLibrary()) ); + aPopup->setItemEnabled ( anId, false ); + aPopup->insertSeparator(); + + aPopup->insertItem( tr("POP_ADDCONTROLLINK"), this, SLOT(onAddLink()) ); + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_COPY"), this, SLOT(onCopyItem()) ); + aPopup->setItemEnabled ( anId, false ); + aPopup->insertItem( tr("POP_DELETE"), this, SLOT(onDeleteItem()) ); + aPopup->insertSeparator(); + + anId = aPopup->insertItem( tr("POP_DISPLAY"), this, SLOT(onDisplayNode()) ); + aPopup->setItemEnabled ( anId, false ); + anId = aPopup->insertItem( tr("POP_ERASE"), this, SLOT(onEraseNode()) ); + aPopup->setItemEnabled ( anId, false ); + } + break; + case YACSGui_EditionTreeView::PortItem: + if ( SubjectDataPort* aSub = dynamic_cast(theSub) ) + { + if ( dynamic_cast( aSub->getPort() ) || dynamic_cast( aSub->getPort() ) ) + aPopup->insertItem( tr("POP_ADDDATALINK"), this, SLOT(onAddLink()) ); + + + if ( !dynamic_cast(aSub->getParent()) ) + // delete ports only for all nodes except SALOME service nodes + // (change its ports only in the Input Panel when the method name is changed) + if ( aSub->isDestructible() ) + { + aPopup->insertSeparator(); + aPopup->insertItem( tr("POP_DELETE"), this, SLOT(onDeleteItem()) ); + } + } + break; + case YACSGui_EditionTreeView::LinkItem: + aPopup->insertItem( tr("POP_DELETE"), this, SLOT(onDeleteItem()) ); + break; + default: + break; + } + + if ( aPopup->count() == 0 ) return 0; + + return aPopup; +} + +void YACSGui_EditionTreeView::showPopup( QPopupMenu* thePopup, const QPoint thePos ) +{ + if ( thePopup ) thePopup->exec(thePos); +} + +void YACSGui_EditionTreeView::warnAboutSelectionChanged() +{ + DEBTRACE("YACSGui_EditionTreeView::warnAboutSelectionChanged"); + if ( !myModule ) return; + + YACSGui_InputPanel* anIP = myModule->getInputPanel(); + if ( !anIP ) return; + + bool aWarnToShow = true; + bool aToApply=false; + list anIds = anIP->getVisiblePagesIds(); + for ( list::iterator anIter = anIds.begin(); anIter != anIds.end(); ++anIter ) + { + int anId = (*anIter); + switch (anId) + { + case YACSGui_InputPanel::ContainerId: + { + if ( YACSGui_ContainerPage* aContPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ContainerId ) ) ) + aContPage->checkModifications( aWarnToShow, aToApply ); + } + break; + case YACSGui_InputPanel::ComponentId: + { + if ( YACSGui_ComponentPage* aCompPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ComponentId ) ) ) + aCompPage->checkModifications( aWarnToShow, aToApply ); + } + break; + case YACSGui_InputPanel::SchemaId: + { + if ( YACSGui_SchemaPage* aSPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::SchemaId ) ) ) + aSPage->checkModifications(); + } + break; + case YACSGui_InputPanel::InDataNodeId: + { + if ( YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InDataNodeId ) ) ) + aINPage->checkModifications(); + } + break; + case YACSGui_InputPanel::OutDataNodeId: + { + if ( YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::OutDataNodeId ) ) ) + aINPage->checkModifications(); + } + break; + case YACSGui_InputPanel::InStudyNodeId: + { + if ( YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InStudyNodeId ) ) ) + aINPage->checkModifications(); + } + break; + case YACSGui_InputPanel::OutStudyNodeId: + { + if ( YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::OutStudyNodeId ) ) ) + aINPage->checkModifications(); + } + break; + case YACSGui_InputPanel::InlineNodeId: + { + if ( YACSGui_InlineNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InlineNodeId ) ) ) + aINPage->checkModifications(); + } + break; + case YACSGui_InputPanel::ServiceNodeId: + { + if ( YACSGui_ServiceNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ServiceNodeId ) ) ) + aSNPage->checkModifications( aWarnToShow, aToApply ); + } + break; + case YACSGui_InputPanel::ForLoopNodeId: + { + if ( YACSGui_ForLoopNodePage* aFLNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ForLoopNodeId ) ) ) + aFLNPage->checkModifications(); + } + break; + case YACSGui_InputPanel::ForEachLoopNodeId: + { + if ( YACSGui_ForEachLoopNodePage* aFELNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ForEachLoopNodeId ) ) ) + aFELNPage->checkModifications(); + } + break; + case YACSGui_InputPanel::WhileLoopNodeId: + { + if ( YACSGui_WhileLoopNodePage* aWLNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::WhileLoopNodeId ) ) ) + aWLNPage->checkModifications(); + } + break; + case YACSGui_InputPanel::SwitchNodeId: + { + if ( YACSGui_SwitchNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::SwitchNodeId ) ) ) + aSNPage->checkModifications(); + } + break; + case YACSGui_InputPanel::BlockNodeId: + { + if ( YACSGui_BlockNodePage* aBNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::BlockNodeId ) ) ) + aBNPage->checkModifications(); + } + break; + case YACSGui_InputPanel::LinkId: + { + } + break; + default: + break; + } + } +} + +void YACSGui_EditionTreeView::syncPageTypeWithSelection() +{ + DEBTRACE("YACSGui_EditionTreeView::syncPageTypeWithSelection"); + if ( !getProc() || !myModule ) return; + + YACSGui_InputPanel* anIP = myModule->getInputPanel(); + if ( !anIP ) return; + + // get the list of selected items + list aSelList = getSelected(); + + QListViewItem* anItem = 0; + + // check if the current selection is a single selection + if ( aSelList.size() == 1 ) anItem = aSelList.front(); + + //if ( aSelList.size() > 0 ) warnAboutSelectionChanged(); + + if(myModule->getGuiMode()==YACSGui_Module::NewMode) { + DEBTRACE(">> Show Input Panel for a new Salome Service node"); + YACSGui_ServiceNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ServiceNodeId ) ); + SubjectComposedNode* aSub = dynamic_cast(getSelectedSubject()); + DEBTRACE("aSub: " << aSub); + if(!aSub) + aSub = GuiContext::getCurrent()->getSubjectProc(); + DEBTRACE("aSub: " << aSub); + if ( aSNPage ) + { + list aPagesIds; + + aSNPage->setSCNode( aSub ); + aSNPage->setSNode( 0 ); + anIP->setOn( true, YACSGui_InputPanel::ServiceNodeId ); + anIP->setMode( YACSGui_InputPanel::NewMode, YACSGui_InputPanel::ServiceNodeId ); + aPagesIds.push_back(YACSGui_InputPanel::ServiceNodeId); + + anIP->setExclusiveVisible( true, aPagesIds ); + anIP->show(); + } + } + else if ( YACSGui_SchemaViewItem* aSchemaItem = dynamic_cast( anItem ) ) + { // this is a schema view item + // find or create a property page for a schema + DEBTRACE(">> Show Input Panel for a given schema (Proc*)"); + + YACSGui_SchemaPage* aSPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::SchemaId ) ); + if ( aSPage ) + { + aSPage->setSProc( aSchemaItem->getSProc() ); + anIP->setOn( true, YACSGui_InputPanel::SchemaId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::SchemaId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::SchemaId) ); + string theErrorLog; + Proc* aProc = getProc(); + // Check validity + if(!aProc->isValid()) + { + theErrorLog="--- YACS schema is not valid ---\n\n"; + theErrorLog += aProc->getErrorReport(); + } + else + { + // Check consistency + LinkInfo info(LinkInfo::ALL_DONT_STOP); + aProc->checkConsistency(info); + if (info.areWarningsOrErrors()) + theErrorLog = info.getGlobalRepr(); + else + { + theErrorLog = "--- No Validity Errors ---\n"; + theErrorLog += "--- No Consistency Errors ---\n"; + } + } + + //Add initial logger info + Logger* logger=getProc()->getLogger("parser"); + if (!logger->isEmpty()) + { + theErrorLog += " --- Original file import log ---\n"; + theErrorLog += logger->getStr(); + } + + aSPage->myErrorLog->setText(theErrorLog.c_str()); + anIP->show(); + } + } + else if ( YACSGui_NodeViewItem* aNodeItem = dynamic_cast( anItem ) ) + { // this is a node data object + // the following method can be used if its needed: + // YACSPrs_ElementaryNode* aNode = getGraph( dynamic_cast(aNodeItem->getNode()->getRootNode()) )->getItem( aNodeItem->getNode() ); + DEBTRACE(">> Show Input Panel for a given node (Node*)"); + + Node* aNode = aNodeItem->getNode(); + DEBTRACE("Show Input Panel for a given node: " << aNode->getName()); + + if ( ServiceNode* sNode = dynamic_cast( aNode ) ) + { + if ( sNode->getKind() == "XML" ) + { + DEBTRACE(">>XML"); + /* + YACSGui_ServiceInlineNodePage* aSINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ServiceInlineNodeId ) ); + if ( aSINPage ) + { + aSINPage->setSNode( aNodeItem->getSNode() ); + + anIP->setOn( true, YACSGui_InputPanel::ServiceInlineNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::ServiceInlineNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ServiceInlineNodeId) ); + anIP->show(); + } + */ + } + else + { + DEBTRACE(">>Service"); + YACSGui_ServiceNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ServiceNodeId ) ); + if ( aSNPage ) + { + DEBTRACE("---service node"); + list aPagesIds; + + if ( !dynamic_cast(sNode) ) + { + YACSGui_ContainerPage* aContPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ContainerId ) ); + if ( aContPage ) + { + SubjectContainer* aCont = 0; + if ( sNode->getComponent() && sNode->getComponent()->getContainer() ) + aCont = GuiContext::getCurrent()->_mapOfSubjectContainer[sNode->getComponent()->getContainer()]; + aContPage->setSContainer(aCont); + anIP->setOn( false, YACSGui_InputPanel::ContainerId ); + aPagesIds.push_back(YACSGui_InputPanel::ContainerId); + } + } + + YACSGui_ComponentPage* aCompPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ComponentId ) ); + if ( aCompPage ) + { + SubjectComponent* aComp = 0; + if ( sNode->getComponent() ) + aComp = GuiContext::getCurrent()->_mapOfSubjectComponent[sNode->getComponent()]; + aCompPage->setSComponent(aComp, false); + anIP->setOn( false, YACSGui_InputPanel::ComponentId ); + aPagesIds.push_back(YACSGui_InputPanel::ComponentId); + } + + aSNPage->setSNode( aNodeItem->getSNode() ); + anIP->setOn( true, YACSGui_InputPanel::ServiceNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::ServiceNodeId ); + aPagesIds.push_back(YACSGui_InputPanel::ServiceNodeId); + + anIP->setExclusiveVisible( true, aPagesIds ); + anIP->show(); + } + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>PresetNode"); + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InDataNodeId ) ); + DEBTRACE(aINPage); + if ( aINPage ) + { + YACS::HMI::SubjectNode* aSub = aNodeItem->getSNode(); + aINPage->setSNode( aSub ); + anIP->setOn( true, YACSGui_InputPanel::InDataNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::InDataNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::InDataNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>OutNode"); + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::OutDataNodeId ) ); + DEBTRACE(aINPage); + if ( aINPage ) + { + YACS::HMI::SubjectNode* aSub = aNodeItem->getSNode(); + aINPage->setSNode( aSub ); + anIP->setOn( true, YACSGui_InputPanel::OutDataNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::OutDataNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::OutDataNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE("show StudyIn page"); + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InStudyNodeId ) ); + DEBTRACE(aINPage); + if ( aINPage ) + { + YACS::HMI::SubjectNode* aSub = aNodeItem->getSNode(); + aINPage->setSNode( aSub ); + anIP->setOn( true, YACSGui_InputPanel::InStudyNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::InStudyNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::InStudyNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>StudyOut"); + DEBTRACE("show StudyOut page"); + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::OutStudyNodeId ) ); + DEBTRACE(aINPage); + if ( aINPage ) + { + YACS::HMI::SubjectNode* aSub = aNodeItem->getSNode(); + aINPage->setSNode( aSub ); + anIP->setOn( true, YACSGui_InputPanel::OutStudyNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::OutStudyNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::OutStudyNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>Inline"); + YACSGui_InlineNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InlineNodeId ) ); + if ( aINPage ) + { + YACS::HMI::SubjectNode* aSub = aNodeItem->getSNode(); + aINPage->setSNode( aSub ); + anIP->setOn( true, YACSGui_InputPanel::InlineNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::InlineNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::InlineNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>Switch"); + YACSGui_SwitchNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::SwitchNodeId ) ); + if ( aSNPage ) + { + aSNPage->setSNode( aNodeItem->getSNode() ); + anIP->setOn( true, YACSGui_InputPanel::SwitchNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::SwitchNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::SwitchNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>For"); + YACSGui_ForLoopNodePage* aFLNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ForLoopNodeId ) ); + if ( aFLNPage ) + { + aFLNPage->setSNode( aNodeItem->getSNode() ); + anIP->setOn( true, YACSGui_InputPanel::ForLoopNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::ForLoopNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ForLoopNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>ForEach"); + YACSGui_ForEachLoopNodePage* aFELNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ForEachLoopNodeId ) ); + if ( aFELNPage ) + { + aFELNPage->setSNode( aNodeItem->getSNode() ); + anIP->setOn( true, YACSGui_InputPanel::ForEachLoopNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::ForEachLoopNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ForEachLoopNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>While"); + YACSGui_WhileLoopNodePage* aWLNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::WhileLoopNodeId ) ); + if ( aWLNPage ) + { + aWLNPage->setSNode( aNodeItem->getSNode() ); + anIP->setOn( true, YACSGui_InputPanel::WhileLoopNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::WhileLoopNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::WhileLoopNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + DEBTRACE(">>Bloc"); + YACSGui_BlockNodePage* aBNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::BlockNodeId ) ); + if ( aBNPage ) + { + aBNPage->setSNode( aNodeItem->getSNode() ); + anIP->setOn( true, YACSGui_InputPanel::BlockNodeId ); + anIP->setMode( YACSGui_InputPanel::EditMode, YACSGui_InputPanel::BlockNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::BlockNodeId) ); + anIP->show(); + } + } + } + else if ( YACSGui_LinkViewItem* aLinkItem = dynamic_cast( anItem ) ) + { // this is a link data object + // YACS::ENGINE::Port* anOutPort = aLinkItem->getOutPort(); + // YACS::ENGINE::Port* anInPort = aLinkItem->getInPort(); + // the following method can be used if its needed: + // to get link presentation here, we need to reimplement the ItemMap in the YACSGui_Graph : + // typedef map< pair, void*> ItemMap + // and maps + // map< pair, YACSPrs_ElementaryNode*> + // or + // typedef map< pair, YACSPrs_Link*> + // Therefore, it is needed to redefine YACSGui_Graph::getItem(...) method! + DEBTRACE(">> Show Input Panel for a given link ()"); + + /* + YACSGui_LinkNodePage* aLPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::LinkId ) ); + if ( aLPage ) + { + aLPage->setSLink( aLinkItem->getSLink() ); + anIP->setOn( true, YACSGui_InputPanel::LinkId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::LinkId) ); + anIP->show(); + } + */ + anIP->hide(); + } + else if ( YACSGui_ContainerViewItem* aContItem = dynamic_cast( anItem ) ) + { // this is a container data object + // find or create a property page for a container + DEBTRACE(">> Show Input Panel for a given container (SalomeContainer*>)"); + + YACSGui_ContainerPage* aCPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::ContainerId ) ); + if ( aCPage ) + { + aCPage->setSContainer( aContItem->getSContainer() ); + anIP->setOn( true, YACSGui_InputPanel::ContainerId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ContainerId) ); + anIP->show(); + } + } + else if ( YACSGui_ComponentViewItem* aCompItem = dynamic_cast( anItem ) ) + { // this is a component data object + // YACS::ENGINE::ComponentInstance* aComponent = aCompItem->getComponent(); + DEBTRACE(">> Show Input Panel for a given component (ComponentInstance*>)"); + + YACSGui_ComponentPage* aCompPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::ComponentId ) ); + if ( aCompPage ) + { + aCompPage->setSComponent(aCompItem->getSComponent()); + anIP->setOn( true, YACSGui_InputPanel::ComponentId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ComponentId) ); + anIP->show(); + } + } + else + anIP->hide(); +} + +//! Private slot. Shows the Input Panel with property pages acoording to the selected item. +/*! + */ +void YACSGui_EditionTreeView::onSelectionChanged() +{ + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + if ( !getProc() || !myModule ) return; + + bool isNewSelection = true; + bool isWarn = false; + + // get the list of selected items + list aSelList = getSelected(); + + QListViewItem* anItem = 0; + + // check if the current selection is a single selection + if ( aSelList.size() == 1 ) anItem = aSelList.front(); + + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + YACSGui_InputPanel* anIP = myModule->getInputPanel(); + if ( anItem && anIP ) + { + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + // check if the case selection of switch node is active + if( ((QWidget*)anIP)->isVisible() && anIP->isVisible( YACSGui_InputPanel::SwitchNodeId ) ) + { + DEBTRACE("SwitchNodeId visible"); + YACSGui_SwitchNodePage* aSNPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::SwitchNodeId ) ); + if ( aSNPage && aSNPage->isSelectChild() ) + { + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + isWarn = false; + if ( YACSGui_NodeViewItem* aNodeItem = dynamic_cast( anItem ) ) + { + if ( aSNPage->getNode() != aNodeItem->getNode() ) + { + aSNPage->setChild(aNodeItem->getSNode()); + + // change selection from the child node back to the switch node + bool block = signalsBlocked(); + blockSignals( true ); + setSelected( aNodeItem, false ); + + QString aName = aSNPage->getNodeName(); + QListViewItem* aSNItem = 0; + bool continueSearch = true; + while ( continueSearch ) + { + aSNItem = findItem( aName, 0 ); + if ( YACSGui_NodeViewItem* aSNVItem = dynamic_cast( aSNItem ) ) + if ( aSNPage->getNode() == aSNVItem->getNode() ) + continueSearch = false; + } + if( aSNItem ) + setSelected( aSNItem, true ); + blockSignals( block ); + } + } + else + { // remove selection from incompatible object (which is not a node) + setSelected( anItem, false ); + } + return; + } + } + + // check if the child node selection of block node is active + if( ((QWidget*)anIP)->isVisible() && anIP->isVisible( YACSGui_InputPanel::BlockNodeId ) ) + { + DEBTRACE("BlockNodeId visible"); + YACSGui_BlockNodePage* aBNPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::BlockNodeId ) ); + if ( aBNPage && aBNPage->isSelectChild() ) + { + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + isWarn = false; + if ( YACSGui_NodeViewItem* aNodeItem = dynamic_cast( anItem ) ) + { + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + if ( aBNPage->getNode() != aNodeItem->getNode() ) + { + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + aBNPage->setChild(aNodeItem->getSNode()); + + // change selection from the child node back to the block node + bool block = signalsBlocked(); + blockSignals( true ); + setSelected( aNodeItem, false ); + + QString aName = aBNPage->getNodeName(); + QListViewItem* aBNItem = 0; + bool continueSearch = true; + while ( continueSearch ) + { + aBNItem = findItem( aName, 0 ); + if ( YACSGui_NodeViewItem* aBNVItem = dynamic_cast( aBNItem ) ) + if ( aBNPage->getNode() == aBNVItem->getNode() ) + continueSearch = false; + } + if( aBNItem ) + setSelected( aBNItem, true ); + blockSignals( block ); + } + } + else + { // remove selection from incompatible object (which is not a node) + setSelected( anItem, false ); + } + return; + } + } + + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + // check if the data type selection is active + if( ((QWidget*)anIP)->isVisible() + && + ( anIP->isVisible( YACSGui_InputPanel::InlineNodeId ) ) ) + { + DEBTRACE("InlineNodeId visible"); + YACSGui_InlineNodePage* aSNPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::InlineNodeId ) ); + if ( aSNPage && aSNPage->isSelectDataType() ) + { + DEBTRACE("aSNPage->isSelectDataType()"); + if ( YACSGui_DataTypeItem* aDTItem = dynamic_cast( anItem ) ) + aSNPage->setDataType(aDTItem->getSDataType()->getTypeCode()); + + bool block = signalsBlocked(); + blockSignals( true ); + setSelected( anItem, false ); + QListViewItem* aSNItem = findItem( aSNPage->getNodeName(), 0 ); + if( aSNItem ) + setSelected( aSNItem, true ); + blockSignals( block ); + + return; + } + } + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + if (((QWidget*)anIP)->isVisible()) + { + int pageId=-1; + if(anIP->isVisible( YACSGui_InputPanel::InDataNodeId )) pageId = YACSGui_InputPanel::InDataNodeId; + else if (anIP->isVisible( YACSGui_InputPanel::OutDataNodeId )) pageId = YACSGui_InputPanel::OutDataNodeId; + else if (anIP->isVisible( YACSGui_InputPanel::InStudyNodeId )) pageId = YACSGui_InputPanel::InStudyNodeId; + else if (anIP->isVisible( YACSGui_InputPanel::OutStudyNodeId )) pageId = YACSGui_InputPanel::OutStudyNodeId; + if (pageId != -1) + { + DEBTRACE("dataNodeId visible"); + YACSGui_DataNodePage* aDNPage = dynamic_cast( anIP->getPage( pageId ) ); + if ( aDNPage && aDNPage->isSelectDataType() ) + { + DEBTRACE("aDNPage->isSelectDataType()"); + if ( YACSGui_DataTypeItem* aDTItem = dynamic_cast( anItem ) ) + aDNPage->setDataType(aDTItem->getSDataType()->getTypeCode()); + + bool block = signalsBlocked(); + blockSignals( true ); + setSelected( anItem, false ); + QListViewItem* aSNItem = findItem( aDNPage->getNodeName(), 0 ); + if( aSNItem ) + setSelected( aSNItem, true ); + blockSignals( block ); + + return; + } + } + } + } + + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + + if ( aSelList.size() == 0 ) // nothing selected, deselect previous + { + if ( myPreviousSelected ) + { + myPreviousSelected = 0; + isWarn = true; + } + } + + // creation of a link --> + YACSGui_ViewItem* aVItem = 0; + if ( anItem ) // an item selected + { + if ( anItem != myPreviousSelected ) // a new item is selected + { + if ( myPreviousSelected ) isWarn = true; + myPreviousSelected = anItem; + aVItem = dynamic_cast(anItem); + } + else + isNewSelection = false; + } + else if ( myPreviousSelected ) // nothing selected, deselect previous (multiselection case) + { + anItem = myPreviousSelected; + myPreviousSelected = 0; + aVItem = dynamic_cast(anItem); + isWarn = true; + } + if ( aVItem ) + { + //aVItem->getSubject()->select(anItem->isSelected()); + if ( mySelectedSubjectOutPort ) + { + if ( YACSGui_PortViewItem* aPItem = dynamic_cast(aVItem) ) + { + SubjectDataPort* aSubPort = aPItem->getSPort(); + if ( dynamic_cast(aSubPort) || dynamic_cast(aSubPort) ) + { + if ( !SubjectDataPort::tryCreateLink( mySelectedSubjectOutPort, aSubPort ) ) + SUIT_MessageBox::warn1(myModule->getApp()->desktop(), + tr("WARNING"), + GuiContext::getCurrent()->_lastErrorMessage, + tr("BUT_OK")); + else myModule->temporaryExport(); + mySelectedSubjectOutPort = 0; + } + } + } + if ( mySelectedSubjectOutNode ) + { + if ( YACSGui_NodeViewItem* aNItem = dynamic_cast(aVItem) ) + { + if ( SubjectNode* aSubNode = aNItem->getSNode() ) + { + if ( !SubjectNode::tryCreateLink( mySelectedSubjectOutNode, aSubNode ) ) + SUIT_MessageBox::warn1(myModule->getApp()->desktop(), + tr("WARNING"), + GuiContext::getCurrent()->_lastErrorMessage, + tr("BUT_OK")); + else myModule->temporaryExport(); + mySelectedSubjectOutNode = 0; + } + } + } + } + // creation of a link <-- + + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + if ( isWarn ) warnAboutSelectionChanged(); + + if ( anIP ) // --- force edit mode to close the catalog, when click on tree or canvas item + { + myModule->setGuiMode(YACSGui_Module::EditMode); + YACSGui_ServiceNodePage* aSNPage = dynamic_cast(anIP->getPage(YACSGui_InputPanel::ServiceNodeId )); + if (aSNPage) aSNPage->setMode(YACSGui_InputPanel::EditMode); + } + + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + if ( isNewSelection ) syncPageTypeWithSelection(); + DEBTRACE("YACSGui_EditionTreeView::onSelectionChanged"); + syncHMIWithSelection(); +} + +//! Private slot. Selects the original node in the tree view if a reference node is double clicked. +/*! + */ +void YACSGui_EditionTreeView::onDblClick( QListViewItem* theItem ) +{ + if ( YACSGui_ReferenceViewItem* aRNItem = dynamic_cast( theItem ) ) + { + QListViewItemIterator anIt( this ); + for ( ; anIt.current(); anIt++ ) + { + YACSGui_NodeViewItem* original = dynamic_cast( anIt.current() ); + if ( original && original->getNode() == aRNItem->getNode() ) + { + setSelected( original, true ); + + QListViewItem* p = original->parent(); + while( p ) + { + setOpen( p, true ); + p = p->parent(); + } + + setCurrentItem( original ); + ensureItemVisible( original ); + emitSelectionChanged(); + //emit selectionChanged(); + + break; + } + } + } +} + +void YACSGui_EditionTreeView::syncHMIWithSelection() +{ + // notify about selection other observers + DEBTRACE("YACSGui_EditionTreeView::syncHMIWithSelection"); + + std::list aSelList = getSelected(); + + // notify about selection + list::iterator it; + for ( it = aSelList.begin(); it != aSelList.end(); ++it ) + { + YACSGui_ViewItem* item = dynamic_cast( *it ); + if ( item ) + { + DEBTRACE(item); + YACS::HMI::Subject* aSub = getSubject( *it ); + if ( aSub ) + { + DEBTRACE(aSub); + DEBTRACE(aSub->getName()); + bool isBlocked = item->blockSelection( true ); + aSub->select( true ); + item->blockSelection( isBlocked ); + myLastSelected.erase( item ); + DEBTRACE("myLastSelected.erase " << item); + } + } + } + + // notify about deselection + std::set< QListViewItem* >::iterator lIt; + for ( lIt = myLastSelected.begin(); lIt != myLastSelected.end(); ++lIt ) + { + YACS::HMI::Subject* aSub = getSubject( *lIt ); + if ( aSub ) + { + aSub->select( false ); + DEBTRACE("myLastSelected subject->select(false) " << *lIt); + } + } + + // fill last mySelected + myLastSelected.clear(); + for ( it = aSelList.begin(); it != aSelList.end(); ++it ) + { + myLastSelected.insert( *it ); + DEBTRACE("myLastSelected.insert " << *it); + } + myModule->updateViewer(); +} + +void YACSGui_EditionTreeView::emitSelectionChanged() +{ + emit selectionChanged(); +} + +//! Constructor. +/*! + */ +YACSGui_RunTreeView::YACSGui_RunTreeView( YACSGui_Module* theModule, YACS::HMI::SubjectProc* theSProc, + QWidget* theParent, const char* theName, WFlags theFlags ) + : YACSGui_TreeView( theModule, theSProc, theParent, theName, theFlags ) +{ + if ( getProc() ) + { + setCaption( tr( "RUN_TREE_VIEW" ) + QString( " of " ) + QString( getProc()->getName() ) ); + + addColumn( "Nodes", 250 ); + addColumn( "State", 100 ); + + build(); + + connect( this, SIGNAL( clicked( QListViewItem* ) ), this, SLOT( onBreakpointClicked( QListViewItem* ) ) ); + connect( this, SIGNAL( selectionChanged() ), this, SLOT( onSelectionChanged() ) ); + connect( this, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ), + this, SLOT( onMenuRequested( QListViewItem *, const QPoint &, int ) ) ); + } +} + +//! Destructor. +/*! + */ +YACSGui_RunTreeView::~YACSGui_RunTreeView() +{ +} + +void YACSGui_RunTreeView::onMenuRequested( QListViewItem* item, const QPoint & point, int col ) +{ + DEBTRACE("lookForExecutor()"); + YACSGui_Executor* anExecutor = myModule->lookForExecutor(); + if ( !anExecutor ) return; + + if (YACSGui_ComposedNodeViewItem* anItem = dynamic_cast(item) ) + { + anItem->popup(anExecutor,point); + } + else if(YACSGui_ElementaryNodeViewItem* anItem = dynamic_cast(item)) + { + anItem->popup(anExecutor,point); + } +} + +//! Udates the tree view starting from the given item. +/*! + * \param theItem - the item, which subtree have to be updated. + * \param theIsRecursive - the flag for recursive or not recursive update. + * By default theIsRecursive = false. + */ +void YACSGui_RunTreeView::update( QListViewItem* theItem, const bool theIsRecursive ) +{ + YACSGui_ComposedNodeViewItem* anItem = dynamic_cast( theItem ); + + if ( !anItem ) + anItem = dynamic_cast( firstChild() ); // get a root item + + if ( anItem && anItem->listView() == this ) + { + anItem->update( theIsRecursive ); + //triggerUpdate(); + } +} + +//! Udates the tree view starting from the given item. +/*! + * \param theItem - the item, which subtree have to be updated. + * \param theIsRecursive - the flag for recursive or not recursive update. + * By default theIsRecursive = false. + */ +void YACSGui_RunTreeView::update( QCheckListItem* theItem, const bool theIsRecursive ) +{ + YACSGui_ElementaryNodeViewItem* anItem = dynamic_cast( theItem ); + + if ( !anItem ) return; + + if ( anItem->listView() == this ) + { + anItem->update( theIsRecursive ); + //triggerUpdate(); + } +} + +//! Builds the tree view according to the schema content. Schema is used as the root object. +/*! + */ +void YACSGui_RunTreeView::build() +{ + if ( !getProc() ) return; + + YACSGui_ComposedNodeViewItem* aRootItem = new YACSGui_ComposedNodeViewItem( this, QString( getProc()->getName() ), getProc() ); + myMapListViewItem[getProc()->getNumId()] = aRootItem; + onNotifyStatus(YACS::NOTYETINITIALIZED); + addTreeNode( aRootItem, getProc() ); +} + +void YACSGui_RunTreeView::addTreeNode( QListViewItem* theParent, + YACS::ENGINE::ComposedNode* theFather ) +{ + list aSetOfNodes = theFather->edGetDirectDescendants(); + for ( list::iterator iter = aSetOfNodes.begin(); iter != aSetOfNodes.end(); iter++) + { + if (ElementaryNode* anElemNode = dynamic_cast(*iter) ) + { + YACSGui_ElementaryNodeViewItem* item = new YACSGui_ElementaryNodeViewItem( theParent, + (*iter)->getQualifiedName(), + YACSGui_ElementaryNodeViewItem::CheckBox, + anElemNode ); + myMapListViewItem[(*iter)->getNumId()] = item; + } + else + { + YACSGui_ComposedNodeViewItem* item = new YACSGui_ComposedNodeViewItem( theParent, + (*iter)->getQualifiedName(), + (ComposedNode*)(*iter) ); + myMapListViewItem[(*iter)->getNumId()] = item; + addTreeNode(item, (ComposedNode*)(*iter)); + } + } +} + +void YACSGui_RunTreeView::syncPageTypeWithSelection() +{ + if ( !getProc() || !myModule ) return; + + YACSGui_InputPanel* anIP = myModule->getInputPanel(); + if ( !anIP ) return; + + // get the list of selected items + list aSelList = getSelected(); + + QListViewItem* anItem = 0; + + // check if the current selection is a single selection + if ( aSelList.size() == 1 ) anItem = aSelList.front(); + + if ( YACSGui_ComposedNodeViewItem* aCNItem = dynamic_cast( anItem ) ) + { + ComposedNode* aNode = aCNItem->getNode(); + if ( !dynamic_cast(aNode) ) + { // show Input Panel with page for composed node in the execution mode + + if ( dynamic_cast( aNode ) ) + { + YACSGui_SwitchNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::SwitchNodeId ) ); + if ( aSNPage ) + { + aSNPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::SwitchNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::SwitchNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::SwitchNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_ForLoopNodePage* aFLNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ForLoopNodeId ) ); + if ( aFLNPage ) + { + aFLNPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::ForLoopNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::ForLoopNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ForLoopNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_ForEachLoopNodePage* aFELNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ForEachLoopNodeId ) ); + if ( aFELNPage ) + { + aFELNPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::ForEachLoopNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::ForEachLoopNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ForEachLoopNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_WhileLoopNodePage* aWLNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::WhileLoopNodeId ) ); + if ( aWLNPage ) + { + aWLNPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::WhileLoopNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::WhileLoopNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::WhileLoopNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_BlockNodePage* aBNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::BlockNodeId ) ); + if ( aBNPage ) + { + aBNPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::BlockNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::BlockNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::BlockNodeId) ); + anIP->show(); + } + } + } + else + { // show Input Panel with page for a schema in the execution mode + YACSGui_SchemaPage* aSPage = dynamic_cast( anIP->getPage( YACSGui_InputPanel::SchemaId ) ); + if ( aSPage ) + { + aSPage->setSProc( GuiContext::getCurrent()->getSubjectProc() ); + anIP->setOn( true, YACSGui_InputPanel::SchemaId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::SchemaId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::SchemaId) ); + std::string theErrorLog; + DEBTRACE("lookForExecutor()"); + YACSGui_Executor* anExecutor = myModule->lookForExecutor(); + if ( anExecutor ) + { + theErrorLog = anExecutor->getErrorReport(getProc()); + } + aSPage->myErrorLog->setText(theErrorLog.c_str()); + anIP->show(); + } + } + } + else if ( YACSGui_ElementaryNodeViewItem* aENItem = dynamic_cast( anItem ) ) + { // show Input Panel with page for elementary node in the execution mode + ElementaryNode* aNode = aENItem->getNode(); + + if ( ServiceNode* sNode = dynamic_cast( aNode ) ) + { + if ( sNode->getKind() == "XML" ) + { + /* + YACSGui_ServiceInlineNodePage* aSINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ServiceInlineNodeId ) ); + if ( aSINPage ) + { + aSINPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::ServiceInlineNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::ServiceInlineNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ServiceInlineNodeId) ); + anIP->show(); + } + */ + } + else + { + YACSGui_ServiceNodePage* aSNPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::ServiceNodeId ) ); + if ( aSNPage ) + { + aSNPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::ServiceNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::ServiceNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::ServiceNodeId) ); + anIP->show(); + } + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InDataNodeId ) ); + if ( aINPage ) + { + aINPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::InDataNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::InDataNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::InDataNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::OutDataNodeId ) ); + if ( aINPage ) + { + aINPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::OutDataNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::OutDataNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::OutDataNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InStudyNodeId ) ); + if ( aINPage ) + { + aINPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::InStudyNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::InStudyNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::InStudyNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_DataNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::OutStudyNodeId ) ); + if ( aINPage ) + { + aINPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::OutStudyNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::OutStudyNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::OutStudyNodeId) ); + anIP->show(); + } + } + else if ( dynamic_cast( aNode ) ) + { + YACSGui_InlineNodePage* aINPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::InlineNodeId ) ); + if ( aINPage ) + { + aINPage->setSNode( GuiContext::getCurrent()->_mapOfSubjectNode[aNode] ); + anIP->setOn( true, YACSGui_InputPanel::InlineNodeId ); + anIP->setMode( YACSGui_InputPanel::RunMode, YACSGui_InputPanel::InlineNodeId ); + anIP->setExclusiveVisible( true, list(1,YACSGui_InputPanel::InlineNodeId) ); + anIP->show(); + } + } + } + else + anIP->hide(); +} + +void YACSGui_RunTreeView::onSelectionChanged() +{ + YACSGui_InputPanel* anIP = myModule->getInputPanel(); + if ( !anIP ) return; + list anIds = anIP->getVisiblePagesIds(); + for ( list::iterator anIter = anIds.begin(); anIter != anIds.end(); ++anIter ) + { + int anId = (*anIter); + switch (anId) + { + case YACSGui_InputPanel::SchemaId: + { + if ( YACSGui_SchemaPage* aSPage = + dynamic_cast( anIP->getPage( YACSGui_InputPanel::SchemaId ) ) ) + aSPage->checkModifications(); + } + break; + default: + break; + } + } + syncPageTypeWithSelection(); + syncHMIWithSelection(); +} + +YACS::HMI::Subject* YACSGui_RunTreeView::getSubject( QListViewItem* theItem ) +{ + Subject* aSub = 0; + + if ( YACSGui_ElementaryNodeViewItem* anItem = dynamic_cast( theItem ) ) + aSub = anItem->getSubject(); + else if ( YACSGui_ComposedNodeViewItem* anCompItem = dynamic_cast( theItem ) ) + aSub = anCompItem->getSubject(); + + return aSub; +} + +/*! + * If a breakpoint is set, the CORBA engine of YACS must be instanciated (findExecutor) + * to update the list of breakpoints. + * While there is no breakpoint, there is no need to instanciate the CORBA engine. + */ +void YACSGui_RunTreeView::onBreakpointClicked( QListViewItem* theItem ) +{ + YACSGui_ElementaryNodeViewItem* anElemNodeItem = dynamic_cast(theItem); + if ( anElemNodeItem ) + { + YACSGui_Executor* anExecutor = 0; + + if ( anElemNodeItem->isOn() ) + { + DEBTRACE("findExecutor()"); + anExecutor = myModule->findExecutor(); + if ( !anExecutor ) return; + if ( anExecutor->getCurrentExecMode() == YACS_ORB::CONTINUE ) + anExecutor->setBreakpointMode(); + + myBreakpointSet.insert(anElemNodeItem->getNode()->getNumId()); + } + else + myBreakpointSet.erase(anElemNodeItem->getNode()->getNumId()); + + list aBreakpointList; + for (set::iterator pos = myBreakpointSet.begin(); pos != myBreakpointSet.end(); ++pos) + { + string aNodeName = + getProc()->getChildName(((YACSGui_ElementaryNodeViewItem*)(myMapListViewItem[*pos]))->getNode()); + aBreakpointList.push_back(aNodeName); + } + if (! aBreakpointList.empty()) + { + anExecutor = myModule->findExecutor(); + assert(anExecutor); + anExecutor->setBreakpointList(aBreakpointList); + } + } +} + +void YACSGui_RunTreeView::onNotifyNodeStatus( int theNodeId, int theStatus ) +{ + QListViewItem* anItem = myMapListViewItem[theNodeId]; + if (!anItem) return; + YACSGui_ElementaryNodeViewItem* aNItem = dynamic_cast(anItem); + if (aNItem) + { + aNItem->setState(theStatus); + return; + } + YACSGui_ComposedNodeViewItem* aCNItem = dynamic_cast(anItem); + if (aCNItem) + { + aCNItem->setState(theStatus); + return; + } + return; +} + +void YACSGui_RunTreeView::onNotifyStatus( int theStatus ) +{ + if ( YACSGui_ComposedNodeViewItem* aRootItem = dynamic_cast(myMapListViewItem[getProc()->getNumId()]) ) + { + aRootItem->setStatus(theStatus); + if(theStatus == YACS::FINISHED) + setSelected(firstChild(),true); + } +} + +void YACSGui_RunTreeView::syncHMIWithSelection() +{ + // notify about selection other observers + + std::list aSelList = getSelected(); + + // notify about selection + list::iterator it; + for ( it = aSelList.begin(); it != aSelList.end(); ++it ) + { + if ( *it ) + { + YACS::HMI::Subject* aSub = getSubject( *it ); + if ( aSub ) + { + if ( YACSGui_ElementaryNodeViewItem* item = dynamic_cast( *it ) ) + { + bool isBlocked = item->blockSelection( true ); + aSub->select( true ); + item->blockSelection( isBlocked ); + } + else if ( YACSGui_ComposedNodeViewItem* cItem = dynamic_cast( *it ) ) + { + bool isBlocked = cItem->blockSelection( true ); + aSub->select( true ); + cItem->blockSelection( isBlocked ); + } + else + continue; + + myLastSelected.erase( *it ); + } + } + } + + // notify about deselection + std::set< QListViewItem* >::iterator lIt; + for ( lIt = myLastSelected.begin(); lIt != myLastSelected.end(); ++lIt ) + { + YACS::HMI::Subject* aSub = getSubject( *lIt ); + if ( aSub ) + aSub->select( false ); + } + + // fill last mySelected + myLastSelected.clear(); + for ( it = aSelList.begin(); it != aSelList.end(); ++it ) + myLastSelected.insert( *it ); + + myModule->updateViewer(); +} + diff --git a/src/gui/YACSGui_TreeView.h b/src/gui/YACSGui_TreeView.h new file mode 100644 index 000000000..296508ed7 --- /dev/null +++ b/src/gui/YACSGui_TreeView.h @@ -0,0 +1,200 @@ +// Copyright (C) 2003 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 YACSGui_TreeView_HeaderFile +#define YACSGui_TreeView_HeaderFile + +#include + +#include +#include +#include +#include + +#include + +class YACSGui_NodeViewItem; +class YACSGui_SchemaViewItem; +class YACSGui_LabelViewItem; + +class QPopupMenu; + +/*! Base class for tree view widgets. + */ +class YACSGui_TreeView: public QListView +{ + Q_OBJECT + + public: + YACSGui_TreeView( YACSGui_Module*, YACS::HMI::SubjectProc*, QWidget* = 0, + const char* = 0, WFlags = 0 ); + ~YACSGui_TreeView(); + + // get the list of selected objects + std::list getSelected(); + + YACS::ENGINE::Proc* getProc() const; + + virtual void update( QListViewItem* theItem = 0, const bool theIsRecursive = false ); + + virtual void build(); //temporary solution, for testing only + + virtual void syncPageTypeWithSelection() {} + virtual void syncHMIWithSelection() {} + + protected slots: + virtual void onContextMenuRequested( QListViewItem*, const QPoint& ) {} + + protected: + enum { SchemaItem, NodeItem }; + + //virtual void build(); + virtual QPopupMenu* contextMenuPopup( const int ) {} + + + protected: + YACSGui_Module* myModule; + YACS::HMI::SubjectProc* mySProc; +}; + +/*! Class for tree view widget in edition mode. + */ +class YACSGui_EditionTreeView: public YACSGui_TreeView +{ + Q_OBJECT + + public: + YACSGui_EditionTreeView( YACSGui_Module*, YACS::HMI::SubjectProc*, QWidget* = 0, + const char* = 0, WFlags = 0 ); + ~YACSGui_EditionTreeView(); + + virtual void update( QListViewItem* theItem = 0, const bool theIsRecursive = false ); + + virtual void build(); //temporary solution, for testing only + + void warnAboutSelectionChanged(); + virtual void syncPageTypeWithSelection(); + + YACSGui_NodeViewItem* displayNodeWithPorts( QListViewItem* theRoot, + YACSGui_NodeViewItem* theAfter, + YACS::HMI::SubjectNode* theSNode ); + void displayChildren( YACSGui_NodeViewItem* theNodeItem ); + + YACS::HMI::Subject* getSelectedSubject(); + virtual YACS::HMI::Subject* getSubject( QListViewItem* theItem ); + + virtual void syncHMIWithSelection(); + + void emitSelectionChanged(); + + public slots: + void onAddToLibrary(); + + void onAddLink(); + + void onCopyItem(); + void onPasteItem(); + void onDeleteItem(); + + void onDisplaySchema(); + void onEraseSchema(); + + void onDisplayNode(); + void onEraseNode(); + + protected slots: + virtual void onContextMenuRequested( QListViewItem*, const QPoint& ); + + protected: + enum { ServiceNodeItem = YACSGui_TreeView::NodeItem+1, LoopNodeItem, PortItem, + LinkItem, ContainerItem, ComponentItem, CorbaComponentItem, ComposedNodeItem, DataTypeItem, + LabelNodesItem, LabelContainersItem }; + + //virtual void build(); + void fillContainerData( YACS::HMI::SubjectComposedNode* theSNode ); + virtual QPopupMenu* contextMenuPopup( const int, YACS::HMI::Subject* theSubj = 0 ); + void showPopup( QPopupMenu*, const QPoint ); + + private slots: + void onSelectionChanged(); + void onDblClick( QListViewItem* ); + void sampleSlot() {}// for testing only! + +private: + + YACSGui_LabelViewItem* buildDataTypesTree( YACSGui_SchemaViewItem* theSchemaItem ); + + private: + typedef std::map< YACS::ENGINE::ComponentInstance*, std::list > Component2ServiceNodesMap; + typedef std::map< YACS::ENGINE::SalomeContainer*, Component2ServiceNodesMap > Container2ComponentsMap; + + Container2ComponentsMap mySalomeComponentData; + Component2ServiceNodesMap myCorbaComponentData; + + QListViewItem* myPreviousSelected; + YACS::HMI::SubjectDataPort* mySelectedSubjectOutPort; + YACS::HMI::SubjectNode* mySelectedSubjectOutNode; + + std::set< QListViewItem* > myLastSelected; +}; + +/*! Class for tree view widget in run mode. + */ +class YACSGui_RunTreeView: public YACSGui_TreeView +{ + Q_OBJECT + + public: + YACSGui_RunTreeView( YACSGui_Module*, YACS::HMI::SubjectProc*, QWidget* = 0, + const char* = 0, WFlags = 0 ); + ~YACSGui_RunTreeView(); + + virtual void update( QListViewItem* theItem = 0, const bool theIsRecursive = false ); + virtual void update( QCheckListItem* theItem, const bool theIsRecursive = false ); + + virtual void build(); //temporary solution, for testing only + + virtual void syncPageTypeWithSelection(); + virtual void syncHMIWithSelection(); + + virtual YACS::HMI::Subject* getSubject( QListViewItem* theItem ); + + public slots: + virtual void onNotifyNodeStatus( int theNodeId, int theStatus ); + virtual void onNotifyStatus( int theStatus ); + virtual void onMenuRequested( QListViewItem*, const QPoint &, int ); + + protected: + //virtual void build(); + void addTreeNode( QListViewItem* theParent, + YACS::ENGINE::ComposedNode* theFather ); + + private slots: + void onSelectionChanged(); + virtual void onBreakpointClicked( QListViewItem* theItem ); + + private: + std::set myBreakpointSet; + std::map myMapListViewItem; + + std::set< QListViewItem* > myLastSelected; +}; + +#endif diff --git a/src/gui/YACSGui_TreeViewItem.cxx b/src/gui/YACSGui_TreeViewItem.cxx new file mode 100644 index 000000000..7a67509b2 --- /dev/null +++ b/src/gui/YACSGui_TreeViewItem.cxx @@ -0,0 +1,3035 @@ +// Copyright (C) 2003 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 +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; +using namespace YACS::HMI; + +/* XPM */ +static const char * const closed_xpm[]={ + "16 16 6 1", + ". c None", + "b c #ffff00", + "d c #000000", + "* c #999999", + "a c #cccccc", + "c c #ffffff", + "................", + "................", + "..*****.........", + ".*ababa*........", + "*abababa******..", + "*cccccccccccc*d.", + "*cbababababab*d.", + "*cabababababa*d.", + "*cbababababab*d.", + "*cabababababa*d.", + "*cbababababab*d.", + "*cabababababa*d.", + "*cbababababab*d.", + "**************d.", + ".dddddddddddddd.", + "................"}; + +/* XPM */ +static const char* const open_xpm[]={ + "16 16 6 1", + ". c None", + "b c #ffff00", + "d c #000000", + "* c #999999", + "c c #cccccc", + "a c #ffffff", + "................", + "................", + "...*****........", + "..*aaaaa*.......", + ".*abcbcba******.", + ".*acbcbcaaaaaa*d", + ".*abcbcbcbcbcb*d", + "*************b*d", + "*aaaaaaaaaa**c*d", + "*abcbcbcbcbbd**d", + ".*abcbcbcbcbcd*d", + ".*acbcbcbcbcbd*d", + "..*acbcbcbcbb*dd", + "..*************d", + "...ddddddddddddd", + "................"}; + + +/* ================ items for tree view in edition mode ================ */ + +// YACSGui_ViewItem class: + +YACSGui_ViewItem::YACSGui_ViewItem( QListView* theParent, + QListViewItem* theAfter ): + QListViewItem( theParent, theAfter ), + GuiObserver() +{ +} + +YACSGui_ViewItem::YACSGui_ViewItem( QListViewItem* theParent, + QListViewItem* theAfter ): + QListViewItem( theParent, theAfter ), + GuiObserver(), + myBlockSelect( false ) +{ +} + +/*! + \brief Block actions performed in select() method. Usually this method is called + from select() in order to avoid circularity because of synchronization: + selection in 2D viewer --> selection in tree view --> selection in 2D viewer --> etc. + \param toBlock block selection + \return previous blocking value +*/ +bool YACSGui_ViewItem::blockSelection( const bool toBlock ) +{ + bool prevVal = myBlockSelect; + myBlockSelect = toBlock; + return prevVal; +} + +/*! + \brief Verifiee whether actions performed in select() method are blocked + (see blockSelection method for more dscription) + \return blocking value +*/ +bool YACSGui_ViewItem::selectionBlocked() const +{ + return myBlockSelect; +} + +void YACSGui_ViewItem::select( bool isSelected ) +{ + if ( selectionBlocked() ) + return; + + //printf(">> YACSGui_ViewItem::select( %d ) \n", isSelected ); + + if ( !isSelected ) // do nothing + return; + + // select item in tree view + QListView* aListView = listView(); + if ( !aListView ) + return; + + bool block = aListView->signalsBlocked(); + aListView->blockSignals( true ); + + blockSelection( true ); + aListView->clearSelection(); + aListView->setCurrentItem( this ); + aListView->setSelected( this, true ); + aListView->ensureItemVisible( this ); + blockSelection( false ); + + aListView->blockSignals( block ); + + if ( YACSGui_EditionTreeView* aETV = dynamic_cast(aListView) ) + aETV->emitSelectionChanged(); +} + +void YACSGui_ViewItem::removeNodeItem( YACS::HMI::Subject* theSNode ) +{ + //printf( "YACSGui_ViewItem::removeNodeItem (this=%s)\n", text(0).latin1() ); + QListViewItem* aNodesL = this; + if( !aNodesL->parent() ) + { + // get the "Nodes" label view item, which is used as a parent for first level nodes + aNodesL = firstChild()->nextSibling(); + if ( !aNodesL || aNodesL->text(0).compare(QString("Nodes")) ) + return; + } + + YACSGui_NodeViewItem* aNode = 0; + QListViewItem* aChild = aNodesL->firstChild(); + while( aChild ) + { + if ( aNode = dynamic_cast(aChild) ) + if ( aNode->getSNode() == theSNode ) + { + //printf(">> the son is found\n"); + break; + } + + aChild = aChild->nextSibling(); + } + + if ( aNode ) + { + if( YACS::HMI::SubjectNode* aSNode = dynamic_cast( theSNode ) ) + { + //printf( ">> remove control links\n" ); + std::list aControlLinks = aSNode->getSubjectControlLinks(); + std::list::iterator cIt = aControlLinks.begin(); + std::list::iterator cItEnd = aControlLinks.end(); + for( ; cIt != cItEnd; cIt++ ) + { + SubjectControlLink* aControlLink = *cIt; + if( aControlLink ) + { + Subject* aParentSNode = aControlLink->getSubjectOutNode()->getParent(); + aParentSNode->update( REMOVE, CONTROLLINK, aControlLink ); + } + } + + //printf( ">> remove data links\n" ); + std::list aDataLinks = aSNode->getSubjectLinks(); + std::list::iterator dIt = aDataLinks.begin(); + std::list::iterator dItEnd = aDataLinks.end(); + for( ; dIt != dItEnd; dIt++ ) + { + SubjectLink* aDataLink = *dIt; + if( aDataLink ) + { + Subject* aParentSNode = aDataLink->getSubjectOutNode()->getParent(); + aParentSNode->update( REMOVE, DATALINK, aDataLink ); + } + } + + //printf( ">> remove port links\n" ); + std::list aDataPorts; + + std::list anInputPorts = aSNode->getSubjectInputPorts(); + for( std::list::iterator pIt = anInputPorts.begin(); pIt != anInputPorts.end(); pIt++ ) + aDataPorts.push_back( *pIt ); + + std::list anOutputPorts = aSNode->getSubjectOutputPorts(); + for( std::list::iterator pIt = anOutputPorts.begin(); pIt != anOutputPorts.end(); pIt++ ) + aDataPorts.push_back( *pIt ); + + std::list anInputDataStreamPorts = aSNode->getSubjectInputDataStreamPorts(); + for( std::list::iterator pIt = anInputDataStreamPorts.begin(); + pIt != anInputDataStreamPorts.end(); pIt++ ) + aDataPorts.push_back( *pIt ); + + std::list anOutputDataStreamPorts = aSNode->getSubjectOutputDataStreamPorts(); + for( std::list::iterator pIt = anOutputDataStreamPorts.begin(); + pIt != anOutputDataStreamPorts.end(); pIt++ ) + aDataPorts.push_back( *pIt ); + + std::list::iterator dpIt = aDataPorts.begin(); + std::list::iterator dpItEnd = aDataPorts.end(); + for( ; dpIt != dpItEnd; dpIt++ ) + { + SubjectDataPort* aDataPort = *dpIt; + if( aDataPort ) + { + std::list lsl = aDataPort->getListOfSubjectLink(); + for( std::list::iterator it = lsl.begin(); it != lsl.end(); ++it ) + { + SubjectLink* aLink = *it; + if( aLink ) + { + //printf( ">> link : %s\n", aLink->getName().c_str() ); + SubjectNode* aNode1 = aLink->getSubjectInNode(); + SubjectNode* aNode2 = aLink->getSubjectOutNode(); + //printf( ">> nodes : %s - %s\n", aNode1->getName().c_str(), aNode2->getName().c_str() ); + if( SubjectComposedNode* aLowestCommonAncestor = + SubjectComposedNode::getLowestCommonAncestor( aNode1, aNode2 ) ) + { + //printf( ">> lowest common ancestor : %s\n", aLowestCommonAncestor->getName().c_str() ); + aLowestCommonAncestor->update( REMOVE, DATALINK, aLink ); + } + } + } + } + } + + //printf( ">> remove leaving/coming current scope links\n" ); + std::vector< std::pair > listLeaving = aSNode->getNode()->getSetOfLinksLeavingCurrentScope(); + std::vector< std::pair > listIncoming = aSNode->getNode()->getSetOfLinksComingInCurrentScope(); + std::vector< std::pair > globalList = listLeaving; + std::vector< std::pair >::iterator it1; + for (it1 = listIncoming.begin(); it1 != listIncoming.end(); ++it1) + { + std::pair outin = std::pair((*it1).second, (*it1).first); + globalList.push_back(outin); + } + std::vector< std::pair >::iterator it2; + for (it2 = globalList.begin(); it2 != globalList.end(); ++it2) + { + if (GuiContext::getCurrent()->_mapOfSubjectLink.count(*it2)) + { + SubjectLink* aLink = GuiContext::getCurrent()->_mapOfSubjectLink[*it2]; + if( aLink ) + { + //printf( ">> link : %s\n", aLink->getName().c_str() ); + SubjectNode* aNode1 = aLink->getSubjectInNode(); + SubjectNode* aNode2 = aLink->getSubjectOutNode(); + //printf( ">> nodes : %s - %s\n", aNode1->getName().c_str(), aNode2->getName().c_str() ); + if( SubjectComposedNode* aLowestCommonAncestor = + SubjectComposedNode::getLowestCommonAncestor( aNode1, aNode2 ) ) + { + //printf( ">> lowest common ancestor : %s\n", aLowestCommonAncestor->getName().c_str() ); + aLowestCommonAncestor->update( REMOVE, DATALINK, aLink ); + } + } + } + } + } + + DEBTRACE(">> delete the son item"); + aNodesL->takeItem(aNode); + delete aNode; + aNode = 0; + } +} + +void YACSGui_ViewItem::removeLinkItem( YACS::HMI::Subject* theSLink ) +{ + DEBTRACE( "YACSGui_ViewItem::removeLinkItem " << text(0).latin1() ); + SubjectLink* aSLink = dynamic_cast(theSLink); + SubjectControlLink* aSCLink = dynamic_cast(theSLink); + if ( aSLink || aSCLink ) + { + // get the "Links" label view item under the parent node of this node view item + YACSGui_LabelViewItem* aLinksL = 0; + QListViewItem* aChildLinks = this; + if( !aChildLinks->parent() ) + aChildLinks = aChildLinks->firstChild(); + while( aChildLinks ) + { + DEBTRACE( ">> item : " << aChildLinks->text(0).latin1() ); + aLinksL = dynamic_cast(aChildLinks); + if ( aLinksL && aLinksL->text(0).compare(QString("Links")) == 0 ) + break; + aChildLinks = aChildLinks->nextSibling(); + } + + if ( !aLinksL ) + return; + + // find the link item published under in the Links folder to delete + QListViewItem* aChild = aLinksL->firstChild(); + while( aChild ) + { + if ( aSLink ) + { + if ( YACSGui_LinkViewItem* aLink = dynamic_cast(aChild) ) + if ( aLink->getSLink() == aSLink ) + { + DEBTRACE(">> the data link is found"); + aLinksL->takeItem(aChild); + delete aChild; + break; + } + } + else if ( aSCLink ) + { + if ( YACSGui_ControlLinkViewItem* aCLink = dynamic_cast(aChild) ) + if ( aCLink->getSLink() == aSCLink ) + { + DEBTRACE(">> the control link is found"); + aLinksL->takeItem(aChild); + delete aChild; + break; + } + } + + aChild = aChild->nextSibling(); + } + } +} + +// YACSGui_LabelViewItem class: + +YACSGui_LabelViewItem::YACSGui_LabelViewItem( QListView* theParent, + QListViewItem* theAfter, + const QString theName ): + YACSGui_ViewItem( theParent, theAfter ), + myName( theName ) +{ + if ( !myName.isEmpty() ) + setText( 0, myName ); + setPixmap( 0, icon() ); +} + +YACSGui_LabelViewItem::YACSGui_LabelViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + const QString theName ): + YACSGui_ViewItem( theParent, theAfter ), + myName( theName ) +{ + if ( !myName.isEmpty() ) + setText( 0, myName ); + setPixmap( 0, icon() ); +} + +QString YACSGui_LabelViewItem::name() const +{ + return myName; +} + +QPixmap YACSGui_LabelViewItem::icon() const +{ + if ( isOpen() ) + return QPixmap( (const char**) open_xpm ); + return QPixmap( (const char**) closed_xpm ); +} + +void YACSGui_LabelViewItem::select( bool isSelected ) +{ + //printf(">> YACSGui_ReferenceViewItem::select( %d ) does nothing\n", isSelected); +} + +void YACSGui_LabelViewItem::update( const bool theIsRecursive ) +{ + +} + +// YACSGui_ReferenceViewItem class: + +YACSGui_ReferenceViewItem::YACSGui_ReferenceViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectReference* theSReference ): + YACSGui_ViewItem( theParent, theAfter ), + mySReference( theSReference ) +{ + if ( mySReference ) mySReference->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); +} + +YACSGui_ReferenceViewItem::YACSGui_ReferenceViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectReference* theSReference ): + YACSGui_ViewItem( theParent, theAfter ), + mySReference( theSReference ) +{ + if ( mySReference ) mySReference->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); +} + +YACSGui_ReferenceViewItem::~YACSGui_ReferenceViewItem() +{ + if ( mySReference ) mySReference->detach(this); +} + +void YACSGui_ReferenceViewItem::select(bool isSelected) +{ + //printf(">> YACSGui_ReferenceViewItem::select( %d ) does nothing\n", isSelected); + DEBTRACE(">> YACSGui_ReferenceViewItem::select( " << isSelected << " ) does nothing"); +} + +void YACSGui_ReferenceViewItem::update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + //printf(">> YACSGui_ReferenceViewItem::update\n"); + DEBTRACE(">> YACSGui_ReferenceViewItem::update"); + switch (event) + { + case RENAME: + update(); + break; + default: + GuiObserver::update(event, type, son); + } +} + +QString YACSGui_ReferenceViewItem::name() const +{ + QString aName; + + if (getNode()) + aName = QString("* ") + QString(getNode()->getRootNode()->getChildName(getNode())); + + return aName; +} + +QColor YACSGui_ReferenceViewItem::color( const ColorRole theCR ) const +{ + QColor clr; + switch ( theCR ) + { + case Text: + case Highlight: + clr = QColor( 255, 0, 0 ); + break; + case HighlightedText: + clr = QColor( 255, 255, 255 ); + break; + } + return clr; +} + +QPixmap YACSGui_ReferenceViewItem::icon() const +{ + return QPixmap(); +} + +YACS::ENGINE::Node* YACSGui_ReferenceViewItem::getNode() const +{ + Node* aRet = 0; + + if ( mySReference ) + if ( SubjectServiceNode* aSSN = dynamic_cast( mySReference->getParent() ) ) + aRet = aSSN->getNode(); + + return aRet; +} + +void YACSGui_ReferenceViewItem::paintCell( QPainter* p, const QColorGroup& cg, int c, int w, int align ) +{ + QColorGroup col_group( cg ); + + if ( color( YACSGui_ReferenceViewItem::Text ).isValid() ) + col_group.setColor( QColorGroup::Text, color( YACSGui_ReferenceViewItem::Text ) ); + if ( color( YACSGui_ReferenceViewItem::Highlight ).isValid() ) + col_group.setColor( QColorGroup::Highlight, color( YACSGui_ReferenceViewItem::Highlight ) ); + if ( color( YACSGui_ReferenceViewItem::HighlightedText ).isValid() ) + col_group.setColor( QColorGroup::HighlightedText, color( YACSGui_ReferenceViewItem::HighlightedText ) ); + + p->fillRect( 0, 0, w, height(), cg.brush( QColorGroup::Base ) ); + + int W = w; + if ( listView() && !listView()->allColumnsShowFocus() ) + W = width( p->fontMetrics(), listView(), c ); + + QListViewItem::paintCell( p, col_group, c, Wattach( this ); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_PortViewItem::YACSGui_PortViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectDataPort* theSPort ): + YACSGui_ViewItem( theParent, theAfter ), + mySPort( theSPort ) +{ + if ( mySPort ) + { + mySPort->attach( this ); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_PortViewItem::~YACSGui_PortViewItem() +{ + if ( mySPort ) mySPort->detach(this); +} + +QString YACSGui_PortViewItem::name() const +{ + QString aName = ""; + + DataPort* aDataPort = getPort(); + if (aDataPort) + aName = aDataPort->getName(); + + return aName; +} + +QPixmap YACSGui_PortViewItem::icon() const +{ + QPixmap aRes; + + QString anIconName; + + if ( dynamic_cast( getPort() ) ) + anIconName = QString(QObject::tr("ICON_OUT_PORT_OBJECT")); + else if ( dynamic_cast( getPort() ) ) + anIconName = QString(QObject::tr("ICON_IN_PORT_OBJECT")); + + if ( !anIconName.isEmpty() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", anIconName, false); + + return aRes; +} + +YACS::ENGINE::DataPort* YACSGui_PortViewItem::getPort() const +{ + return ( mySPort ? mySPort->getPort() : 0 ); +} + +void YACSGui_PortViewItem::update( const bool theIsRecursive ) +{ + +} + +// YACSGui_DataTypeItem class: + +/*! + \brief Constructor +*/ +YACSGui_DataTypeItem::YACSGui_DataTypeItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectDataType* theSDataType ) +: YACSGui_ViewItem( theParent, theAfter ), + mySDataType( theSDataType ) +{ + if ( theSDataType ) + theSDataType->attach( this ); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); +} + +/*! + \brief Constructor +*/ +YACSGui_DataTypeItem::YACSGui_DataTypeItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectDataType* theSDataType ) +: YACSGui_ViewItem( theParent, theAfter ), + mySDataType( theSDataType ) +{ + if ( theSDataType ) + theSDataType->attach( this ); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); +} + +/*! + \brief Destructor +*/ +YACSGui_DataTypeItem::~YACSGui_DataTypeItem() +{ +} + +/*! + \brief Updates item in accordance with GUI event +*/ +void YACSGui_DataTypeItem::update( YACS::HMI::GuiEvent event, + int type, + YACS::HMI::Subject* son ) +{ + //printf(">> YACSGui_DataTypeItem::update\n"); + DEBTRACE(">> YACSGui_DataTypeItem::update"); + switch ( event ) + { + case RENAME: + update(); + break; + default: + GuiObserver::update( event, type, son ); + break; + } +} + +/*! + \brief Gets item name +*/ +QString YACSGui_DataTypeItem::name() const +{ + QString aName; + if ( mySDataType ) + aName = QString( mySDataType->getName() ); + return aName; +} + +/*! + \brief Gets item icon +*/ +QPixmap YACSGui_DataTypeItem::icon() +{ + QPixmap aRes; + QString anIconName( QObject::tr( "ICON_TEXT" ) ); + + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", anIconName, false ); + + return aRes; +} + +void YACSGui_DataTypeItem::update( const bool /*theIsRecursive*/ ) +{ + // nothing to be updated +} + +// YACSGui_NodeViewItem class: + +YACSGui_NodeViewItem::YACSGui_NodeViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectNode* theSNode ): + YACSGui_ViewItem( theParent, theAfter ), + mySNode( theSNode ) +{ + if ( mySNode ) mySNode->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); +} + +YACSGui_NodeViewItem::YACSGui_NodeViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectNode* theSNode ): + YACSGui_ViewItem( theParent, theAfter ), + mySNode( theSNode ) +{ + if ( mySNode ) mySNode->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); +} + +YACSGui_NodeViewItem::~YACSGui_NodeViewItem() +{ + if ( mySNode ) mySNode->detach(this); +} + +void YACSGui_NodeViewItem::update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSGui_NodeViewItem::update"); + switch (event) + { + case RENAME: + update(); + break; + case EDIT: + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + // rename a port item (this = node item) + //printf("NodeViewItem: EDIT port\n"); + renamePortItem(son); + } + break; + default: + { + if ( !type ) + update(true); + } + break; + } + break; + case ADDREF: + { + // add a reference item (this = node item) + //printf("NodeViewItem: ADDREF\n"); + addReferenceItem(son); + } + break; + case ADD: + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + // add a port item (this = node item) + //printf("NodeViewItem: ADD port\n"); + addPortItem(son); + } + break; + case BLOC: + case FOREACHLOOP: + case OPTIMIZERLOOP: + case FORLOOP: + case WHILELOOP: + case SWITCH: + case PYTHONNODE: + case PYFUNCNODE: + case CORBANODE: + case SALOMENODE: + case CPPNODE: + case SALOMEPYTHONNODE: + case PRESETNODE: + case OUTNODE: + case STUDYINNODE: + case STUDYOUTNODE: + case XMLNODE: + { + // remove a node inside a block (this = block item) + DEBTRACE("NodeViewItem: ADD"); + addNodeItem(son); + } + break; + default: + break; + } + break; + case REMOVE: + switch (type) + { + case DATATYPE: + { + // Readdress this event to schema item + YACSGui_SchemaViewItem* aSchema = + dynamic_cast( listView()->firstChild() ); + if ( aSchema ) + aSchema->update( event, type, son ); + } + break; + case DATALINK: + case CONTROLLINK: + { + // remove a link item (this = out node item) + DEBTRACE("NodeViewItem: REMOVE link"); + removeLinkItem(son); + } + break; + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + // remove a port item (this = node item) + DEBTRACE("NodeViewItem: REMOVE port"); + removePortItem(son); + } + break; + case BLOC: + case FOREACHLOOP: + case OPTIMIZERLOOP: + case FORLOOP: + case WHILELOOP: + case SWITCH: + case PYTHONNODE: + case PYFUNCNODE: + case CORBANODE: + case SALOMENODE: + case CPPNODE: + case SALOMEPYTHONNODE: + case PRESETNODE: + case OUTNODE: + case STUDYINNODE: + case STUDYOUTNODE: + case XMLNODE: + { + // remove a node inside a block (this = block item) + //printf("NodeViewItem: REMOVE\n"); + removeNodeItem(son); + } + break; + case REFERENCE: + { + // remove a reference to a component (this = service node item) + //printf("NodeViewItem: REMOVE reference\n"); + removeReferenceItem(son); + } + break; + default: + break; + } + break; + case UP: + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + // move up a port item (this = node item) + //printf("NodeViewItem: UP port\n"); + moveUpPortItem(son); + } + break; + default: + break; + } + break; + case DOWN: + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + // move down a port item (this = node item) + DEBTRACE("NodeViewItem: DOWN port"); + moveDownPortItem(son); + } + break; + default: + break; + } + break; + case ADDLINK: + case ADDCONTROLLINK: + { + // add link item (this = composed node item) + DEBTRACE("NodeViewItem: ADDLINK"); + addLinkItem(son); + } + break; + default: + GuiObserver::update(event, type, son); + } +} + +QString YACSGui_NodeViewItem::name() const +{ + QString aName; + + if (getNode()) + aName = QString(getNode()->getName()); + + return aName; +} + +QPixmap YACSGui_NodeViewItem::icon( YACS::ENGINE::Node* theNode ) +{ + QPixmap aRes; + + QString anIconName; + + if ( dynamic_cast( theNode ) ) + anIconName = QString(QObject::tr("ICON_BLOCK_OBJECT")); + else if ( dynamic_cast( theNode ) || dynamic_cast( theNode ) ) + anIconName = QString(QObject::tr("ICON_LOOP_NODE_OBJECT")); + else if ( dynamic_cast( theNode ) ) + anIconName = QString(QObject::tr("ICON_SWITCH_NODE_OBJECT")); + else + anIconName = QString(QObject::tr("ICON_NODE_OBJECT")); + + if ( !anIconName.isEmpty() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", anIconName, false); + + return aRes; +} + +QPixmap YACSGui_NodeViewItem::icon() const +{ + return icon( getNode() ); +} + +YACS::ENGINE::Node* YACSGui_NodeViewItem::getNode() const +{ + return ( mySNode ? mySNode->getNode() : 0 ); +} + +void YACSGui_NodeViewItem::update( const bool theIsRecursive ) +{ + if ( theIsRecursive ) // total update + { + ComposedNode* aComposedNode = dynamic_cast( getNode() ); + + std::list aChildrenToMove; + + QListViewItem* aChild = firstChild(); + while( aChild ) + { + if ( aComposedNode ) + { // this node is a block + if ( YACSGui_NodeViewItem* aChildNode = dynamic_cast( aChild ) ) + { + if ( !aComposedNode->isInMyDescendance( aChildNode->getNode() ) ) + { // a current child is not in the block now + aChildrenToMove.push_back( aChildNode->getSNode() ); + } + } + } + + // remove old child objects of this view item (this case is suitable for the elementary nodes, + // where we delete and recreate its ports) + takeItem(aChild); + delete aChild; + + aChild = firstChild(); + } + + if ( YACSGui_EditionTreeView* anETV = dynamic_cast(listView()) ) + anETV->displayChildren( this ); + + if ( aComposedNode ) + if ( YACSGui_SchemaViewItem* aSchema = dynamic_cast(listView()->firstChild()) ) + { + //aSchema->update( true, 0, this ); + + if ( !aChildrenToMove.empty() ) + { + // get the "Nodes" label view item, which is used as a parent for first level nodes + YACSGui_LabelViewItem* aNodesL = + dynamic_cast(listView()->firstChild()->firstChild()->nextSibling()); + if ( !aNodesL || aNodesL->text(0).compare(QString("Nodes")) ) return; + + // find the last view item under "Nodes" label + YACSGui_NodeViewItem* aLast = 0; + QListViewItem* aChildL = aNodesL->firstChild(); + while( aChildL ) + { + if ( YACSGui_NodeViewItem* aChildLNodeItem = dynamic_cast(aChildL) ) + aLast = aChildLNodeItem; + aChildL = aChildL->nextSibling(); + } + + if ( YACSGui_EditionTreeView* anETV = dynamic_cast(listView()) ) + { + std::list::iterator anIt = aChildrenToMove.begin(); + for (; anIt != aChildrenToMove.end(); anIt++) + { + // create list view items after the last view item under "Nodes" label + aLast = anETV->displayNodeWithPorts( aNodesL, aLast, *anIt ); + } + } + + } + } + } + + setText( 0, name() ); // only rename +} + +void YACSGui_NodeViewItem::renamePortItem( YACS::HMI::Subject* theSPort ) +{ + if ( SubjectDataPort* aSPort = dynamic_cast(theSPort) ) + { + YACSGui_PortViewItem* aPort = 0; + QListViewItem* aChild = firstChild(); + while( aChild ) + { + if ( aPort = dynamic_cast(aChild) ) + if ( aPort->getPort() == aSPort->getPort() ) + { + //printf(">> the son is found\n"); + break; + } + + aChild = aChild->nextSibling(); + } + + if ( aPort ) + { + //printf(">> rename the son item\n"); + aPort->setText( 0, aPort->name() ); + } + } +} + +void YACSGui_NodeViewItem::addPortItem( YACS::HMI::Subject* theSPort ) +{ + if ( SubjectDataPort* aSPort = dynamic_cast(theSPort) ) + { + Port* aPort = aSPort->getPort(); + if ( !aPort ) return; + + if ( isPublished(aPort) ) return; + + YACSGui_PortViewItem* aPortItem = new YACSGui_PortViewItem( this, 0, aSPort ); + if ( !aPortItem ) return; + + Port* anAfter = 0; + // find the port, after which aPort is stored in the engine + if ( dynamic_cast(aPort) ) + { + std::list anInPorts = getNode()->getSetOfInPort(); + std::list::iterator InPortsIter = anInPorts.begin(); + for(; InPortsIter != anInPorts.end(); InPortsIter++) + { + if ( *InPortsIter == aPort ) break; + anAfter = *InPortsIter; + } + } + else if ( dynamic_cast(aPort) ) + { + std::list anOutPorts = getNode()->getSetOfOutPort(); + std::list::iterator OutPortsIter = anOutPorts.begin(); + for(; OutPortsIter != anOutPorts.end(); OutPortsIter++) + { + if ( *OutPortsIter == aPort ) break; + anAfter = *OutPortsIter; + } + } + + // find the port, after which aPortItem should be stored in the tree + YACSGui_PortViewItem* anAfterItem = 0; + + QListViewItem* aChild; + if ( dynamic_cast(aPort) ) + aChild = firstChild(); + else if ( dynamic_cast(aPort) ) + { + // find tree view item corresponds to the last input port + QListViewItem* aLastInPort = firstChild(); + while( aLastInPort ) + { + if ( YACSGui_PortViewItem* aFirstOutPortItem = dynamic_cast(aLastInPort->nextSibling()) ) + if ( dynamic_cast(aFirstOutPortItem->getPort()) ) + break; + aLastInPort = aLastInPort->nextSibling(); + } + aChild = aLastInPort; + + if ( !anAfter ) + { + aPortItem->moveItem(aLastInPort); + return; + } + } + + while( aChild ) + { + if ( anAfterItem = dynamic_cast(aChild) ) + if ( anAfterItem->getPort() == anAfter ) + { + //printf(">> the son is found\n"); + aPortItem->moveItem(anAfterItem); + break; + } + + aChild = aChild->nextSibling(); + } + } +} + +void YACSGui_NodeViewItem::removePortItem( YACS::HMI::Subject* theSPort ) +{ + if ( SubjectDataPort* aSPort = dynamic_cast(theSPort) ) + { + QListViewItem* aChild = firstChild(); + while( aChild ) + { + if ( YACSGui_PortViewItem* aPort = dynamic_cast(aChild) ) + if ( aPort->getPort() == aSPort->getPort() ) + { + //printf(">> the son is found\n"); + takeItem(aChild); + delete aChild; + break; + } + + aChild = aChild->nextSibling(); + } + } +} + +void YACSGui_NodeViewItem::addNodeItem( YACS::HMI::Subject* theSNode ) +{ + if ( SubjectNode* aSNode = dynamic_cast(theSNode) ) + { + YACSGui_NodeViewItem* aNodeItem = new YACSGui_NodeViewItem( this, 0, aSNode ); + + if ( SubjectComposedNode* aSCompNode = dynamic_cast(aSNode) ) + YACSGui_LabelViewItem* aLinksItem = new YACSGui_LabelViewItem( aNodeItem, 0, QObject::tr( "LINKS" ) ); + } +} + +void YACSGui_NodeViewItem::moveUpPortItem( YACS::HMI::Subject* theSPort ) +{ + if ( SubjectDataPort* aSPort = dynamic_cast(theSPort) ) + { + QListViewItem* aChild = firstChild(); + while( aChild ) + { + if ( YACSGui_PortViewItem* aPort = dynamic_cast(aChild->nextSibling()) ) + if ( aPort->getPort() == aSPort->getPort() ) + break; + + aChild = aChild->nextSibling(); + } + + // here aChild is an after item for old position of theSPort + YACSGui_PortViewItem* aCPort = dynamic_cast(aChild); + if ( !aCPort ) return; + + if ( dynamic_cast(aSPort->getPort()) && dynamic_cast(aCPort->getPort()) + || + dynamic_cast(aSPort->getPort()) && dynamic_cast(aCPort->getPort()) ) + //if ( dynamic_cast(aSPort->getPort()) + // || + // aChild->text(0).compare( QString("Gate") ) ) + { + aChild->moveItem(aChild->nextSibling()); + } + } +} + +void YACSGui_NodeViewItem::moveDownPortItem( YACS::HMI::Subject* theSPort ) +{ + if ( SubjectDataPort* aSPort = dynamic_cast(theSPort) ) + { + QListViewItem* aChild = firstChild(); + while( aChild ) + { + if ( YACSGui_PortViewItem* aPort = dynamic_cast(aChild) ) + if ( aPort->getPort() == aSPort->getPort() ) + { + //printf(">> the son is found\n"); + break; + } + + aChild = aChild->nextSibling(); + } + + // here aChild is an item corresponding to the old position of theSPort + YACSGui_PortViewItem* aCPort = dynamic_cast(aChild); + if ( !aCPort ) return; + + YACSGui_PortViewItem* aCNPort = dynamic_cast(aChild->nextSibling()); + if ( !aCNPort ) return; + + if ( !dynamic_cast(aCPort->getPort()) || !dynamic_cast(aCNPort->getPort()) ) + //if ( aChild->nextSibling()->text(0).compare( QString("Gate") ) ) + aChild->moveItem(aChild->nextSibling()); + } +} + +bool YACSGui_NodeViewItem::isPublished( YACS::ENGINE::Port* thePort ) +{ + QListViewItem* aChild = firstChild(); + while( aChild ) + { + if ( YACSGui_PortViewItem* aPort = dynamic_cast(aChild) ) + if ( aPort->getPort() == thePort ) + return true; + aChild = aChild->nextSibling(); + } + return false; +} + +void YACSGui_NodeViewItem::addReferenceItem( YACS::HMI::Subject* theSRef ) +{ + if ( SubjectReference* aSRef = dynamic_cast(theSRef) ) + { + // get component subject of the given reference + if ( SubjectComponent* aSComp = dynamic_cast(aSRef->getReference()) ) + { + // get "Containers" label view item + YACSGui_LabelViewItem* aContainersL = + dynamic_cast(listView()->firstChild()->firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContainersL || aContainersL->text(0).compare(QString("Containers")) ) return; + + ComponentInstance* aComp = aSComp->getComponent(); + if ( aComp && aComp->getKind() != CORBAComponent::KIND ) + { + // get container corresponds to the component + Container* aCont = aComp->getContainer(); + if ( aCont ) + { + QListViewItem* aContItem = 0; + QListViewItem* aChild = aContainersL->firstChild(); + while( aChild ) + { + if ( YACSGui_ContainerViewItem* aC = dynamic_cast(aChild) ) + if ( aC->getContainer() == aCont ) + { + aContItem = aChild; + break; + } + aChild = aChild->nextSibling(); + } + + if ( aContItem ) + { + // find component view item corresponds to the aSComp + QListViewItem* aCompItem = 0; + QListViewItem* aChild = aContItem->firstChild(); + while( aChild ) + { + if ( YACSGui_ComponentViewItem* aC = dynamic_cast(aChild) ) + if ( aC->getComponent() == aComp ) + { + aCompItem = aChild; + break; + } + aChild = aChild->nextSibling(); + } + + if ( aCompItem ) + { + // add a new reference to the end + QListViewItem* anAfter = 0; + + if ( QListViewItem* aChild = aCompItem->firstChild() ) + { + while( aChild->nextSibling() ) + aChild = aChild->nextSibling(); + anAfter = aChild; + } + + new YACSGui_ReferenceViewItem( aCompItem, anAfter, aSRef ); + } + } + } + } + else + { // it is a CORBA component + // find component view item corresponds to the aSComp + QListViewItem* aCompItem = 0; + QListViewItem* aChild = aContainersL->firstChild(); + while( aChild ) + { + if ( YACSGui_ComponentViewItem* aC = dynamic_cast(aChild) ) + if ( aC->getComponent() == aComp ) + { + aCompItem = aChild; + break; + } + aChild = aChild->nextSibling(); + } + + if ( aCompItem ) + { + // add a new reference to the end + QListViewItem* anAfter = 0; + + if ( QListViewItem* aChild = aCompItem->firstChild() ) + { + while( aChild->nextSibling() ) + aChild = aChild->nextSibling(); + anAfter = aChild; + } + + new YACSGui_ReferenceViewItem( aCompItem, anAfter, aSRef ); + } + } + } + } +} + +void YACSGui_NodeViewItem::removeReferenceItem( YACS::HMI::Subject* theSRef ) +{ + if ( SubjectReference* aSRef = dynamic_cast(theSRef) ) + { + // get component subject of the given reference + if ( SubjectComponent* aSComp = dynamic_cast(aSRef->getReference()) ) + { + // get "Containers" label view item + YACSGui_LabelViewItem* aContainersL = + dynamic_cast(listView()->firstChild()->firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContainersL || aContainersL->text(0).compare(QString("Containers")) ) return; + + ComponentInstance* aComp = aSComp->getComponent(); + if ( aComp && aComp->getKind() != CORBAComponent::KIND ) + { + // get container corresponds to the component + Container* aCont = aComp->getContainer(); + if ( aCont ) + { + QListViewItem* aContItem = 0; + QListViewItem* aChild = aContainersL->firstChild(); + while( aChild ) + { + if ( YACSGui_ContainerViewItem* aC = dynamic_cast(aChild) ) + if ( aC->getContainer() == aCont ) + { + aContItem = aChild; + break; + } + aChild = aChild->nextSibling(); + } + + if ( aContItem ) + { + // find component view item corresponds to the aSComp + QListViewItem* aCompItem = 0; + QListViewItem* aChild = aContItem->firstChild(); + while( aChild ) + { + if ( YACSGui_ComponentViewItem* aC = dynamic_cast(aChild) ) + if ( aC->getComponent() == aComp ) + { + aCompItem = aChild; + break; + } + aChild = aChild->nextSibling(); + } + + if ( aCompItem ) + { + // delete a given reference + if ( QListViewItem* aChild = aCompItem->firstChild() ) + { + while( aChild ) + { + if ( YACSGui_ReferenceViewItem* aRefItem = dynamic_cast(aChild) ) + if ( aRefItem->getSReference() == aSRef ) + { + aCompItem->takeItem(aChild); + delete aChild; + break; + } + aChild = aChild->nextSibling(); + } + } + } + } + } + } + else + { // it is a CORBA component + // find component view item corresponds to the aSComp + QListViewItem* aCompItem = 0; + QListViewItem* aChild = aContainersL->firstChild(); + while( aChild ) + { + if ( YACSGui_ComponentViewItem* aC = dynamic_cast(aChild) ) + if ( aC->getComponent() == aComp ) + { + aCompItem = aChild; + break; + } + aChild = aChild->nextSibling(); + } + + if ( aCompItem ) + { + // delete a given reference + if ( QListViewItem* aChild = aCompItem->firstChild() ) + { + while( aChild ) + { + if ( YACSGui_ReferenceViewItem* aRefItem = dynamic_cast(aChild) ) + if ( aRefItem->getSReference() == aSRef ) + { + aCompItem->takeItem(aChild); + delete aChild; + break; + } + aChild = aChild->nextSibling(); + } + } + } + } + } + } +} + +void YACSGui_NodeViewItem::addLinkItem( YACS::HMI::Subject* theSLink ) +{ + DEBTRACE("YACSGui_NodeViewItem::addLinkItem"); + SubjectLink* aSLink = dynamic_cast(theSLink); + SubjectControlLink* aSCLink = dynamic_cast(theSLink); + if ( aSLink || aSCLink ) + { + // get the "Links" label view item under this node view item + YACSGui_LabelViewItem* aLinksL = 0; + QListViewItem* aChildLinks = firstChild(); + while( aChildLinks ) + { + aLinksL = dynamic_cast(aChildLinks); + if ( aLinksL && aLinksL->text(0).compare(QString("Links")) == 0 ) + break; + aChildLinks = aChildLinks->nextSibling(); + } + + if ( !aLinksL ) + return; + + // find the last link item published under in the Links folder + QListViewItem* anAfter = 0; + if ( QListViewItem* aChild = aLinksL->firstChild() ) + { + while( aChild->nextSibling() ) + aChild = aChild->nextSibling(); + anAfter = aChild; + } + + if ( aSLink ) new YACSGui_LinkViewItem( aLinksL, anAfter, aSLink ); + else if ( aSCLink ) new YACSGui_ControlLinkViewItem( aLinksL, anAfter, aSCLink ); + } +} + +// YACSGui_LinkViewItem class: + +YACSGui_LinkViewItem::YACSGui_LinkViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectLink* theSLink ): + YACSGui_ViewItem( theParent, theAfter ), + mySLink( theSLink ) +{ + if ( mySLink ) + { + mySLink->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_LinkViewItem::YACSGui_LinkViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectLink* theSLink ): + YACSGui_ViewItem( theParent, theAfter ), + mySLink( theSLink ) +{ + if ( mySLink ) + { + mySLink->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_LinkViewItem::~YACSGui_LinkViewItem() +{ + if ( mySLink ) mySLink->detach(this); +} + +QString YACSGui_LinkViewItem::name() const +{ + QString aName = ""; + + if ( !mySLink ) return aName; + + DataPort* anOutPort = mySLink->getSubjectOutPort()->getPort(); + DataPort* anInPort = mySLink->getSubjectInPort()->getPort(); + if ( anOutPort && anInPort ) + { + Node* anOutPortNode = anOutPort->getNode(); + ComposedNode* aRootO = 0; + if ( dynamic_cast( anOutPortNode->getFather() ) ) + aRootO = anOutPortNode->getFather(); + else + aRootO = anOutPortNode->getRootNode(); + + Node* anInPortNode = anInPort->getNode(); + ComposedNode* aRootI = 0; + if ( dynamic_cast( anInPortNode->getFather() ) ) + aRootI = anInPortNode->getFather(); + else + aRootI = anInPortNode->getRootNode(); + + ComposedNode* aRoot = 0; + if ( aRootO->isInMyDescendance(aRootI) ) + aRoot = aRootO; + else if ( aRootI->isInMyDescendance(aRootO) ) + aRoot = aRootI; + else + { + Bloc* aBlocOut = 0; + Bloc* aBlocIn = 0; + // find the nearest common ancestor for anOutNode and anInNode + Proc* aProc = dynamic_cast(aRootI->getRootNode()); + if ( !aProc ) return aName; + + aRoot = aProc; + while ( aRootI->getFather() != aProc ) + { + if ( aBlocOut = dynamic_cast(aRootI->getFather()->isInMyDescendance(aRootO)) ) + { + aBlocIn = dynamic_cast(aRootI); + break; + } + aRootI = aRootI->getFather(); + } + + if ( aBlocOut && aBlocIn ) + aRoot = aBlocOut->getFather(); + } + + if (aRoot) + aName += QString(aRoot->getChildName(anOutPortNode)); + + aName += QString(".%1").arg(anOutPort->getName()); + aName += QString(" --> "); + + if (aRoot) + aName += QString(aRoot->getChildName(anInPortNode)); + + aName += QString(".%1").arg(anInPort->getName()); + } + + return aName; +} + +QPixmap YACSGui_LinkViewItem::icon() const +{ + QPixmap aRes; + + QString anIconName; + + if ( !mySLink ) return aRes; + + if ( DataPort* anOutPort = mySLink->getSubjectOutPort()->getPort() ) + { + if ( dynamic_cast( anOutPort ) ) + anIconName = QString(QObject::tr("ICON_STREAM_LINK_OBJECT")); + else if ( dynamic_cast( anOutPort ) ) + anIconName = QString(QObject::tr("ICON_DATA_LINK_OBJECT")); + + if ( !anIconName.isEmpty() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", anIconName, false); + } + + return aRes; +} + +void YACSGui_LinkViewItem::update( const bool theIsRecursive ) +{ + +} + +// YACSGui_ControlLinkViewItem class: + +YACSGui_ControlLinkViewItem::YACSGui_ControlLinkViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectControlLink* theSLink ): + YACSGui_ViewItem( theParent, theAfter ), + mySLink( theSLink ) +{ + if ( mySLink ) + { + mySLink->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_ControlLinkViewItem::YACSGui_ControlLinkViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectControlLink* theSLink ): + YACSGui_ViewItem( theParent, theAfter ), + mySLink( theSLink ) +{ + if ( mySLink ) + { + mySLink->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_ControlLinkViewItem::~YACSGui_ControlLinkViewItem() +{ + if ( mySLink ) mySLink->detach(this); +} + +QString YACSGui_ControlLinkViewItem::name() const +{ + QString aName = ""; + + if ( !mySLink ) return aName; + + Node* anOutPortNode = mySLink->getSubjectOutNode()->getNode(); + ComposedNode* aRootO = 0; + if ( dynamic_cast( anOutPortNode->getFather() ) ) + aRootO = anOutPortNode->getFather(); + else + aRootO = anOutPortNode->getRootNode(); + + Node* anInPortNode = mySLink->getSubjectInNode()->getNode(); + ComposedNode* aRootI = 0; + if ( dynamic_cast( anInPortNode->getFather() ) ) + aRootI = anInPortNode->getFather(); + else + aRootI = anInPortNode->getRootNode(); + + ComposedNode* aRoot = 0; + if ( aRootO->isInMyDescendance(aRootI) ) + aRoot = aRootO; + else if ( aRootI->isInMyDescendance(aRootO) ) + aRoot = aRootI; + else + { + Bloc* aBlocOut = 0; + Bloc* aBlocIn = 0; + // find the nearest common ancestor for anOutNode and anInNode + Proc* aProc = dynamic_cast(aRootI->getRootNode()); + if ( !aProc ) return aName; + + while ( aRootI->getFather() != aProc ) + { + if ( aBlocOut = dynamic_cast(aRootI->getFather()->isInMyDescendance(aRootO)) ) + { + aBlocIn = dynamic_cast(aRootI); + break; + } + aRootI = aRootI->getFather(); + } + + if ( aBlocOut && aBlocIn ) + aRoot = aBlocOut->getFather(); + } + + if (aRoot) + aName += QString(aRoot->getChildName(anOutPortNode)); + + aName += QString(" --> "); + + if (aRoot) + aName += QString(aRoot->getChildName(anInPortNode)); + + return aName; +} + +QPixmap YACSGui_ControlLinkViewItem::icon() const +{ + QPixmap aRes; + + QString anIconName; + + anIconName = QString(QObject::tr("ICON_CONTROL_LINK_OBJECT")); + if ( !anIconName.isEmpty() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", anIconName, false); + + return aRes; +} + +void YACSGui_ControlLinkViewItem::update( const bool theIsRecursive ) +{ + +} + +// YACSGui_SchemaViewItem class: + +YACSGui_SchemaViewItem::YACSGui_SchemaViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectProc* theSProc ): + YACSGui_ViewItem( theParent, theAfter ), + mySProc( theSProc ) +{ + if ( mySProc ) mySProc->attach(this); + + if ( getProc() ) + setText( 0, QString( getProc()->getName() ) ); + setPixmap( 0, icon() ); +} + +YACSGui_SchemaViewItem::YACSGui_SchemaViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectProc* theSProc ): + YACSGui_ViewItem( theParent, theAfter ), + mySProc( theSProc ) +{ + if ( mySProc ) mySProc->attach(this); + + if ( getProc() ) + setText( 0, QString( getProc()->getName() ) ); + setPixmap( 0, icon() ); +} + +YACSGui_SchemaViewItem::~YACSGui_SchemaViewItem() +{ + if ( mySProc ) mySProc->detach(this); +} + +YACSGui_LabelViewItem* YACSGui_SchemaViewItem::buildDataTypesTree() +{ + GuiContext* aContext = GuiContext::getCurrent(); + if ( !aContext ) + return 0; + + YACS::ENGINE::Proc* aProc = aContext->getProc(); + if ( !aProc ) + return 0; + + // Create "Data Types" label + + YACSGui_LabelViewItem* aDataTypesItem = + new YACSGui_LabelViewItem( this, 0, QObject::tr( "DT_DATA_TYPES" ) ); + + // Create "Simple" label + YACSGui_LabelViewItem* aSimpleItem = new YACSGui_LabelViewItem( aDataTypesItem, 0, QObject::tr( "DT_SIMPLE" ) ); + myRootDataTypeItems[ YACS::ENGINE::Double ] = aSimpleItem; + myRootDataTypeItems[ YACS::ENGINE::Int ] = aSimpleItem; + myRootDataTypeItems[ YACS::ENGINE::String ] = aSimpleItem; + myRootDataTypeItems[ YACS::ENGINE::Bool ] = aSimpleItem; + + // Create "Objref" label + myRootDataTypeItems[ YACS::ENGINE::Objref ] = + new YACSGui_LabelViewItem( aDataTypesItem, aSimpleItem, QObject::tr( "DT_OBJREF" ) ); + + // Create "Sequence" label + myRootDataTypeItems[ YACS::ENGINE::Sequence ] = new YACSGui_LabelViewItem( + aDataTypesItem, myRootDataTypeItems[ YACS::ENGINE::Objref ], QObject::tr( "DT_SEQUENCE" ) ); + + // Create "Array" label + myRootDataTypeItems[ YACS::ENGINE::Array ] = new YACSGui_LabelViewItem( + aDataTypesItem, myRootDataTypeItems[ YACS::ENGINE::Sequence ], QObject::tr( "DT_ARRAY" ) ); + + // Create "Struct" label + myRootDataTypeItems[ YACS::ENGINE::Struct ] = new YACSGui_LabelViewItem( + aDataTypesItem, myRootDataTypeItems[ YACS::ENGINE::Array ], QObject::tr( "DT_STRUCT" ) ); + + // Iterate through DataTypes and build tree + + std::map::iterator it; + for ( it = aContext->_mapOfSubjectDataType.begin(); + it != aContext->_mapOfSubjectDataType.end(); ++it ) + { + std::string aName = (*it).first; + YACS::HMI::SubjectDataType* aSub = (*it).second; + if ( !aSub ) + continue; + + addDataTypeItem( aSub ); + } + + return aDataTypesItem; +} + +void YACSGui_SchemaViewItem::update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSGui_SchemaViewItem::update"); + switch (event) + { + case RENAME: + update(); + case EDIT: + update(true, son); + break; + case ADD: + switch (type) + { + case BLOC: + case FOREACHLOOP: + case OPTIMIZERLOOP: + case FORLOOP: + case WHILELOOP: + case SWITCH: + case PYTHONNODE: + case PYFUNCNODE: + case CORBANODE: + case SALOMENODE: + case CPPNODE: + case SALOMEPYTHONNODE: + case PRESETNODE: + case OUTNODE: + case STUDYINNODE: + case STUDYOUTNODE: + case XMLNODE: + { + // add a node item (this = schema item) + DEBTRACE("SchemaViewItem: ADD node"); + addNodeItem(son); + } + break; + case CONTAINER: + { + // add a container item (this = schema item) + DEBTRACE("SchemaViewItem: ADD container"); + addContainerItem(son); + } + break; + case DATATYPE: + { + DEBTRACE("SchemaViewItem: ADD data type"); + addDataTypeItem( son ); + } + break; + default: + break; + } + break; + case REMOVE: + switch (type) + { + case CONTAINER: + { + // remove a container item (this = schema item) + DEBTRACE("SchemaViewItem: REMOVE container"); + removeContainerItem(son); + } + break; + case COMPONENT: + { + // remove a CORBA component item (this = schema item) + DEBTRACE("SchemaViewItem: REMOVE component"); + removeComponentItem(son); + } + break; + case DATATYPE: + { + // remove a CORBA component item (this = schema item) + DEBTRACE("SchemaViewItem: REMOVE Data type"); + removeDataTypeItem( son ); + } + break; + case DATALINK: + case CONTROLLINK: + { + // remove a link item (this = schema item) + DEBTRACE("SchemaViewItem: REMOVE link"); + removeLinkItem(son); + } + break; + case BLOC: + case FOREACHLOOP: + case OPTIMIZERLOOP: + case FORLOOP: + case WHILELOOP: + case SWITCH: + case PYTHONNODE: + case PYFUNCNODE: + case CORBANODE: + case SALOMENODE: + case CPPNODE: + case SALOMEPYTHONNODE: + case PRESETNODE: + case OUTNODE: + case STUDYINNODE: + case STUDYOUTNODE: + case XMLNODE: + { + DEBTRACE("SchemaViewItem: REMOVE"); + removeNodeItem(son); + } + default: + break; + } + break; + case ADDLINK: + case ADDCONTROLLINK: + { + // add link item (this = schema item) + DEBTRACE("SchemaViewItem: ADDLINK"); + addLinkItem(son); + } + break; + default: + GuiObserver::update(event, type, son); + } +} + +QPixmap YACSGui_SchemaViewItem::icon() const +{ + QPixmap aRes; + + QString anIconName = QString(QObject::tr("ICON_SCHEMA_OBJECT")); + if ( !anIconName.isEmpty() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", anIconName, false); + + return aRes; +} + +YACS::ENGINE::Proc* YACSGui_SchemaViewItem::getProc() const +{ + return ( mySProc ? dynamic_cast(mySProc->getNode()) : 0 ); +} + +void YACSGui_SchemaViewItem::update( const bool theIsRecursive, + YACS::HMI::Subject* theSon, + YACSGui_NodeViewItem* theBlocItem ) +{ + if ( theIsRecursive ) // total update + { + if ( SubjectNode* aNodeSon = dynamic_cast(theSon) ) // theSon is a node + { + // get the "Nodes" label view item, which is used as a parent for first level nodes + YACSGui_LabelViewItem* aNodesL = dynamic_cast(firstChild()->nextSibling()); + if ( !aNodesL || aNodesL->text(0).compare(QString("Nodes")) ) return; + + // find list view item before theSon + YACSGui_NodeViewItem* anAfter = 0; + YACSGui_NodeViewItem* anUpdated = 0; + QListViewItem* aChild = aNodesL->firstChild(); + + if ( YACSGui_NodeViewItem* aFirst = dynamic_cast(aChild) ) + if ( aFirst->getSNode() == aNodeSon ) + anUpdated = aFirst; + else + { + while( aChild ) + { + if ( YACSGui_NodeViewItem* aNext = dynamic_cast(aChild->nextSibling()) ) + if ( aNext->getSNode() == aNodeSon ) + { + anAfter = dynamic_cast(aChild); + anUpdated = aNext; + break; + } + aChild = aChild->nextSibling(); + } + } + + if ( anUpdated ) + { + if ( YACSGui_EditionTreeView* anETV = dynamic_cast(listView()) ) + { + bool anIsOpen = anUpdated->isOpen(); + + // remove list view item for theSon from the tree + aNodesL->takeItem(anUpdated); + delete anUpdated; + + // recreate list view item for theSon + if ( anUpdated = anETV->displayNodeWithPorts( aNodesL, anAfter, aNodeSon ) ) + anUpdated->setOpen(anIsOpen); + } + } + } + else if ( !theSon && theBlocItem ) // theSon is null => remove any nodes under theBlocItem + // and add these nodes under "Nodes" label + { + Bloc* aBloc = dynamic_cast( theBlocItem->getNode() ); + if ( !aBloc ) return; + + // get the "Nodes" label view item, which is used as a parent for first level nodes + YACSGui_LabelViewItem* aNodesL = dynamic_cast(firstChild()->nextSibling()); + if ( !aNodesL || aNodesL->text(0).compare(QString("Nodes")) ) return; + + QListViewItem* aChild = theBlocItem->firstChild(); + while( aChild ) + { + if ( YACSGui_NodeViewItem* aChildNodeItem = dynamic_cast(aChild) ) + if ( !aBloc->isInMyDescendance( aChildNodeItem->getNode() ) ) + { + //printf(">> Delete and insert : %s\n",aChildNodeItem->getNode()->getName().c_str()); + QListViewItem* anAuxItem = aChild->nextSibling(); + + // remove view item from theBlocItem + takeItem(aChild); + aNodesL->insertItem(aChild); + + aChild = anAuxItem; + continue; + } + + aChild = aChild->nextSibling(); + } + } + } + else if ( mySProc ) // only rename + setText( 0, QString( mySProc->getName() ) ); +} + +/*! + \brief Add data type item in tree view +*/ +void YACSGui_SchemaViewItem::addDataTypeItem( YACS::HMI::Subject* theSDataType ) +{ + YACS::HMI::SubjectDataType* aSub = + dynamic_cast( theSDataType ); + + if ( !aSub ) + return; + + GuiContext* aContext = GuiContext::getCurrent(); + if ( !aContext ) + return; + + YACS::ENGINE::Proc* aProc = aContext->getProc(); + if ( !aProc ) + return; + + std::string aName = aSub->getName(); + + if ( aProc->typeMap.find( aName ) == aProc->typeMap.end() ) + return; + + YACS::ENGINE::TypeCode* aTypeCode = aProc->typeMap[ aName ]; + if ( !aTypeCode ) + return; + + DynType aDynType = aTypeCode->kind(); + + // Create types item if necessary + if ( myRootDataTypeItems.find( aDynType ) == myRootDataTypeItems.end() ) + return; + + QListViewItem* aFatherItem = myRootDataTypeItems[ aDynType ]; + + // Create new item under aFatherItem + new YACSGui_DataTypeItem( aFatherItem, 0, aSub ); +} + + +void YACSGui_SchemaViewItem::addNodeItem( YACS::HMI::Subject* theSNode ) +{ + if ( SubjectNode* aSNode = dynamic_cast(theSNode) ) + { + // get the "Nodes" label view item, which is used as a parent for first level nodes + YACSGui_LabelViewItem* aNodesL = dynamic_cast(firstChild()->nextSibling()); + if ( !aNodesL || aNodesL->text(0).compare(QString("Nodes")) ) return; + + QListViewItem* anAfter = 0; + + if ( QListViewItem* aChild = aNodesL->firstChild() ) + { + while( aChild->nextSibling() ) + aChild = aChild->nextSibling(); + anAfter = aChild; + } + + YACSGui_NodeViewItem* aNodeItem = new YACSGui_NodeViewItem( aNodesL, anAfter, aSNode ); + + if ( SubjectComposedNode* aSCompNode = dynamic_cast(aSNode) ) + YACSGui_LabelViewItem* aLinksItem = new YACSGui_LabelViewItem( aNodeItem, 0, QObject::tr( "LINKS" ) ); + } +} + +void YACSGui_SchemaViewItem::addContainerItem( YACS::HMI::Subject* theSContainer ) +{ + if ( SubjectContainer* aSContainer = dynamic_cast(theSContainer) ) + { + // get the "Containers" label view item + YACSGui_LabelViewItem* aContainersL = dynamic_cast(firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContainersL || aContainersL->text(0).compare(QString("Containers")) ) return; + + QListViewItem* anAfter = 0; + + if ( QListViewItem* aChild = aContainersL->firstChild() ) + { + while( aChild->nextSibling() ) + aChild = aChild->nextSibling(); + anAfter = aChild; + } + + new YACSGui_ContainerViewItem( aContainersL, anAfter, aSContainer ); + } +} + +void YACSGui_SchemaViewItem::removeContainerItem( YACS::HMI::Subject* theSContainer ) +{ + if ( SubjectContainer* aSContainer = dynamic_cast(theSContainer) ) + { + // get the "Containers" label view item + YACSGui_LabelViewItem* aContainersL = dynamic_cast(firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContainersL || aContainersL->text(0).compare(QString("Containers")) ) return; + + QListViewItem* aChild = aContainersL->firstChild(); + while( aChild ) + { + if ( YACSGui_ContainerViewItem* aCont = dynamic_cast(aChild) ) + if ( aCont->getSContainer() == aSContainer ) + { + aContainersL->takeItem(aChild); + delete aChild; + break; + } + aChild = aChild->nextSibling(); + } + } +} + +void YACSGui_SchemaViewItem::removeDataTypeItem( YACS::HMI::Subject* theSDataType ) +{ + YACS::HMI::SubjectDataType* aSub = + dynamic_cast( theSDataType ); + + if ( !aSub ) + return; + + GuiContext* aContext = GuiContext::getCurrent(); + if ( !aContext ) + return; + + YACS::ENGINE::Proc* aProc = aContext->getProc(); + if ( !aProc ) + return; + + std::string aName = aSub->getName(); + + if ( aProc->typeMap.find( aName ) == aProc->typeMap.end() ) + return; + + YACS::ENGINE::TypeCode* aTypeCode = aProc->typeMap[ aName ]; + if ( !aTypeCode ) + return; + + DynType aDynType = aTypeCode->kind(); + if ( myRootDataTypeItems.find( aDynType ) == myRootDataTypeItems.end() ) + return; + + // find item corresponding to aSub + + QListViewItem* aFatherItem = myRootDataTypeItems[ aDynType ]; + + QListViewItemIterator it( aFatherItem ); + QListViewItem* toRemoveItem = 0; + while ( it.current() ) + { + YACSGui_DataTypeItem* currItem = dynamic_cast( it.current() ); + if ( currItem && currItem->getSDataType() == aSub ) + { + toRemoveItem = currItem; + break; + } + ++it; + } + + if ( !toRemoveItem ) + return; + + // remove item + + aFatherItem->takeItem( toRemoveItem ); + delete toRemoveItem; +} + +void YACSGui_SchemaViewItem::removeComponentItem( YACS::HMI::Subject* theSComponent ) +{ + // ! for CORBA components only + if ( SubjectComponent* aSComponent = dynamic_cast(theSComponent) ) + { + CORBAComponent* aCComp = dynamic_cast(aSComponent->getComponent()); + if ( !aCComp ) return; + + // get the "Containers" label view item + YACSGui_LabelViewItem* aContainersL = dynamic_cast(firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContainersL || aContainersL->text(0).compare(QString("Containers")) ) return; + + QListViewItem* aChild = aContainersL->firstChild(); + while( aChild ) + { + if ( YACSGui_ComponentViewItem* aCont = dynamic_cast(aChild) ) + if ( aCont->getSComponent() == aSComponent ) + { + aContainersL->takeItem(aChild); + delete aChild; + break; + } + aChild = aChild->nextSibling(); + } + } +} + +void YACSGui_SchemaViewItem::addLinkItem( YACS::HMI::Subject* theSLink ) +{ + DEBTRACE("YACSGui_SchemaViewItem::addLinkItem"); + SubjectLink* aSLink = dynamic_cast(theSLink); + SubjectControlLink* aSCLink = dynamic_cast(theSLink); + if ( aSLink || aSCLink ) + { + // get the "Links" label view item under the schema (root) view item + YACSGui_LabelViewItem* aLinksL = dynamic_cast(firstChild()->nextSibling()->nextSibling()); + if ( !aLinksL || aLinksL->text(0).compare(QString("Links")) ) return; + + QListViewItem* anAfter = 0; + + if ( QListViewItem* aChild = aLinksL->firstChild() ) + { + while( aChild->nextSibling() ) + aChild = aChild->nextSibling(); + anAfter = aChild; + } + + if ( aSLink ) new YACSGui_LinkViewItem( aLinksL, anAfter, aSLink ); + else if ( aSCLink ) new YACSGui_ControlLinkViewItem( aLinksL, anAfter, aSCLink ); + } +} + +// YACSGui_ContainerViewItem class: + +YACSGui_ContainerViewItem::YACSGui_ContainerViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectContainer* theSContainer ): + YACSGui_ViewItem( theParent, theAfter ), + mySContainer( theSContainer ) +{ + if ( mySContainer ) + { + mySContainer->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_ContainerViewItem::YACSGui_ContainerViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectContainer* theSContainer ): + YACSGui_ViewItem( theParent, theAfter ), + mySContainer( theSContainer ) +{ + if ( mySContainer ) + { + mySContainer->attach(this); + + QString aName = name(); + if ( !aName.isEmpty() ) + setText( 0, aName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_ContainerViewItem::~YACSGui_ContainerViewItem() +{ + if ( mySContainer ) mySContainer->detach(this); +} + +void YACSGui_ContainerViewItem::update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + //printf(">> YACSGui_ContainerViewItem::update\n"); + DEBTRACE(">> YACSGui_ContainerViewItem::update"); + switch (event) + { + case RENAME: + update(); + break; + case ADD: + switch (type) + { + case COMPONENT: + { + // add a component item (this = container item) + //printf("ContainerViewItem: ADD component\n"); + addComponentItem(son); + } + break; + default: + break; + } + break; + case REMOVE: + switch (type) + { + case COMPONENT: + { + // remove a component item (this = container item) + //printf("ContainerViewItem: REMOVE component\n"); + removeComponentItem(son); + } + break; + default: + break; + } + break; + default: + GuiObserver::update(event, type, son); + } +} + +QString YACSGui_ContainerViewItem::name() const +{ + return ( mySContainer ? QString(mySContainer->getName()) : QString("") ); +} + +QPixmap YACSGui_ContainerViewItem::icon() const +{ + QPixmap aRes; + + if ( getContainer() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", QObject::tr("ICON_CONTAINER_OBJECT")); + + return aRes; +} + +YACS::ENGINE::Container* YACSGui_ContainerViewItem::getContainer() const +{ + return ( mySContainer ? mySContainer->getContainer() : 0 ); +} + +void YACSGui_ContainerViewItem::update( YACSGui_ComponentViewItem* theComponent ) +{ + if ( theComponent ) + { + takeItem(theComponent); + + // get the "Containers" label view item + YACSGui_LabelViewItem* aContsL = + dynamic_cast(listView()->firstChild()->firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContsL || aContsL->text(0).compare(QString("Containers")) ) return; + + // find new container view item, under which theComponent view item should be moved + YACSGui_ContainerViewItem* aCont = 0; + QListViewItem* aChild = aContsL->firstChild(); + while( aChild ) + { + if ( YACSGui_ContainerViewItem* aChildContItem = dynamic_cast(aChild) ) + if ( aChildContItem->getContainer() == theComponent->getComponent()->getContainer() ) + { + aCont = aChildContItem; + break; + } + aChild = aChild->nextSibling(); + } + + if ( aCont ) aCont->insertItem(theComponent); + } + + setText( 0, name() ); // only rename +} + +void YACSGui_ContainerViewItem::addComponentItem( YACS::HMI::Subject* theSComponent ) +{ + if ( SubjectComponent* aSComponent = dynamic_cast(theSComponent) ) + { + QListViewItem* anAfter = 0; + + if ( QListViewItem* aChild = firstChild() ) + { + while( aChild->nextSibling() ) + aChild = aChild->nextSibling(); + anAfter = aChild; + } + + new YACSGui_ComponentViewItem( this, anAfter, aSComponent ); + } +} + +void YACSGui_ContainerViewItem::removeComponentItem( YACS::HMI::Subject* theSComponent ) +{ + if ( SubjectComponent* aSComponent = dynamic_cast(theSComponent) ) + { + QListViewItem* aChild = firstChild(); + while( aChild ) + { + if ( YACSGui_ComponentViewItem* aComp = dynamic_cast(aChild) ) + if ( aComp->getSComponent() == aSComponent ) + { + takeItem(aChild); + delete aChild; + break; + } + + aChild = aChild->nextSibling(); + } + } +} + +// YACSGui_ComponentViewItem class: + +YACSGui_ComponentViewItem::YACSGui_ComponentViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectComponent* theSComponent ): + YACSGui_ViewItem( theParent, theAfter ), + mySComponent( theSComponent ) +{ + if ( mySComponent ) + { + mySComponent->attach(this); + + QString anInstName = instanceName(); + if ( !anInstName.isEmpty() ) + setText( 0, anInstName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_ComponentViewItem::YACSGui_ComponentViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectComponent* theSComponent ): + YACSGui_ViewItem( theParent, theAfter ), + mySComponent( theSComponent ) +{ + if ( mySComponent ) + { + mySComponent->attach(this); + + QString anInstName = instanceName(); + if ( !anInstName.isEmpty() ) + setText( 0, anInstName ); + setPixmap( 0, icon() ); + } +} + +YACSGui_ComponentViewItem::~YACSGui_ComponentViewItem() +{ + if ( mySComponent ) mySComponent->detach(this); +} + +void YACSGui_ComponentViewItem::update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + //printf(">> YACSGui_ComponentViewItem::update\n"); + DEBTRACE(">> YACSGui_ComponentViewItem::update\n"); + switch (event) + { + case RENAME: + update(); + break; + case EDIT: + switch (type) + { + case REFERENCE: + break; + default: + update(true); + break; + } + break; + default: + GuiObserver::update(event, type, son); + } +} + +QString YACSGui_ComponentViewItem::name() const +{ + return instanceName(); +} + +QString YACSGui_ComponentViewItem::instanceName() const +{ + QString instName =""; + if (mySComponent) + instName = mySComponent->getComponent()->getInstanceName(); + return instName; +} + +QPixmap YACSGui_ComponentViewItem::icon() const +{ + QPixmap aRes; + + if ( getComponent() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", QObject::tr("ICON_COMPONENT_OBJECT")); + + return aRes; +} + +YACS::ENGINE::ComponentInstance* YACSGui_ComponentViewItem::getComponent() const +{ + return ( mySComponent ? mySComponent->getComponent() : 0 ); +} + +void YACSGui_ComponentViewItem::update( const bool theMove ) +{ + if ( theMove ) + { + // find the container view item under which this component is published now + YACSGui_ContainerViewItem* aCont = 0; + QListViewItem* aParent = parent(); + while( aParent ) + { + if ( aCont = dynamic_cast(aParent) ) + break; + aParent = aParent->parent(); + } + + if ( aCont ) aCont->update(this); + } + + setText( 0, name() ); // only rename +} + +void YACSGui_ComponentViewItem::move( YACS::HMI::Subject* theSReference ) +{ + //printf( "YACSGui_ComponentViewItem::move %s\n", theSReference->getName().c_str() ); + + SubjectServiceNode* aSServiceNode = dynamic_cast( theSReference ); + + if( aSServiceNode ) + { + ServiceNode* aServiceNode = dynamic_cast( aSServiceNode->getNode() ); + + // get the "Containers" label view item + YACSGui_LabelViewItem* aContsL = + dynamic_cast(listView()->firstChild()->firstChild()->nextSibling()->nextSibling()->nextSibling()); + if ( !aContsL || aContsL->text(0).compare(QString("Containers")) ) return; + + // find new component view item, under which theReference view item should be moved + YACSGui_ReferenceViewItem* aReference = 0; + YACSGui_ComponentViewItem* aComponent = 0; + QListViewItem* aChildContainer = aContsL->firstChild(); + while( aChildContainer ) + { + //printf( "ContainerViewItem - %s\n", aChildContainer->text(0).latin1() ); + if( YACSGui_ContainerViewItem* aChildContItem = dynamic_cast(aChildContainer) ) + { + QListViewItem* aChildComponent = aChildContItem->firstChild(); + while( aChildComponent ) + { + //printf( " ComponentViewItem - %s\n", aChildComponent->text(0).latin1() ); + if( YACSGui_ComponentViewItem* aChildCompItem = dynamic_cast(aChildComponent) ) + { + QListViewItem* aChildReference = aChildCompItem->firstChild(); + while( aChildReference ) + { + //printf( " ReferenceViewItem - %s\n", aChildReference->text(0).latin1() ); + if( YACSGui_ReferenceViewItem* aChildRefItem = dynamic_cast(aChildReference) ) + { + if( !aReference && aChildRefItem->getNode() == aServiceNode ) + aReference = aChildRefItem; + } + aChildReference = aChildReference->nextSibling(); + } + + if( !aComponent && aChildCompItem->getComponent() == aServiceNode->getComponent() ) + aComponent = aChildCompItem; + } + aChildComponent = aChildComponent->nextSibling(); + } + } + aChildContainer = aChildContainer->nextSibling(); + } + + //printf( "Reference - %s\n", aReference->name().latin1() ); + takeItem( aReference ); + if( aComponent ) + aComponent->insertItem( aReference ); + } +} + +/* ================ items for tree view in run mode ================ */ + +// YACSGui_ComposedNodeViewItem class: + +YACSGui_ComposedNodeViewItem::YACSGui_ComposedNodeViewItem(QListView *parent, + QString label, + YACS::ENGINE::ComposedNode *node) + : YACSGui_ViewItem(parent, 0), + _node(node) +{ + setText( 0, label ); + + _cf = Qt::black; + setPixmap( 0, icon() ); + + // attach to HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->attach( this ); +} + +YACSGui_ComposedNodeViewItem::YACSGui_ComposedNodeViewItem(QListViewItem *parent, + QString label, + YACS::ENGINE::ComposedNode *node) + : YACSGui_ViewItem(parent, 0), + _node(node) +{ + setText( 0, label ); + + _cf = Qt::black; + + // attach to HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->attach( this ); +} + +YACSGui_ComposedNodeViewItem::~YACSGui_ComposedNodeViewItem() +{ + // detach from HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->detach( this ); +} + +YACS::HMI::Subject* YACSGui_ComposedNodeViewItem::getSubject() const +{ + YACS::HMI::Subject* aSub = 0; + + if ( _node ) + { + GuiContext* aContext = GuiContext::getCurrent(); + if ( aContext ) + { + if ( aContext->_mapOfSubjectNode.find( _node ) != aContext->_mapOfSubjectNode.end() ) + aSub = aContext->_mapOfSubjectNode[ _node ]; + } + } + + return aSub; +} + +void YACSGui_ComposedNodeViewItem::paintCell( QPainter *p, const QColorGroup &cg, + int column, int w, int alignment ) +{ + //MESSAGE("ComposedNodeViewItem::paintCell " << column); + QColorGroup _cg( cg ); + QColor c = _cg.text(); + if (column == 1) + { + _cg.setColor( QColorGroup::Text, _cf ); + if ( dynamic_cast(getNode()) ) + _cg.setColor( QColorGroup::Background, statusBgColor() ); + } + + p->fillRect( 0, 0, w, height(), cg.brush( QColorGroup::Base ) ); + + int W = w; + if ( listView() && !listView()->allColumnsShowFocus() ) + W = width( p->fontMetrics(), listView(), column ); + + QListViewItem::paintCell( p, _cg, column, W(getNode()) ) // this veiw item is a schema (root) view item + { + QString aStatus(""); + + _state = status; + switch (_state) + { + case YACS::NOTYETINITIALIZED: aStatus = "Not Yet Initialized"; break; + case YACS::INITIALISED: aStatus = "Initialized"; break; + case YACS::RUNNING: aStatus = "Running"; break; + case YACS::WAITINGTASKS: aStatus = "Waiting Tasks"; break; + case YACS::PAUSED: aStatus = "Paused"; break; + case YACS::FINISHED: aStatus = "Finished"; break; + case YACS::STOPPED: aStatus = "Stopped"; break; + default: aStatus = "Status Unknown"; + } + setText(1,aStatus); + repaint(); + } +} + +QPixmap YACSGui_ComposedNodeViewItem::icon() const +{ + QPixmap aRes; + + QString anIconName = QString(QObject::tr("ICON_SCHEMA_OBJECT")); + if ( !anIconName.isEmpty() ) + aRes = SUIT_Session::session()->resourceMgr()->loadPixmap("YACS", anIconName, false); + + return aRes; +} + +void YACSGui_ComposedNodeViewItem::update( const bool theIsRecursive ) +{ + if ( this == listView()->firstChild() ) + { // this is a root schema object + if ( YACSGui_RunTreeView* aRTV = dynamic_cast( listView() ) ) + setText( 0, QString(aRTV->getProc()->getName()) ); + } + else + { // this is a composed node + // update state + // ... + } +} + +void YACSGui_ComposedNodeViewItem::popup(YACSGui_Executor* anExecutor,const QPoint & point) +{ + QPopupMenu menu(listView()); + menu.insertItem("Error Details",0); + menu.insertItem("Error Report",1); + if ( this == listView()->firstChild() ) + { //root schema object + menu.insertItem("Schema container log",2); + } + int id=menu.exec(point); + if(id==0) + { + std::string msg = anExecutor->getErrorDetails(getNode()); + LogViewer* log=new LogViewer(msg,listView(),"dialog",WDestructiveClose); + log->setCaption("Error Details"); + log->show(); + } + else if(id==1) + { + std::string msg = anExecutor->getErrorReport(getNode()); + LogViewer* log=new LogViewer(msg,listView(),"dialog",WDestructiveClose); + log->setCaption("Error Report"); + log->show(); + } + else if(id==2) + { + std::string msg = anExecutor->getContainerLog(); + DEBTRACE(msg); + LogViewer* log=new LogViewer(msg,listView(),"dialog",WDestructiveClose); + log->readFile(msg); + log->setCaption("Schema container log"); + log->show(); + } +} + +// YACSGui_ElementaryNodeViewItem class: + +YACSGui_ElementaryNodeViewItem::YACSGui_ElementaryNodeViewItem(QListView *parent, + const QString &text, + Type tt, + YACS::ENGINE::ElementaryNode *node) + : GuiObserver(), + QCheckListItem(parent, text, tt), + myBlockSelect( false ) +{ + _cf = Qt::green; + _node = node; + + // attach to HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->attach( this ); +} + +YACSGui_ElementaryNodeViewItem::YACSGui_ElementaryNodeViewItem(QListViewItem *parent, + const QString &text, + Type tt, + YACS::ENGINE::ElementaryNode *node) + : QCheckListItem(parent, text, tt), + myBlockSelect( false ) +{ + _cf = Qt::green; + _node = node; + + // attach to HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->attach( this ); +} + +YACSGui_ElementaryNodeViewItem::~YACSGui_ElementaryNodeViewItem() +{ + // detach from HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->detach( this ); +} + +YACS::HMI::Subject* YACSGui_ElementaryNodeViewItem::getSubject() const +{ + YACS::HMI::Subject* aSub = 0; + + if ( _node ) + { + GuiContext* aContext = GuiContext::getCurrent(); + if ( aContext ) + { + if ( aContext->_mapOfSubjectNode.find( _node ) != aContext->_mapOfSubjectNode.end() ) + aSub = aContext->_mapOfSubjectNode[ _node ]; + } + } + + return aSub; +} + +/*! + \brief Block actions performed in select() method. Usually this method is called + from select() in order to avoid circularity because of synchronization: + selection in 2D viewer --> selection in tree view --> selection in 2D viewer --> etc. + \param toBlock block selection + \return previous blocking value +*/ +bool YACSGui_ElementaryNodeViewItem::blockSelection( const bool toBlock ) +{ + bool prevVal = myBlockSelect; + myBlockSelect = toBlock; + return prevVal; +} + +/*! + \brief Verifiee whether actions performed in select() method are blocked + (see blockSelection method for more dscription) + \return blocking value +*/ +bool YACSGui_ElementaryNodeViewItem::selectionBlocked() const +{ + return myBlockSelect; +} + +/*! + \brief Selects item in tree view + \param isSelected specifies whether item has to be selected +*/ +void YACSGui_ElementaryNodeViewItem::select( bool isSelected ) +{ + if ( selectionBlocked() ) + return; + + //printf(">> YACSGui_ViewItem::select( %d ) \n", isSelected ); + + if ( !isSelected ) // do nothing + return; + + // select item in tree view + QListView* aListView = listView(); + if ( !aListView ) + return; + + blockSelection( true ); + aListView->clearSelection(); + aListView->setCurrentItem( this ); + aListView->setSelected( this, true ); + aListView->ensureItemVisible( this ); + blockSelection( false ); +} + +void YACSGui_ElementaryNodeViewItem::paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ) +{ + QColorGroup _cg( cg ); + QColor c = _cg.text(); + if (column == 1) _cg.setColor( QColorGroup::Text, _cf ); + QCheckListItem::paintCell( p, _cg, column, width, alignment ); + if (column == 1) _cg.setColor( QColorGroup::Text, c ); +} + +void YACSGui_ElementaryNodeViewItem::setState(int state) +{ + //MESSAGE("ElementaryNodeViewItem::setState: " << state); + _state = state; + switch (_state) + { + case YACS::UNDEFINED: _cf=Qt::lightGray; setText(1,"UNDEFINED"); repaint(); break; + case YACS::INVALID: _cf=Qt::red; setText(1,"INVALID"); repaint(); break; + case YACS::READY: _cf=Qt::gray; setText(1,"READY"); repaint(); break; + case YACS::TOLOAD: _cf=Qt::darkYellow; setText(1,"TOLOAD"); repaint(); break; + case YACS::LOADED: _cf=Qt::darkMagenta; setText(1,"LOADED"); repaint(); break; + case YACS::TOACTIVATE: _cf=Qt::darkCyan; setText(1,"TOACTIVATE"); repaint(); break; + case YACS::ACTIVATED: _cf=Qt::darkBlue; setText(1,"ACTIVATED"); repaint(); break; + case YACS::DESACTIVATED: _cf=Qt::gray; setText(1,"DESACTIVATED"); repaint(); break; + case YACS::DONE: _cf=Qt::darkGreen; setText(1,"DONE"); repaint(); break; + case YACS::SUSPENDED: _cf=Qt::gray; setText(1,"SUSPENDED"); repaint(); break; + case YACS::LOADFAILED: _cf.setHsv(320,255,255); setText(1,"LOADFAILED"); repaint(); break; + case YACS::EXECFAILED: _cf.setHsv( 20,255,255); setText(1,"EXECFAILED"); repaint(); break; + case YACS::PAUSE: _cf.setHsv(180,255,255); setText(1,"PAUSE"); repaint(); break; + case YACS::INTERNALERR: _cf.setHsv(340,255,255); setText(1,"INTERNALERR"); repaint(); break; + case YACS::DISABLED: _cf.setHsv( 40,255,255); setText(1,"DISABLED"); repaint(); break; + case YACS::FAILED: _cf.setHsv( 20,255,255); setText(1,"FAILED"); repaint(); break; + case YACS::ERROR: _cf.setHsv( 0,255,255); setText(1,"ERROR"); repaint(); break; + default: _cf=Qt::lightGray; repaint(); + } +} + +void YACSGui_ElementaryNodeViewItem::update( const bool theIsRecursive ) +{ + // update state + // ... +} + +void YACSGui_ElementaryNodeViewItem::popup(YACSGui_Executor* anExecutor,const QPoint & point) +{ + QPopupMenu menu(listView()); + menu.insertItem("Error Details",0); + menu.insertItem("Error Report",1); + menu.insertItem("Node container log",2); + int id=menu.exec(point); + if(id==0) + { + std::string msg = anExecutor->getErrorDetails(getNode()); + LogViewer* log=new LogViewer(msg,listView(),"dialog",WDestructiveClose); + log->setCaption("Error Details"); + log->show(); + } + else if(id==1) + { + std::string msg = anExecutor->getErrorReport(getNode()); + LogViewer* log=new LogViewer(msg,listView(),"dialog",WDestructiveClose); + log->setCaption("Error Report"); + log->show(); + } + else if(id==2) + { + std::string msg; + std::string file = anExecutor->getContainerLog(getNode()); + DEBTRACE(file); + if(file != "") + msg=file; + else + msg="This node has no container"; + LogViewer* log=new LogViewer(msg,listView(),"dialog",WDestructiveClose); + log->setCaption("Node container log"); + if(file != "") + log->readFile(file); + log->show(); + } +} diff --git a/src/gui/YACSGui_TreeViewItem.h b/src/gui/YACSGui_TreeViewItem.h new file mode 100644 index 000000000..dd397201a --- /dev/null +++ b/src/gui/YACSGui_TreeViewItem.h @@ -0,0 +1,454 @@ +// Copyright (C) 2003 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 YACSGui_TreeViewItem_HeaderFile +#define YACSGui_TreeViewItem_HeaderFile + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* ================ items for tree view in edition mode ================ */ + +class YACSGui_Executor; + +/*! + * YACS tree view item + */ +class YACSGui_ViewItem : public QListViewItem, public YACS::HMI::GuiObserver +{ +public: + YACSGui_ViewItem( QListView* theParent, + QListViewItem* theAfter ); + YACSGui_ViewItem( QListViewItem* theParent, + QListViewItem* theAfter ); + + virtual void select(bool isSelected); + //virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + // axiluary methods for blocking reaction inside select() method + bool blockSelection( const bool toBlock ); + bool selectionBlocked() const; + + virtual void update( const bool theIsRecursive = false ) {} + +protected: + void removeNodeItem( YACS::HMI::Subject* theSNode ); + void removeLinkItem( YACS::HMI::Subject* theSLink ); + +protected: + bool myBlockSelect; +}; + +/*! + * YACS label tree view item + */ +class YACSGui_LabelViewItem : public YACSGui_ViewItem +{ +public: + YACSGui_LabelViewItem( QListView* theParent, + QListViewItem* theAfter, + const QString theName ); + YACSGui_LabelViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + const QString theName ); + + virtual void select( bool isSelected ); + + QString name() const; + QPixmap icon() const; + + virtual void update( const bool theIsRecursive = false ); + +protected: + QString myName; +}; + +/*! + * YACS reference tree view item + */ +class YACSGui_ReferenceViewItem : public YACSGui_ViewItem +{ +public: + typedef enum { Text, HighlightedText, Highlight } ColorRole; + + YACSGui_ReferenceViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectReference* theSReference ); + YACSGui_ReferenceViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectReference* theSReference ); + virtual ~YACSGui_ReferenceViewItem(); + + virtual void select(bool isSelected); + virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + QString name() const; + QPixmap icon() const; + QColor color( const ColorRole = Text ) const; + + YACS::ENGINE::Node* getNode() const; + YACS::HMI::SubjectReference* getSReference() const { return mySReference; } + + virtual void paintCell( QPainter* p, const QColorGroup& cg, int c, int w, int align ); + + virtual void update( const bool theIsRecursive = false ); + +private: + YACS::HMI::SubjectReference* mySReference; +}; + +/*! + * YACS tree view item for port + */ +class YACSGui_PortViewItem : public YACSGui_ViewItem +{ +public: + YACSGui_PortViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectDataPort* theSPort ); + YACSGui_PortViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectDataPort* theSPort ); + virtual ~YACSGui_PortViewItem(); + + QString name() const; + QPixmap icon() const; + + YACS::ENGINE::DataPort* getPort() const; + YACS::HMI::SubjectDataPort* getSPort() const { return mySPort; } + + virtual void update( const bool theIsRecursive = false ); + +private: + YACS::HMI::SubjectDataPort* mySPort; +}; + +/*! + * YACS tree view item for node + */ +class YACSGui_NodeViewItem : public YACSGui_ViewItem +{ +public: + typedef enum { Text, HighlightedText, Highlight } ColorRole; + + YACSGui_NodeViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectNode* theSNode ); + YACSGui_NodeViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectNode* theSNode ); + virtual ~YACSGui_NodeViewItem(); + + virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + QString name() const; + QPixmap icon() const; + + static QPixmap icon( YACS::ENGINE::Node* ); + + YACS::ENGINE::Node* getNode() const; + YACS::HMI::SubjectNode* getSNode() const { return mySNode; } + + virtual void update( const bool theIsRecursive = false ); + +private: + void renamePortItem( YACS::HMI::Subject* theSPort ); + void addPortItem( YACS::HMI::Subject* theSPort ); + void removePortItem( YACS::HMI::Subject* theSPort ); + void addNodeItem( YACS::HMI::Subject* theSNode ); + void moveUpPortItem( YACS::HMI::Subject* theSPort ); + void moveDownPortItem( YACS::HMI::Subject* theSPort ); + bool isPublished( YACS::ENGINE::Port* thePort ); + + void addReferenceItem( YACS::HMI::Subject* theSRef ); + void removeReferenceItem( YACS::HMI::Subject* theSRef ); + + void addLinkItem( YACS::HMI::Subject* theSLink ); + + YACS::HMI::SubjectNode* mySNode; +}; + +/*! + * YACS tree view item for data link + */ +class YACSGui_LinkViewItem : public YACSGui_ViewItem +{ +public: + YACSGui_LinkViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectLink* theSLink ); + YACSGui_LinkViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectLink* theSLink ); + virtual ~YACSGui_LinkViewItem(); + + QString name() const; + QPixmap icon() const; + + YACS::HMI::SubjectLink* getSLink() const { return mySLink; } + + virtual void update( const bool theIsRecursive = false ); + +private: + YACS::HMI::SubjectLink* mySLink; +}; + +/*! + * YACS tree view item for control link + */ +class YACSGui_ControlLinkViewItem : public YACSGui_ViewItem +{ +public: + YACSGui_ControlLinkViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectControlLink* theSLink ); + YACSGui_ControlLinkViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectControlLink* theSLink ); + virtual ~YACSGui_ControlLinkViewItem(); + + QString name() const; + QPixmap icon() const; + + YACS::HMI::SubjectControlLink* getSLink() const { return mySLink; } + + virtual void update( const bool theIsRecursive = false ); + +private: + YACS::HMI::SubjectControlLink* mySLink; +}; + +/*! + * YACS tree view item for schema + */ +class YACSGui_SchemaViewItem : public YACSGui_ViewItem +{ +public: + YACSGui_SchemaViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectProc* theSProc ); + YACSGui_SchemaViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectProc* theSProc ); + virtual ~YACSGui_SchemaViewItem(); + + virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + QPixmap icon() const; + + YACS::ENGINE::Proc* getProc() const; + YACS::HMI::SubjectProc* getSProc() const { return mySProc; } + + virtual void update( const bool theIsRecursive = false, + YACS::HMI::Subject* theSon = 0, + YACSGui_NodeViewItem* theBlocItem = 0 ); + + YACSGui_LabelViewItem* buildDataTypesTree(); + +private: + void addNodeItem( YACS::HMI::Subject* theSNode ); + void addContainerItem( YACS::HMI::Subject* theSContainer ); + void removeContainerItem( YACS::HMI::Subject* theSContainer ); + void removeComponentItem( YACS::HMI::Subject* theSComponent ); + void addDataTypeItem( YACS::HMI::Subject* theSDataType ); + void removeDataTypeItem( YACS::HMI::Subject* theSDataType ); + + void addLinkItem( YACS::HMI::Subject* theSLink ); + + YACS::HMI::SubjectProc* mySProc; + + std::map< YACS::ENGINE::DynType, QListViewItem* > myRootDataTypeItems; + +}; + +class YACSGui_ComponentViewItem; +/*! + * YACS tree view item for container + */ +class YACSGui_ContainerViewItem : public YACSGui_ViewItem +{ +public: + YACSGui_ContainerViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectContainer* theSContainer = 0 ); + YACSGui_ContainerViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectContainer* theSContainer = 0 ); + virtual ~YACSGui_ContainerViewItem(); + + virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + QString name() const; + QPixmap icon() const; + + YACS::ENGINE::Container* getContainer() const; + YACS::HMI::SubjectContainer* getSContainer() const { return mySContainer; } + + virtual void update( YACSGui_ComponentViewItem* theComponent = 0 ); + + void addComponentItem( YACS::HMI::Subject* theSComponent ); + +private: + void removeComponentItem( YACS::HMI::Subject* theSComponent ); + + YACS::HMI::SubjectContainer* mySContainer; +}; + +/*! + * YACS tree view item for component + */ +class YACSGui_ComponentViewItem : public YACSGui_ViewItem +{ +public: + YACSGui_ComponentViewItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectComponent* theSComponent = 0 ); + YACSGui_ComponentViewItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectComponent* theSComponent = 0 ); + + virtual ~YACSGui_ComponentViewItem(); + + virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + QString name() const; + QString instanceName() const; + QPixmap icon() const; + + YACS::ENGINE::ComponentInstance* getComponent() const; + YACS::HMI::SubjectComponent* getSComponent() const { return mySComponent; } + + virtual void update( const bool theMove = false ); + virtual void move( YACS::HMI::Subject* theSReference ); + +private: + YACS::HMI::SubjectComponent* mySComponent; +}; + +/*! + * YACS tree view item for data type + */ +class YACSGui_DataTypeItem : public YACSGui_ViewItem +{ +public: + //typedef enum { Text, HighlightedText, Highlight } ColorRole; + + YACSGui_DataTypeItem( QListView* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectDataType* theSDataType ); + YACSGui_DataTypeItem( QListViewItem* theParent, + QListViewItem* theAfter, + YACS::HMI::SubjectDataType* theSDataType ); + virtual ~YACSGui_DataTypeItem(); + + virtual void update(YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + QString name() const; + static QPixmap icon(); + + YACS::HMI::SubjectDataType* getSDataType() const { return mySDataType; } + + virtual void update( const bool theIsRecursive = false ); + +private: + YACS::HMI::SubjectDataType* mySDataType; +}; + +/* ================ items for tree view in run mode ================ */ + + +class YACSGui_ComposedNodeViewItem: public YACSGui_ViewItem +{ + public: + YACSGui_ComposedNodeViewItem(QListView *parent, + QString label, + YACS::ENGINE::ComposedNode *node = 0); + YACSGui_ComposedNodeViewItem(QListViewItem *parent, + QString label, + YACS::ENGINE::ComposedNode *node = 0); + virtual ~YACSGui_ComposedNodeViewItem(); + + void setState(int state); + void setStatus(int status); + virtual void paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ); + QColor statusBgColor() const; + YACS::ENGINE::ComposedNode* getNode() {return _node;}; + + QPixmap icon() const; + + void update( const bool theIsRecursive = false ); + + YACS::HMI::Subject* getSubject() const; + void popup(YACSGui_Executor* anExecutor,const QPoint & point); + + protected: + int _state; + QColor _cf; + YACS::ENGINE::ComposedNode *_node; +}; + +class YACSGui_ElementaryNodeViewItem: public QCheckListItem, + public YACS::HMI::GuiObserver +{ + public: + YACSGui_ElementaryNodeViewItem(QListView *parent, + const QString &text, + Type tt = RadioButtonController, + YACS::ENGINE::ElementaryNode *node = 0); + YACSGui_ElementaryNodeViewItem(QListViewItem *parent, + const QString &text, + Type tt = RadioButtonController, + YACS::ENGINE::ElementaryNode *node = 0); + virtual ~YACSGui_ElementaryNodeViewItem(); + + void setState(int state); + virtual void paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ); + YACS::ENGINE::ElementaryNode* getNode() {return _node;}; + + virtual void select(bool isSelected); + + void update( const bool theIsRecursive = false ); + + // axiluary methods for blocking reaction inside select() method + bool blockSelection( const bool toBlock ); + bool selectionBlocked() const; + + YACS::HMI::Subject* getSubject() const; + void popup(YACSGui_Executor* anExecutor,const QPoint & point); + + protected: + int _state; + QColor _cf; + YACS::ENGINE::ElementaryNode *_node; + + bool myBlockSelect; +}; + +#endif diff --git a/src/gui/YACSGui_WhileLoopNodePage.cxx b/src/gui/YACSGui_WhileLoopNodePage.cxx new file mode 100644 index 000000000..7a62dc56b --- /dev/null +++ b/src/gui/YACSGui_WhileLoopNodePage.cxx @@ -0,0 +1,325 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_WhileLoopNodePage + Description : Page for WHILE node properties +*/ + +YACSGui_WhileLoopNodePage::YACSGui_WhileLoopNodePage( QWidget* theParent, const char* theName, WFlags theFlags ) + : WhileLoopNodePage( theParent, theName, theFlags ), + YACSGui_NodePage() +{ + // TODO: implement presentation of the FOR node in collapsed mode + // temporary solution : + myCollapsedRadioButton->setEnabled(false ); + + connect( myNodeName, SIGNAL(textChanged( const QString& )), this, SLOT(onNodeNameChanged( const QString& )) ); +} + +YACSGui_WhileLoopNodePage::~YACSGui_WhileLoopNodePage() +{ + if (getInputPanel()) getInputPanel()->removePage(this); +} + +void YACSGui_WhileLoopNodePage::setSNode( YACS::HMI::SubjectNode* theSNode ) +{ + if ( !theSNode ) return; + + if ( dynamic_cast( theSNode->getNode() ) ) + YACSGui_NodePage::setSNode( theSNode ); +} + +void YACSGui_WhileLoopNodePage::setMode( const YACSGui_InputPanel::PageMode theMode ) +{ + YACSGui_NodePage::setMode(theMode); + + if ( myMode == YACSGui_InputPanel::EditMode ) + { + myNodeName->setReadOnly(false); + ViewModeButtonGroup->show(); + + ExecutionGroupBox->hide(); + } + else if ( myMode == YACSGui_InputPanel::RunMode ) + { + myNodeName->setReadOnly(true); + ViewModeButtonGroup->hide(); + + ExecutionGroupBox->show(); + } +} + +void YACSGui_WhileLoopNodePage::notifyNodeStatus( int theStatus ) +{ + if ( myNodeState ) + { + myNodeState->setPaletteForegroundColor(getColor(theStatus)); + myNodeState->setText(getText(theStatus)); + } +} + +void YACSGui_WhileLoopNodePage::notifyNodeProgress() +{ + if ( myProgressBar ) + { + Proc* aProc = dynamic_cast(getNode()->getRootNode()); + if ( !aProc ) return; + + YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( aProc ); + if ( !aGraph ) return; + + if ( YACSPrs_ElementaryNode* anItem = aGraph->getItem(getNode()) ) + { + int aProgress = (int)( ( (anItem->getStoredPercentage() < 0) ? anItem->getPercentage() : + anItem->getStoredPercentage() ) ); + myProgressBar->setProgress(aProgress); + } + } +} + +void YACSGui_WhileLoopNodePage::notifyInPortValues( std::map theInPortName2Value ) +{ + //printf("==> WhileLoopNodePage : Size of theInPortName2Value : %d\n",theInPortName2Value.size()); + + WhileLoop* aWhileLoopNode = dynamic_cast( getNode() ); + if ( !aWhileLoopNode ) return; + + if ( theInPortName2Value.size() == 1 ) + { + QString aName(aWhileLoopNode->edGetConditionPort()->getName()); + map::iterator it = theInPortName2Value.begin(); + QString aGivenName( (*it).first ); + if ( !aGivenName.compare(aName) && myCondInputPortValue ) + { + QString aValue( (*it).second ); + int anId = 0; + if ( !aValue.compare(QString("< ? >")) || + aValue.compare(QString("false")) || + !aValue.toInt() ) + anId = 1; + myCondInputPortValue->setCurrentItem(anId); + } + } +} + +void YACSGui_WhileLoopNodePage::notifyOutPortValues( std::map theOutPortName2Value ) +{ + //printf("==> WhileLoopNodePage : Size of theOutPortName2Value : %d\n",theOutPortName2Value.size()); +} + +void YACSGui_WhileLoopNodePage::notifyNodeCreateBody( YACS::HMI::Subject* theSubject ) +{ + if( myLoopBodyNodeName ) + { + QString aBodyName = theSubject->getName(); + myLoopBodyNodeName->setText( aBodyName ); + } +} + +void YACSGui_WhileLoopNodePage::checkModifications() +{ + if ( !getNode() ) return; + + // 1) check if the content of the page is really modified (in compare with the content of engine object) + bool isModified = false; + + if ( myNodeName->text().compare(getNodeName()) != 0 ) isModified = true; + else if ( YACS::ENGINE::WhileLoop* aWhileLoopNode = dynamic_cast( getNode() ) ) + if( YACS::ENGINE::InputPort* aPort = aWhileLoopNode->edGetConditionPort() ) + { + QString aValue = getPortValue( aPort ); + int anIndex = aValue == "True" ? 0 : 1; + if( myCondInputPortValue->currentItem() != anIndex ) isModified = true; + } + + //if ( !isModified ) + // TODO: compare view mode: expanded or collapsed (not yet in use) + + // 2) if yes, show a warning message: Apply or Cancel + if ( isModified ) + if ( SUIT_MessageBox::warn2(getInputPanel()->getModule()->getApp()->desktop(), + tr("WRN_WARNING"), + tr("APPLY_CANCEL_MODIFICATIONS"), + tr("BUT_YES"), tr("BUT_NO"), 0, 1, 0) == 0 ) + { + onApply(); + if ( getInputPanel() ) getInputPanel()->emitApply(YACSGui_InputPanel::InlineNodeId); + } +} + +void YACSGui_WhileLoopNodePage::onApply() +{ + // Rename a node + if ( myNodeName ) setNodeName( myNodeName->text() ); + + // Reset condition input port value + if ( YACS::ENGINE::WhileLoop* aWhileLoopNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aPort = aWhileLoopNode->edGetConditionPort() ) + { + bool aValue = myCondInputPortValue->currentItem() == 0 ? true : false; + aPort->edInit( aValue ); + mySNode->update( EDIT, INPUTPORT, GuiContext::getCurrent()->_mapOfSubjectDataPort[aPort] ); + } + } + + // Reset the view mode + // ... + + updateBlocSize(); +} + +void YACSGui_WhileLoopNodePage::updateState() +{ + // Set node name + if ( myNodeName ) myNodeName->setText( getNodeName() ); + + // Set node full name (read only) + if ( myNodeFullName ) + myNodeFullName->setText( getNode()->getRootNode()->getChildName(getNode()) ); + + // Set condition input port value and loop body node name + if ( YACS::ENGINE::WhileLoop* aWhileLoopNode = dynamic_cast( getNode() ) ) + { + if( YACS::ENGINE::InputPort* aPort = aWhileLoopNode->edGetConditionPort() ) + { + QString aValue = getPortValue( aPort ); + int anIndex = aValue == "True" ? 0 : 1; + myCondInputPortValue->setCurrentItem( anIndex ); + } + + if( myLoopBodyNodeName ) + { + std::list aNodes = aWhileLoopNode->edGetDirectDescendants(); + if ( !aNodes.empty() ) + { + QString aBodyName; + + std::list::iterator aNodesIt = aNodes.begin(); + Node* aNode = *aNodesIt; + if( aNode ) + aBodyName = aNode->getName(); + + myLoopBodyNodeName->setText( aBodyName ); + } + } + } + + // Set view mode of the given WHILE node + // the following method can be used if its needed: + // YACSGui_Graph* aGraph = getInputPanel()->getModule()->getGraph( myProc ); + // ... +} + +void YACSGui_WhileLoopNodePage::onNodeNameChanged( const QString& theName ) +{ + if ( myNodeFullName ) + { + QString anOldName = myNodeFullName->text(); + int aRDotId = anOldName.findRev('.'); + myNodeFullName->setText( anOldName.replace( aRDotId+1, anOldName.length()-(aRDotId+1), theName ) ); + } +} + diff --git a/src/gui/YACSGui_XMLDriver.cxx b/src/gui/YACSGui_XMLDriver.cxx index c225dfbe7..f26aac26f 100644 --- a/src/gui/YACSGui_XMLDriver.cxx +++ b/src/gui/YACSGui_XMLDriver.cxx @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include @@ -17,6 +19,9 @@ #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; using namespace std; @@ -27,7 +32,7 @@ static prslinktype_parser prslink_parser; void prslinktype_parser::onStart(const XML_Char* el, const XML_Char** attr) { - std::cerr << "prslinktype_parser::onStart: " << el << std::endl; + DEBTRACE("prslinktype_parser::onStart: " << el ); std::string element(el); parser* pp=&main_parser; if(element == "point") pp = &point_parser; @@ -38,8 +43,8 @@ void prslinktype_parser::onStart(const XML_Char* el, const XML_Char** attr) } YACSGui_VisitorSaveSchema::YACSGui_VisitorSaveSchema(YACSGui_Module* module, - ComposedNode *root) - : VisitorSaveSchema(root), myModule(module) + ComposedNode *root) + : VisitorSaveSalomeSchema(root), myModule(module) { } @@ -60,11 +65,18 @@ void YACSGui_VisitorSaveSchema::writePresentation(Proc *proc) if ( !aGraph || !aGraph->getCanvas() ) return; + QxGraph_CanvasView* aCV = myModule->getViewWindow(proc)->getViewModel()->getCurrentView(); + if ( !aCV ) return; + int depth = 1; _out << indent(depth) << "getCanvas()->width() << "\""; _out << " height=\"" << aGraph->getCanvas()->height() << "\""; + _out << " left=\"" << aCV->contentsX() << "\""; + _out << " top=\"" << aCV->contentsY() << "\""; + _out << " xscale=\"" << aCV->worldMatrix().m11() << "\""; + _out << " yscale=\"" << aCV->worldMatrix().m22() << "\""; _out << "/>" << endl; set nodeSet = getAllNodes(proc); @@ -109,36 +121,36 @@ void YACSGui_VisitorSaveSchema::writeLinks(YACS::ENGINE::Proc *proc) { YACSPrs_InOutPort* anIOPort; if ( ( anIOPort = dynamic_cast( aPort ) ) && !anIOPort->isInput() - || - dynamic_cast( aPort ) ) + || + dynamic_cast( aPort ) ) { // this port is an output port => iterates on its links - list aLinks = aPort->getLinks(); - for(list::iterator itL = aLinks.begin(); itL != aLinks.end(); itL++) - { - _out << indent(depth) << "( *itL ) ) { - _out << " fromnode=\"" << proc->getChildName( aNode ) << "\""; - _out << " fromport=\"" << aPort->getName() << "\""; - _out << " tonode=\"" << proc->getChildName( aPL->getInputPort()->getEngine()->getNode() ) << "\""; - _out << " toport=\"" << aPL->getInputPort()->getName() << "\""; - } - else if ( YACSPrs_LabelLink* aLL = dynamic_cast( *itL ) ) { - _out << " tonode=\"" << proc->getChildName( aLL->getSlaveNode()->getEngine() ) << "\""; - } - - _out << ">" << endl; - - list aPoints = (*itL)->getPoints(); - for(list::iterator itP = aPoints.begin(); itP != aPoints.end(); itP++) { - _out << indent(depth+1) << "" << endl; - } - - _out << indent(depth) << "" << endl; - } + list aLinks = aPort->getLinks(); + for(list::iterator itL = aLinks.begin(); itL != aLinks.end(); itL++) + { + _out << indent(depth) << "( *itL ) ) { + _out << " fromnode=\"" << proc->getChildName( aNode ) << "\""; + _out << " fromport=\"" << aPort->getName() << "\""; + _out << " tonode=\"" << proc->getChildName( aPL->getInputPort()->getEngine()->getNode() ) << "\""; + _out << " toport=\"" << aPL->getInputPort()->getName() << "\""; + } + else if ( YACSPrs_LabelLink* aLL = dynamic_cast( *itL ) ) { + _out << " tonode=\"" << proc->getChildName( aLL->getSlaveNode()->getEngine() ) << "\""; + } + + _out << ">" << endl; + + list aPoints = (*itL)->getPoints(); + for(list::iterator itP = aPoints.begin(); itP != aPoints.end(); itP++) { + _out << indent(depth+1) << "" << endl; + } + + _out << indent(depth) << "" << endl; + } } } } @@ -147,11 +159,10 @@ void YACSGui_VisitorSaveSchema::writeLinks(YACS::ENGINE::Proc *proc) YACSGui_Loader::YACSGui_Loader() : YACSLoader() { - _defaultParsersMap.clear(); - presentation_parser.collector_ = this; prslink_parser.collector_ = this; + canvas_parser.pre(); _defaultParsersMap.insert(make_pair("canvas",&canvas_parser)); _defaultParsersMap.insert(make_pair("presentation",&presentation_parser)); _defaultParsersMap.insert(make_pair("point",&point_parser)); @@ -162,7 +173,10 @@ YACSGui_Loader::~YACSGui_Loader() { } -const YACSGui_Loader::PrsDataMap& YACSGui_Loader::getPrsData(Proc* proc, int& width, int& height) +const YACSGui_Loader::PrsDataMap& YACSGui_Loader::getPrsData(Proc* proc, + int& width, int& height, + int& left, int& top, + double& xscale, double& yscale) { myPrsMap.clear(); @@ -173,6 +187,10 @@ const YACSGui_Loader::PrsDataMap& YACSGui_Loader::getPrsData(Proc* proc, int& wi // get information from canvastype_parser width = ((canvastype_parser*)_defaultParsersMap["canvas"])->width_; height = ((canvastype_parser*)_defaultParsersMap["canvas"])->height_; + left = ((canvastype_parser*)_defaultParsersMap["canvas"])->left_; + top = ((canvastype_parser*)_defaultParsersMap["canvas"])->top_; + xscale = ((canvastype_parser*)_defaultParsersMap["canvas"])->xscale_; + yscale = ((canvastype_parser*)_defaultParsersMap["canvas"])->yscale_; for ( InputMap::iterator it = myInputMap.begin(); it != myInputMap.end(); it++ ) { @@ -240,23 +258,23 @@ void YACSGui_Loader::process(std::string theElement, bool theNewLink) prslinktype_parser* aP = (prslinktype_parser*)_defaultParsersMap["prslink"]; if ( aP->type() == "portlink" ) { - if ( theNewLink ) { - PortLinkData aPLData(aP->fromnode_,aP->fromport_,aP->tonode_,aP->toport_); - //aPLData.fillPoints(aP->points_); - myInputPLList.push_back(aPLData); - } - else if ( !myInputPLList.empty() ) - myInputPLList.back().appendPoint(aP->points_.back()); + if ( theNewLink ) { + PortLinkData aPLData(aP->fromnode_,aP->fromport_,aP->tonode_,aP->toport_); + //aPLData.fillPoints(aP->points_); + myInputPLList.push_back(aPLData); + } + else if ( !myInputPLList.empty() ) + myInputPLList.back().appendPoint(aP->points_.back()); } else if ( aP->type() == "labellink" ) { - if ( theNewLink ) { - LabelLinkData aLLData(aP->tonode_); - //aLLData.fillPoints(aP->points_); - myInputLLList.push_back(aLLData); - } - else if ( !myInputLLList.empty() ) - myInputLLList.back().appendPoint(aP->points_.back()); + if ( theNewLink ) { + LabelLinkData aLLData(aP->tonode_); + //aLLData.fillPoints(aP->points_); + myInputLLList.push_back(aLLData); + } + else if ( !myInputLLList.empty() ) + myInputLLList.back().appendPoint(aP->points_.back()); } } } diff --git a/src/gui/YACSGui_XMLDriver.h b/src/gui/YACSGui_XMLDriver.h index 270ef4759..482dfcd78 100644 --- a/src/gui/YACSGui_XMLDriver.h +++ b/src/gui/YACSGui_XMLDriver.h @@ -3,18 +3,20 @@ #include #include -#include +#include #include #include +using YACS::parser; + class YACSGui_Module; /*! - * Class that extends engine XML wirter capabilities by + * Class that extends engine XML writer capabilities by * adding information about node presentations to the output file. */ -class YACSGui_VisitorSaveSchema : public YACS::ENGINE::VisitorSaveSchema +class YACSGui_VisitorSaveSchema : public YACS::ENGINE::VisitorSaveSalomeSchema { public: YACSGui_VisitorSaveSchema(YACSGui_Module* module, YACS::ENGINE::ComposedNode *root); @@ -44,13 +46,13 @@ public: PrsData() { x = y = z = 0.; width = height = 1.; } PrsData(float theX, float theY, float theZ, - float theWidth, float theHeight) + float theWidth, float theHeight) { - x = theX; + x = theX; y = theY; - z = theZ; - width = theWidth; - height = theHeight; + z = theZ; + width = theWidth; + height = theHeight; } }; @@ -63,13 +65,13 @@ public: LinkData() { points = std::list(0); } void appendPoint(QPoint thePoint) { - points.push_back( thePoint ); + points.push_back( thePoint ); } void fillPoints(std::list theList) { - points.clear(); - for (std::list::iterator it = theList.begin(); it != theList.end(); ++it) - points.push_back( *it ); + points.clear(); + for (std::list::iterator it = theList.begin(); it != theList.end(); ++it) + points.push_back( *it ); } }; @@ -79,12 +81,12 @@ public: PortLinkData():LinkData() { fromnode = fromport = tonode = toport = ""; } PortLinkData(std::string theFromnode, std::string theFromport, - std::string theTonode, std::string theToport):LinkData() + std::string theTonode, std::string theToport):LinkData() { - fromnode = theFromnode; - fromport = theFromport; - tonode = theTonode; - toport = theToport; + fromnode = theFromnode; + fromport = theFromport; + tonode = theTonode; + toport = theToport; } }; @@ -95,7 +97,7 @@ public: LabelLinkData():LinkData() { slavenode = ""; } LabelLinkData(std::string theSlavenode):LinkData() { - slavenode = theSlavenode; + slavenode = theSlavenode; } }; @@ -107,7 +109,7 @@ public: YACSGui_Loader(); virtual ~YACSGui_Loader(); - const PrsDataMap& getPrsData(YACS::ENGINE::Proc* proc, int&, int&); + const PrsDataMap& getPrsData(YACS::ENGINE::Proc* proc, int&, int&, int&, int&, double&, double&); const PortLinkDataMap& getPortLinkData(YACS::ENGINE::Proc* proc); const LabelLinkDataMap& getLabelLinkData(YACS::ENGINE::Proc* proc); @@ -136,7 +138,6 @@ struct canvastype_parser: parser { virtual void onStart(const XML_Char* el, const XML_Char** attr) { - std::cerr << "canvastype_parser::onStart: " << el << std::endl; std::string element(el); parser* pp=&main_parser; SetUserDataAndPush(pp); @@ -149,17 +150,26 @@ struct canvastype_parser: parser { required("width",attr); required("height",attr); + required("left",attr); + required("top",attr); + required("xscale",attr); + required("yscale",attr); for (int i = 0; attr[i]; i += 2) { - std::cerr << attr[i] << "=" << attr[i + 1] << std::endl; - if(std::string(attr[i]) == "width") width(attr[i+1]); - if(std::string(attr[i]) == "height") height(attr[i+1]); + if(std::string(attr[i]) == "width") width(attr[i+1]); + if(std::string(attr[i]) == "height") height(attr[i+1]); + if(std::string(attr[i]) == "left") left(attr[i+1]); + if(std::string(attr[i]) == "top") top(attr[i+1]); + if(std::string(attr[i]) == "xscale") xscale(attr[i+1]); + if(std::string(attr[i]) == "yscale") yscale(attr[i+1]); } } virtual void pre () { width_ = height_ = 1; + left_ = top_ = 0; + xscale_ = yscale_ = -1; } virtual void width(const std::string& width) @@ -172,7 +182,28 @@ struct canvastype_parser: parser height_ = QString( height ).toInt(); } - int width_, height_; + virtual void left(const std::string& left) + { + left_ = QString( left ).toInt(); + } + + virtual void top(const std::string& top) + { + top_ = QString( top ).toInt(); + } + + virtual void xscale(const std::string& xscale) + { + xscale_ = QString( xscale ).toDouble(); + } + + virtual void yscale(const std::string& yscale) + { + yscale_ = QString( yscale ).toDouble(); + } + + int width_, height_, left_, top_; + double xscale_, yscale_; }; /*! @@ -187,7 +218,6 @@ struct presentationtype_parser: parser virtual void onStart(const XML_Char* el, const XML_Char** attr) { - std::cerr << "presentationtype_parser::onStart: " << el << std::endl; std::string element(el); parser* pp=&main_parser; SetUserDataAndPush(pp); @@ -206,17 +236,16 @@ struct presentationtype_parser: parser required("height",attr); for (int i = 0; attr[i]; i += 2) { - std::cerr << attr[i] << "=" << attr[i + 1] << std::endl; - if(std::string(attr[i]) == "name") name(attr[i+1]); - if(std::string(attr[i]) == "x") x(attr[i+1]); - if(std::string(attr[i]) == "y") y(attr[i+1]); - if(std::string(attr[i]) == "z") z(attr[i+1]); - if(std::string(attr[i]) == "width") width(attr[i+1]); - if(std::string(attr[i]) == "height") height(attr[i+1]); + if(std::string(attr[i]) == "name") name(attr[i+1]); + if(std::string(attr[i]) == "x") x(attr[i+1]); + if(std::string(attr[i]) == "y") y(attr[i+1]); + if(std::string(attr[i]) == "z") z(attr[i+1]); + if(std::string(attr[i]) == "width") width(attr[i+1]); + if(std::string(attr[i]) == "height") height(attr[i+1]); } if ( collector_ ) - collector_->process("presentation"); + collector_->process("presentation"); } virtual void pre () @@ -270,7 +299,6 @@ struct pointtype_parser: parser { virtual void onStart(const XML_Char* el, const XML_Char** attr) { - std::cerr << "pointtype_parser::onStart: " << el << std::endl; std::string element(el); parser* pp=&main_parser; SetUserDataAndPush(pp); @@ -285,9 +313,8 @@ struct pointtype_parser: parser required("y",attr); for (int i = 0; attr[i]; i += 2) { - std::cerr << attr[i] << "=" << attr[i + 1] << std::endl; - if(std::string(attr[i]) == "x") x(attr[i+1]); - if(std::string(attr[i]) == "y") y(attr[i+1]); + if(std::string(attr[i]) == "x") x(attr[i+1]); + if(std::string(attr[i]) == "y") y(attr[i+1]); } } @@ -329,7 +356,6 @@ struct prslinktype_parser: parser virtual void onEnd(const char *el,parser* child) { - std::cerr << "prslinktype_parser::onEnd: " << el << std::endl; std::string element(el); if(element == "point") point(((pointtype_parser*)child)->post()); } @@ -339,22 +365,21 @@ struct prslinktype_parser: parser required("tonode",attr); for (int i = 0; attr[i]; i += 2) { - std::cerr << attr[i] << "=" << attr[i + 1] << std::endl; - if(std::string(attr[i]) == "fromnode") fromnode(attr[i+1]); - if(std::string(attr[i]) == "fromport") fromport(attr[i+1]); - if(std::string(attr[i]) == "tonode") tonode(attr[i+1]); - if(std::string(attr[i]) == "toport") toport(attr[i+1]); + if(std::string(attr[i]) == "fromnode") fromnode(attr[i+1]); + if(std::string(attr[i]) == "fromport") fromport(attr[i+1]); + if(std::string(attr[i]) == "tonode") tonode(attr[i+1]); + if(std::string(attr[i]) == "toport") toport(attr[i+1]); } if ( collector_ ) - collector_->process("prslink", true); + collector_->process("prslink", true); } virtual void point(const QPoint& thePoint) { points_.push_back(thePoint); if ( collector_ ) - collector_->process("prslink"); + collector_->process("prslink"); } virtual void pre () @@ -386,9 +411,9 @@ struct prslinktype_parser: parser { std::string aType = ""; if ( fromnode_ != "" && fromport_ != "" && tonode_ != "" && toport_ != "" ) - aType = "portlink"; + aType = "portlink"; else if ( fromnode_ == "" && fromport_ == "" && tonode_ != "" && toport_ == "" ) - aType = "labellink"; + aType = "labellink"; return aType; } diff --git a/src/gui/YACSGui_YACSORBContainerDialog.cxx b/src/gui/YACSGui_YACSORBContainerDialog.cxx new file mode 100644 index 000000000..6060d7ac7 --- /dev/null +++ b/src/gui/YACSGui_YACSORBContainerDialog.cxx @@ -0,0 +1,279 @@ +// Copyright (C) 2003 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 +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SPACING 5 +#define MARGIN 5 + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; +using namespace std; + + +/* + Class : YACSGui_YACSORBContainerDialog + Description : Page for container properties +*/ + +YACSGui_YACSORBContainerDialog::YACSGui_YACSORBContainerDialog( QWidget* theParent, const char* theName, WFlags theFlags ) + : QDialog( theParent, theName, true, theFlags ) +{ + setCaption(theName); + + QVBoxLayout* aTopLayout = new QVBoxLayout( this ); + aTopLayout->setSpacing( 6 ); + aTopLayout->setMargin( 11 ); + + myPage = new ContainerPage(this); + + QGroupBox* aGrpBtns = new QGroupBox( this, "GroupButtons" ); + aGrpBtns->setColumnLayout(0, Qt::Vertical ); + aGrpBtns->layout()->setSpacing( 0 ); aGrpBtns->layout()->setMargin( 0 ); + aGrpBtns->setFrameStyle( QFrame::NoFrame ); + QHBoxLayout* aGrpBtnsLayout = new QHBoxLayout( aGrpBtns->layout() ); + aGrpBtnsLayout->setAlignment( Qt::AlignTop ); + aGrpBtnsLayout->setSpacing( 0 ); aGrpBtnsLayout->setMargin( 0 ); + + QPushButton* okB = new QPushButton( tr( "BUT_OK" ), aGrpBtns ); + connect( okB, SIGNAL( clicked() ), this, SLOT( onApply() ) ); + + aGrpBtnsLayout->addItem ( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + aGrpBtnsLayout->addWidget( okB ); + aGrpBtnsLayout->addItem ( new QSpacerItem( 5, 5, QSizePolicy::Expanding, QSizePolicy::Minimum ) ); + + aTopLayout->addWidget(myPage); + aTopLayout->addStretch(1); + aTopLayout->addWidget(aGrpBtns); + + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if( anApp ) + { + anApp->lcc()->preSet(myParams); + myParams.container_name = "YACSServer"; + myParams.hostname = "localhost"; + } + else + { + myParams.container_name = "YACSServer"; + myParams.hostname = "localhost"; + myParams.OS = ""; + myParams.mem_mb = 0; + myParams.cpu_clock = 0; + myParams.nb_proc_per_node = 0; + myParams.nb_node = 0; + myParams.isMPI = false; + myParams.parallelLib = ""; + myParams.nb_component_nodes = 0; + } + + myPage->showAdvanced->setChecked(false); + onShowAdvanced(); + updateState(); + myPage->myHostName->setEditable(true); + connect(myPage->showAdvanced, SIGNAL(clicked()), this, SLOT(onShowAdvanced())); +} + +YACSGui_YACSORBContainerDialog::~YACSGui_YACSORBContainerDialog() +{ +} + +void YACSGui_YACSORBContainerDialog::fillHostNames() const +{ + SalomeApp_Application* anApp = dynamic_cast( SUIT_Session::session()->activeApplication() ); + if ( !anApp ) return; + + SALOME_NamingService* namingService = anApp->namingService(); + + CORBA::Object_var obj = namingService->Resolve(SALOME_ResourcesManager::_ResourcesManagerNameInNS); + if ( !CORBA::is_nil(obj) ) + if ( Engines::ResourcesManager_var aResManager=Engines::ResourcesManager::_narrow(obj) ) + { + Engines::CompoList aCompoList ; + Engines::MachineParameters params; + anApp->lcc()->preSet(params); + + Engines::MachineList* aMachineList = aResManager->GetFittingResources( params, aCompoList ); + + myPage->myHostName->clear(); + myPage->myHostName->insertItem( QString("localhost") ); + for ( unsigned int i = 0; i < aMachineList->length(); i++ ) + { + const char* aMachine = (*aMachineList)[i]; + myPage->myHostName->insertItem( QString(aMachine) ); + } + } +} + +void YACSGui_YACSORBContainerDialog::onShowAdvanced() +{ + if(myPage->showAdvanced->isChecked()) + myPage->groupBoxAdv->show(); + else + myPage->groupBoxAdv->hide(); +} + +void YACSGui_YACSORBContainerDialog::updateState() +{ + fillHostNames(); + + // Set container name + if ( myPage->myExecutionName ) + myPage->myExecutionName->setText(QString(myParams.container_name)); + + // Set host name + if ( myPage->myHostName ) + myPage->myHostName->setCurrentText(QString(myParams.hostname)); + + // Set mem_mb + if ( myPage->myMemMb ) + myPage->myMemMb->setValue(myParams.mem_mb); + + // Set cpu_clock + if ( myPage->myCpuClock ) + myPage->myCpuClock->setValue(myParams.cpu_clock); + + // Set nb_proc_per_node + if ( myPage->myNbProcPerNode ) + myPage->myNbProcPerNode->setValue(myParams.nb_proc_per_node); + + // Set nb_node + if ( myPage->myNbNode ) + myPage->myNbNode->setValue(myParams.nb_node); + + // Set MPI usage + if ( myPage->myMpiUsage ) + myPage->myMpiUsage->setCurrentItem( myParams.isMPI ? 0 : 1 ); + + // Set parallel library + if ( myPage->myParallelLib ) + myPage->myParallelLib->setText(QString(myParams.parallelLib)); + + // Set nb_component_nodes + if ( myPage->myNbComponentNodes ) + myPage->myNbComponentNodes->setValue(myParams.nb_component_nodes); +} + +void YACSGui_YACSORBContainerDialog::onApply() +{ + if ( myPage->myExecutionName ) + myParams.container_name = myPage->myExecutionName->text().latin1(); + + if ( myPage->myHostName ) + myParams.hostname = myPage->myHostName->currentText().latin1(); + + if ( myPage->myMemMb ) + myParams.mem_mb = myPage->myMemMb->value(); + + if ( myPage->myCpuClock ) + myParams.cpu_clock = myPage->myCpuClock->value(); + + if ( myPage->myNbProcPerNode ) + myParams.nb_proc_per_node = myPage->myNbProcPerNode->value(); + + if ( myPage->myNbNode ) + myParams.nb_node = myPage->myNbNode->value(); + + if ( myPage->myMpiUsage ) + myParams.isMPI = ( myPage->myMpiUsage->currentItem() ? false : true ); + + if ( myPage->myParallelLib ) + myParams.parallelLib = myPage->myParallelLib->text().latin1(); + + if ( myPage->myNbComponentNodes ) + myParams.nb_component_nodes = myPage->myNbComponentNodes->value(); + + accept(); +} + diff --git a/src/gui/blocknodepage.ui b/src/gui/blocknodepage.ui new file mode 100644 index 000000000..495cc76ce --- /dev/null +++ b/src/gui/blocknodepage.ui @@ -0,0 +1,260 @@ + +BlockNodePage + + + BlockNodePage + + + + 0 + 0 + 308 + 240 + + + + + 5 + 0 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + BlockNodeFrame + + + + 5 + 0 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + myNodeFullName + + + true + + + + + NodeName + + + Node Name: + + + + + NodeFullName + + + Node Full Name: + + + + + NodeType + + + Node Type: + + + + + myNodeName + + + + + myNodeType + + + Block node + + + true + + + + + + + myDirectChildrenGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + ViewModeButtonGroup + + + View Mode + + + + unnamed + + + + myExpandedRadioButton + + + Expanded + + + true + + + + + myCollapsedRadioButton + + + Collapsed + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + + + + + YACSGui_PlusMinusGrp +
YACSGui_PlusMinusGrp.h
+ + -1 + -1 + + 1 + + 5 + 5 + 0 + 0 + + image0 +
+
+ + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082 + + + + onApply() + + + + YACSGui_PlusMinusGrp.h + +
diff --git a/src/gui/componentpage.ui b/src/gui/componentpage.ui new file mode 100644 index 000000000..ea7da33c5 --- /dev/null +++ b/src/gui/componentpage.ui @@ -0,0 +1,169 @@ + +ComponentPage + + + ComponentPage + + + + 0 + 0 + 348 + 156 + + + + + 2 + 0 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + ComponentFrame + + + + 5 + 0 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + ComponentGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + myContainerName + + + + + ContainerType + + + + 0 + 5 + 0 + 0 + + + + Container: + + + + + myComponentType + + + true + + + + + ComponentType + + + + 0 + 5 + 0 + 0 + + + + Type: + + + + + InstanceName + + + Instance: + + + + + ComponentName + + + + 0 + 5 + 0 + 0 + + + + Name: + + + + + myComponentName + + + + + myInstanceName + + + + + + + + + + diff --git a/src/gui/containerpage.ui b/src/gui/containerpage.ui new file mode 100644 index 000000000..a89ecd250 --- /dev/null +++ b/src/gui/containerpage.ui @@ -0,0 +1,344 @@ + +ContainerPage + + + ContainerPage + + + + 0 + 0 + 347 + 448 + + + + + 2 + 0 + 0 + 0 + + + + Form1 + + + + + + + unnamed + + + 0 + + + 0 + + + + ContainerFrame + + + + 5 + 0 + 0 + 251 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + Basic Parameters + + + + unnamed + + + + myHostName + + + Host name of the computer on which the container is instanciated at execution time + + + + + HostName + + + Host: + + + + + myDefinitionName + + + Name used in edition to distinguish the different containers (not used to name the containers in execution) + + + + + myExecutionName + + + Container name used in execution and published in naming service under /Containers/HostName/containerName + + + + + ExecutionName + + + Instance: + + + + + ContainerName + + + Name: + + + + + + + showAdvanced + + + Show Advanced parameters + + + + + groupBoxAdv + + + + 5 + 0 + 0 + 0 + + + + Advanced Parameters + + + + unnamed + + + + CpuClock + + + cpu_clock: + + + + + NbNode + + + nb_node: + + + + + MemMb + + + mem_mb: + + + + + MpiUsage + + + MPI usage: + + + + + ParallelLib + + + Parallel Library: + + + + + NbProcPerNode + + + nb_proc_per_node: + + + + + NbComponentNodes + + + nb_component_nodes: + + + + + WorkingDir + + + working directory: + + + + + myWorkingDir + + + false + + + differents containers on the same computer must avoid to share the same working directory to avoid to write simultaneously on the same files + + + + + myParallelLib + + + false + + + + + + yes + + + + + no + + + + myMpiUsage + + + 1 + + + + + myNbComponentNodes + + + 100 + + + 0 + + + 0 + + + + + myNbNode + + + 100 + + + 0 + + + 0 + + + + + myNbProcPerNode + + + 100 + + + 0 + + + 0 + + + + + myCpuClock + + + 100 + + + 0 + + + 0 + + + + + myMemMb + + + 100 + + + 0 + + + 0 + + + + + + + + + + onApply() + + + diff --git a/src/gui/datanodepage.ui b/src/gui/datanodepage.ui new file mode 100644 index 000000000..86faa0304 --- /dev/null +++ b/src/gui/datanodepage.ui @@ -0,0 +1,433 @@ + +DataNodePage + + + DataNodePage + + + + 0 + 0 + 399 + 855 + + + + + 2 + 7 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + DataNodeFrame + + + + 5 + 7 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + frame4 + + + StyledPanel + + + Raised + + + + unnamed + + + + splitter1 + + + Vertical + + + + EditPortsGroupBox + + + + 5 + 7 + 0 + 0 + + + + + 0 + 100 + + + + Edit Ports + + + + unnamed + + + + ports + + + + 0 + 0 + + + + + tab + + + Input Ports + + + + unnamed + + + + myInputPortsGroupBox + + + + 7 + 7 + 0 + 0 + + + + + 0 + 100 + + + + + + + + tab + + + Output Ports + + + + unnamed + + + + myOutputPortsGroupBox + + + + 7 + 7 + 0 + 0 + + + + + 0 + 100 + + + + + + + + + + + + + + FileGroupBox + + + + 5 + 0 + 0 + 0 + + + + file + + + + unnamed + + + + FileName + + + file name: + + + + + myFileName + + + + + + + StudyGroupBox + + + + 5 + 0 + 0 + 0 + + + + study + + + + unnamed + + + + layout2 + + + + unnamed + + + + StudyId + + + Study ID: + + + + + myStudyId + + + + + myStudyName + + + + + StudyName + + + Study Name: + + + + + + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + myNodeFullName + + + true + + + + + NodeName + + + Node Name: + + + + + NodeFullName + + + Node Full Name: + + + + + NodeType + + + Node Type: + + + + + myNodeName + + + + + myNodeType + + + data node + + + true + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + + + + + YACSGui_PlusMinusGrp +
YACSGui_PlusMinusGrp.h
+ + -1 + -1 + + 1 + + 5 + 5 + 0 + 0 + + image0 +
+
+ + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082 + + + + onApply() + + + + YACSGui_PlusMinusGrp.h + YACSGui_PlusMinusGrp.h + +
diff --git a/src/gui/datatypepage.ui b/src/gui/datatypepage.ui new file mode 100644 index 000000000..78c86dfd2 --- /dev/null +++ b/src/gui/datatypepage.ui @@ -0,0 +1,160 @@ + +DataTypePage + + + DataTypePage + + + + 0 + 0 + 482 + 464 + + + + + 2 + 7 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + DataTypeFrame + + + + 5 + 7 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + CatalogGroupBox + + + + 5 + 5 + 0 + 0 + + + + Catalog + + + + unnamed + + + + mySessionRadioButton + + + + 3 + 0 + 0 + 0 + + + + Session Catalog + + + true + + + + + myBrowseButton + + + + 5 + 0 + 0 + 0 + + + + Browse + + + + + myProcRadioButton + + + Proc catalog + + + + + + Catalog + + + true + + + true + + + + + New Item + + + + + + + CatalogTree + + + + + + + + + + onApply() + + + diff --git a/src/gui/foreachloopnodepage.ui b/src/gui/foreachloopnodepage.ui new file mode 100644 index 000000000..67cffb085 --- /dev/null +++ b/src/gui/foreachloopnodepage.ui @@ -0,0 +1,275 @@ + +ForEachLoopNodePage + + + ForEachLoopNodePage + + + + 0 + 0 + 398 + 348 + + + + + 2 + 0 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + ForEachLoopNodeFrame + + + + 5 + 0 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + myNodeFullName + + + true + + + + + myNodeType + + + FOREACH loop + + + true + + + + + myNodeName + + + + + myNbBranchesInputPortValue + + + 1000000 + + + 0 + + + 0 + + + + + myLoopBodyNodeName + + + true + + + + + myDataPortToDispatchValue + + + false + + + + + NodeName + + + Node Name: + + + + + NodeFullName + + + Node Full Name: + + + + + NodeType + + + Node Type: + + + + + NbBranchesInputPortValue + + + Number of Branches: + + + + + DataPortToDispatchValue + + + Data Port to Dispatch Value: + + + + + LoopBodyNodeName + + + Loop Body Node Name: + + + + + + + ViewModeButtonGroup + + + View Mode + + + + unnamed + + + + myExpandedRadioButton + + + Expanded + + + true + + + + + myCollapsedRadioButton + + + Collapsed + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + + + + onApply() + + + diff --git a/src/gui/forloopnodepage.ui b/src/gui/forloopnodepage.ui new file mode 100644 index 000000000..aa95b0544 --- /dev/null +++ b/src/gui/forloopnodepage.ui @@ -0,0 +1,259 @@ + +ForLoopNodePage + + + ForLoopNodePage + + + + 0 + 30 + 360 + 326 + + + + + 2 + 0 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + ForLoopNodeFrame + + + + 5 + 0 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + NodeType + + + Node Type: + + + + + myNodeFullName + + + true + + + + + myNodeType + + + FOR loop + + + true + + + + + NodeFullName + + + Node Full Name: + + + + + NodeName + + + Node Name: + + + + + myNodeName + + + + + myLoopBodyNodeName + + + true + + + + + NbTimesInputPortValue + + + Number of Times: + + + + + LoopBodyNodeName + + + Loop Body Node Name: + + + + + myNbTimesInputPortValue + + + 1000000 + + + 0 + + + 0 + + + + + + + ViewModeButtonGroup + + + View Mode + + + + unnamed + + + + myExpandedRadioButton + + + Expanded + + + true + + + + + myCollapsedRadioButton + + + Collapsed + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + + + + onApply() + + + diff --git a/src/gui/inlinenodepage.ui b/src/gui/inlinenodepage.ui new file mode 100644 index 000000000..e1732dac2 --- /dev/null +++ b/src/gui/inlinenodepage.ui @@ -0,0 +1,397 @@ + +InlineNodePage + + + InlineNodePage + + + + 0 + 0 + 399 + 754 + + + + + 2 + 7 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + InlineNodeFrame + + + + 5 + 7 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + myNodeFullName + + + true + + + + + NodeName + + + Node Name: + + + + + NodeFullName + + + Node Full Name: + + + + + NodeType + + + Node Type: + + + + + myNodeName + + + + + myNodeType + + + Inline function node + + + true + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + frame4 + + + StyledPanel + + + Raised + + + + unnamed + + + + splitter1 + + + Vertical + + + + EditPortsGroupBox + + + + 5 + 7 + 0 + 0 + + + + + 0 + 100 + + + + Edit Ports + + + + unnamed + + + + ports + + + + 0 + 0 + + + + + tab + + + Input Ports + + + + unnamed + + + + myInputPortsGroupBox + + + + 7 + 7 + 0 + 0 + + + + + 0 + 100 + + + + + + + + tab + + + Output Ports + + + + unnamed + + + + myOutputPortsGroupBox + + + + 7 + 7 + 0 + 0 + + + + + 0 + 100 + + + + + + + + + + + InPythonEditorGroupBox + + + + 5 + 7 + 0 + 0 + + + + Built-in Python Code Editor + + + + unnamed + + + + myTextEdit + + + + 0 + 100 + + + + + + layout1 + + + + unnamed + + + + Search + + + Search: + + + + + mySearch + + + + + + + + + + + + + + + + YACSGui_PlusMinusGrp +
YACSGui_PlusMinusGrp.h
+ + -1 + -1 + + 1 + + 5 + 5 + 0 + 0 + + image0 +
+
+ + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082 + + + + onApply() + + + + YACSGui_PlusMinusGrp.h + YACSGui_PlusMinusGrp.h + +
diff --git a/src/gui/resources/SalomeApp.xml b/src/gui/resources/SalomeApp.xml index 0ad6c8958..28671b2f6 100644 --- a/src/gui/resources/SalomeApp.xml +++ b/src/gui/resources/SalomeApp.xml @@ -1,12 +1,19 @@ -
+
- - + + +
+
+ + + + +
diff --git a/src/gui/resources/YACSGuiCatalog.xml.in b/src/gui/resources/YACSCatalog.xml.in similarity index 87% rename from src/gui/resources/YACSGuiCatalog.xml.in rename to src/gui/resources/YACSCatalog.xml.in index edd2eea9e..4463b488f 100644 --- a/src/gui/resources/YACSGuiCatalog.xml.in +++ b/src/gui/resources/YACSCatalog.xml.in @@ -12,8 +12,8 @@ - YACSGui - YACSGui TUI + YACS + YACS TUI Data P. RASCLE @VERSION@ diff --git a/src/gui/resources/YACSGui_images.po b/src/gui/resources/YACSGui_images.po deleted file mode 100755 index eba036cfc..000000000 --- a/src/gui/resources/YACSGui_images.po +++ /dev/null @@ -1,83 +0,0 @@ -#### YACS module root icon #### -msgid "YACS_MODULE_ICON" -msgstr "ModuleYacs.png" - -#### Icons for YACS module menus and toolbars #### - -msgid "ICON_ADD_DATAFLOW_IN_STUDY" -msgstr "add_in_study.png" - -msgid "ICON_ADD_NODE" -msgstr "add_node.png" - -msgid "ICON_CHANGE_INFORMATIONS" -msgstr "change_informations.png" - -msgid "ICON_CONTROL_VIEW" -msgstr "control_view.png" - -msgid "ICON_EXPORT_DATAFLOW" -msgstr "export_dataflow.png" - -msgid "ICON_FILTERNEXTSTEPS" -msgstr "filter_next_steps.png" - -msgid "ICON_FILTER_NOTIFICATION" -msgstr "filter_notification.png" - -msgid "ICON_FULL_VIEW" -msgstr "full_view.png" - -msgid "ICON_IMPORT_DATAFLOW" -msgstr "import_dataflow.png" - -msgid "ICON_IMPORT_SUPERV_DATAFLOW" -msgstr "import_superv_dataflow.png" - -msgid "ICON_INSERT_FILE" -msgstr "insert_file.png" - -msgid "ICON_KILL_DATAFLOW" -msgstr "kill.png" - -msgid "ICON_BREAKPOINT_DATAFLOW" -msgstr "mode_breakpoint.png" - -msgid "ICON_CONTINUE_DATAFLOW" -msgstr "mode_continue.png" - -msgid "ICON_MODIFY_DATAFLOW" -msgstr "modify_dataflow.png" - -msgid "ICON_MODIFY_SUPERV_DATAFLOW" -msgstr "modify_superv_dataflow.png" - -msgid "ICON_NEW_DATAFLOW" -msgstr "new_dataflow.png" - -msgid "ICON_REBUILD_LINKS" -msgstr "rebuild_links.png" - -msgid "ICON_RELOAD_DATAFLOW" -msgstr "reload.png" - -msgid "ICON_REMOTE_RUN_DATAFLOW" -msgstr "remote_run.png" - -msgid "ICON_RUN_DATAFLOW" -msgstr "run.png" - -msgid "ICON_SAVEDATAFLOWSTATE" -msgstr "save_dataflow_state.png" - -msgid "ICON_STEPBYSTEP_DATAFLOW" -msgstr "step_by_step.png" - -msgid "ICON_SUSPEND_RESUME_DATAFLOW" -msgstr "suspend_resume.png" - -msgid "ICON_TABLE_VIEW" -msgstr "table_view.png" - -msgid "ICON_TOGGLESTOPONERROR" -msgstr "toggle_stop_on_error.png" diff --git a/src/gui/resources/YACSGui_msg_en.po b/src/gui/resources/YACSGui_msg_en.po deleted file mode 100755 index 7ebbfe674..000000000 --- a/src/gui/resources/YACSGui_msg_en.po +++ /dev/null @@ -1,325 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR Free Software Foundation, Inc. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"PO-Revision-Date: 2007-03-12 16:44+0300\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - - -#### YACSGui module menus and toolbars #### - -msgid "MEN_FILE" -msgstr "File" - -msgid "TOOLBAR_DATAFLOW" -msgstr "Dataflow" - -msgid "TOOLBAR_EXECUTION" -msgstr "Execution" - -msgid "TOOLBAR_EXECUTIONMODE" -msgstr "Execution Mode" - -msgid "MEN_NEW_DATAFLOW" -msgstr "New dataflow" - -msgid "TOP_NEW_DATAFLOW" -msgstr "New dataflow" - -msgid "STB_NEW_DATAFLOW" -msgstr "Create new dataflow" - -msgid "MEN_MODIFY_DATAFLOW" -msgstr "Modify dataflow" - -msgid "TOP_MODIFY_DATAFLOW" -msgstr "Modify dataflow" - -msgid "STB_MODIFY_DATAFLOW" -msgstr "Modify dataflow" - -msgid "MEN_IMPORT_DATAFLOW" -msgstr "Import dataflow" - -msgid "TOP_IMPORT_DATAFLOW" -msgstr "Import dataflow" - -msgid "STB_IMPORT_DATAFLOW" -msgstr "Import dataflow" - -msgid "MEN_MODIFY_SUPERV_DATAFLOW" -msgstr "Modify SUPERV dataflow" - -msgid "TOP_MODIFY_SUPERV_DATAFLOW" -msgstr "Modify SUPERV dataflow" - -msgid "STB_MODIFY_SUPERV_DATAFLOW" -msgstr "Modify SUPERV dataflow" - -msgid "MEN_IMPORT_SUPERV_DATAFLOW" -msgstr "Import SUPERV dataflow" - -msgid "TOP_IMPORT_SUPERV_DATAFLOW" -msgstr "Import SUPERV dataflow" - -msgid "STB_IMPORT_SUPERV_DATAFLOW" -msgstr "Import SUPERV dataflow" - -msgid "MEN_EXPORT_DATAFLOW" -msgstr "Export dataflow" - -msgid "TOP_EXPORT_DATAFLOW" -msgstr "Export dataflow" - -msgid "STB_EXPORT_DATAFLOW" -msgstr "Export dataflow" - -msgid "MEN_SUPERVISOR" -msgstr "Supervisor" - -msgid "MEN_RELOAD_DATAFLOW" -msgstr "Reload" - -msgid "TOP_RELOAD_DATAFLOW" -msgstr "Reload" - -msgid "STB_RELOAD_DATAFLOW" -msgstr "Reload dataflow" - -msgid "MEN_REBUILD_LINKS" -msgstr "Rebuild links" - -msgid "TOP_REBUILD_LINKS" -msgstr "Rebuild links" - -msgid "STB_REBUILD_LINKS" -msgstr "Rebuild dataflow links" - -msgid "MEN_ADD_NODE" -msgstr "Add Node to Dataflow" - -msgid "TOP_ADD_NODE" -msgstr "Add Node to Dataflow" - -msgid "STB_ADD_NODE" -msgstr "Add Node to Dataflow" - -msgid "MEN_INSERT_FILE" -msgstr "Insert File" - -msgid "TOP_INSERT_FILE" -msgstr "Insert File" - -msgid "STB_INSERT_FILE" -msgstr "Insert File" - -msgid "MEN_RUN_DATAFLOW" -msgstr "Local Run" - -msgid "TOP_RUN_DATAFLOW" -msgstr "Local Run" - -msgid "STB_RUN_DATAFLOW" -msgstr "Local Run of Dataflow without control" - -msgid "MEN_REMOTE_RUN_DATAFLOW" -msgstr "Remote Run - Direct" - -msgid "TOP_REMOTE_RUN_DATAFLOW" -msgstr "Remote Run - Direct" - -msgid "STB_REMOTE_RUN_DATAFLOW" -msgstr "Remote Run of Dataflow without control" - -msgid "MEN_KILL_DATAFLOW" -msgstr "Stop Dataflow" - -msgid "TOP_KILL_DATAFLOW" -msgstr "Stop Dataflow" - -msgid "STB_KILL_DATAFLOW" -msgstr "Stop Dataflow as soon as possible..." - -msgid "MEN_STEPBYSTEP_DATAFLOW" -msgstr "Step by Step Mode" - -msgid "TOP_STEPBYSTEP_DATAFLOW" -msgstr "Step by Step Exec Mode" - -msgid "STB_STEPBYSTEP_DATAFLOW" -msgstr "Step by Step Execution Mode" - -msgid "MEN_CONTINUE_DATAFLOW" -msgstr "continue Mode" - -msgid "TOP_CONTINUE_DATAFLOW" -msgstr "continue Mode" - -msgid "STB_CONTINUE_DATAFLOW" -msgstr "continue Mode" - -msgid "MEN_BREAKPOINT_DATAFLOW" -msgstr "breakpoint Mode" - -msgid "TOP_BREAKPOINT_DATAFLOW" -msgstr "breakpoint Mode" - -msgid "STB_BREAKPOINT_DATAFLOW" -msgstr "breakpoint Mode" - -msgid "MEN_FILTERNEXTSTEPS" -msgstr "Filter Next Steps" - -msgid "TOP_FILTERNEXTSTEPS" -msgstr "Filter Next Steps" - -msgid "STB_FILTERNEXTSTEPS" -msgstr "Filter Next Steps" - -msgid "MEN_SAVEDATAFLOWSTATE" -msgstr "Save Dataflow state" - -msgid "TOP_SAVEDATAFLOWSTATE" -msgstr "Save Dataflow state" - -msgid "STB_SAVEDATAFLOWSTATE" -msgstr "Save Dataflow state" - -msgid "MEN_TOGGLESTOPONERROR" -msgstr "Toggle stop on error" - -msgid "TOP_TOGGLESTOPONERROR" -msgstr "Toggle stop on error" - -msgid "STB_TOGGLESTOPONERROR" -msgstr "Toggle stop on error" - -msgid "MEN_SUSPEND_RESUME_DATAFLOW" -msgstr "Remote Run - Control" - -msgid "TOP_SUSPEND_RESUME_DATAFLOW" -msgstr "Remote Run - Control" - -msgid "STB_SUSPEND_RESUME_DATAFLOW" -msgstr "Remote Run of Dataflow with execution control" - -msgid "MEN_FILTER_NOTIFICATION" -msgstr "Filter Notification ..." - -msgid "TOP_FILTER_NOTIFICATION" -msgstr "Filter Notification ..." - -msgid "STB_FILTER_NOTIFICATION" -msgstr "Filter Notification ..." - -msgid "MEN_ADD_DATAFLOW_IN_STUDY" -msgstr "Add In Study" - -msgid "TOP_ADD_DATAFLOW_IN_STUDY" -msgstr "Add Dataflow In Study" - -msgid "STB_ADD_DATAFLOW_IN_STUDY" -msgstr "Add Dataflow In Study" - -msgid "MEN_CHANGE_INFORMATIONS" -msgstr "Change Informations ..." - -msgid "TOP_CHANGE_INFORMATIONS" -msgstr "Change Informations ..." - -msgid "STB_CHANGE_INFORMATIONS" -msgstr "Change Informations ..." - -msgid "MEN_FULL_VIEW" -msgstr "Full View" - -msgid "TOP_FULL_VIEW" -msgstr "Full View" - -msgid "STB_FULL_VIEW" -msgstr "Full View" - -msgid "MEN_CONTROL_VIEW" -msgstr "Control View" - -msgid "TOP_CONTROL_VIEW" -msgstr "Control View" - -msgid "STB_CONTROL_VIEW" -msgstr "Control View" - -msgid "MEN_TABLE_VIEW" -msgstr "Table View" - -msgid "TOP_TABLE_VIEW" -msgstr "Table View" - -msgid "STB_TABLE_VIEW" -msgstr "Table View" - - -#### YACSGui module dialog titles #### - -msgid "TLT_MODIFY_DATAFLOW" -msgstr "Modify Dataflow" - -msgid "TLT_IMPORT_DATAFLOW" -msgstr "Import Dataflow" - -msgid "TLT_MODIFY_SUPERV_DATAFLOW" -msgstr "Modify SUPERV Dataflow" - -msgid "TLT_IMPORT_SUPERV_DATAFLOW" -msgstr "Import SUPERV Dataflow" - -msgid "TLT_EXPORT_DATAFLOW" -msgstr "Export Dataflow" - -#### YACSGui module message boxes #### - -msgid "ERROR" -msgstr "Error" - -msgid "WARNING" -msgstr "Warning" - -msgid "BUT_OK" -msgstr "Ok" - -msgid "MSG_NO_DATAFLOW_SELECTED" -msgstr "No dataflow has been selected." - -msgid "MSG_IMPORT_FILE_ERROR" -msgstr "The file is incorrect." - -msgid "MSG_DATAFLOW_NOT_EDITABLE" -msgstr "Current dataflow is not editable." - -msgid "MSG_NO_DATAFLOW_LOADED" -msgstr "No dataflow for execution is selected." - -msgid "MSG_NO_DATAFLOW_TO_RUN" -msgstr "No dataflow for execution is selected." - -msgid "MSG_NO_DATAFLOW_TO_KILL" -msgstr "No dataflow to kill is selected." - -msgid "MSG_NO_DATAFLOW_TO_SUSPEND_RESUME" -msgstr "No dataflow to suspend/resume is selected." - -msgid "MSG_NO_DATAFLOW_TO_SUSPEND_RESUME" -msgstr "No dataflow to suspend/resume is selected." - -msgid "MSG_DATAFLOW_IS_NOT_RUNNING" -msgstr "The dataflow is not running." - - - diff --git a/src/gui/resources/YACS_images.po b/src/gui/resources/YACS_images.po new file mode 100755 index 000000000..883f052a8 --- /dev/null +++ b/src/gui/resources/YACS_images.po @@ -0,0 +1,276 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2007-09-11 15:28+0400\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#### YACS module root icon #### +msgid "YACS_MODULE_ICON" +msgstr "ModuleYacs.png" + +#### Icons for YACS module menus and toolbars #### + +msgid "ICON_IMPORT_YACS_SCHEMA" +msgstr "import_dataflow.png" + +msgid "ICON_IMPORT_SUPERV_SCHEMA" +msgstr "import_superv_dataflow.png" + +msgid "ICON_EXPORT_SCHEMA" +msgstr "export_dataflow.png" + +msgid "ICON_NEW_CONTAINER" +msgstr "container.png" + +msgid "ICON_NEW_SALOME_COMPONENT" +msgstr "new_salome_component.png" + +msgid "ICON_NEW_SALOMEPYTHON_COMPONENT" +msgstr "new_salomepy_component.png" + +msgid "ICON_NEW_CORBA_COMPONENT" +msgstr "new_corba_component.png" + +msgid "ICON_NEW_SCHEMA" +msgstr "new_dataflow.png" + +msgid "ICON_NEW_SALOME_SERVICE_NODE" +msgstr "new_salome_service_node.png" + +msgid "ICON_NEW_CORBA_SERVICE_NODE" +msgstr "new_corba_service_node.png" + +msgid "ICON_NEW_NODENODE_SERVICE_NODE" +msgstr "new_nodenode_service_node.png" + +msgid "ICON_NEW_CPP_NODE" +msgstr "new_cpp_node.png" + +msgid "ICON_NEW_SERVICE_INLINE_NODE" +msgstr "new_service_inline_node.png" + +msgid "ICON_NEW_XML_NODE" +msgstr "new_xml_node.png" + +msgid "ICON_NEW_INLINE_SCRIPT_NODE" +msgstr "new_inline_script_node.png" + +msgid "ICON_NEW_INLINE_FUNCTION_NODE" +msgstr "new_inline_function_node.png" + +msgid "ICON_NEW_BLOCK_NODE" +msgstr "block_node.png" + +msgid "ICON_NEW_FOR_LOOP_NODE" +msgstr "loop_node.png" + +msgid "ICON_NEW_FOREACH_LOOP_NODE" +msgstr "loop_node.png" + +msgid "ICON_NEW_WHILE_LOOP_NODE" +msgstr "loop_node.png" + +msgid "ICON_NEW_SWITCH_NODE" +msgstr "switch_node.png" + +msgid "ICON_NEW_FROM_LIBRARY_NODE" +msgstr "new_from_library_node.png" + +msgid "ICON_NEW_LINK" +msgstr "new_link.png" + + +msgid "ICON_ADD_DATAFLOW_IN_STUDY" +msgstr "add_in_study.png" + +msgid "ICON_ADD_NODE" +msgstr "add_node.png" + +msgid "ICON_CHANGE_INFORMATIONS" +msgstr "change_informations.png" + +msgid "ICON_CONTROL_VIEW" +msgstr "control_view.png" + +msgid "ICON_DATAFLOW_VIEW" +msgstr "dataflow_view.png" + +msgid "ICON_DATASTREAM_VIEW" +msgstr "datastream_view.png" + + +msgid "ICON_FILTERNEXTSTEPS" +msgstr "filter_next_steps.png" + +msgid "ICON_FILTER_NOTIFICATION" +msgstr "filter_notification.png" + +msgid "ICON_FULL_VIEW" +msgstr "full_view.png" + + +msgid "ICON_INSERT_FILE" +msgstr "insert_file.png" + +msgid "ICON_ABORT" +msgstr "kill.png" + +msgid "ICON_BREAKPOINT_DATAFLOW" +msgstr "mode_breakpoint.png" + +msgid "ICON_CONTINUE_DATAFLOW" +msgstr "mode_continue.png" + +msgid "ICON_MODIFY_DATAFLOW" +msgstr "modify_dataflow.png" + +msgid "ICON_MODIFY_SUPERV_DATAFLOW" +msgstr "modify_superv_dataflow.png" + + +msgid "ICON_ARRANGE_NODES" +msgstr "arrange_nodes.png" + +msgid "ICON_REBUILD_LINKS" +msgstr "rebuild_links.png" + +msgid "ICON_RELOAD_DATAFLOW" +msgstr "reload.png" + +msgid "ICON_REMOTE_RUN_DATAFLOW" +msgstr "remote_run.png" + +msgid "ICON_NEW_EXECUTION" +msgstr "new_execution.png" + +msgid "ICON_NEW_EDITION" +msgstr "new_edition.png" + +msgid "ICON_NEW_BATCH_EXECUTION" +msgstr "new_batch_execution.png" + +msgid "ICON_LOAD_EXECUTION_STATE" +msgstr "load_execution_state.png" + +msgid "ICON_WITHOUTSTOP_MODE" +msgstr "run.png" + +msgid "ICON_WITHOUTSTOP_ACTIVE_MODE" +msgstr "run_active.png" + +msgid "ICON_BREAKPOINTS_MODE" +msgstr "breakpoints.png" + +msgid "ICON_BREAKPOINTS_ACTIVE_MODE" +msgstr "breakpoints_active.png" + +msgid "ICON_STEPBYSTEP_MODE" +msgstr "step_by_step.png" + +msgid "ICON_STEPBYSTEP_ACTIVE_MODE" +msgstr "step_by_step_active.png" + +msgid "ICON_EXECUTE" +msgstr "run.png" + +msgid "ICON_EXECUTE_STBY" +msgstr "step_by_step.png" + +msgid "ICON_EXECUTE_BATCH" +msgstr "execute_in_batch.png" + +msgid "ICON_PAUSE" +msgstr "pause.png" + +msgid "ICON_STARTRESUME" +msgstr "resume.png" + +msgid "ICON_RESUME" +msgstr "resume.png" + +msgid "ICON_RESET" +msgstr "reset.png" + +msgid "ICON_SAVE_EXECUTION_STATE" +msgstr "save_dataflow_state.png" + +msgid "ICON_CONNECT_TO_RUNNING" +msgstr "connect_to_batch_session.png" + +msgid "ICON_SUSPEND_RESUME" +msgstr "suspend_resume.png" + +msgid "ICON_TABLE_VIEW" +msgstr "table_view.png" + +msgid "ICON_TOGGLESTOPONERROR" +msgstr "toggle_stop_on_error.png" + +msgid "ICON_SCHEMA_OBJECT" +msgstr "schema.png" + +msgid "ICON_BLOCK_OBJECT" +msgstr "block_node.png" + +msgid "ICON_LOOP_NODE_OBJECT" +msgstr "loop_node.png" + +msgid "ICON_SWITCH_NODE_OBJECT" +msgstr "switch_node.png" + +msgid "ICON_NODE_OBJECT" +msgstr "node.png" + +msgid "ICON_OUT_PORT_OBJECT" +msgstr "out_port.png" + +msgid "ICON_IN_PORT_OBJECT" +msgstr "in_port.png" + +msgid "ICON_CONTROL_LINK_OBJECT" +msgstr "control_link.png" + +msgid "ICON_DATA_LINK_OBJECT" +msgstr "data_link.png" + +msgid "ICON_STREAM_LINK_OBJECT" +msgstr "stream_link.png" + +msgid "ICON_CONTAINER_OBJECT" +msgstr "container.png" + +msgid "ICON_COMPONENT_OBJECT" +msgstr "component.png" + +msgid "ICON_RUN_OBJECT" +msgstr "run_object.png" + +msgid "ICON_UP" +msgstr "icon_up.png" + +msgid "ICON_DOWN" +msgstr "icon_down.png" + +msgid "ICON_INSERT" +msgstr "icon_insert.png" + +msgid "ICON_SELECT" +msgstr "icon_select.png" + +msgid "ICON_PLUS" +msgstr "icon_plus.png" + +msgid "ICON_MINUS" +msgstr "icon_minus.png" + +msgid "ICON_TEXT" +msgstr "icon_text.png" diff --git a/src/gui/resources/YACS_msg_en.po b/src/gui/resources/YACS_msg_en.po new file mode 100755 index 000000000..36f2419d1 --- /dev/null +++ b/src/gui/resources/YACS_msg_en.po @@ -0,0 +1,1001 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2007-03-12 16:44+0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + + +#### YACSGui input panel #### + +msgid "INLINE_FUNCTION_NODE" +msgstr "Inline function node" + +msgid "IN_DATANODE" +msgstr "Input data node" + +msgid "OUT_DATANODE" +msgstr "Output data node" + +msgid "IN_STUDYNODE" +msgstr "Input study data node" + +msgid "OUT_STUDYNODE" +msgstr "Output study data node" + +msgid "INLINE_SCRIPT_NODE" +msgstr "Inline script node" + +msgid "SALOME_SERVICE_NODE" +msgstr "SALOME service node" + +msgid "CORBA_SERVICE_NODE" +msgstr "CORBA service node" + +msgid "NODENODE_SERVICE_NODE" +msgstr "Node-node service" + +msgid "CPP_NODE" +msgstr "CPP node" + +msgid "SERVICE_INLINE_NODE" +msgstr "Service inline" + +msgid "XML_NODE" +msgstr "XML node" + +msgid "APPLY_CANCEL_MODIFICATIONS" +msgstr "Properties of the previous selected object were changed. Do you want to apply these modifications?" + +#### YACSGui module menus and toolbars #### + +msgid "MEN_FILE" +msgstr "File" + +msgid "MEN_IMPORT_SCHEMA" +msgstr "Import Schema" + +msgid "MEN_IMPORT_YACS_SCHEMA" +msgstr "YACS XML" + +msgid "TOP_IMPORT_YACS_SCHEMA" +msgstr "Import schema" + +msgid "STB_IMPORT_YACS_SCHEMA" +msgstr "Import schema" + +msgid "MEN_IMPORT_SUPERV_SCHEMA" +msgstr "SUPERV XML" + +msgid "TOP_IMPORT_SUPERV_SCHEMA" +msgstr "Import SUPERV schema" + +msgid "STB_IMPORT_SUPERV_SCHEMA" +msgstr "Import SUPERV schema" + +msgid "MEN_EXPORT_SCHEMA" +msgstr "Export schema" + +msgid "TOP_EXPORT_SCHEMA" +msgstr "Export schema" + +msgid "STB_EXPORT_SCHEMA" +msgstr "Export schema" + +msgid "TOOLBAR_EXECUTION" +msgstr "Execution" + +msgid "TOOLBAR_SCHEMA" +msgstr "Schema" + +msgid "TOOLBAR_CREATION" +msgstr "Creation" + +msgid "TOOLBAR_VISUALIZATION" +msgstr "Visualization" + +msgid "MEN_CREATE" +msgstr "Create" + +msgid "MEN_NEW_SCHEMA" +msgstr "New Schema" + +msgid "TOP_NEW_SCHEMA" +msgstr "New Schema" + +msgid "STB_NEW_SCHEMA" +msgstr "Create new schema" + +msgid "MEN_NEW_CONTAINER" +msgstr "New container" + +msgid "TOP_NEW_CONTAINER" +msgstr "New container" + +msgid "STB_NEW_CONTAINER" +msgstr "Create new container" + +msgid "MEN_NEW_COMPONENT" +msgstr "New Component" + +msgid "MEN_NEW_SALOME_COMPONENT" +msgstr "New SALOME component" + +msgid "TOP_NEW_SALOME_COMPONENT" +msgstr "New SALOME component" + +msgid "STB_NEW_SALOME_COMPONENT" +msgstr "Create new SALOME component" + +msgid "MEN_NEW_SALOMEPYTHON_COMPONENT" +msgstr "New SALOME Python component" + +msgid "TOP_NEW_SALOMEPYTHON_COMPONENT" +msgstr "New SALOME Python component" + +msgid "STB_NEW_SALOMEPYTHON_COMPONENT" +msgstr "Create new SALOME Python component" + +msgid "MEN_NEW_CORBA_COMPONENT" +msgstr "New CORBA component" + +msgid "TOP_NEW_CORBA_COMPONENT" +msgstr "New CORBA component" + +msgid "STB_NEW_CORBA_COMPONENT" +msgstr "Create new CORBA component" + +msgid "MEN_NEW_NODE" +msgstr "New Node" + +msgid "MEN_NEW_SALOME_SERVICE_NODE" +msgstr "From catalog" + +msgid "TOP_NEW_SALOME_SERVICE_NODE" +msgstr "New node from catalog" + +msgid "STB_NEW_SALOME_SERVICE_NODE" +msgstr "Create new node from catalog" + +msgid "MEN_NEW_CORBA_SERVICE_NODE" +msgstr "CORBA service" + +msgid "TOP_NEW_CORBA_SERVICE_NODE" +msgstr "New CORBA service node" + +msgid "STB_NEW_CORBA_SERVICE_NODE" +msgstr "Create new CORBA service node" + +msgid "MEN_NEW_NODENODE_SERVICE_NODE" +msgstr "Node-node service" + +msgid "TOP_NEW_NODENODE_SERVICE_NODE" +msgstr "New node-node service node" + +msgid "STB_NEW_NODENODE_SERVICE_NODE" +msgstr "Create new node-node service node" + +msgid "MEN_NEW_CPP_NODE" +msgstr "CPP node" + +msgid "TOP_NEW_CPP_NODE" +msgstr "New CPP node" + +msgid "STB_NEW_CPP_NODE" +msgstr "Create new CPP node" + +msgid "MEN_NEW_SERVICE_INLINE_NODE" +msgstr "Service inline" + +msgid "TOP_NEW_SERVICE_INLINE_NODE" +msgstr "New service inline node" + +msgid "STB_NEW_SERVICE_INLINE_NODE" +msgstr "Create new service inline node" + +msgid "MEN_NEW_XML_NODE" +msgstr "XML node" + +msgid "TOP_NEW_XML_NODE" +msgstr "New XML node" + +msgid "STB_NEW_XML_NODE" +msgstr "Create new XML node" + +msgid "MEN_NEW_IN_DATANODE" +msgstr "Input data node" + +msgid "TOP_NEW_IN_DATANODE" +msgstr "New input data node" + +msgid "STB_NEW_IN_DATANODE" +msgstr "Create new input data node" + +msgid "MEN_NEW_OUT_DATANODE" +msgstr "Output data node" + +msgid "TOP_NEW_OUT_DATANODE" +msgstr "New output data node" + +msgid "STB_NEW_OUT_DATANODE" +msgstr "Create new output data node" + +msgid "MEN_NEW_IN_STUDYNODE" +msgstr "Input study node" + +msgid "TOP_NEW_IN_STUDYNODE" +msgstr "New input study node" + +msgid "STB_NEW_IN_STUDYNODE" +msgstr "Create new input study node" + +msgid "MEN_NEW_OUT_STUDYNODE" +msgstr "Output study node" + +msgid "TOP_NEW_OUT_STUDYNODE" +msgstr "New output study node" + +msgid "STB_NEW_OUT_STUDYNODE" +msgstr "Create new output study node" + +msgid "MEN_NEW_INLINE_SCRIPT_NODE" +msgstr "Inline script" + +msgid "TOP_NEW_INLINE_SCRIPT_NODE" +msgstr "New inline script node" + +msgid "STB_NEW_INLINE_SCRIPT_NODE" +msgstr "Create new inline sript node" + +msgid "MEN_NEW_INLINE_FUNCTION_NODE" +msgstr "Inline function" + +msgid "TOP_NEW_INLINE_FUNCTION_NODE" +msgstr "New inline function node" + +msgid "STB_NEW_INLINE_FUNCTION_NODE" +msgstr "Create new inline function node" + +msgid "MEN_NEW_BLOCK_NODE" +msgstr "Block" + +msgid "TOP_NEW_BLOCK_NODE" +msgstr "New block node" + +msgid "STB_NEW_BLOCK_NODE" +msgstr "Create new block node" + +msgid "MEN_NEW_FOR_LOOP_NODE" +msgstr "FOR loop" + +msgid "TOP_NEW_FOR_LOOP_NODE" +msgstr "New FOR loop node" + +msgid "STB_NEW_FOR_LOOP_NODE" +msgstr "Create new FOR loop node" + +msgid "MEN_NEW_FOREACH_LOOP_NODE" +msgstr "FOREACH loop" + +msgid "TOP_NEW_FOREACH_LOOP_NODE" +msgstr "New FOREACH loop node" + +msgid "STB_NEW_FOREACH_LOOP_NODE" +msgstr "Create new FOREACH loop node" + +msgid "MEN_NEW_WHILE_LOOP_NODE" +msgstr "WHILE loop" + +msgid "TOP_NEW_WHILE_LOOP_NODE" +msgstr "New WHILE loop node" + +msgid "STB_NEW_WHILE_LOOP_NODE" +msgstr "Create new WHILE loop node" + +msgid "MEN_NEW_SWITCH_NODE" +msgstr "SWITCH" + +msgid "TOP_NEW_SWITCH_NODE" +msgstr "New SWITCH node" + +msgid "STB_NEW_SWITCH_NODE" +msgstr "Create new SWITCH node" + +msgid "MEN_NEW_FROM_LIBRARY_NODE" +msgstr "From library ..." + +msgid "TOP_NEW_FROM_LIBRARY_NODE" +msgstr "New from node from library" + +msgid "STB_NEW_FROM_LIBRARY_NODE" +msgstr "Create new node from library" + +msgid "MEN_NEW_LINK" +msgstr "New Link" + +msgid "TOP_NEW_LINK" +msgstr "New Link" + +msgid "STB_NEW_LINK" +msgstr "Create new link" + + + +msgid "MEN_SUPERVISOR" +msgstr "Supervisor" + +msgid "MEN_RELOAD_DATAFLOW" +msgstr "Reload" + +msgid "TOP_RELOAD_DATAFLOW" +msgstr "Reload" + +msgid "STB_RELOAD_DATAFLOW" +msgstr "Reload dataflow" + +msgid "MEN_REBUILD_LINKS" +msgstr "Rebuild links" + +msgid "TOP_REBUILD_LINKS" +msgstr "Rebuild links" + +msgid "STB_REBUILD_LINKS" +msgstr "Rebuild schema links" + +msgid "MEN_ARRANGE_NODES" +msgstr "Arrange nodes" + +msgid "TOP_ARRANGE_NODES" +msgstr "Arrange nodes" + +msgid "STB_ARRANGE_NODES" +msgstr "Arrange schema nodes" + +msgid "MEN_ADD_NODE" +msgstr "Add Node to Dataflow" + +msgid "TOP_ADD_NODE" +msgstr "Add Node to Dataflow" + +msgid "STB_ADD_NODE" +msgstr "Add Node to Dataflow" + +msgid "MEN_INSERT_FILE" +msgstr "Insert File" + +msgid "TOP_INSERT_FILE" +msgstr "Insert File" + +msgid "STB_INSERT_FILE" +msgstr "Insert File" + +msgid "MEN_RUN_DATAFLOW" +msgstr "Local Run" + +msgid "TOP_RUN_DATAFLOW" +msgstr "Local Run" + +msgid "STB_RUN_DATAFLOW" +msgstr "Local Run of Dataflow without control" + +msgid "MEN_REMOTE_RUN_DATAFLOW" +msgstr "Remote Run - Direct" + +msgid "TOP_REMOTE_RUN_DATAFLOW" +msgstr "Remote Run - Direct" + +msgid "STB_REMOTE_RUN_DATAFLOW" +msgstr "Remote Run of Dataflow without control" + +msgid "MEN_KILL_DATAFLOW" +msgstr "Stop Dataflow" + +msgid "TOP_KILL_DATAFLOW" +msgstr "Stop Dataflow" + +msgid "STB_KILL_DATAFLOW" +msgstr "Stop Dataflow as soon as possible..." + +msgid "MEN_STEPBYSTEP_DATAFLOW" +msgstr "Step by Step Mode" + +msgid "TOP_STEPBYSTEP_DATAFLOW" +msgstr "Step by Step Exec Mode" + +msgid "STB_STEPBYSTEP_DATAFLOW" +msgstr "Step by Step Execution Mode" + +msgid "MEN_CONTINUE_DATAFLOW" +msgstr "continue Mode" + +msgid "TOP_CONTINUE_DATAFLOW" +msgstr "continue Mode" + +msgid "STB_CONTINUE_DATAFLOW" +msgstr "continue Mode" + +msgid "MEN_BREAKPOINT_DATAFLOW" +msgstr "breakpoint Mode" + +msgid "TOP_BREAKPOINT_DATAFLOW" +msgstr "breakpoint Mode" + +msgid "STB_BREAKPOINT_DATAFLOW" +msgstr "breakpoint Mode" + +msgid "MEN_FILTERNEXTSTEPS" +msgstr "Filter Next Steps" + +msgid "TOP_FILTERNEXTSTEPS" +msgstr "Filter Next Steps" + +msgid "STB_FILTERNEXTSTEPS" +msgstr "Filter Next Steps" + +msgid "MEN_SAVEDATAFLOWSTATE" +msgstr "Save Dataflow state" + +msgid "TOP_SAVEDATAFLOWSTATE" +msgstr "Save Dataflow state" + +msgid "STB_SAVEDATAFLOWSTATE" +msgstr "Save Dataflow state" + +msgid "MEN_TOGGLESTOPONERROR" +msgstr "Stop on error Option" + +msgid "TOP_TOGGLESTOPONERROR" +msgstr "Stop on error Option" + +msgid "STB_TOGGLESTOPONERROR" +msgstr "Stop on error Option" + +msgid "MEN_SUSPEND_RESUME_DATAFLOW" +msgstr "Remote Run - Control" + +msgid "TOP_SUSPEND_RESUME_DATAFLOW" +msgstr "Remote Run - Control" + +msgid "STB_SUSPEND_RESUME_DATAFLOW" +msgstr "Remote Run of Dataflow with execution control" + +msgid "MEN_FILTER_NOTIFICATION" +msgstr "Filter Notification ..." + +msgid "TOP_FILTER_NOTIFICATION" +msgstr "Filter Notification ..." + +msgid "STB_FILTER_NOTIFICATION" +msgstr "Filter Notification ..." + +msgid "MEN_ADD_DATAFLOW_IN_STUDY" +msgstr "Add In Study" + +msgid "TOP_ADD_DATAFLOW_IN_STUDY" +msgstr "Add Dataflow In Study" + +msgid "STB_ADD_DATAFLOW_IN_STUDY" +msgstr "Add Dataflow In Study" + +msgid "MEN_CHANGE_INFORMATIONS" +msgstr "Change Informations ..." + +msgid "TOP_CHANGE_INFORMATIONS" +msgstr "Change Informations ..." + +msgid "STB_CHANGE_INFORMATIONS" +msgstr "Change Informations ..." + +msgid "MEN_FULL_VIEW" +msgstr "Full View" + +msgid "TOP_FULL_VIEW" +msgstr "Full View" + +msgid "STB_FULL_VIEW" +msgstr "Full View" + +msgid "MEN_CONTROL_VIEW" +msgstr "Control View" + +msgid "TOP_CONTROL_VIEW" +msgstr "Control View" + +msgid "STB_CONTROL_VIEW" +msgstr "Control View" + +msgid "MEN_TABLE_VIEW" +msgstr "Table View" + +msgid "TOP_TABLE_VIEW" +msgstr "Table View" + +msgid "STB_TABLE_VIEW" +msgstr "Table View" + +#execurion menu +msgid "MEN_EXECUTE" +msgstr "Execute" + +msgid "TOP_NEW_EXECUTION" +msgstr "New execution" + +msgid "MEN_NEW_EXECUTION" +msgstr "New execution" + +msgid "STB_NEW_EXECUTION" +msgstr "Create new execution" + +msgid "TOP_LOAD_EXECUTION_STATE" +msgstr "Load execution state" + +msgid "MEN_LOAD_EXECUTION_STATE" +msgstr "Load execution state" + +msgid "STB_LOAD_EXECUTION_STATE" +msgstr "Load execution state" + +msgid "TOP_NEW_BATCH_EXECUTION" +msgstr "New Bacth Execution" + +msgid "MEN_NEW_BATCH_EXECUTION" +msgstr "New Bacth Execution" + +msgid "STB_NEW_BATCH_EXECUTION" +msgstr "Create new bacth execution" + +msgid "TOP_STARTRESUME" +msgstr "Start/Resume" + +msgid "MEN_STARTRESUME" +msgstr "Start/Resume" + +msgid "STB_STARTRESUME" +msgstr "Start/Resume schema execution" + +msgid "TOP_EXECUTE" +msgstr "Execute" + +msgid "STB_EXECUTE" +msgstr "Execute" + +msgid "TOP_EXECUTE_STBY" +msgstr "Execute step-by-step" + +msgid "MEN_EXECUTE_STBY" +msgstr "Execute step-by-step" + +msgid "STB_EXECUTE_STBY" +msgstr "Execute step-by-step" + +msgid "TOP_EXECUTE_BATCH" +msgstr "Execute in batch" + +msgid "MEN_EXECUTE_BATCH" +msgstr "Execute in batch" + +msgid "STB_EXECUTE_BATCH" +msgstr "Execute in batch" + +msgid "TOP_PAUSE" +msgstr "Pause" + +msgid "MEN_PAUSE" +msgstr "Pause" + +msgid "STB_PAUSE" +msgstr "Pause" + +msgid "TOP_RESUME" +msgstr "Resume" + +msgid "MEN_RESUME" +msgstr "Resume" + +msgid "STB_RESUME" +msgstr "Resume" + +msgid "TOP_SUSPEND_RESUME" +msgstr "Suspend/Resume" + +msgid "MEN_SUSPEND_RESUME" +msgstr "Suspend/Resume" + +msgid "STB_SUSPEND_RESUME" +msgstr "Suspend/Resume schema execution" + +msgid "TOP_ABORT" +msgstr "Abort" + +msgid "MEN_ABORT" +msgstr "Abort" + +msgid "STB_ABORT" +msgstr "Abort" + +msgid "TOP_RESET" +msgstr "Reset" + +msgid "MEN_RESET" +msgstr "Reset" + +msgid "STB_RESET" +msgstr "Reset" + +msgid "TOP_WITHOUTSTOP_MODE" +msgstr "Without stop Mode" + +msgid "MEN_WITHOUTSTOP_MODE" +msgstr "Without stop Mode" + +msgid "STB_WITHOUTSTOP_MODE" +msgstr "Without stop mode of schema execution" + +msgid "TOP_BREAKPOINTS_MODE" +msgstr "Breakpoints Mode" + +msgid "MEN_BREAKPOINTS_MODE" +msgstr "Breakpoints Mode" + +msgid "STB_BREAKPOINTS_MODE" +msgstr "Breakpoints mode of schema execution" + +msgid "TOP_STEPBYSTEP_MODE" +msgstr "Step by step Mode" + +msgid "MEN_STEPBYSTEP_MODE" +msgstr "Step by step Mode" + +msgid "STB_STEPBYSTEP_MODE" +msgstr "Step by step mode of schema execution" + +msgid "TOP_ADD_BREAK_POINT" +msgstr "Add a breakpoint ..." + +msgid "MEN_ADD_BREAK_POINT" +msgstr "Add a breakpoint ..." + +msgid "STB_ADD_BREAK_POINT" +msgstr "Add a breakpoint ..." + +msgid "TOP_SAVE_EXECUTION_STATE" +msgstr "Save execution state ..." + +msgid "MEN_SAVE_EXECUTION_STATE" +msgstr "Save execution state ..." + +msgid "STB_SAVE_EXECUTION_STATE" +msgstr "Save execution state ..." + +msgid "TOP_NEW_EDITION" +msgstr "New edition" + +msgid "MEN_NEW_EDITION" +msgstr "New edition" + +msgid "STB_NEW_EDITION" +msgstr "Create a schema copy in the edition mode" + +msgid "TOP_CONNECT_TO_RUNNING" +msgstr "Connect to a running batch session ..." + +msgid "MEN_CONNECT_TO_RUNNING" +msgstr "Connect to a running batch session ..." + +msgid "STB_CONNECT_TO_RUNNING" +msgstr "Connect to a running batch session ..." + +msgid "MEN_DATAFLOW_VIEW" +msgstr "Data Flow View" + +msgid "TOP_DATAFLOW_VIEW" +msgstr "Data Flow View" + +msgid "STB_DATAFLOW_VIEW" +msgstr "Data Flow View" + +msgid "MEN_DATASTREAM_VIEW" +msgstr "Data Stream View" + +msgid "TOP_DATASTREAM_VIEW" +msgstr "Data Stream View" + +msgid "STB_DATASTREAM_VIEW" +msgstr "Data Stream View" + + + +#### POPUP items +msgid "TOP_SET_ACTIVE" +msgstr "Set as active" + +msgid "MEN_SET_ACTIVE" +msgstr "Set as active" + +msgid "STB_SET_ACTIVE" +msgstr "Set the selected object to be an active" + +#### YACSGui module dialog titles #### + +msgid "TLT_MODIFY_SCHEMA" +msgstr "Modify Schema" + +msgid "TLT_IMPORT_SCHEMA" +msgstr "Import Schema" + +msgid "TLT_MODIFY_SUPERV_SCHEMA" +msgstr "Modify SUPERV Schema" + +msgid "TLT_IMPORT_SUPERV_SCHEMA" +msgstr "Import SUPERV Schema" + +msgid "TLT_EXPORT_SCHEMA" +msgstr "Export Schema" + +msgid "TLT_SAVE_SCHEMA_STATE" +msgstr "Save Schema state" + +msgid "TLT_LOAD_SCHEMA_STATE" +msgstr "Load Schema state" + +#### YACSGui module message boxes #### + +msgid "ERROR" +msgstr "Error" + +msgid "WARNING" +msgstr "Warning" + +msgid "BUT_OK" +msgstr "Ok" + +msgid "MSG_NO_DATAFLOW_SELECTED" +msgstr "No dataflow has been selected." + +msgid "MSG_IMPORT_FILE_ERROR" +msgstr "The file is incorrect." + +msgid "MSG_OPEN_STUDY_ERROR" +msgstr "Open study error: the schema file %1 is incorrect." + +msgid "MSG_DATAFLOW_NOT_EDITABLE" +msgstr "Current dataflow is not editable." + +msgid "MSG_NO_DATAFLOW_LOADED" +msgstr "No dataflow for execution is selected." + +msgid "MSG_NO_DATAFLOW_TO_RUN" +msgstr "No dataflow for execution is selected." + +msgid "MSG_NO_DATAFLOW_TO_KILL" +msgstr "No dataflow to kill is selected." + +msgid "MSG_NO_DATAFLOW_TO_SUSPEND_RESUME" +msgstr "No dataflow to suspend/resume is selected." + +msgid "MSG_DATAFLOW_IS_NOT_RUNNING" +msgstr "The dataflow is not running." + +msgid "MSG_DATAFLOW_IS_CURRENTLY_RUNNING" +msgstr "The dataflow is running or suspended." + +msgid "MSG_DATAFLOW_IS_CURRENTLY_RUNNING_ABORT" +msgstr "The dataflow is running or suspended. Abort the schema execution and try to start it again." + +msgid "MSG_ARRANGE_NODES_ERROR" +msgstr "Error(s) in arrange nodes algorithm." + +msgid "MSG_ARRANGE_NODES_EXCEPTION" +msgstr "Exception in arrange nodes algorithm." + +msgid "MSG_NO_ANY_CONTAINER_SELECTED_IN_TREE_VIEW" +msgstr "A container item is not selected in the tree view." + +msgid "EDIT_TREE_VIEW" +msgstr "Tree View : edition mode" + +msgid "RUN_TREE_VIEW" +msgstr "Tree View : run mode" + +#### YACSGui module input panel #### + +msgid "INPUT_PANEL" +msgstr "Input Panel" + +msgid "APPLY_BTN" +msgstr "Apply" + +msgid "CLOSE_BTN" +msgstr "Close" + +msgid "SELECT_BTN_TOOLTIP" +msgstr "Select a new child node in the tree view" + +msgid "PLUS_BTN_TOOLTIP" +msgstr "Add an empty row for a new child node" + +msgid "MINUS_BTN_TOOLTIP" +msgstr "Remove selected row from the children list" + +#### YACSGui module tree view #### + +msgid "POP_EXPORT" +msgstr "Export" + +msgid "POP_CREATE_DATA_TYPE" +msgstr "Create a Data Type" + +msgid "POP_EDIT" +msgstr "Edit" + +msgid "POP_IMPORT_DATA_TYPE" +msgstr "Import a Data Type" + +msgid "POP_CREATE_CONTAINER_DEF" +msgstr "Create a Container definition" + +msgid "POP_SALOME_SERVICE" +msgstr "From catalog" + +msgid "POP_CORBA_SERVICE" +msgstr "CORBA service" + +msgid "POP_NODENODE_SERVICE" +msgstr "Node-node service" + +msgid "POP_CPP" +msgstr "CPP node" + +msgid "POP_SERVICE_INLINE" +msgstr "Service inline" + +msgid "POP_XML" +msgstr "XML node" + +msgid "POP_IN_DATANODE" +msgstr "Input data node" + +msgid "POP_OUT_DATANODE" +msgstr "Output data node" + +msgid "POP_IN_STUDYNODE" +msgstr "Input study node" + +msgid "POP_OUT_STUDYNODE" +msgstr "Output study node" + +msgid "POP_INLINE_SCRIPT" +msgstr "Inline script" + +msgid "POP_INLINE_FUNCTION" +msgstr "Inline function" + +msgid "POP_BLOCK" +msgstr "Block" + +msgid "POP_FOR_LOOP" +msgstr "FOR loop" + +msgid "POP_FOREACH_LOOP" +msgstr "FOREACH loop" + +msgid "POP_WHILE_LOOP" +msgstr "WHILE loop" + +msgid "POP_SWITCH" +msgstr "SWITCH" + +msgid "POP_FROM_LIBRARY" +msgstr "From library" + +msgid "POP_CREATE_NODE" +msgstr "Create a node" + +msgid "POP_EXECUTE" +msgstr "Execute" + +msgid "POP_ADDDATALINK" +msgstr "Add data link" + +msgid "POP_ADDCONTROLLINK" +msgstr "Add control link to other node" + +msgid "POP_COPY" +msgstr "Copy" + +msgid "POP_PASTE" +msgstr "Paste" + +msgid "POP_DELETE" +msgstr "Delete" + +msgid "POP_DISPLAY" +msgstr "Display" + +msgid "POP_ERASE" +msgstr "Erase" + +msgid "POP_SALOME_COMPONENT" +msgstr "SALOME" + +msgid "POP_PYTHON_COMPONENT" +msgstr "SALOME Python" + +msgid "POP_CREATE_COMPONENT" +msgstr "Create a component instance definition" + +msgid "POP_CREATE_SALOME_SERVICE_NODE" +msgstr "Create a SALOME service node" + +msgid "POP_CREATE_SERVICE_INLINE_NODE" +msgstr "Create a service inline node" + +msgid "POP_CREATE_CORBA_SERVICE_NODE" +msgstr "Create a CORBA service node" + +msgid "POP_CREATE_NODE-NODE_SERVICE_NODE" +msgstr "Create a node-node service node" + +msgid "POP_CREATE_BODY" +msgstr "Create a body" + +msgid "POP_CREATE_LOOP" +msgstr "Create a loop" + +msgid "POP_ADD_TO_LIBRARY" +msgstr "Add to library" + +msgid "DT_DATA_TYPES" +msgstr "Data Types" + +msgid "DT_SIMPLE" +msgstr "Simple" + +msgid "DT_OBJREF" +msgstr "Objref" + +msgid "DT_SEQUENCE" +msgstr "Sequence" + +msgid "DT_ARRAY" +msgstr "Array" + +msgid "DT_STRUCT" +msgstr "Struct" + +msgid "DT_DOUBLE" +msgstr "Double" + +msgid "DT_INT" +msgstr "Int" + +msgid "DT_STRING" +msgstr "String" + +msgid "DT_BOOL" +msgstr "Bool" + +msgid "YACSGui_EditionTreeView::NODES" +msgstr "Nodes" + +msgid "YACSGui_EditionTreeView::LINKS" +msgstr "Links" + +msgid "YACSGui_ServiceNodePage::NODES" +msgstr "Nodes" + +msgid "YACSGui_ServiceNodePage::COMPOSED_NODES" +msgstr "Composed nodes" + +msgid "YACSGui_DataTypePage::DATA_TYPES" +msgstr "Data Types" + + diff --git a/src/gui/resources/arrange_nodes.png b/src/gui/resources/arrange_nodes.png new file mode 100644 index 0000000000000000000000000000000000000000..53e038b5fc2d5345ef9df54e6c57b532b465ade1 GIT binary patch literal 906 zcmV;519kj~P)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ<07*naRCwBA{Qv(y12q9a01n3B1b`3*f_rd{SxnNS zuV6_&R6BUGsE5+Yc2HNzw)iM6p^=yC?n$iR2AnO%sDZ}c>W3? zuz?`K*49=Akf9(9(hwCD1(K2m;&&j!fj|hP^vjno3>_UEaCIOY5fK4b3lKnX1AESX zXGm?0X7~qW{{_16kFYRE$_$840f7vVRsrItKYsjR=sp8f+Ze|152)@Z(4~I_1>tG| z0tjp%$cxFf!3>Z4t}y)h^M~QbkFN}Wn;k$>AcHQ0?1Y68$h9f8K@5+2uQ2=ssspQS zbA_t~2q3V5pFVwJm}E1T;m@jrz;OJ<@b}M8aCpLinwr{^Teoh3octXWUK4HRF#KA% z7pU$B&;dVC)B*$$*g%js&YjGFhY5PjBlAI#aqeU$*btCf5P;Dj01!ZoAjOP~jG*xG zgoYC`xC6x7pd21MwIL&AHv+gid-7gfi009Ix5EK#TPG-Tw4>>ELXDv`foIjO|Gn)bg5Y@9DKmZYy g_0Yudss#uz05LZ5oY=3JR{#J207*qoM6N<$f@w#CJOBUy literal 0 HcmV?d00001 diff --git a/src/gui/resources/block_node.png b/src/gui/resources/block_node.png new file mode 100644 index 0000000000000000000000000000000000000000..94b97ba8392842947f1ac88dcdcc15b3c1b1b1be GIT binary patch literal 703 zcmX9+dq`7p6h3!XudnH5X4}l%q@*XgnL{dY*P1p9ABjR?wONWnP=ZQ6_fVP`S(22Z zh8BeckqVMxwujqL873x{C}>h3hUCrXba(gH9sTj0@0`Qov$f=oDk}}3G6q0j z2e6A+UI8eR0{qqhoNEOT+<&HaqyTW_smi46^10hILJB+vB>HRR6&1(hFg79Wb@iPh z;VX`0y7z40k!>W#Z3>Bpr$Qd5rR(ju6ZqsQ>G-!V&7>7+=#6EyQEf(6`GbLZ!;C(D zgz8c2gye#szhn?oo0z=J6T@Sa8;Ol-q?OUTNbr8QvQcI;oB1u#ceOiz|VzE#^g`7P%*=pNkn?n9f2B*X%Settp7XAT44hD8`d3B}A+Rz5rqpwX`F%--X*y zr^4F0#IwVv0fmL}6;U2{Lf6m^pI$oTRj;jD8hvW!H=4CFsh(?yptk14L~i$UQf@Y! zc7^n>p0xEhydbw0t?Pi*TQazvikf^E_l=dHD@Lhx zN5UZHwM%TyEt)&623OGjTO_*(4ZiTX3J=L?vM*1H4SAGrk)_JmQCgt9oDW2tw1zHp zaUZYq$ScTj^Z)p8ML@bx(rvhb#Yqn5U@^T6?ZHbOv0YZ3&{WOXEn{|{1MK}$qN1W6 h#f6a|%W8Xxaky{>-OK0^&3c~?Qj^n_A1-KW{{d$(G?@SZ literal 0 HcmV?d00001 diff --git a/src/gui/resources/breakpoints.png b/src/gui/resources/breakpoints.png new file mode 100644 index 0000000000000000000000000000000000000000..93fb7303e96406b46220e50baaac32b3e2bd0232 GIT binary patch literal 867 zcmV-p1DyPcP)!P&OP>M7?*&ceZl%CQ(Ex3rZCrz*rLgM;wW_D-BL)>K(W3qe54~7Tt z`+c8z@B5hFh^V{!PnMx%JtlGW>ONpK@PE|Z{rx;`Kd=T6&!-~bUR~f=EcW`Y_0He_ zP2E0djEsElI!?Bt8HVxNM;rG3RqG$Ub#0qg57@G-W`Ip^Y(Ben-TNP`yLt1=il&rm z0vO3Resmj*bo;;M}i+v3EPxfAfyHamRaw!dJE0e81dr|Na+3h&RJ9eCbO} z)6|)SwpUv@J30_MviroTxF6HEkB=WTO>-@iFZ!irS#OsMD{d^AbKC%C;payOjU&5H zX5u2QYj#*D%>&!EEv0SSO%sJ_MsnFDBZ;C2fY$a_&iyiA^nBdcA3Y8RN<5w8Q%dQY zQc8Mw0F+#R(WmT{D0?MJu1`yAj5F6W&Hi-IS6N^7N_coErKGehOZRXAcs%o@p^u=Y zy@m5XpK3m^^H6oYhl^!dy0mRucX4_2=pjvQ5>3+(LLh{Orp+B^;|K}Es5%<)75w3M)p2WpPDJ8W;B2kT^ zQ7D1n#PLCY=E+R;Vm(|EiG(gK%hKKF;5Dn)E($9aA5eVw0CVLkq7wAdp!!RO%Pn`XWLSJcbBRhNnDJ6jy(v$w$@7mirlysbbFAiUt<24LJNZ?jJ zH+G<=J1tn7wrtG;l%ED1>(BUI`#Oh`j`KV4*1~Nwl{&p-pjWQ^1W=qR(wolsUCGX& zq~rWXDwVEi^Gj>w!g|vgKRFA%K`NE5)qWkzVv#Y7e3o+h%l$MlHn}3N|HT z+;kJsq8<{7f0mYthEk;IrRt%Fmf|VyX~7_(CpEMXLgM;wW_D-BL)>K(W3qe54~7Tt z`+c8z@B5hFh~3eFe^`W))tG)313Q7`!2i3W1Ha7Db^$8@@nR|h?pFnl#bR%6S?gTC zJ8^6Oka2#mbgExX(Da z?MON<;<{#sqlH;u+qR{&ZM$x4bdsTLX2D3JC<36dxsj8<_Zpp_b@xP1g5CnpX84p+ zx~7zp9v%P%*Pr((dIgGJfr9JP&=}*#%jtT5GUzU?FM0($Jd{#WT9&1IxBxtvdRo&* z(9qn#so##)@7erKdA)~=Wm&qkZCiJ7dHnbhbxjgY(-1-+godWg9H-+53B#y78u2Au z{OcS+5Fm^Q7Z=;Mb*Yq+E-v@S?(tykUQIhTmo7s@8eQM^a^dnBCML&maZyT1Es;o+ zqo@^1AUJ%e&!2iaRlZmcmqa3=OUtr!_XT*x@|E+#^7)74A3elex{Rm*o!v+LFTdE{ ze|qrjcO{Qo%GfZB2;g&P*Syfznw!WB_9LYv@IpFMKlp7sS_hJjbLaHn*%@BLFoXnd z=CUJuD!S90weG|98Gz!mfbV3Ur?E)&9Nv*9NN@OVN&o-=07*qoM6N<$f{%%wO8@`> literal 0 HcmV?d00001 diff --git a/src/gui/resources/component.png b/src/gui/resources/component.png new file mode 100644 index 0000000000000000000000000000000000000000..0c30968b02e5558123974dcbbc30b907aefefdea GIT binary patch literal 884 zcmV-)1B?8LP)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;>PbXFRCwBA{Qv(y12UL1eb0XepwOSce;NM%`N#0* z&tHaLzy2_M`}&jN%abn`84jLlVFU;u7G%vcr|kOg>E+4*GV}jG z28Mq~_|I=3{=>lV``3SlqP#kW_a8oi^#BAA6HN2u-mU*VJX{(6{bc}SkYcbVIR4M@ z`zJ)RqeB40?>}F_`Tzn5?1Hw2wf|XJnHg5C+z8b8kKyN!-wa>B{$Tk2{TI;2zhL^~ zhp%9#yEq0heE#|d=*4ef0{{XDY{2(#KN&m&BN#y80dnqNppCzQIIqH#p||NY*fqa^ zwpUdbgEfBv8}J=$06+kNz3}ZT&?c}G8GyDkF#G`G_)Im1wyIMML9rqXKfe8E`26`Z z*x6sczGe9O?E}N#zdyhR00a=k1wbc){0a6u)b@Ap-T`f8U|2BuHNy{}so%bRWcd5< z7cfS?g7Lrqf4~L+1Q6JOpFe*CqYPreUvMD)2P*mni4Cx~{(>=(1#~)4?Z4kZ@xNdL z00Ic?1yEdrqYJD7==^LMApajjKrAa*<6oer-+zDx{`&)T-FG1V0XG03fWQX)_zrOa zEV^d*KLLir4~8W(UIG35j^Weiw?GUDxNqM-0=@JZXxVSD0RRC6_QK~+-+_Vm9~#=f zz=}ZN^_xdPn|}iNpBO%Udd=|rFE9|ly#>4C-#C@tLq@SW!>iX1 zAO^gC2zJGrw~rX!eRu{=JU@PXX1IIrD#M!(7Z^cm00Ic?0+7Vp_s@VXdC8EQI)|Za zas)$IKsCdgcaMS2{Rwmh(2Ku*fTQujqgxCgKHp-5WdVQyVgyB#nq2h%-@kzg00RK~BlTkxJsS1^0000< KMNUMnLSTY!=aHxY literal 0 HcmV?d00001 diff --git a/src/gui/resources/connect_to_batch_session.png b/src/gui/resources/connect_to_batch_session.png new file mode 100644 index 0000000000000000000000000000000000000000..33f8362281f290b5fb302eef4740167a5a749893 GIT binary patch literal 974 zcmV;<12O!GP)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZw13&=bH4tO~JC8U6DBeJt8UI4W;64E| znScLh=$l~7ke7Fgp}tj<0U&_z8ut1@_bTw>U^U5&xs?mSp-#*CQ^ zDJjVe-@kunSOIeF1QUkOnY$PO0tj!U`~ij!NP~;h8K7Z`45lVW84es$V)*pw6GK!~ zB$%ExYc|8*zkh)~_{Z@3=T`=R0Aj-LWd?>{zkV_7*{jZAW_p_8)EO-XZOxMmKY#vY zSh#Qz!=FEY7-C|g89-?nWZ>VwzZd`lh=oux`1u%f%K_pYs;a7Byk}_+*fljZH4K`XT40x~Sg{g}L15Xk&xCo>cz#_L&=%vS1~aRXV0EvxPJW_LyMXr!>=!28CLQ# zGN`DiFsxm>mf`Q8p9}y2#L{c+;%@Nx4a0w+YdQ^W-0$4K&+zm1ZHE6q7ybM8jo~xU z%b$UAe}IAR`Q!=1OC==+_uJ1I>>j*k`1lx)01f>L^u`w;{si(i(EA__2gSu1?(W1DCKWgP^oI12YR713&z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;r%6OXRCwBAU|?YQ55hpeKr9S`^E6_!#9Qx@4qs3>kLF9XQDKff6me*I)%`1$icLt$B?fWTg8s9eFo#?H#X#Kg$(>(?KK z_wT+iJbUtv;n~x73|Sc^3=Pc%3^yJwWW;6wKmaj;Z2$D}JA;dpKZBElAH(^p%Nb6b zpUn^(na}X<-CKrd&u=sQ`uz#33qX1S0toDdxUh)~-@h<0{QbwkaP{g{hR&MH3=baN zWcdE`HN$U)rwpm-u?$VstNwre`U4m)-@xJW>g7jE<;JZ2{>k+zqrHj?fXZd7rrv=*tvn>#k&(=eEItK!5=NL_U?nI@?mS00000NkvXXu0mjfZYXW~ literal 0 HcmV?d00001 diff --git a/src/gui/resources/control_link.png b/src/gui/resources/control_link.png new file mode 100644 index 0000000000000000000000000000000000000000..29a30905b45500ae9cac8eca4d077cfba1a1d985 GIT binary patch literal 439 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx-l>?>Uz33hE&{2`t$$4J+mr>3Y9T*HBUgo*Pa=9Z%!ia%G zLCneQ@n%^T2BwbAMkfXV2N7u?5y9(FZgj$X$04A0iI1+zh8ux`JyVu3H!w6+D_T|> zg-yP6d3j<-ISc#YqYO+OISw^{TK>{>*I}| zynfjTRCvMWxEn*0g9xkqV+PTiOu3QMQw3klG5^lU+hcy~$}PjQbMEDzc{9JZK1=t> z9zn$=C*P?*y_(Jw^QbF{Jig*G}#004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0004sNklC4fPYxXaoxffqF{c0Z2&@2 zObkRi0t65vv0erlcKGmNZd+U1uej6z<(mNlh$sVLh5?z1Kx_uZVpx=31qdL52BH}T z@+*vu&A|Hr0mKOO0$vl*40{d4ub_r!jTHa{5P#Uf9_HI%PWhRq2m>LM56BQu*uV@Ulnwy`h@h8Y-iEpi9HzL^AyAzn zKmf5oy%i3`+Smdai1&k%3eX_9Aii`65I~GTLIK2p20TU}LnGl8G~B)d4Zngf9RdUp zBQ(IpV6i4ACx@cp(W6H?P&rtV5rg^$YdQo7Ae3~ds&lFe=G?x0n-Q6R=gu8&Buho1 zF^@GJ0t67=ybLoK3Lbz6U;)4dWn)c;00BgDX#E#KL7v# delta 431 zcmV;g0Z{&w1lLF$&n!#e+P6)O+^RS0}T!f0q98JZ2$lP zYDq*vR2b8(lre9@Fc5{GOD21EW;|!cbCyah{V|oIh^0Hq!Y`u0ISssN+~2s(hCNld*q@hptbG=e**xv-EPBTvA}M(YkcI*W&>kPZ(t;Z zfKsY4DTF|lWk}N$#+bl4XI<7~L=?)hY*Y=vQItH-QGe_<>n)c{M4WRr91dGY@ZJaK z9Ezeiy5wQ&)zGS{kmvd1);ouGS+DoD;hZz2RH$7drEIp|tqazB-zuUI;&xzHJmH_? Z6%Y42;lA0rX!rmC002ovPDHLkV1ljF#25eo diff --git a/src/gui/resources/data_link.png b/src/gui/resources/data_link.png new file mode 100644 index 0000000000000000000000000000000000000000..db71822b2d18ed0b48e6f98959f5176be8c21564 GIT binary patch literal 440 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx-l>?>Up|2hE&{2`t$$4J+mrL2;BnlIp~*pnRsJ!9=uM{F$mywqFXotkXXNcMzkB7D;n_L&^3S~4|08$F zHK%jZf=;vE)CI-W9y_4Aj$;}FQ+wmAs8j#<*Y9T({hLzpAwkz`Q)pNpqt?&U1@G?_ zZK#;gbm+gm1M@$ouer5z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ-!bwCyRCwBA{Qv(y11Z4H&JL%BLx&DA0t65X0~w&T zwG~6Gy1JTyk&#gWAb?oNaoxffqF{c0Z2&@2ObkRi0t65vv0erlcKGmNZd+U1uej6z z<(mNlh$sVLh5?z1Kx_uZVpx=31qdL52BH}T@+*vu&A|Hr0mKOO0$vl*40{d4ub_r< zV^RJUAb`M;!rZe3L*{RZ56CbbAQObSpoZNC`sf>!jTHa{5ZJ&T=G$OS`I)B(10j?T z$PiH2zzidl4gms)pqF9ZhPn(Krnu4}P@N(`0I@*56%NGO*a8`d_k)rO&>*-VzH|r> zK#V{_0mOg?JVqcxBjFV^+`a-0zk)9v0t67FtgP&RCMG5ZQ1bcx`!`tP`Sa&Gl9G~F zSXo)Y{9nI*G5r1emw}m?nc>BY7r9X1U`>Yr0mSm?(IZAxRaI~}K79BP}1{rUgjo>}w2xpREW+nn3^44GI2xS1svY~3pAyk^&~S&b7X1~Mu% zM4TwRdq{jyLS0=hgHweGnBs&l@>KI4S-+sIC^_(-s6xYmiHGiN zW_5m+-^qW%KvqGxW#@vnyX?PSNKfe%WndAwaX{|b?F7G{GnaEPD^B4*ArNrm0FUw% zKA?3ArYGKO+r=ZZY{wzKxit-(~b%RN=<9qWYt_un~6!w*H2srdOI58e+ zV6$;ka8`aOYI0{E6Yu^eeOaJC7H``0>A!vbKLZ8z`R@I4FAv-(Dk=*9_xJbl58vO% zZH1r@w4JB6MFt$5fIaCjqA14EM16RQae4S2ZuYF;ri zajb8Au}+x{=-b6zU8m}E);XDpOqVfZ0J?lh7-I{ALjxm2c=_?pPle)BfpN{?>FVdQ I&MBb@08&)dUH||9 literal 0 HcmV?d00001 diff --git a/src/gui/resources/execute_in_batch.png b/src/gui/resources/execute_in_batch.png new file mode 100644 index 0000000000000000000000000000000000000000..1a42e231c5fc5f196e775805163905cc9dc9f700 GIT binary patch literal 837 zcmV-L1G@Z)P)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;yGcYrRCwBA{Qv(y12q9a0I`6G`7>YqXXjvIU}9om z`1_ZE;rH)<41fOMx9In;{|sL~|7G~_{tv_JSHBsaKKaS8b-yknKmdUa{PE)-11pOV z!#_qwpn?Axe*FL$ir*!_e*S0p`sqJI!IMIUzt3JU1b!-DU}R)e1_&UqfnUG=1={$U zff4A!KfnJoeEaqfsNo-81HXU&$ME*eZ?It>-o0n|@$U&p*aIMdzy^Yx&cyVO0Ti4d zgT8$E%kc9DVFN*44fKuoYO1R1nwi8R=--FxL3K79B9#;aDX0%I5(S?u4x ze+(TR9bo$JKZpYW0*DFO)&Rfj414zKFqjx!V7PkS2*pLacJ0D&<-B?GFvI`?2*tn+ zn=~0*oUbsPIcLD2t$7YE?&jtOr$Gk8_(@4g7zP3a5F;pIXC>YK|MFu6(Ca^d5%PuM z{rmUe@WBVb-UKFESQv7#L@?ZcI&lI(0HL_BuC5MDPo6v(OwXJ-6O3VObg`zUCWgYo zLKKSt0*LA^1PCAu7q+*zW4H*}WibAvNt3`dx(fjU2<*b-sGI*EzsUtBozI^?gVPwu z1;n}#M02qOGdz4gV*)?`fnE6S?H`6`&z>>V)YLFkR#r0n`t^$;H#ZlIv9UpPMn(oh zbaXUBU|=A`;J=^276Akh*oAh+7ydtf2a$kbLM{a91E~RF5Sx?5k>SPL4HEzY2%PnP z{(cG0b};7?Yak4RgMj%bm<9+SNb&XaDFYXC62p(b&lrCFe+yLf5vb!Q0R#VnjA3A4 z1R_ROpaUS~9Y6qqy$meJ^nq+p?lz#Xz`g(wKrB$k7a+bvg&N=vK!5=N#@5jw!6?YF P00000NkvXXu0mjfP19=@ literal 0 HcmV?d00001 diff --git a/src/gui/resources/icon_down.png b/src/gui/resources/icon_down.png new file mode 100644 index 0000000000000000000000000000000000000000..9c872192d1481f4a3e3dce5d7cf7c9c29bbd18bf GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprE^_ zi(^Q|oaBmv|Ax$}GnCG{NFO+G;Ddadry0Ziv?exzOExmR4%Zww9+xm`&MK^Gj5u3y sxIyCVmVVY5iWN^eB^@p>dGRtZM5}x5U2;x#I?zZ4Pgg&ebxsLQ0E}5JQ2+n{ literal 0 HcmV?d00001 diff --git a/src/gui/resources/icon_insert.png b/src/gui/resources/icon_insert.png new file mode 100755 index 0000000000000000000000000000000000000000..576efe7dd98c2ad3c66141b7170d623518b30fc6 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`^`0({Ar-ftPCCeYK!L+GQLTKF zac$b9nL4+!W~oU$S~$HZP`GlRe+pNa)5;}PvN@rmdC`2#MrsFUrRPgL2)&b_?sRTt zmqxyO17pUPQxBb4loKuNywPH{Tn>Is0 h$J&3tgzY;Em@3aD3A)}XI1h9RgQu&X%Q~loCIIM=Ltg*@ literal 0 HcmV?d00001 diff --git a/src/gui/resources/icon_minus.png b/src/gui/resources/icon_minus.png new file mode 100755 index 0000000000000000000000000000000000000000..055182e1ac781ed8d8f606e54045aeb043bc574f GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP(s_& z#WBRfKRH2y^{_6Bl!U}T;X@UFc`p6gzl>3x?WC|tgOWJUb`43Re~b(qhl~!3-9N1h P)W+cH>gTe~DWM4fT5>HD literal 0 HcmV?d00001 diff --git a/src/gui/resources/icon_plus.png b/src/gui/resources/icon_plus.png new file mode 100755 index 0000000000000000000000000000000000000000..21a187e52ad8da1efce2ddf54bf380a146f2e9bc GIT binary patch literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP{P^M z#WBRfKRH2y)x!Beh1%hI2{r8*4zteBnaOF^QpcuXEq#;KrJ8*i=aZ7084Joa${33h oczqNW?QU39;t+O+zeA1TL2J^*iw@T;fW|R+y85}Sb4q9e08NuO&Hw-a literal 0 HcmV?d00001 diff --git a/src/gui/resources/icon_select.png b/src/gui/resources/icon_select.png new file mode 100755 index 0000000000000000000000000000000000000000..a79d19af94c8b615dd8e6ebd8634453ba58289fb GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP`w+O$rh+6^oG@#H_PZ!4!iOW|f8}czJ3b@LzXqDpT zH*$aI(_&mG!k2VLENV?3@9Z3&-OasjR!0B-O8#KjAD6duneClxuOv2R(?IkFe_Lx{r6dQHsLo7)g6x-H+~l~U2eos{XlHdoK<1>E%!6TOBICo z%nIJgfX3-FVdQ&MBb@ E0KmgtNB{r; literal 0 HcmV?d00001 diff --git a/src/gui/resources/icon_text.png b/src/gui/resources/icon_text.png new file mode 100755 index 0000000000000000000000000000000000000000..ca2c80cefe12af0da7d2da4d6d2b53b3391821ac GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCijSl0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP{Pd9 z#WBRfKRH1nF5%gkng2TvTGaAh^3m}4u&UAXQ4#Bjf<-(Bo^vhYktk(US+eorL=o;K bDk==^8k-uYXrzAvn!w=c>gTe~DWM4fR-rYU literal 0 HcmV?d00001 diff --git a/src/gui/resources/icon_up.png b/src/gui/resources/icon_up.png new file mode 100644 index 0000000000000000000000000000000000000000..45b275007fa72c9d6a7f050d5c0eb42db4775906 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9F5he4R}c>anMprEIx zi(^Q|oaBmv|Ax$}GnCG{NFF$F;KTeJW(f(2e}@fDvMFRAOXs*at5DKuQd&;igf)_P v1#YoEGB9Y6IP0>Mxn>q;RilK@Mn(q7wVr#ge9{jA8p`15>gTe~DWM4fM!qlz literal 0 HcmV?d00001 diff --git a/src/gui/resources/in_port.png b/src/gui/resources/in_port.png new file mode 100644 index 0000000000000000000000000000000000000000..6c5e06d9905c19acc0f1f383273d87eec5ea1471 GIT binary patch literal 642 zcmV-|0)737P)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ-_(?=TRCwBA`2YVu13GrHZTpW+92*7*ASMQEfa3!L zu>c@|uo}R@&Puca00G2;O;A)+0M71g+wz~8nTg@YkKYV`|NeuEfBX82;ql|Q3;+Ry z)c|pEK`>okz3zWXY7oP}{|rFQ3_w34)cpO!05p_=0U&_jUZ`(e1ea!IVP+`KU-myC zF$k{n(JO{uzZe)^ynN3P8lA%M8_53p^)thpx6c^>0*J-ix8^@PhY-X2ch4FA{N-k_ zbtwMN#l_C>^CJ(#pWhIt|NQwIXCMLu5X;uhEsP+BqH+K*TK_UUxVM>6Qzzv=^RNG4 z&Hw&E;u{8*&7Z>%m6!tO0|XE}5dZx7#_;&zF0f&L|Ndn7`RyCfTVEL%89_q-ak>B? zfZ$;O(+mRt|NjGe=L^G=r*|2iJ%7OP`}bFd7cU-x>6b4bGxT@V1HJc+;oZAe3;+Sd zi0nKVP}PY3fBVK#MhOw$|M>+`49v{TKm-4vc;yE$T0VSy%K#8SSknO`BgA1Z-fU(R z7O?sM?;l9>FQ7*d2?^v%U|xW2q3Hm`~y0d cSO5@U07pUvItt2gZvX%Q07*qoM6N<$f(~dEu>b%7 literal 0 HcmV?d00001 diff --git a/src/gui/resources/load_execution_state.png b/src/gui/resources/load_execution_state.png new file mode 100644 index 0000000000000000000000000000000000000000..b5a04eb10f7eb916ab97d88c1d77854083a474bc GIT binary patch literal 756 zcmVz@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;YDq*vRCwBA{Qv(y10y42Dgy(98v}mu2#9w9@lIqx zfB<3u82|)p{^J3^|NQ;`_{p>HQqs~ppcXN~^aBJC%z*WO|Nj5~=MQ%L^3CV}|Ni~^ zfBxc?Z~XlHdw}X4VTJ$%5ZC}O)1&`k_}h>Fa2kd$Tz~ri$8U)Ep(7{1aB_0)2I{o{ z83GVMj3B{nr>(bLxpCL){f93M?YUntJYO|KnxQS@DV(2N^WpQ{76D$MK3;$TVg&NJ zfrfx}c_!aw;O60BSTj)^%oY=uU=S4(XXq*T!eAKoh~fMyIR8egmerowm8p!0>-DKmdWg z05i=q<0XTTh&aQ$H!m5s&k#rPhFS0>hEr?xz-+t7OALpWL)ZWT1oi?DZ=JDlo&C%S z%?znUoeW%D+zfACzhwCF?F++Opka?6-enLL6=#r@Q)c-3?JENh2LnTONhT;zHUb0? z$N-R48w?E%EpVkE4I^iU8|U`I`H{(m3}rcSKrb*X2M8cg7<>U~u2NUWs=4jvO$M)9 zCmDi}0a{&T~1sc(ucJ6)* zhjwmaVBr?QFo2JXhk>0-92hHK8NLH!hM$jz0h$-i00a;tG&@&<0vGBUb|C%-#W3&} mi2p$S%?#yV2jVFJ0R{m7DI%0g)XdWW0000z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ-&`Cr=RCwBA{Qv(y10mq#dC#0KEQUBGKEn|HD?i+(_{bPo||Nk-k{`Z^V-@l&>|ACnK-yeos zVbXBTno6DjuiqW}Vj7{%?BqD&up-=Ks$@QTX>S!*?M53Ni$!`415P z`pwPo@Y!szdL^0s|M#9uWCRExj4)7=Dfs{Q-*<@9{{y}7{}(7Sp)O=%c=l=~BeHsc o0AeI2H{t^T0mQ^WApi(407&bCVF?9^QUCw|07*qoM6N<$f>^x%y#N3J literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_batch_execution.png b/src/gui/resources/new_batch_execution.png new file mode 100644 index 0000000000000000000000000000000000000000..0ab240dac5f95e04d459dc2715179168700bb678 GIT binary patch literal 709 zcmW-fdq`7p6vxkY*EGGh*(#?NTgWKzv8z)_#WwRzDyGrnk8)$(6?*6*-k8{49!0ft0KJV$&$0XTEG)|@$_JjcR;Yh00uRn_!G1r2bjO>CS1no_t}&fnj3y=^hmGE5USw z-BT{)<&b`hl%UckeTeXB;mJ7UXZ>yXAvgbxUfFWTcPyefGdlVs+FwB ztVEX4{Pvrac*gXBDg^vItb!mx|5Gd<(CnPF8!dc_q!<&3@|L?e@p~(G5l^tW|goeU-pE3?6c)sF_t>6e4t%z})UN948t0lQ{4XaE2J literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_block_node.png b/src/gui/resources/new_block_node.png new file mode 100644 index 0000000000000000000000000000000000000000..f0e3aa56c6ae0a2de414ca9ddac51fb54bc80d63 GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Eg6TTIlmGw# literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_corba_component.png b/src/gui/resources/new_corba_component.png new file mode 100644 index 0000000000000000000000000000000000000000..362ca8cdd62f11c7fff40686c157cc7d4ad9439a GIT binary patch literal 706 zcmV;z0zLhSP)b?K~0#8Xq zK~xx5rIEjjT}2efKQCtg152@te}TOL1Bum|LIM&}35uA)G?IXbND3iXte|2F3mXLs z3mdVqRSO%Npt7zSb>F>r-+gyx?#!Gy=UBX#-Dm9=PB-80e19z5on74j;2X!GsiMtj zO{uk!Vj+agdQ1#`;P~&6Z-01aaekNl(feQfmFF(u4sKvO*92Mvsm|*+-{fSq2H@Ny z^1;2Y{PN{Xn1bo%ag*J1q-@9+pV>!R0N^~p-M7B*y}ify{If4<%_v!jF*DBoz<2(9U6E(dqG@#+(p8T;4w zFjG_oX%)AI$c#w-uRxwR4j#?*@q2%ebLP_zj|p*LJ@u@oO>t=+$z{S^<|fnUa0m zb|uXt0L$(OX@xYeS+AFf214o)nK9exU>p-AJ0T9lG!o(o0LR@SRWkD&m_m=VKuiOw z?X<*m0AWg;tp1`O{^aFbPjS3F+z2dxW7!?i^+yb=hcr#(Jn_q~KhdpzT%0;+n&?j+ zGLHZ7+DrF&_uv{Y?BAgqen+HGWv0}OTIKNQ0juf3f-M&A&V?smbdd?sNYjK`!K`A| oa17jVoCOP3;pbEGslflizxyNgV=@!;Qvd(}07*qoM6N<$f~p-yEC2ui literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_corba_service_node.png b/src/gui/resources/new_corba_service_node.png new file mode 100644 index 0000000000000000000000000000000000000000..5fba5b51505bffde96a064af95bc9c304874924b GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef`#J2uK)l5 literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_cpp_node.png b/src/gui/resources/new_cpp_node.png new file mode 100644 index 0000000000000000000000000000000000000000..da1222f5c3c83c4cea6a56e7dddeaec1d1e6fcef GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef>NHqEC2ui literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_edition.png b/src/gui/resources/new_edition.png new file mode 100644 index 0000000000000000000000000000000000000000..cbfcf19545590ca95e2cf22451a5774604cb6805 GIT binary patch literal 624 zcmV-$0+0QPP)#f@NaA>F!i;l_;%H+}-YfZ#?^ zD7aFQF05_hCdGyArV5t2)=Wh$iP}tNGXJiNWX7}&#RG?T-{W!az31JhLu1w>3?x0hfSGQi=*=@WR9NBWQO5LIFR{aA9Uzf4TI! ztdv>+^4X-7AOb%e?p}6moCi-=`SJ4?XG;^z&P*0T&4Qdr1hS3B4xKKNP^W8Aq}8GOG{z{n1k z`tVtuSU`>RGOxV10hpVzsIJ?o@Wz%+dD4o3Y-Uj4_KkVG5Y)HrXxZccimnO)^Vtmtu5eQV&b%EntXG6wfTU`7x4iUWb`5dy%oST z6~JlWVj^G^3vgya4IQLR;#eQW0sx}`Neg#@1)vCw@PGIWEdB-3@GkQ@U|CcE0000< KMNUMnLSTYSdk-W4 literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_execution.png b/src/gui/resources/new_execution.png new file mode 100644 index 0000000000000000000000000000000000000000..541729ceecff885d01b2aad83fc344f8ddd5db55 GIT binary patch literal 700 zcmV;t0z>_YP)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;GD$>1RCwBA{Qv(y10y42Dgy(98v}mu2#9w9@lIqx zfB<3u82|)p{^J3^|NQ;`_{p>HQqs~ppcXN~^aBJC%z*WO|Nj5~=MQ%L^3CV}|Ni~^ zfBxc?Z~XlHdw}X4VTJ$%5X^v$KY#!K|Lq5MeBt`j|3858Uw{1lf9S}`FPxm5yMcNv zK!yMW5X>ozfBrEr{P=^3fBj`(`10*H!ylkMzy2{X=o=exuid!S3>a=fKz&>Q0mK6H z%5R{;Uw^QN9t#@>!{qrp8D72qz@V-o!(eT!%?Gs8nt|cJC_n(g3}AWk2 zX^>-C00M{!*?_EQdvL%pa`1y`7yyPL7=u7gj6E!@Kn5@X1Q3b~+GZbQ_ytt>?%hW) z4Fkw*kec6MUqjLXKmcJ4gGIZa!f9kSS{PghVjqA2Vua>}ZQD*g^?dpU=zK;726j$v zhM(WRf@zTXFgAz=0cjBi1}`(|t3YN2KmftKU?e3a#qj()#BHGPV&vij(+ofZnYj5F zK)wLcARr~h2%?mM*c2duU0b^B7h7oH*VuFPj6oAwM0V{|A2q2gjih*oU(gaz- i%s?Et0mO>{0t^65WJz~MzFlkp0000HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Eg4rm*i2wiq literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_foreach_loop_node.png b/src/gui/resources/new_foreach_loop_node.png new file mode 100644 index 0000000000000000000000000000000000000000..ba9202ae4a214c87bfb5b1e7b13391a460b808a5 GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef=`~nDgXcg literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_from_library_node.png b/src/gui/resources/new_from_library_node.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d170bc1df79f20473f4bcd3fbc5f992c37c23d GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef`2f-n*aa+ literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_inline_function_node.png b/src/gui/resources/new_inline_function_node.png new file mode 100644 index 0000000000000000000000000000000000000000..6a130c10d25601bcc08c3da92f54b8859196ba64 GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Eg8DPTPXGV_ literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_inline_script_node.png b/src/gui/resources/new_inline_script_node.png new file mode 100644 index 0000000000000000000000000000000000000000..2dac9091a9fd04a3a58549a41964243b4a0f995d GIT binary patch literal 462 zcmV;<0WtoGP)NfxY0b5B# zK~xx5-I5_sTVWK2pHsSI76GDS0XKmnh>HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef_U7(_5c6? literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_link.png b/src/gui/resources/new_link.png new file mode 100644 index 0000000000000000000000000000000000000000..f978559cd353a86506a41462fd9adc3cd2032c48 GIT binary patch literal 430 zcmV;f0a5;mP)%yGmu zhNDY0_#!OFHIXPU_WqSjUIf^AJiZ)r)j*rK($16k Y4Wrr4&vnH3mH+?%07*qoM6N<$g8yr=%K!iX literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_nodenode_service_node.png b/src/gui/resources/new_nodenode_service_node.png new file mode 100644 index 0000000000000000000000000000000000000000..da1222f5c3c83c4cea6a56e7dddeaec1d1e6fcef GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef>NHqEC2ui literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_salome_component.png b/src/gui/resources/new_salome_component.png new file mode 100644 index 0000000000000000000000000000000000000000..33e466d0ec9f6742c61186e791f3e3317643f199 GIT binary patch literal 706 zcmV;z0zLhSP)F>r-+gyx?#!Gy=UBX#-Dm9=PB-80e19z5on74j;2X!GsiMtj zO{uk!Vj+agdQ1#`;P~&6Z-01aaekNl(feQfmFF(u4sKvO*92Mvsm|*+-{fSq2H@Ny z^1;2Y{PN{Xn1bo%ag*J1q-@9+pV>!R0N^~p-M7B*y}ify{If4<%_v!jF*DBoz<2(9U6E(dqG@#+(p8T;4w zFjG_oX%)AI$c#w-uRxwR4j#?*@q2%ebLP_zj|p*LJ@u@oO>t=+$z{S^<|fnUa0m zb|uXt0L$(OX@xYeS+AFf214o)nK9exU>p-AJ0T9lG!o(o0LR@SRWkD&m_m=VKuiOw z?X<*m0AWg;tp1`O{^aFbPjS3F+z2dxW7!?i^+yb=hcr#(Jn_q~KhdpzT%0;+n&?j+ zGLHZ7+DrF&_uv{Y?BAgqen+HGWv0}OTIKNQ0juf3f-M&A&V?smbdd?sNYjK`!K`A| oa17jVoCOP3;pbEGslflizxyNgV=@!;Qvd(}07*qoM6N<$f+Dy^9{>OV literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_salome_service_node.png b/src/gui/resources/new_salome_service_node.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d84ff6981a3216a6bf84b3fdf57bcb86555634 GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Eg0f7%zW@LL literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_salomepy_component.png b/src/gui/resources/new_salomepy_component.png new file mode 100644 index 0000000000000000000000000000000000000000..2b126efb586ad0f3202007ab1da8156ef88fa443 GIT binary patch literal 706 zcmV;z0zLhSP)F>r-+gyx?#!Gy=UBX#-Dm9=PB-80e19z5on74j;2X!GsiMtj zO{uk!Vj+agdQ1#`;P~&6Z-01aaekNl(feQfmFF(u4sKvO*92Mvsm|*+-{fSq2H@Ny z^1;2Y{PN{Xn1bo%ag*J1q-@9+pV>!R0N^~p-M7B*y}ify{If4<%_v!jF*DBoz<2(9U6E(dqG@#+(p8T;4w zFjG_oX%)AI$c#w-uRxwR4j#?*@q2%ebLP_zj|p*LJ@u@oO>t=+$z{S^<|fnUa0m zb|uXt0L$(OX@xYeS+AFf214o)nK9exU>p-AJ0T9lG!o(o0LR@SRWkD&m_m=VKuiOw z?X<*m0AWg;tp1`O{^aFbPjS3F+z2dxW7!?i^+yb=hcr#(Jn_q~KhdpzT%0;+n&?j+ zGLHZ7+DrF&_uv{Y?BAgqen+HGWv0}OTIKNQ0juf3f-M&A&V?smbdd?sNYjK`!K`A| oa17jVoCOP3;pbEGslflizxyNgV=@!;Qvd(}07*qoM6N<$f;P@YQ~&?~ literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_service_inline_node.png b/src/gui/resources/new_service_inline_node.png new file mode 100644 index 0000000000000000000000000000000000000000..d1b2b322401756366635d00a466c4821d9532739 GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Eg5es#j{pDw literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_switch_loop_node.png b/src/gui/resources/new_switch_loop_node.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7b91eb005aa3929e1d1526a2b001cc79be553e GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef)lmCu>b%7 literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_while_loop_node.png b/src/gui/resources/new_while_loop_node.png new file mode 100644 index 0000000000000000000000000000000000000000..adaf74736302fc1efa58446deec6ce37315cdd80 GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Ef)&revH$=8 literal 0 HcmV?d00001 diff --git a/src/gui/resources/new_xml_node.png b/src/gui/resources/new_xml_node.png new file mode 100644 index 0000000000000000000000000000000000000000..3ff4b4893989b2b5e1b6cb9dd65a406257625e2a GIT binary patch literal 462 zcmV;<0WtoGP)HDznu_fQOf^g(CMFP|%1^+N@C!%?3z?eR zR2Qn2Os}GarfV;7n|tqfzVDowZpk`D5KH!|H}9J~$;o-e-Fb{^%fUnS9{}ph!T!4s zE(;%{QI?UaiWG&C=YjLf*S~6D0qF1T`S$U#0E7@}ydB~0L{F4f5lpEpFx*`SV0-Jp z`(KX)7AK^l;7h0D0JCX9ruWSBmZ@e;L&lFVW2zbBn;d{FoAZ3L>j3hp-F5&sLuxe+ zCoRr)zTqi>Dpd%SF;b;O`|~rv2s+_OeHD=!^%oZx^0C=;HKWz*$!N3dqwyFuqezLl zDrHJ&N(6n%V00>twO1~(!uR2c)B)~Pd3kju02(s}c}^MQZ-AN+&CqxYK(dPA@I(M) zdCD7&H=eA-Jz%bw1;7@qa6Nhd#~1zrJXDV!(!U4%1R=o8pCv908~^|S07*qoM6N<$ Eg1iF2b^rhX literal 0 HcmV?d00001 diff --git a/src/gui/resources/node.png b/src/gui/resources/node.png new file mode 100644 index 0000000000000000000000000000000000000000..11ecdea893ce990621e27186c561df7e88f69d4b GIT binary patch literal 559 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx-l>?F7l!(Qh68awe*d*T{PIdjLCwDU?{gm> zet(|leSLjO#rNOLhj+)zOWgZc#hL+W?fp-3QNfVLT2VXHVb$r|~Uw+2N|M%_L z+|<5UJ~FFcFiFH!f0v5NV`cWWi~ke~ezufI3vS)+0SV>#~b|N9%+D&|=o{UMX_>2vsc35P%L9em>(+x{?I+TZx&dOly9`}yaF zUY%_J(^FE?Dt_dcDFc0b_xq#@iIUN0|vzdXXfwJwfX>zTn0~9KbLh*2~7YK+vy$v literal 0 HcmV?d00001 diff --git a/src/gui/resources/ob_bloc_node.png b/src/gui/resources/ob_bloc_node.png new file mode 100644 index 0000000000000000000000000000000000000000..709d97ff66265c20e5b888bc5bccb00018d08800 GIT binary patch literal 146 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|k)AG&AsjQ4|NQ@N&#c+d+1R+S zb>ha>i4#589{>OUKUzX^@xS}38Q+ZDp3eIJUsBO;*YSe>1#GHpsx6Z{3T<5^g$=zX u9$Yb*t$lKYf{ce%Bgex;g*h%Z3=C2WENw+ozC8q5!rhy8j z3E_}mJD({sGczCl|NnpGtf&8k85K@N82CDEtt2JNrN4VhOdvhXsiuV?BwZ^TYGfvUSbd~Wk^J!&A@1@(c z^q1eh)OhGW%m3!nK~agfn*F?V^uDk;n5_N%aB|Kb_RcW(nRbScegdsy@O1TaS?83{ F1ORt~J4gTk literal 0 HcmV?d00001 diff --git a/src/gui/resources/out_port.png b/src/gui/resources/out_port.png new file mode 100644 index 0000000000000000000000000000000000000000..13d3c5adc614614d1c7e3b9ed7ee6fb70ac21737 GIT binary patch literal 754 zcmVz@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;Xh}ptRCwBA`2YVu1F_i7qUArj7(f6qF^~W_1ixa4 z0R#|92Cy(=DhCK4mg@4=|Jm4C7?^>QASeC$^_St-&p!{&`}f}rzk!NhzWfLb3kHVg&pt5x`0)qG{>kw9^Lqwn zuFnigDnb9**#&`N^oK!1EAc--0I_`j1To+>(6%o?!@hk5D*p5lXxm$cA3r}ZJbru! zNPhhNOc(f4(z3daxZF^Z)_GGJR$}Lx5i{!{n)j3?DzeW5`Ue zWGF6;VtDra0Z`K?h8Hh@2LAa4jEx@*O#gm?4S;C|0e}EvJh=D$|JQGxF}!>Cis8eD zHw>SEe*OOK3($}MfG+wAbowub<;%7+y!&{RQB1=0|Em|LQPKoJ0I@_z6##Ae%<%W` zSD=RPK#f1a0mQ(-2!CSinepQs%@E0|+3J^1{EL!Wd!z k0Ys7k%uE~@VgLaK04wilA7$-0>Hq)$07*qoM6N<$f)@Q#bN~PV literal 0 HcmV?d00001 diff --git a/src/gui/resources/pause.png b/src/gui/resources/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..75f61fe77fe60872f951ff9f73c8b753c3ef75bd GIT binary patch literal 609 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`j)FbFd;%$g$s6l6(v z^mSxl*w|O|J8&|PuaN8!}1{rUgjp4pVqfx*x)K$3w)fZNQ`&CShKL6zm{Jl9EwRL?Pd)^uQK zlsqB9kt5>j@=yBoi9hDkrm%4OG`~8i+Ly%Vz>sKM@bXei%m4q@R{#F%>#=eEX=mfr zD|Aa?W@O^1miYJg^nnk5t(gx`*EbMk4EXTp_holXVXJG* z`qRZxWALNPSq2nDVa)c9u^sQWo)2LDSShK{utDmF=nBRsUHdZ{|MRv(G_^7dtZ#aD z_5X#SrA!^gjTOpbh3pDqtuNU*6x?!HbvFEX#2EC+A&2G2qy-7AkBS}s@XVTU@n}Bt z*-Gw9+yV|d7BYON{NfvbsA_Cv_*for!D+L&u-M0VgI)&4meZ{Y-4zR3HN`cInLb8m n%u7A0^p7)x&!U-`MS>x`+wQC|bP0l+XkKzd+ki literal 0 HcmV?d00001 diff --git a/src/gui/resources/reset.png b/src/gui/resources/reset.png new file mode 100644 index 0000000000000000000000000000000000000000..a031c6ef4ce330e0dd42a13003420b2808dd2497 GIT binary patch literal 1321 zcmV+^1=jkBP)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ=pGibPRCwBAU?2^!5mEpUK!lJ15cdM{0U-X&#?1U5 zNPh$3r9fx0aRCstPvo9uo*a6RX`x8!o-9jP)?44;qPAt1|}v323A%EMmC_2|Nm$B|NT3| zhqrGTy!Y;9xc=o!Hc-zrm}Yk@1*3FnrpdKE0x(Cn?6n$RP9O%dd4nxl=%V5r~!C1O&^-5=bxtxzyH2rc=_T3Lt5B5hWGD&Gk6C|f`TO$ zh<^j|3s81E0CX7$gJL#3Ufz|7nGxi|7XSgovTE_&EFgm&h&?Z!zw0KWB+2mi&wmCk zZe|8XUA!6PS<4+lVk@a69#q;CI)UE7KS&kelq;|{U69?W6;#&Vfgyx zH^T>DQ1rFjX4tdkb z@%#5bP=WIXstIPuL#V4jN#;G!9B^p^5J1=r1i6|Yh?Svz@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;)(u9Qn|2sPV|1T~E34rjXjmgRX|M&I%|6E`HUx1_mJUOd#e*j$D8M!s)`lKtsR${tXk60OAKvKYw041?bBE zKzUag83uKJes`d_9}siFTnP|B*bM}_;13Z024X1ShPq;5>xmN#uYuwF320%YiV8?B z4(dua5ChfUV^&2#04(={TLWZ+*Y1_k(kfB?d3;3udHk-V%Iq^QWi$I1$J-AbVAfZ@0fYS3pOehwMSD-;4*ZoCAinfh}1jCURFBtB8`owVh^=nw60ZJ+_f%p|j8^}O_0AfThHGnZ? z1ElhRI20;$4vIl}R~Q%RsaK0|XEYj&kxZ)C(`6vG^StR==QO^#ZB}6fFarSs3;?Z2XlrQnD0%<@002ovPDHLk FV1hG1SH}PV literal 0 HcmV?d00001 diff --git a/src/gui/resources/run.png b/src/gui/resources/run.png index 88416dc0873ba22983ee3918b14e0e3ce76b31ed..4dfa5e4610980d0799a37cbe34cb89a005c15522 100644 GIT binary patch delta 989 zcmV<310wv}2l)q(Du4d~{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2iO7(4iz7=j2_Vd00V|eL_t(I%axR0Oj~6b#(!VWcS;N4@1~Kti)CK8EALG7$}`2N ziwnEZxMc}+X`;K@g)!c7r5A>%QL_soRw$EY{vi&TW=otLb$=M6W5KvVpbFG(6pCA0 z+j35OzSH9cgSC_deJ{Vf@00g?p7(i#7Y>iJLy1VlK$Cc(ZgZzz-+uv%riSVL{w?&u zsPVr5MI>T~twWl`hajEEpj<_5|B$gQpom0_zS)l$N)93Kg37_DfvW()N-U1l-Xi*T zl+ls%c;T?QEr(91+k9!?QBdIbHQ?pTpujF#l$A%xDt}UREHbNE?6h42Rs*OH4jJak zIL&$!IN%pL)0d|B`t%qh?|(@)nWd~e%9OFO>3Q?DO-`#gT)#6NT!)}P0M_+syW96**%o#9X?);*(DcoDFVtlUz?)0QC{sq4F0sX1lqiyQvV8L1 z87>W9#D7zs0MP4o@7#^gxbw#yusxJg6jt-JwzVM;oILsp5=|#|Jw|dl$;|8whmIV= zvJ?^>r4&-TcL-9G1locWoIG`29c$Ja>D3H#b8`q=;J6Ob3w4=(qtkF)2VK*7;n<55 zoC3;nc&f95{RbXG*6W_GNzNn&SdK5_IEs?%uzxbY%)34Bpldpg>)?gMrUWR3y37qO zSN}@kYjp78qvgI99@+aSA0B@kS_FxBitIuLT+nTu$*Yr~>6`P_hYfh)uqh56Holu0 zC%2X&NPu)M%Sz5B=j14<5-5*G(L^$pWa7e=n!u>>^6&BMWYWtNi$(siatOe&9eheq zQhz0EtIW+?37XoQ3B7TGt=_Nl@^pNLh4}>rPM;<8bQgbKyTMZ8HmD-Se2&}GfAjMf zKQQp>$E224Xl!qy^VH$06sqvD&dmG_KV6<+Y-DWx`#pUInxy0SLH0cSAYXlOo_xl} z3w4{~^#SAgQ_q1ds#2)R%l^S3V?(Wtw^rTXj2bWZo?v$RCZoNdqbfL)gHgkERaJkL zD3xk$+OeU5hW0k(TmpAX9;$5;T<(;>$tOBY`Am-y+!d?|g6-;Gw1&#@$;V3^00000 LNkvXXu0mjf-p}tw delta 959 zcmV;w13>)w2ipgbDu4C>_5k+Vphn36000SaNLh0L01FcU01FcV0GgZ_00007bV*G` z2iF4)4HPL7;rLJh00U@AL_t&-(~XtSPh3?L$3JJ@y~7L$1^Od`T^L>1m2uNVcN$A# ziI&Fb0&7hD2f8qByVAJv$HExXh?Wr3#)VC)bWzpPYNX=X;K*Dmy(9Q38W{Cp*QOM}ZB@pP@KDi#1l=4$#!rWHGkB z6^1#Irp|?3_a(`gh-PTUIyhvaE6k@FQ&GeBnDN2PB&-c8@E4@cqE>sW^y*@caE}!F% zOTXh1_n_*{qF7_~%;a~hge$nXN-YCXRHeaZNF_p6vNR@*v}JY?E{6%gCH!$6>3CiP05hO`hcut$V6E*TIH?o-hVpSHkGYO>y_eV7E1S6s#Zvg z<*$p^$PeF!#B%ucE*kbVu*xbmB2Iqz{zgyhfNOJRA#r5W83-XQmcfg^a^>t*CWj{o z0>hIB_Oqv>lQ0TtAWie*`yj9z`RZdaBBJA^9ILEiO+s$+4puBxSEVpqU~+f@^=lQ_ zMyp5OK7YdffA16ekjL7a`S{C^Xlrjr5Yi^ChQN{=&M`YT%jnoB-AB6#Lyy7Yy~hL( zx?%!DrajAwTc$x9sD@Qacgu{Ak0X)b5{FSAOWLH>B@P={-spXk6}N&99WVDB;;92q zV;Zg6!0>IMpSh_yob$wqqnMxLvy-1<1B*)>s(&g5V0|b>MDO07C)Mmok)m~PE6?sf z$XCZ+fL5U}HP7Ni84|FOW$5}41a>2To674B`1!_VD%E+iWGGb@DOMsXu0rf%@Jh3^ zFgriX;7?b#EsSkmzBx5axim+uR%0owAb^V;DKEr6CJI-XzEhy3V;9Fic$cl-Pi=;c zOn;3sk)NRdi?bZ>dWTzo{=-aR0ep?xa)pJFdtCee7y92j&HPM}=8hJ6PP~TQ1l{Ci z%V>U--!2Vu;oOCd?-Ljf9eat+XP)54&(E`5j!^GJjMZ099EM2hw$KJ}v)b#Eud1@A zbFUukdXBM?X~O?uYw>H_C`o*s{pxxc`#4y(deb&F(bUn7F-o#!AA0Y$#ml3d0As9X hcW0>-mv%e>{{cVm)#sy#@ml}@002ovPDHLkV1l%v&UF9) diff --git a/src/gui/resources/run_active.png b/src/gui/resources/run_active.png new file mode 100644 index 0000000000000000000000000000000000000000..745d1cd58a87ec69d96f3171c4cf331d28b1b54e GIT binary patch literal 1018 zcmVE z^Stl#e8TSr#@OTZiY^09;#VEvy=p!80}HJT()s;6gk;e8U%+0`W%O=u(j*=P$yf^I zD0bF&8@mE~MVE1Y_G1R(1N3h|`(@C;QGg&3i6S+*{`(vClhNO}{OxB9lt5+am+Y@^ zAeBnfGk>1b@{G~5)PqNQNXC*p)ok$mi59Z445vk_abt0U$b5uful<7U*jpG;I+TzM z8iR`$$(cFq!WwxmSk@Yq%8SPl_=Jxtr;2*-KFq91=-m*PhDY$bf$**xzN$LH#||C` z1r?rZ+-wmPSb3A8aw(X3^0rB8HI0?DcEEN3L$cclC&t*P*MbcdLTCEwB;TAHW%$Fd zNXOF@l}nK#78YmUesfFHG7Z=FOb5rtSK$S79X5XDN5VtbS)5ux(C3MTQ(jgD5wIKS>*Pe7`2W2Xnm`V?cOi* z@^o~Dh4}^g&JEG}+$sLNd5fjkT~K-Q*$j85|K{f}f1vM;Pgq$>P}5jTbKq!M3YBq&6UI0s!rBIod2V}Rg zIjzmRk)|QzwazwXr*Ctq^9x!_H0zf^!*Ntuec4b-r?q+X>T0SR8<2A`oNam7x=VtK o`*{NTWzg{L_i-%Iw&xS@FLpF07*qoM6N<$f~mpiasU7T literal 0 HcmV?d00001 diff --git a/src/gui/resources/run_object.png b/src/gui/resources/run_object.png new file mode 100644 index 0000000000000000000000000000000000000000..d511655d9ec6a2c1894b50f3e831381ac9c5984e GIT binary patch literal 619 zcmV-x0+juUP)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ-;Ymb6RCwBA{Qv(y10?_;fLK68e%{jm|Ns4G`1R`# z!?*9h7`}b`$-u^;M^ zt51RIo-zFX{Q)cn5I{Ix;N#WzUq(iVfrFD3?6r4qzcO3}YX11?A;YhquNhvv+6lG< zAb=P^2Iy#2{Z~=S{|{n=u!dSWoDISzM)hEMX{ittaS#RwAO>^+kYZ%MolPrHb0Jtv zOw<*_0Du4j6S~?}|25SsFeJT!-q6>rhKpk}03d+Cfq3akE7m}}ed`6#|L@@ZfB$|k z2nw3~XJlYx`1|iC!^e-87y$wZ!wbk578Wwn;s0@|0SF)#nCao6Q~xtE0Zsn%k74!N z9I%U6SeU_bkDshyl$VYB|M2l543`1~5Zr*5FF!FHI8+H%psrf>|KGpgKxh7dD+Fnl z5cm53;^j6JLjVE@uNTm@n@=vg{|Ni~P z@c-W*s0;ss@v|437{x@L|1&YNAW|U^00a;trP&!EzyMD`f_glEH(vk%002ovPDHLk FV1i`n5nBKN literal 0 HcmV?d00001 diff --git a/src/gui/resources/schema.png b/src/gui/resources/schema.png new file mode 100644 index 0000000000000000000000000000000000000000..513ed0251b6c6bc37f585fce2c9f96e7a2c85cbd GIT binary patch literal 800 zcmV+*1K<3KP)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;mPtfGRCwBA{Qv(y12R~$^eR~B>$l%1;xAu*W!SU# z0mI<~(TvFA00G3rfCg^de9Isns=*);r^CR)%*7xlD+0!mE7&kkQ>kd@_U;Ns+Ec=Prd!9`g&G7Bte+DilMg|d}DciQ6!SL$GPd^z93}hL;ef`V8!pg|-`SWjv z1q)U%00a=riIdM6#6Nvuc=O;s1M9c14DX*mWBB;~EQ7pa>VFs5Q+;HEWG^x!^fWtA3pqGc>DGT!_{lA8J<18%K#8SEU({u zWALoEVfgxwfdP~&egnx$lU@cjjk^Er9AXUO;-U=7O8g9beC!NvuIdawe*R_n^XET< zAuvFjnh!Dn1Q5%y<4+l6?mu97arZ967od~AKYGOQ;`s)KcW;lQxIjy%>pwU5M}}|T zK7sk~-acpe^7#e>Kmai+D(CVBr0000&eGFiNh^_#* z0HEc0-ZyqKd5L4pJ(|nT0G%VE4aV3q5nUi65K(}L-uKrSNB2C>gJoF3vp&+n60dQ4nRFTJp8g$D%Jgd zKV(^kBuU^n4&`$BQLR?HYR}B1U#98=*mNA9BuQ7p;eYTlW9<3C!NG#A>!zY80N~_u zxkt5H?K5X~cClxBb{ZtIwRI&Ljs6*pMx}bap3mp=a~#J-hK7bd+27y)*)WV-0BQh6 z0r&wFJx%-m)Z(eC>Qhx!8Xg`-EEao36veMHnareN7{A%J{S3f3fF&Y&9RLsDDWy`E zJx$x_34hLJvlT%Qeix%%c`+PosFc>@mtyZhWcDsGU)3o)zowv2OH-GW|{kCOU%cWB3Zvapf z1+pwd6h$jR)0g)y!tI oFLYhs1n}6?wC_4U%wF*?+oyFFHoK&Q01E&B07*qoM6N<$g1_Rz4gdfE delta 828 zcmV-C1H=5)2Y?5VQGe4291{!&UT~m60009GNkl^AP|}!5}I3ZdPoQ)w8uap^w3j#DPE zfQ8ps%S7}SW9%7YOg%RuS_M!)cvu?)XmZZaa?V#c=K}zx6w);9N-5Jx!5U-iv~Anp z=(_F_(STD*nP*w{06=dNFk_6JoSB)q>^P1)>_D&Adm^R$8Njniz*XC}SIXsbUDx%2 z^oa<2dwYoE_h91~4}lVZqeOJvG)G`eg~dvxa=%uqK`Diejg8Glqj5^pw5M5?{R`j(fD1(QHUJ&K1Ethg z0Q`}U*K9UBhGG0UJ3ISs5Co4mH#dI=u%2aEiHLpx@EH*mUh0x}09-o=KC~kMe6&9s zGyqGCv41}pV~TS=U__(N^`i%sr<8&a;$E7j;iQtTo2Gf) zb=_l(u@|uY3z4R2636kc0REc`0L{eHh8rTh`VL_^30@TsP0 z=G4^GE6^|u+ewmK0kAc;@&HsAV;@K<*OMeU;eUBv$#q>Ah5^nwy4`Lk2!iWEh+6>i zv6KgZo2L2s^z`&kmSt6vBw1;<+rD8Kuq+FmPRDOHn_tIq{Qa;JjEdN+)oK^(_4=aY zILktawcXv_--HnF2SIQz2!e}3h&zW3pHVfQE*6V#&Ck!nFpQGpINz?WuAXVNS|0=G z05wR)`NxJuEG)}9QYaLbq9{tjFuWZ_(Jui00U*cyApZwgusY^h8IBeJ0000N{Ow1=tZ!2(Srw}+XkA0sTnujW&dW#X1lvH^PBM^l5Dn{&4b_R zz2ArLkN3XsM+qh$c{FBEtN`F$fj!rw>*D-uPfyRhs;XMMnrgM0y?$I}(Y+L{Z%Hd?G@+1dG|P$+Eq{eGyb3Pn*M2m*@5;{8gcl04^JSbUbMePC{J zpQ0$qa5$V|j6K=j-kvc{)6z5z0C*;oxnHSNE}Z9+vz;1Gtp>RhS(=PSqklxBQDtju zE1S(`rvyQW^!4?PZ*Fe>SgY0M0aO4C0`LRKC%oj%1DmJox=+`2rN6%)u~_UmS(ZOd zr_-agTJ4_WIFA7g1DGSC7XgR>9xYJnbizw6cLW=TQIaI-=ic7lmy5;XlZ}myy8s?K zj&p>Ft^znkM1fsX@)CfV0~L=p-dkFr)Y;Y5)d2tofE<8V7-N_J+Y@MYU%O~K#|baF zxNAZ_6h-m2D2fB^pq6F*Y1?-BP?lbx)R{maa8=W^=NV&r6cQ0^+io@*jqlI%$)#44 z_&O~gQ54^eL?R~wfx!N}>!Mbxr8(z|#OU>|6>mK#&jPsU^ZES2U~nI_TrTIE&E}I`uh6gwY9Zha=F~Ov(^WrouF;OKfHSLVK^LqAs&xoczF28(9qClmSyowCiB|K ze@;mwPscAF1Z@i*vnQ@stJS;Za@jHr(^b literal 0 HcmV?d00001 diff --git a/src/gui/resources/stream_link.png b/src/gui/resources/stream_link.png new file mode 100644 index 0000000000000000000000000000000000000000..203224459fb17d6897a0bfacd2c5dd27d9e08c64 GIT binary patch literal 439 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>?0v z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0 zx-l>?>Uz33hE&{2`t$$4J+mrr-6~tAz!wrLml3-4h)75FY{dDICP?IA#(#m zlG3r6KVldJ9C~&fYKYKhU=dJW=-~2=&#V$8mtw65loF|CRA`XU^krvYWclt?^eJVH z+S29zhXvkq@U?X_vIyL0`0<1DzkThmV-KEQZCUu^^YiyS4T+qmu$H3C4(ZOfv;JVEr`dVtFjLGXX`vvUhi>oF_SudM;`FHQkznk7OZWSxK z*CB8z<@@AM*V1`n9(5&fDilbpSh@7i|KH!G11|cvvGZSB#4=-35l_I$__pfr)0&Sq zi-`RD&nWdld`152$H#ksZskfem^St6Z~kQEWXqinJca3=o;xHQ7y@Ou85oZoaZqI7 bFkr}^vgQ`wjnARLKxXiC^>bP0l+XkKHvXe- literal 0 HcmV?d00001 diff --git a/src/gui/resources/switch_node.png b/src/gui/resources/switch_node.png new file mode 100644 index 0000000000000000000000000000000000000000..12dbebce38471b635b5bd1948e5e99d5e666df03 GIT binary patch literal 641 zcmV-{0)G98P)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ-_en%SRCwBA{Qv(y10?_;fS4F41ONfVLaGK&*Y5vc zzx-tQ@ZlT7rR!~s00Bg@3%2hrW&HK)55xB#zrcKe0Ac`z0V&wozWqOlR+K3K(*Oa) zh#rU)CENZpLfL=+{b%_3;|~Ma#&5qFUcP<|b^)?_fB*uA!Gns5{|X%)UUogCT`xR`!zkfd&ROKtd>Hz|X@v^Jye^zmEhF{N~F)%VQ zG30&=W>{l#o#FrAzYGk&e>0eF;{>|q4-o%l`2X)W0~@Od!_VI@8Q53^!S(|L5R=ZX zU5vk9zh?OQ;st}w?%j;fpS@;y{^}LOW1!gWw{IEd8b1J<^PXXr@lysSCU%B9k2)Ct z0loC^|8Iu7k9!ya0tg%iAAbE}u(^5_?5E#iKp3&0AeHg|@4p{FCxdMH3wAyuBNGs_GW_}bh2iC!O(?Md z5I`iS14+?PaQsV&MS*F603tahK6|x_QAQ%}KO-YEm=6#@BpVI literal 0 HcmV?d00001 diff --git a/src/gui/schemapage.ui b/src/gui/schemapage.ui new file mode 100644 index 000000000..92217ea5a --- /dev/null +++ b/src/gui/schemapage.ui @@ -0,0 +1,372 @@ + +SchemaPage + + + SchemaPage + + + + 0 + 0 + 358 + 786 + + + + + 5 + 5 + 0 + 0 + + + + Form3 + + + + unnamed + + + 0 + + + 0 + + + + SchemaFrame + + + + 7 + 7 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + layout5 + + + + unnamed + + + + NameGroupBox + + + + 5 + 5 + 0 + 0 + + + + + + + + unnamed + + + + SchemaNameLabel + + + Schema Name: + + + + + mySchemaName + + + + + + + ViewModeButtonGroup + + + + 5 + 5 + 0 + 0 + + + + View Mode + + + true + + + + unnamed + + + + myFullMode_2 + + + Full + + + true + + + + + myDataFlowMode_2 + + + Data Flow + + + + + myControlMode_2 + + + Control + + + + + myDataStreamMode_2 + + + Data Stream + + + + + + + ContainerGroupBox + + + YACS Engine Container + + + + unnamed + + + + myHostName + + + + + myExecutionName + + + + + ExecutionName + + + Name: + + + + + HostName + + + Host Name + + + + + + + errorLogGroupBox + + + Error Log + + + + unnamed + + + + myErrorLog + + + + + + + NextToRunGroupBox + + + Next to Run + + + + unnamed + + + + + Nodes + + + true + + + true + + + + + + + + + + + + myNextStepsListView + + + + 7 + 7 + 0 + 0 + + + + List next steps - select nodes to execute + + + + + layout9 + + + + unnamed + + + + spacer6 + + + Horizontal + + + Expanding + + + + 56 + 20 + + + + + + myAddAllToolButton + + + --> + + + Select all nodes to run + + + + + myRemoveAllToolButton + + + <-- + + + Remove all nodes from run list + + + + + spacer7 + + + Horizontal + + + Expanding + + + + 67 + 20 + + + + + + + + + + + + + + + + myAddAllToolButton + clicked() + SchemaPage + onAddAllNextToRun() + + + myRemoveAllToolButton + clicked() + SchemaPage + onRemoveAllNextToRun() + + + myNextStepsListView + clicked(QListViewItem*) + SchemaPage + onNextStepClicked(QListViewItem*) + + + + mySchemaName + + + onApply() + onAddAllNextToRun() + onRemoveAllNextToRun() + onNextStepClicked(QListViewItem* theItem) + + + diff --git a/src/gui/servicenodepage.ui b/src/gui/servicenodepage.ui new file mode 100644 index 000000000..76989ef17 --- /dev/null +++ b/src/gui/servicenodepage.ui @@ -0,0 +1,491 @@ + +ServiceNodePage + + + ServiceNodePage + + + + 0 + 0 + 377 + 1008 + + + + + 2 + 7 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + ServiceNodeFrame + + + + 5 + 7 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + InPythonEditorGroupBox + + + + 5 + 7 + 0 + 0 + + + + Built-in Python Code Editor + + + + unnamed + + + + myTextEdit + + + + + layout1 + + + + unnamed + + + + Search + + + Search: + + + + + mySearch + + + + + + + + + PortListGroupBox + + + + 5 + 7 + 0 + 0 + + + + Port List + + + + unnamed + + + + ports + + + + tab + + + Input Ports + + + + unnamed + + + + myInputPortsGroupBox + + + + 7 + 7 + 0 + 0 + + + + + + + + tab + + + Output Ports + + + + unnamed + + + + myOutputPortsGroupBox + + + + 7 + 7 + 0 + 0 + + + + + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + CatalogGroupBox + + + + 5 + 5 + 0 + 0 + + + + Catalog + + + + unnamed + + + + myProcRadioButton + + + Proc catalog + + + + + myBrowseButton + + + + 5 + 0 + 0 + 0 + + + + Browse + + + + + + Catalog + + + true + + + true + + + + + New Item + + + + + + + CatalogTree + + + + + mySessionRadioButton + + + + 3 + 0 + 0 + 0 + + + + Session Catalog + + + true + + + + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + NodeFullName + + + Full Name: + + + + + NodeType + + + Type: + + + + + myNodeFullName + + + Sunken + + + true + + + + + myNodeName + + + + + myNodeType + + + Sunken + + + SALOME service node + + + AlignLeft + + + true + + + + + myComponentDefinition + + + Sunken + + + AlignLeft + + + true + + + + + MethodName + + + Method: + + + + + myMethodName + + + Sunken + + + + + ComponentDefinitionLabel + + + Component: + + + + + InstanceName + + + Component Instance: + + + + + myInstanceName + + + + + NodeName + + + Name: + + + + + + + + + + + YACSGui_PlusMinusGrp +
YACSGui_PlusMinusGrp.h
+ + -1 + -1 + + 1 + + 5 + 5 + 0 + 0 + + image0 +
+
+ + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082 + + + + onApply() + + + + YACSGui_PlusMinusGrp.h + YACSGui_PlusMinusGrp.h + +
diff --git a/src/gui/switchnodepage.ui b/src/gui/switchnodepage.ui new file mode 100644 index 000000000..9d8f1a558 --- /dev/null +++ b/src/gui/switchnodepage.ui @@ -0,0 +1,287 @@ + +SwitchNodePage + + + SwitchNodePage + + + + 0 + 0 + 300 + 302 + + + + + 5 + 0 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + SwitchNodeFrame + + + + 5 + 0 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + myNodeFullName + + + true + + + + + NodeName + + + Node Name: + + + + + NodeFullName + + + Node Full Name: + + + + + myNodeName + + + + + NodeType + + + Node Type: + + + + + SelectInputPortValue + + + Select Input Port: + + + + + myNodeType + + + SWITCH node + + + true + + + + + mySelectInputPortValue + + + + 7 + 0 + 0 + 0 + + + + 1000000 + + + -1000000 + + + + + + + mySwitchCasesGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + ViewModeButtonGroup + + + View Mode + + + + unnamed + + + + myExpandedRadioButton + + + Expanded + + + true + + + + + myCollapsedRadioButton + + + Collapsed + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + + + + + YACSGui_PlusMinusGrp +
YACSGui_PlusMinusGrp.h
+ + 0 + 0 + + 1 + + 5 + 0 + 0 + 0 + + image0 +
+
+ + + 89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082 + + + + onApply() + + + + YACSGui_PlusMinusGrp.h + +
diff --git a/src/gui/whileloopnodepage.ui b/src/gui/whileloopnodepage.ui new file mode 100644 index 000000000..1fc449e41 --- /dev/null +++ b/src/gui/whileloopnodepage.ui @@ -0,0 +1,263 @@ + +WhileLoopNodePage + + + WhileLoopNodePage + + + + 0 + 0 + 393 + 318 + + + + + 2 + 0 + 0 + 0 + + + + Form1 + + + + unnamed + + + 0 + + + 0 + + + + WhileLoopNodeFrame + + + + 5 + 0 + 0 + 0 + + + + StyledPanel + + + Raised + + + + unnamed + + + 5 + + + 5 + + + + NameGroupBox + + + + 5 + 0 + 0 + 0 + + + + + + + + unnamed + + + + NodeType + + + Node Type: + + + + + myNodeFullName + + + true + + + + + myNodeType + + + WHILE loop + + + true + + + + + NodeFullName + + + Node Full Name: + + + + + NodeName + + + Node Name: + + + + + myNodeName + + + + + + true + + + + + false + + + + myCondInputPortValue + + + 1 + + + + + myLoopBodyNodeName + + + true + + + + + CondInputPortValue + + + Condition Input Port Value: + + + + + LoopBodyNodeName + + + Loop Body Node Name: + + + + + + + ViewModeButtonGroup + + + View Mode + + + + unnamed + + + + myExpandedRadioButton + + + Expanded + + + true + + + + + myCollapsedRadioButton + + + Collapsed + + + + + + + ExecutionGroupBox + + + Execution + + + + unnamed + + + + NodeState + + + Node State: + + + + + myNodeState + + + + + + AlignCenter + + + + + ExecutionProgress + + + Execution Progress: + + + + + myProgressBar + + + 0 + + + + + + + + + + onApply() + + + diff --git a/src/hmi/Makefile.am b/src/hmi/Makefile.am new file mode 100644 index 000000000..9d7411da5 --- /dev/null +++ b/src/hmi/Makefile.am @@ -0,0 +1,118 @@ + +include $(top_srcdir)/adm/unix/make_begin.am + +bin_PROGRAMS = guidemo + +lib_LTLIBRARIES = libHMI.la + +# Implementation files +LIBSOURCES = \ + commands.cxx \ + commandsProc.cxx \ + guiObservers.cxx \ + guiContext.cxx + +# Headers +LIBHEADERS = + +# MOC-generated files +MOCSOURCES = + +# UIC-generated files + +mainempty.cxx: mainempty.h +wiedittree.cxx: wiedittree.h +winodeedition.cxx: winodeedition.h +dichoosename.cxx: dichoosename.h +catalog.cxx: catalog.h + +UISOURCES = \ + mainempty.cxx \ + wiedittree.cxx \ + winodeedition.cxx \ + dichoosename.cxx \ + catalog.cxx + +# Resources +LIBPOFILES = + +LIBICONS = \ + editcopy.png \ + editcut.png \ + editpaste.png \ + filenew.png \ + fileopen.png \ + filesave.png \ + print.png \ + redo.png \ + searchfind.png \ + undo.png + + +# Add "resources" subdirectory to resource file names +POFILES += $(LIBPOFILES:%=resources/%) +ICONS += $(LIBICONS:%=resources/%) + +libHMI_la_SOURCES = $(LIBSOURCES) $(LIBHEADERS) +#nodist_libHMI_la_SOURCES = $(UISOURCES) $(MOCSOURCES) +libHMI_la_LDFLAGS = @QT_MT_LDFLAGS@ + +libHMI_la_LIBADD = \ + ../runtime/libYACSRuntimeSALOME.la \ + ../yacsloader/libYACSloader.la \ + @QT_MT_LIBADD@ \ + $(EXPAT_LIBS) $(LIBXML_LIBS) + +libHMI_la_CXXFLAGS = \ + $(THREAD_DEF) \ + $(PYTHON_CPPFLAGS) \ + $(OMNIORB_INCLUDES) \ + -I$(KERNEL_ROOT_DIR)/include/salome \ + -I$(srcdir)/../bases \ + -I$(srcdir)/../engine \ + -I$(srcdir)/../runtime \ + -I$(srcdir)/../yacsloader \ + -I../../idl \ + -I../yacsorb \ + @QT_INCLUDES@ + +# List all generated files here +BUILT_SOURCES = $(UISOURCES) $(MOCSOURCES) mainempty.h + +guidemo_SOURCES = \ + main.cxx \ + editTree.cxx \ + editCanvas.cxx \ + nodeEdition.cxx \ + browseCatalog.cxx \ + chooseName.cxx \ + mainempty_moc.cxx \ + wiedittree_moc.cxx \ + dichoosename_moc.cxx \ + winodeedition_moc.cxx \ + catalog_moc.cxx \ + editTree_moc.cxx \ + editCanvas_moc.cxx \ + nodeEdition_moc.cxx \ + chooseName_moc.cxx \ + browseCatalog_moc.cxx \ + $(UISOURCES) $(MOCSOURCES) + +guidemo_CPPFLAGS = @QSCINTILLA_CCPFLAGS@ + +guidemo_CXXFLAGS = \ + $(libHMI_la_CXXFLAGS) + +guidemo_LDFLAGS=@QT_MT_LDFLAGS@ + +guidemo_LDADD = \ + libHMI.la \ + @QSCINTILLA_LIBADD@ + +EXTRA_DIST = \ +browseCatalog.h chooseName.h commands.hxx commandsProc.hxx editCanvas.h \ +editTree.h guiContext.hxx guiObservers.hxx nodeEdition.h \ +mainempty.h wiedittree.h winodeedition.h dichoosename.h catalog.h + + +include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/hmi/browseCatalog.cxx b/src/hmi/browseCatalog.cxx new file mode 100644 index 000000000..7a040e5aa --- /dev/null +++ b/src/hmi/browseCatalog.cxx @@ -0,0 +1,133 @@ + +#include "browseCatalog.h" +#include "guiContext.hxx" +#include "Catalog.hxx" +#include "ComponentDefinition.hxx" +#include "ServiceNode.hxx" +#include "editTree.h" +#include "guiObservers.hxx" + +#include + +#include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace std; + +using namespace YACS; +using namespace YACS::HMI; + + + +BrowseCatalog::BrowseCatalog(editTree* editTree, + Subject* sub, + int cataType, + QWidget* parent, + const char* name, + bool modal, + WFlags fl) + : catalog(parent, name, modal, fl), _editTree(editTree), _subject(sub), _cataType(cataType) +{ + resetTree(); +} + +BrowseCatalog::~BrowseCatalog() +{ +} + +void BrowseCatalog::resetTree() +{ + lv1->clear(); + lv1->setRootIsDecorated( TRUE ); + _currentCatalog = YACS::HMI::GuiContext::getCurrent()->getCurrentCatalog(); + if (_currentCatalog) + switch (_cataType) + { + case CATALOGNODE: + { + map::const_iterator itComp; + for (itComp = _currentCatalog->_componentMap.begin(); + itComp != _currentCatalog->_componentMap.end(); + ++itComp) + { + string compoName = (*itComp).first; + YACS::ENGINE::ComponentDefinition* compo = (*itComp).second; + DEBTRACE("Component: " << compoName); + QListViewItem *item = new QListViewItem(lv1, compoName.c_str()); + map::iterator itServ; + for (itServ = compo->_serviceMap.begin(); itServ != compo->_serviceMap.end(); ++itServ) + { + string serviceName = (*itServ).first; + YACS::ENGINE::ServiceNode* service = (*itServ).second; + DEBTRACE(" Service: " << serviceName); + QListViewItem *sitem = new QListViewItem(item, serviceName.c_str()); + _serviceMap[sitem] = pair(compoName,serviceName); + } + } + break; + } + case CATALOGINPUTPORT: + case CATALOGOUTPUTPORT: + case CATALOGIDSPORT: + case CATALOGODSPORT: + case CATALOGDATATYPE: + { + map::const_iterator itType; + for(itType = _currentCatalog->_typeMap.begin(); + itType != _currentCatalog->_typeMap.end(); + ++itType) + { + string typeName = (*itType).first; + YACS::ENGINE::TypeCode* typcod = (*itType).second; + DEBTRACE("Type Code " << typeName); + QListViewItem *item = new QListViewItem(lv1, typeName.c_str()); + _typeCodeMap[item] = typeName; + } + break; + } + default: + DEBTRACE("BrowseCatalog::resetTree: type not handled " << _cataType); + } +} + +void BrowseCatalog::addSelection() +{ + QListViewItem *it =lv1->selectedItem(); + if (it) // an item selected + switch (_cataType) + { + case CATALOGNODE: + { + _editTree->newNode(_currentCatalog, _subject, _serviceMap[it]); + break; + } + case CATALOGDATATYPE: + { + _editTree->newDataType(_currentCatalog, _subject, _typeCodeMap[it]); + break; + } + case CATALOGINPUTPORT: + { + _editTree->newDFInputPort(_currentCatalog, _subject, _typeCodeMap[it]); + break; + } + case CATALOGOUTPUTPORT: + { + _editTree->newDFOutputPort(_currentCatalog, _subject, _typeCodeMap[it]); + break; + } + case CATALOGIDSPORT: + { + _editTree->newDSInputPort(_currentCatalog, _subject, _typeCodeMap[it]); + break; + } + case CATALOGODSPORT: + { + _editTree->newDSOutputPort(_currentCatalog, _subject, _typeCodeMap[it]); + break; + } + default: + DEBTRACE("BrowseCatalog::resetTree: type not handled " << _cataType); + } +} diff --git a/src/hmi/browseCatalog.h b/src/hmi/browseCatalog.h new file mode 100644 index 000000000..6a99c92a3 --- /dev/null +++ b/src/hmi/browseCatalog.h @@ -0,0 +1,65 @@ +#ifndef _BROWSECATALOG_H_ +#define _BROWSECATALOG_H_ + +#include "catalog.h" + +#include +#include +#include +#include + +#include + +namespace YACS +{ + namespace ENGINE + { + class Catalog; +/* class ServiceNode; */ + } + + namespace HMI + { + + typedef enum + { + CATALOGNODE, + CATALOGDATATYPE, + CATALOGINPUTPORT, + CATALOGOUTPUTPORT, + CATALOGIDSPORT, + CATALOGODSPORT, + CATALOGCOMPOSEDNODE + } TypeOfCatalogItem; + + class editTree; + class Subject; + + class BrowseCatalog: public catalog + { + Q_OBJECT + + public: + BrowseCatalog(editTree* editTree, + Subject* sub, + int cataType, + QWidget* parent = 0, + const char* name = 0, + bool modal = FALSE, + WFlags fl = 0 ); + virtual ~BrowseCatalog(); + virtual void resetTree(); + public slots: + virtual void addSelection(); + protected: + YACS::ENGINE::Catalog* _currentCatalog; + std::map > _serviceMap; + std::map _typeCodeMap; + editTree* _editTree; + Subject* _subject; + int _cataType; + }; + + } +} +#endif diff --git a/src/hmi/catalog.ui b/src/hmi/catalog.ui new file mode 100644 index 000000000..f2fe09d10 --- /dev/null +++ b/src/hmi/catalog.ui @@ -0,0 +1,95 @@ + +catalog + + + catalog + + + + 0 + 0 + 411 + 337 + + + + Catalog + + + + unnamed + + + + layout10 + + + + unnamed + + + + spacer8 + + + Horizontal + + + Expanding + + + + 201 + 20 + + + + + + btAddSel + + + add selection + + + + + + + + Column 1 + + + true + + + true + + + + + New Item + + + + + + + lv1 + + + + + + + btAddSel + clicked() + catalog + addSelection() + + + + addSelection() + + + diff --git a/src/hmi/chooseName.cxx b/src/hmi/chooseName.cxx new file mode 100644 index 000000000..10741e534 --- /dev/null +++ b/src/hmi/chooseName.cxx @@ -0,0 +1,51 @@ + +#include "chooseName.h" +#include "guiObservers.hxx" +#include +#include + +using namespace std; + +using namespace YACS; +using namespace YACS::HMI; +//#define _DEVDEBUG_ + +#include "YacsTrace.hxx" + +#include + + +ChooseName::ChooseName( std::string parentName, + std::string typeName, + std::string defaultName, + QWidget* parent, + const char* name, + bool modal, + WFlags fl ) + : diChooseName(parent, name, modal, fl) +{ +// _parentName = parentName; +// _typeName = typeName; +// _defaultName = defaultName; + tlParentPath->setText(parentName.c_str()); + tlTypeValue->setText(typeName.c_str()); + leName->setText(defaultName.c_str()); + _choosenName = defaultName; + _isOk = false; +} + +ChooseName::~ChooseName() +{ +} + +void ChooseName::accept() +{ + _choosenName = leName->text().latin1(); + _isOk = true; + diChooseName::accept(); +} + +void ChooseName::reject() +{ + diChooseName::reject(); +} diff --git a/src/hmi/chooseName.h b/src/hmi/chooseName.h new file mode 100644 index 000000000..3496e2e2f --- /dev/null +++ b/src/hmi/chooseName.h @@ -0,0 +1,36 @@ +#ifndef __CHOOSENAME_H_ +#define __CHOOSENAME_H_ + +#include "dichoosename.h" + +namespace YACS +{ + namespace HMI + { + + class ChooseName: public diChooseName + { + Q_OBJECT + + public slots: + void accept(); + void reject(); + public: + ChooseName( std::string parentName, + std::string typeName, + std::string defaultName, + QWidget* parent = 0, + const char* name = 0, + bool modal = FALSE, + WFlags fl = 0 ); + ~ChooseName(); + std::string getChoosenName() { return _choosenName; }; + bool isOk() { return _isOk; }; + protected: + std::string _choosenName; + bool _isOk; + }; + + } +} +#endif diff --git a/src/hmi/commands.cxx b/src/hmi/commands.cxx new file mode 100644 index 000000000..a0aa7aeae --- /dev/null +++ b/src/hmi/commands.cxx @@ -0,0 +1,86 @@ + +#include "commands.hxx" + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace std; + +using namespace YACS; +using namespace YACS::HMI; + +Command::Command() +{ + _subCommands.clear(); +} + +bool Command::execute() +{ + bool ret=true; + ret = localExecute(); + if (! _subCommands.empty()) + { + list::iterator it; + for (it=_subCommands.begin(); it!=_subCommands.end(); it++) + { + if (!ret) break; + ret = (*it)->execute(); + } + } + return ret; +} + +bool Command::reverse() +{ + bool ret=true; + if (! _subCommands.empty()) + { + list::reverse_iterator it; + for (it=_subCommands.rbegin(); it!=_subCommands.rend(); it++) + { + ret =(*it)->execute(); + if (!ret) break; + } + } + if (ret) ret = localReverse(); + return ret; +} + +void Command::addSubCommand(Command* command) +{ + _subCommands.push_back(command); +} + +Invocator::Invocator() +{ +} + +void Invocator::add(Command* command) +{ + _commandsDone.push(command); // to do after execute ok +} + +bool Invocator::undo() +{ + bool ret = true; + if (! _commandsDone.empty()) + { + _commandsDone.pop(); + ret = _commandsDone.top()->reverse(); + _commandsUndone.push(_commandsDone.top()); + } + return ret; +} + +bool Invocator::redo() +{ + bool ret = true; + if (! _commandsUndone.empty()) + { + _commandsUndone.pop(); + ret = _commandsUndone.top()->execute(); + _commandsDone.push(_commandsUndone.top()); + } + return ret; +} + diff --git a/src/hmi/commands.hxx b/src/hmi/commands.hxx new file mode 100644 index 000000000..4562e00be --- /dev/null +++ b/src/hmi/commands.hxx @@ -0,0 +1,40 @@ + +#ifndef _COMMANDS_HXX_ +#define _COMMANDS_HXX_ + +#include +#include +#include + +namespace YACS +{ + namespace HMI + { + class Command + { + public: + Command(); + virtual bool execute(); + virtual bool reverse(); + //virtual std::string getCommandType() = 0; // utiliser un dynamic_cast plutot + void addSubCommand(Command* command); + protected: + virtual bool localExecute() = 0; + virtual bool localReverse() = 0; + std::list _subCommands; + }; + + class Invocator + { + public: + Invocator(); + void add(Command* command); + bool undo(); + bool redo(); + protected: + std::stack _commandsDone; + std::stack _commandsUndone; + }; + } +} +#endif diff --git a/src/hmi/commandsProc.cxx b/src/hmi/commandsProc.cxx new file mode 100644 index 000000000..2612c230e --- /dev/null +++ b/src/hmi/commandsProc.cxx @@ -0,0 +1,935 @@ + +#include +#include "commandsProc.hxx" + +#include "Node.hxx" +#include "ComposedNode.hxx" +#include "Bloc.hxx" +#include "Proc.hxx" +#include "ElementaryNode.hxx" +#include "InlineNode.hxx" +#include "ServiceNode.hxx" +#include "PythonNode.hxx" +#include "CORBANode.hxx" +#include "CppNode.hxx" +#include "XMLNode.hxx" +#include "SalomePythonNode.hxx" +#include "XMLNode.hxx" +#include "ForLoop.hxx" +#include "ForEachLoop.hxx" +#include "WhileLoop.hxx" +#include "Switch.hxx" +#include "OptimizerLoop.hxx" +#include "PresetNode.hxx" +#include "OutNode.hxx" +#include "StudyNodes.hxx" +#include "Exception.hxx" +#include "DataPort.hxx" +#include "InputDataStreamPort.hxx" +#include "OutputDataStreamPort.hxx" +#include "ComponentDefinition.hxx" +#include "SalomeContainer.hxx" +#include "SalomeComponent.hxx" +#include "TypeCode.hxx" + +#include "guiContext.hxx" + +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace std; + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; + +std::map ProcInvoc::_typeNameMap; + +// ---------------------------------------------------------------------------- + +ProcInvoc::ProcInvoc() + : Invocator() +{ + _typeNameMap.clear(); + _typeNameMap[SALOMEPROC] = "SALOMEPROC"; + _typeNameMap[BLOC] = "BLOC"; + _typeNameMap[FOREACHLOOP] = "FOREACHLOOP"; + _typeNameMap[OPTIMIZERLOOP] = "OPTIMIZERLOOP"; + _typeNameMap[FORLOOP] = "FORLOOP"; + _typeNameMap[WHILELOOP] = "WHILELOOP"; + _typeNameMap[SWITCH] = "SWITCH"; + _typeNameMap[PYTHONNODE] = "PYTHONNODE"; + _typeNameMap[PYFUNCNODE] = "PYFUNCNODE"; + _typeNameMap[CORBANODE] = "CORBANODE"; + _typeNameMap[SALOMENODE] = "SALOMENODE"; + _typeNameMap[CPPNODE] = "CPPNODE"; + _typeNameMap[SALOMEPYTHONNODE] = "SALOMEPYTHONNODE"; + _typeNameMap[XMLNODE] = "XMLNODE"; + _typeNameMap[SPLITTERNODE] = "SPLITTERNODE"; + _typeNameMap[DFTODSFORLOOPNODE] = "DFTODSFORLOOPNODE"; + _typeNameMap[DSTODFFORLOOPNODE] = "DSTODFFORLOOPNODE"; + _typeNameMap[PRESETNODE] = "PRESETNODE"; + _typeNameMap[OUTNODE] = "OUTNODE"; + _typeNameMap[STUDYINNODE] = "STUDYINNODE"; + _typeNameMap[STUDYOUTNODE] = "STUDYOUTNODE"; + _typeNameMap[INPUTPORT] = "INPUTPORT"; + _typeNameMap[OUTPUTPORT] = "OUTPUTPORT"; + _typeNameMap[INPUTDATASTREAMPORT] = "INPUTDATASTREAMPORT"; + _typeNameMap[OUTPUTDATASTREAMPORT] = "OUTPUTDATASTREAMPORT"; + _typeNameMap[CONTAINER] = "CONTAINER"; + _typeNameMap[COMPONENT] = "COMPONENT"; + _typeNameMap[REFERENCE] = "REFERENCE"; + _typeNameMap[DATATYPE] = "DATATYPE"; +} + +TypeOfElem ProcInvoc::getTypeOfNode(YACS::ENGINE::Node* node) +{ + TypeOfElem nodeType = UNKNOWN; + if (dynamic_cast(node)) nodeType = BLOC; + else if (dynamic_cast(node)) nodeType = PYTHONNODE; + else if (dynamic_cast(node)) nodeType = PYFUNCNODE; + else if (dynamic_cast(node)) nodeType = CORBANODE; + else if (dynamic_cast(node)) nodeType = CPPNODE; + else if (dynamic_cast(node)) nodeType = SALOMENODE; + else if (dynamic_cast(node)) nodeType = SALOMEPYTHONNODE; + else if (dynamic_cast(node)) nodeType = XMLNODE; + else if (dynamic_cast(node)) nodeType = SPLITTERNODE; + else if (dynamic_cast(node)) nodeType = FORLOOP; + else if (dynamic_cast(node)) nodeType = WHILELOOP; + else if (dynamic_cast(node)) nodeType = SWITCH; + else if (dynamic_cast(node)) nodeType = FOREACHLOOP; + else if (dynamic_cast(node)) nodeType = OPTIMIZERLOOP; + else if (dynamic_cast(node)) nodeType = PRESETNODE; + else if (dynamic_cast(node)) nodeType = OUTNODE; + else if (dynamic_cast(node)) nodeType = STUDYINNODE; + else if (dynamic_cast(node)) nodeType = STUDYOUTNODE; + return nodeType; +} + +TypeOfElem ProcInvoc::getTypeOfPort(YACS::ENGINE::DataPort* port) +{ + TypeOfElem portType = UNKNOWN; + if (dynamic_cast(port)) portType = INPUTPORT; + else if (dynamic_cast(port)) portType = OUTPUTPORT; + else if (dynamic_cast(port)) portType = INPUTDATASTREAMPORT; + else if (dynamic_cast(port)) portType = OUTPUTDATASTREAMPORT; + return portType; +} + +std::string ProcInvoc::getTypeName(TypeOfElem type) +{ + if (_typeNameMap.count(type)) + return _typeNameMap[type]; + else + return "UNKNOWN"; +} + +// ---------------------------------------------------------------------------- + +CommandAddNodeFromCatalog::CommandAddNodeFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string position, + std::string name, + int swCase) + : Command(), _catalog(catalog), _compoName(compo), _typeName(type), + _position(position), _name(name), _swCase(swCase) +{ + _nodeToClone = 0; + if (_compoName.empty()) + { + if (_catalog->_nodeMap.count(_typeName)) + _nodeToClone = _catalog->_nodeMap[_typeName]; + else if (_catalog->_composednodeMap.count(_typeName)) + _nodeToClone = _catalog->_composednodeMap[_typeName]; + } + else + if (_catalog->_componentMap.count(_compoName)) + { + YACS::ENGINE::ComponentDefinition* compodef = _catalog->_componentMap[_compoName]; + if (compodef->_serviceMap.count(_typeName)) + _nodeToClone = compodef->_serviceMap[_typeName]; + } + if (_nodeToClone) + _typeNode = ProcInvoc::getTypeOfNode(_nodeToClone); +} + + +YACS::ENGINE::Node *CommandAddNodeFromCatalog::getNode() +{ + return _node; +} + +bool CommandAddNodeFromCatalog::localExecute() +{ + Node *son = 0; + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* node = proc; + if (!_position.empty()) node = proc->getChildByName(_position); + ComposedNode* father =dynamic_cast (node); + if (father) + { + son = _nodeToClone->clone(0); + son->setName(_name); + } + if (son) + { + TypeOfElem fatherType = ProcInvoc::getTypeOfNode(father); + switch (fatherType) + { + case BLOC: + (dynamic_cast(father))->edAddChild(son); + break; + case FORLOOP: + (dynamic_cast(father))->edSetNode(son); + break; + case WHILELOOP: + (dynamic_cast(father))->edSetNode(son); + break; + case SWITCH: + (dynamic_cast(father))->edSetNode(_swCase,son); + break; + case FOREACHLOOP: + (dynamic_cast(father))->edSetNode(son); + break; + case OPTIMIZERLOOP: + (dynamic_cast(father))->edSetNode(son); + break; + default: + assert(0); + } + } + _node = son; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddNode::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + if (son) delete son; + _node = 0; + } + return (_node != 0); +} + +bool CommandAddNodeFromCatalog::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandRenameNode::CommandRenameNode(std::string position, std::string name) + : Command(), _position(position), _name(name) +{ + DEBTRACE("CommandRenameNode::CommandRenameNode " << _position << " " << _name); +} + +bool CommandRenameNode::localExecute() +{ + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* node = proc; + try + { + if (_position != proc->getName()) node = proc->getChildByName(_position); + node->setName(_name); + } + catch (Exception& ex) + { + DEBTRACE("CommandRenameNode::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + node = 0; + } + return (node != 0); +} + +bool CommandRenameNode::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddDataTypeFromCatalog::CommandAddDataTypeFromCatalog(YACS::ENGINE::Catalog* catalog, + std::string typeName) + : Command(), _catalog(catalog), _typeName(typeName) +{ + DEBTRACE("CommandAddDataTypeFromCatalog::CommandAddDataTypeFromCatalog: " << typeName); +} + +YACS::ENGINE::TypeCode *CommandAddDataTypeFromCatalog::getTypeCode() +{ + + if (GuiContext::getCurrent()->getProc()->typeMap.count(_typeName)) + return GuiContext::getCurrent()->getProc()->typeMap[_typeName]; + else return 0; +} + +bool CommandAddDataTypeFromCatalog::localExecute() +{ + Proc* proc = GuiContext::getCurrent()->getProc(); + if (proc->typeMap.count(_typeName)) + { + DEBTRACE("typecode already existing in proc: " << _typeName); + //GuiContext::getCurrent()->_lastErrorMessage = "typecode already existing in proc: " + _typeName; + //return false; + return true; + } + else + if (_catalog->_typeMap.count(_typeName)) + { + DEBTRACE("typecode found in catalog, cloned: " << _typeName); + proc->typeMap[_typeName] = _catalog->_typeMap[_typeName]->clone(); + return true; + } + GuiContext::getCurrent()->_lastErrorMessage = "typecode not found in catalog: " + _typeName; + return false; +} + +bool CommandAddDataTypeFromCatalog::localReverse() +{ +} + + +// ---------------------------------------------------------------------------- + +CommandAddInputPortFromCatalog::CommandAddInputPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name) + : Command(), _catalog(catalog), _typePort(type), _node(node), _name(name) +{ + _inputPort = 0; +} + +YACS::ENGINE::InputPort *CommandAddInputPortFromCatalog::getInputPort() +{ + return _inputPort; +} + +bool CommandAddInputPortFromCatalog::localExecute() +{ + InputPort *son = 0; + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* node = proc->getChildByName(_node); + ElementaryNode* father =dynamic_cast (node); + if (father) + { + if (_catalog->_typeMap.count(_typePort)) + son = father->edAddInputPort(_name, _catalog->_typeMap[_typePort]); + else + { + DEBTRACE(_typePort << " not found in catalog"); + GuiContext::getCurrent()->_lastErrorMessage = _typePort + " not found in catalog"; + } + } + _inputPort = son; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddInputPortFromCatalog::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + if (son) delete son; + _inputPort = 0; + } + return (_inputPort != 0); +} + +bool CommandAddInputPortFromCatalog::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddOutputPortFromCatalog::CommandAddOutputPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name) + : Command(), _catalog(catalog), _typePort(type), _node(node), _name(name) +{ + _outputPort = 0; +} + +YACS::ENGINE::OutputPort *CommandAddOutputPortFromCatalog::getOutputPort() +{ + return _outputPort; +} + +bool CommandAddOutputPortFromCatalog::localExecute() +{ + OutputPort *son = 0; + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* node = proc->getChildByName(_node); + ElementaryNode* father =dynamic_cast (node); + if (father) + { + if (_catalog->_typeMap.count(_typePort)) + son = father->edAddOutputPort(_name, _catalog->_typeMap[_typePort]); + else + { + DEBTRACE(_typePort << " not found in catalog"); + GuiContext::getCurrent()->_lastErrorMessage = _typePort + " not found in catalog"; + } + } + _outputPort = son; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddOutputPortFromCatalog::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + if (son) delete son; + _outputPort = 0; + } + return (_outputPort != 0); +} + +bool CommandAddOutputPortFromCatalog::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddIDSPortFromCatalog::CommandAddIDSPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name) + : Command(), _catalog(catalog), _typePort(type), _node(node), _name(name) +{ + _IDSPort = 0; +} + +YACS::ENGINE::InputDataStreamPort *CommandAddIDSPortFromCatalog::getIDSPort() +{ + return _IDSPort; +} + +bool CommandAddIDSPortFromCatalog::localExecute() +{ + InputDataStreamPort *son = 0; + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* node = proc->getChildByName(_node); + ElementaryNode* father =dynamic_cast (node); + if (father) + { + if (_catalog->_typeMap.count(_typePort)) + son = father->edAddInputDataStreamPort(_name, _catalog->_typeMap[_typePort]); + else + { + DEBTRACE(_typePort << " not found in catalog"); + GuiContext::getCurrent()->_lastErrorMessage = _typePort + " not found in catalog"; + } + } + _IDSPort = son; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddIDSPortFromCatalog::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + if (son) delete son; + _IDSPort = 0; + } + return (_IDSPort != 0); +} + +bool CommandAddIDSPortFromCatalog::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddODSPortFromCatalog::CommandAddODSPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name) + : Command(), _catalog(catalog), _typePort(type), _node(node), _name(name) +{ + _ODSPort = 0; +} + +YACS::ENGINE::OutputDataStreamPort *CommandAddODSPortFromCatalog::getODSPort() +{ + return _ODSPort; +} + +bool CommandAddODSPortFromCatalog::localExecute() +{ + OutputDataStreamPort *son = 0; + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* node = proc->getChildByName(_node); + ElementaryNode* father =dynamic_cast (node); + if (father) + { + if (_catalog->_typeMap.count(_typePort)) + son = father->edAddOutputDataStreamPort(_name, _catalog->_typeMap[_typePort]); + else + { + DEBTRACE(_typePort << " not found in catalog"); + GuiContext::getCurrent()->_lastErrorMessage = _typePort + " not found in catalog"; + } + } + _ODSPort = son; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddODSPortFromCatalog::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + if (son) delete son; + _ODSPort = 0; + } + return (_ODSPort != 0); +} + +bool CommandAddODSPortFromCatalog::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandDestroy::CommandDestroy(std::string position, Subject* subject) + : Command(), _position(position), _subject(subject) +{ + DEBTRACE("CommandDestroy::CommandDestroy"); + //todo: store what is needed to recreate the subject +} + +bool CommandDestroy::localExecute() +{ + DEBTRACE("CommandDestroy::localExecute"); + try + { + Subject::erase(_subject); + _subject = 0; + return true; + } + catch (Exception& ex) + { + DEBTRACE("CommandDestroy::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandDestroy::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddLink::CommandAddLink(std::string outNode, std::string outPort, + std::string inNode, std::string inPort) + : Command(), _outNode(outNode), _outPort(outPort), _inNode(inNode), _inPort(inPort) +{ + DEBTRACE("CommandAddLink::CommandAddLink "<"<"<<_inNode<<"."<<_inPort); + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* outn = proc->getChildByName(_outNode); + Node* inn = proc->getChildByName(_inNode); + OutPort* outp = outn->getOutPort(_outPort); + InPort* inp = inn->getInPort(_inPort); + ComposedNode *cla = ComposedNode::getLowestCommonAncestor(outn->getFather(),inn->getFather()); + DEBTRACE(cla->getName()); + if (dynamic_cast(outp)) + cla->edAddLink(outp,inp); + else + cla->edAddDFLink(outp,inp); + return true; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddLink::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandAddLink::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddControlLink::CommandAddControlLink(std::string outNode, std::string inNode) + : Command(), _outNode(outNode), _inNode(inNode) +{ + DEBTRACE("CommandAddControlLink::CommandAddControlLink "<>"<getProc(); + Node* outn = proc; + if (! _outNode.empty()) + outn = proc->getChildByName(_outNode); + Node* inn = proc; + if (! _inNode.empty()) + inn = proc->getChildByName(_inNode); + ComposedNode *cla = ComposedNode::getLowestCommonAncestor(outn,inn); + DEBTRACE(cla->getName()); + cla->edAddCFLink(outn,inn); + return true; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddControlLink::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandAddControlLink::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddContainer::CommandAddContainer(std::string name, + std::string refContainer) + : Command(), _name(name), _containerToClone(refContainer), _container(0) +{ + DEBTRACE("CommandAddContainer::CommandAddContainer " << name << " " << refContainer); +} + +bool CommandAddContainer::localExecute() +{ + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + if (proc->containerMap.count(_name)) + { + GuiContext::getCurrent()->_lastErrorMessage = "There is already a container with that name"; + return false; + } + Container *container = new SalomeContainer(); + if (! _containerToClone.empty()) + { + if (proc->containerMap.count(_containerToClone)) + { + Container *ref = proc->containerMap[_containerToClone]; + assert(ref); + container->setProperties(ref->getProperties()); + } + else + { + GuiContext::getCurrent()->_lastErrorMessage = "There is no reference container to clone properties"; + return false; + } + } + _container = container; + _container->setName(_name); + proc->containerMap[_name] = _container; + return true; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddContainer::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandAddContainer::localReverse() +{ +} + +YACS::ENGINE::Container* CommandAddContainer::getContainer() +{ + return _container; +} + +// ---------------------------------------------------------------------------- + +CommandSetContainerProperties::CommandSetContainerProperties(std::string container, + std::map properties) + : Command(), _container(container), _properties(properties) +{ + DEBTRACE("CommandSetContainerProperties::CommandSetContainerProperties " << container); +} + +bool CommandSetContainerProperties::localExecute() +{ + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + if (proc->containerMap.count(_container)) + { + Container *ref = proc->containerMap[_container]; + assert(ref); + ref->setProperties(_properties); + return true; + } + GuiContext::getCurrent()->_lastErrorMessage = "container not found: " + _container; + return false; + } + catch (Exception& ex) + { + DEBTRACE("CommandSetContainerProperties::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandSetContainerProperties::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandSetDSPortProperties::CommandSetDSPortProperties(std::string node, std::string port, bool isInport, + std::map properties) + : Command(), _nodeName(node), _portName(port), _isInport(isInport), _properties(properties) +{ + DEBTRACE("CommandSetDSPortProperties::CommandSetDSPortProperties " << node << "." << port << " " << isInport); +} + +bool CommandSetDSPortProperties::localExecute() +{ + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + Node* node = proc->getChildByName(_nodeName); + DataStreamPort* DSPort = 0; + if (_isInport) + DSPort = node->getInputDataStreamPort(_portName); + else + DSPort = node->getOutputDataStreamPort(_portName); + DSPort->setProperties(_properties); + return true; + } + catch (Exception& ex) + { + DEBTRACE("CommandSetDSPortProperties::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandSetDSPortProperties::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandSetFuncNodeFunctionName::CommandSetFuncNodeFunctionName(std::string node, std::string funcName) + : Command(), _nodeName(node), _funcName(funcName) +{ + DEBTRACE("CommandSetFuncNodeFunctionName::CommandSetFuncNodeFunctionName " << node << " " <getProc(); + Node* node = proc->getChildByName(_nodeName); + if (_funcName.empty()) + { + GuiContext::getCurrent()->_lastErrorMessage = "InlineFuncNode function name empty: " + _nodeName; + return false; + } + if (YACS::ENGINE::InlineFuncNode* funcNode = dynamic_cast(node)) + { + funcNode->setFname(_funcName); + return true; + } + else + { + GuiContext::getCurrent()->_lastErrorMessage = "node is not an InlineFuncNode: " + _nodeName; + return false; + } + } + catch (Exception& ex) + { + DEBTRACE("CommandSetFuncNodeFunctionName::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandSetFuncNodeFunctionName::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandSetInlineNodeScript::CommandSetInlineNodeScript(std::string node, std::string script) + : Command(), _nodeName(node), _script(script) +{ + DEBTRACE("CommandSetInlineNodeScript::CommandSetInlineNodeScript " << node << " " <getProc(); + Node* node = proc->getChildByName(_nodeName); + if (_script.empty()) + { + GuiContext::getCurrent()->_lastErrorMessage = "InlineNode script empty: " + _nodeName; + return false; + } + if (YACS::ENGINE::InlineNode* inlineNode = dynamic_cast(node)) + { + inlineNode->setScript(_script); + return true; + } + else + { + GuiContext::getCurrent()->_lastErrorMessage = "node is not an InlineNode: " + _nodeName; + return false; + } + } + catch (Exception& ex) + { + DEBTRACE("CommandSetInlineNodeScript::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandSetInlineNodeScript::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAddComponentInstance::CommandAddComponentInstance(std::string compoName) + : Command(), _compoName(compoName), _compoInst(0) +{ + DEBTRACE("CommandAddComponentInstance::CommandAddComponentInstance " <<_compoName); +} + +bool CommandAddComponentInstance::localExecute() +{ + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + _compoInst = new SalomeComponent(_compoName); + pair key = pair(_compoName, _compoInst->getNumId()); + proc->componentInstanceMap[key] = _compoInst; + return true; + } + catch (Exception& ex) + { + DEBTRACE("CommandAddComponentInstance::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandAddComponentInstance::localReverse() +{ +} + +YACS::ENGINE::ComponentInstance* CommandAddComponentInstance::getComponentInstance() +{ + return _compoInst; +} + + +// ---------------------------------------------------------------------------- + +CommandAssociateComponentToContainer::CommandAssociateComponentToContainer(std::pair key, + std::string container) + : Command(), _key(key), _container(container) +{ + DEBTRACE("CommandAssociateComponentToContainer::CommandAssociateComponentToContainer " + << key.first << " " << key.second << " " << container); +} + +bool CommandAssociateComponentToContainer::localExecute() +{ + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + if (proc->containerMap.count(_container)) + { + Container *cont = proc->containerMap[_container]; + if (proc->componentInstanceMap.count(_key)) + { + ComponentInstance *compo = proc->componentInstanceMap[_key]; + compo->setContainer(cont); + return true; + } + else + GuiContext::getCurrent()->_lastErrorMessage = "Component instance not found: " + _key.first; + } + else + GuiContext::getCurrent()->_lastErrorMessage = "Container not found: " + _container; + return false; + } + catch (Exception& ex) + { + DEBTRACE("CommandAssociateComponentToContainer::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandAssociateComponentToContainer::localReverse() +{ +} + +// ---------------------------------------------------------------------------- + +CommandAssociateServiceToComponent::CommandAssociateServiceToComponent(std::string service, + std::pair key) + : Command(), _service(service), _key(key) +{ + DEBTRACE("CommandAssociateServiceToComponent::CommandAssociateServiceToComponent " + << service << " " << key.first << " " << key.second); +} + +bool CommandAssociateServiceToComponent::localExecute() +{ + try + { + Proc* proc = GuiContext::getCurrent()->getProc(); + if (_service == proc->getName()) return false; // proc is not an elementary node + Node* node = proc->getChildByName(_service); + if (ServiceNode *service = dynamic_cast(node)) + { + if (proc->componentInstanceMap.count(_key)) + { + ComponentInstance *compo = proc->componentInstanceMap[_key]; + service->setComponent(compo); + return true; + } + else + GuiContext::getCurrent()->_lastErrorMessage = "Component instance not found: " + _key.first; + } + else + GuiContext::getCurrent()->_lastErrorMessage = "Node is note a service node: " + _service; + return false; + } + catch (Exception& ex) + { + DEBTRACE("CommandAssociateServiceToComponent::localExecute() : " << ex.what()); + GuiContext::getCurrent()->_lastErrorMessage = ex.what(); + return false; + } +} + +bool CommandAssociateServiceToComponent::localReverse() +{ +} + +// ---------------------------------------------------------------------------- diff --git a/src/hmi/commandsProc.hxx b/src/hmi/commandsProc.hxx new file mode 100644 index 000000000..1f0dbbef8 --- /dev/null +++ b/src/hmi/commandsProc.hxx @@ -0,0 +1,400 @@ + +#ifndef _COMMANDSPROC_HXX_ +#define _COMMANDSPROC_HXX_ + +#include "commands.hxx" + +#include +#include +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class Proc; + class Node; + class TypeCode; + class Catalog; + class DataPort; + class InputPort; + class OutputPort; + class InputDataStreamPort; + class OutputDataStreamPort; + class Container; + class ComponentInstance; + } + + namespace HMI + { + + typedef enum + { + SALOMEPROC, + BLOC, + FOREACHLOOP, + OPTIMIZERLOOP, + FORLOOP, + WHILELOOP, + SWITCH, + PYTHONNODE, + PYFUNCNODE, + CORBANODE, + SALOMENODE, + CPPNODE, + SALOMEPYTHONNODE, + XMLNODE, + SPLITTERNODE, + DFTODSFORLOOPNODE, + DSTODFFORLOOPNODE, + PRESETNODE, + OUTNODE, + STUDYINNODE, + STUDYOUTNODE, + INPUTPORT, + OUTPUTPORT, + INPUTDATASTREAMPORT, + OUTPUTDATASTREAMPORT, + DATALINK, + CONTROLLINK, + CONTAINER, + COMPONENT, + REFERENCE, + DATATYPE, + UNKNOWN + } TypeOfElem; + + class ProcInvoc: public Invocator + { + public: + ProcInvoc(); + static TypeOfElem getTypeOfNode(YACS::ENGINE::Node* node); + static TypeOfElem getTypeOfPort(YACS::ENGINE::DataPort* port); + static std::string getTypeName(TypeOfElem type); + protected: + static std::map _typeNameMap; + }; + + + class CommandAddNodeFromCatalog: public Command + { + public: + CommandAddNodeFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string position, + std::string name, + int swCase =0); + YACS::ENGINE::Node *getNode(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + YACS::ENGINE::Catalog* _catalog; + YACS::ENGINE::Node *_nodeToClone; + TypeOfElem _typeNode; + std::string _compoName; + std::string _typeName; + std::string _position; + std::string _name; + int _swCase; + YACS::ENGINE::Node *_node; + }; + + class CommandRenameNode: public Command + { + public: + CommandRenameNode(std::string position, std::string name); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _position; + std::string _name; + }; + + class CommandAddDataTypeFromCatalog: public Command + { + public: + CommandAddDataTypeFromCatalog(YACS::ENGINE::Catalog* catalog, + std::string typeName); + YACS::ENGINE::TypeCode *getTypeCode(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + YACS::ENGINE::Catalog* _catalog; + std::string _typeName; + }; + + class CommandAddInputPortFromCatalog: public Command + { + public: + CommandAddInputPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name); + YACS::ENGINE::InputPort *getInputPort(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + YACS::ENGINE::Catalog* _catalog; + std::string _typePort; + std::string _node; + std::string _name; + YACS::ENGINE::InputPort *_inputPort; + }; + + class CommandAddOutputPortFromCatalog: public Command + { + public: + CommandAddOutputPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name); + YACS::ENGINE::OutputPort *getOutputPort(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + YACS::ENGINE::Catalog* _catalog; + std::string _typePort; + std::string _node; + std::string _name; + YACS::ENGINE::OutputPort *_outputPort; + }; + + class CommandAddIDSPortFromCatalog: public Command + { + public: + CommandAddIDSPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name); + YACS::ENGINE::InputDataStreamPort *getIDSPort(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + YACS::ENGINE::Catalog* _catalog; + std::string _typePort; + std::string _node; + std::string _name; + YACS::ENGINE::InputDataStreamPort *_IDSPort; + }; + + class CommandAddODSPortFromCatalog: public Command + { + public: + CommandAddODSPortFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string type, + std::string node, + std::string name); + YACS::ENGINE::OutputDataStreamPort *getODSPort(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + YACS::ENGINE::Catalog* _catalog; + std::string _typePort; + std::string _node; + std::string _name; + YACS::ENGINE::OutputDataStreamPort *_ODSPort; + }; + + class CommandAddLink: public Command + { + public: + CommandAddLink(std::string outNode, std::string outPort, + std::string inNode, std::string inPort); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _outNode; + std::string _outPort; + std::string _inNode; + std::string _inPort; + }; + + class CommandAddControlLink: public Command + { + public: + CommandAddControlLink(std::string outNode, std::string inNode); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _outNode; + std::string _inNode; + }; + + class CommandAddContainer: public Command + { + public: + CommandAddContainer(std::string name, + std::string refContainer =""); + virtual YACS::ENGINE::Container* getContainer(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _name; + std::string _containerToClone; + YACS::ENGINE::Container* _container; + }; + + class CommandSetContainerProperties: public Command + { + public: + CommandSetContainerProperties(std::string container, + std::map properties); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _container; + std::map _properties; + }; + + class CommandSetDSPortProperties: public Command + { + public: + CommandSetDSPortProperties(std::string node, std::string port, bool isInport, + std::map properties); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _nodeName; + std::string _portName; + bool _isInport; + std::map _properties; + }; + + class CommandSetFuncNodeFunctionName: public Command + { + public: + CommandSetFuncNodeFunctionName(std::string node, std::string funcName); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _nodeName; + std::string _funcName; + }; + + class CommandSetInlineNodeScript: public Command + { + public: + CommandSetInlineNodeScript(std::string node, std::string script); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _nodeName; + std::string _script; + }; + + class CommandAddComponentInstance: public Command + { + public: + CommandAddComponentInstance(std::string compoName); + virtual YACS::ENGINE::ComponentInstance* getComponentInstance(); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _compoName; + YACS::ENGINE::ComponentInstance *_compoInst; + }; + + class CommandAssociateComponentToContainer: public Command + { + public: + CommandAssociateComponentToContainer(std::pair key, + std::string container); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::pair _key; + std::string _container; + }; + + class CommandAssociateServiceToComponent: public Command + { + public: + CommandAssociateServiceToComponent(std::string service, + std::pair key); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _service; + std::pair _key; + }; + + class Subject; + class CommandDestroy: public Command + { + public: + CommandDestroy(std::string position, Subject* subject); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + protected: + std::string _position; + Subject* _subject; + }; + + class CommandDeleteNode: public Command + { + public: + CommandDeleteNode(std::string node); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _node; + }; + + class CommandCutNode: public Command + { + public: + CommandCutNode(std::string node); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _node; + }; + + class CommandCopyNode: public Command + { + public: + CommandCopyNode(std::string node); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _node; + }; + + class CommandPasteNode: public Command + { + public: + CommandPasteNode(std::string position); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _node; + }; + + class CommandDeleteInPort: public Command + { + public: + CommandDeleteInPort(std::string node, std::string port); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _node; + std::string _port; + }; + + class CommandDeleteOutPort: public Command + { + public: + CommandDeleteOutPort(std::string node, std::string port); + protected: + virtual bool localExecute(); + virtual bool localReverse(); + std::string _node; + std::string _port; + }; + + } +} +#endif diff --git a/src/hmi/dichoosename.ui b/src/hmi/dichoosename.ui new file mode 100644 index 000000000..c67baf676 --- /dev/null +++ b/src/hmi/dichoosename.ui @@ -0,0 +1,215 @@ + +diChooseName + + + diChooseName + + + + 0 + 0 + 378 + 163 + + + + Choose Name + + + true + + + + unnamed + + + + layout13 + + + + unnamed + + + + Layout1 + + + + unnamed + + + 0 + + + 6 + + + + buttonHelp + + + &Help + + + F1 + + + true + + + + + Horizontal Spacing2 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + buttonOk + + + &OK + + + + + + true + + + true + + + + + buttonCancel + + + &Cancel + + + + + + true + + + + + + + layout12 + + + + unnamed + + + + layout9 + + + + unnamed + + + + tlParent + + + parent: + + + + + tlParentPath + + + path of parent item + + + + + + + layout10 + + + + unnamed + + + + tlItemType + + + item type: + + + + + tlTypeValue + + + type of item + + + + + + + layout11 + + + + unnamed + + + + textLabel3 + + + name: + + + + + leName + + + + + + + + + + + + + buttonOk + clicked() + diChooseName + accept() + + + buttonCancel + clicked() + diChooseName + reject() + + + + diff --git a/src/hmi/editCanvas.cxx b/src/hmi/editCanvas.cxx new file mode 100644 index 000000000..892ba4ab1 --- /dev/null +++ b/src/hmi/editCanvas.cxx @@ -0,0 +1,660 @@ + +#include "editCanvas.h" +#include "guiContext.hxx" + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#include +#include + +using namespace std; + +using namespace YACS; +using namespace YACS::HMI; + +#define LX 60 +#define LY 40 +#define OX 20 +#define OY 5 +#define PX 6 +#define PY 6 +#define DX 3 +#define DY 3 + +// ---------------------------------------------------------------------------- + +EditCanvas::EditCanvas( YACS::HMI::Subject *context, + QCanvas* c, QWidget* parent, + const char* name, WFlags f) + : GuiObserver(), _context(context), QCanvasView(c,parent,name,f) +{ + _context->attach(this); + //_previousSelected = 0; +} + +void EditCanvas::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("editCanvas::update"); + switch (event) + { + case YACS::HMI::NEWROOT: + setNewRoot(son); + break; + default: + DEBTRACE("editCanvas::update(), event not handled: "<< event); + } +} + +void EditCanvas::setNewRoot(YACS::HMI::Subject *root) +{ + YACS::ENGINE::Proc* proc = GuiContext::getCurrent()->getProc(); +// SubjectProc* subjectProc =GuiContext::getCurrent()->getSubjectProc(); + _rootItem = new ComposedNodeCanvasItem(0, proc->getName(), root); +} + +void EditCanvas::contentsMousePressEvent(QMouseEvent* e) +{ + QCanvasItemList l = canvas()->collisions(e->pos()); + double zmax = - 1.E9; + QCanvasItem *item = 0; + for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) + { +// if ( (*it)->rtti() == QCanvasRectangle::RTTI ) +// DEBTRACE("A QCanvasRectangle lies somewhere at this point"); + if ((*it)->z() > zmax) + { + zmax = (*it)->z(); + item = *it; + } + } + if (item) + { + CanvasItem* citem = dynamic_cast(item); + if (citem) + citem->getSubject()->select(true); + } +} + +// ---------------------------------------------------------------------------- + +CanvasItem::CanvasItem(CanvasItem *parent, QString label, Subject* subject) : + GuiObserver(), QCanvasRectangle(OX,OY,LX,LY,YACS::HMI::GuiContext::getCurrent()->getCanvas()) +{ + _parent = parent; + _label = label; + _subject = subject; + _subject->attach(this); + _level = 1; + _root = this; + if (_parent) + { + _level = _parent->getLevel() +1; + _root = _parent->getRoot(); + } + _ofx = OX; _ofy = OY; _lx = LX; _ly = LY; +} + +CanvasItem::~CanvasItem() +{ + DEBTRACE("CanvasItem::~CanvasItem " << _subject->getName()); + QCanvasItem* can = GuiContext::getCurrent()->getSelectedCanvasItem(); + if (can == this) + GuiContext::getCurrent()->setSelectedCanvasItem(0); +// QCanvas * canvas = GuiContext::getCurrent()->getCanvas(); +// canvas->update(); +} + +CanvasItem *CanvasItem::getParent() +{ + return _parent; +} + +CanvasItem *CanvasItem::getRoot() +{ + return _root; +} + +void CanvasItem::select(bool isSelected) +{ + DEBTRACE("CanvasItem::select: " << isSelected << " " << this); + QColor col; + if (isSelected) + { + col = getSelectedColor(); + QCanvasItem* can = GuiContext::getCurrent()->getSelectedCanvasItem(); + if (can) + { + CanvasItem* citem = dynamic_cast(can); + DEBTRACE("previous: " << citem); + if (citem != this) + { + assert(citem); + citem->select(false); + } + } + GuiContext::getCurrent()->setSelectedCanvasItem(this); + } + else + col = getNormalColor(); + setBrush(col); + show(); + QCanvas * canvas = GuiContext::getCurrent()->getCanvas(); + canvas->update(); +} + +QColor CanvasItem::getNormalColor() +{ + return QColor(180,180,180); +} + +QColor CanvasItem::getSelectedColor() +{ + return QColor(215,215,215); +} + +Subject* CanvasItem::getSubject() +{ + return _subject; +} + +int CanvasItem::getLevel() +{ + return _level; +} + +int CanvasItem::getOfx() +{ + _ofx = (_level +1)*OX; + return _ofx; +} + +int CanvasItem::getOfy() +{ + int oy = OY; + if (_parent) + { + ComposedNodeCanvasItem* parent = dynamic_cast(_parent); + assert(parent); + oy = parent->getOfyChild(this); + } + _ofy = oy; + return _ofy; +} + +int CanvasItem::getLx() +{ + return _lx; +} + +int CanvasItem::getLy() +{ + return _ly; +} + +int CanvasItem::getOfxInPort(CanvasItem *child) +{ + return getOfx() +DX; // used only in derivation +} + +int CanvasItem::getOfxOutPort(CanvasItem *child) +{ + return getOfy() +DY; // used only in derivation +} + +void CanvasItem::redraw() +{ +// DEBTRACE("CanvasItem::redraw"); +} + +void CanvasItem::drawNode(int ofx, int ofy, int lx, int ly, int level) +{ + setBrush(getNormalColor()); + setPen( QPen(Qt::black, 2) ); + setSize(lx,ly); + setX(ofx); + setY(ofy); + setZ(level); + show(); +} + +// ---------------------------------------------------------------------------- + +NodeCanvasItem::NodeCanvasItem(CanvasItem *parent, QString label, Subject* subject) + : CanvasItem(parent, label, subject) +{ + _inPorts.clear(); + _outPorts.clear(); +} + +NodeCanvasItem::~NodeCanvasItem() +{ + DEBTRACE("NodeCanvasItem::~NodeCanvasItem " << _subject->getName()); +} + +void NodeCanvasItem::removeInPort(CanvasItem* inport) +{ + _inPorts.remove(inport); +} + +void NodeCanvasItem::removeOutPort(CanvasItem* outport) +{ + _outPorts.remove(outport); +} + +// ---------------------------------------------------------------------------- + +ElementaryNodeCanvasItem::ElementaryNodeCanvasItem(CanvasItem *parent, QString label, Subject* subject) + : NodeCanvasItem(parent, label, subject) +{ +} + +ElementaryNodeCanvasItem::~ElementaryNodeCanvasItem() +{ + DEBTRACE("ElementaryNodeCanvasItem::~ElementaryNodeCanvasItem " << _subject->getName()); + if (_parent) + { + ComposedNodeCanvasItem* cnci = dynamic_cast(_parent); + if (cnci) cnci->removeChild(this); + } +} + +int ElementaryNodeCanvasItem::getLx() +{ + return LX; +} + +int ElementaryNodeCanvasItem::getLy() +{ + return LY; +} + +void ElementaryNodeCanvasItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("ElementaryNodeCanvasItem::update"); + CanvasItem *item; + switch (event) + { + case YACS::HMI::ADD: + switch (type) + { + case YACS::HMI::INPUTPORT: + case YACS::HMI::INPUTDATASTREAMPORT: + item = new InPortCanvasItem(this, + son->getName(), + son); + _inPorts.push_back(item); + _root->redraw(); + break; + case YACS::HMI::OUTPUTPORT: + case YACS::HMI::OUTPUTDATASTREAMPORT: + item = new OutPortCanvasItem(this, + son->getName(), + son); + _outPorts.push_back(item); + _root->redraw(); + break; + default: + DEBTRACE("ElementaryNodeCanvasItem::update() ADD, type not handled:" << type); + } + break; + default: + DEBTRACE("ElementaryNodeCanvasItem::update(), event not handled: << event"); + } +} + +void ElementaryNodeCanvasItem::redraw() +{ +// DEBTRACE(" ElementaryNodeCanvasItem::redraw() "<getCanvas(); + drawNode(getOfx(), getOfy(), getLx(), getLy(), getLevel()); + for (list::iterator it = _inPorts.begin(); it!=_inPorts.end(); ++it) + (*it)->redraw(); + for (list::iterator it = _outPorts.begin(); it!=_outPorts.end(); ++it) + (*it)->redraw(); + canvas->update(); +} + +QColor ElementaryNodeCanvasItem::getNormalColor() +{ + return QColor(171,167,118); +} + +QColor ElementaryNodeCanvasItem::getSelectedColor() +{ + return QColor(219,213,151); +} + +int ElementaryNodeCanvasItem::getOfxInPort(CanvasItem *child) +{ + int ofx = getOfx() +DX; + for (list::iterator it = _inPorts.begin(); it!=_inPorts.end(); ++it) + { + if ((*it) == static_cast(child)) break; + else ofx += PX+ DX; + } + return ofx; +} + +int ElementaryNodeCanvasItem::getOfxOutPort(CanvasItem *child) +{ + int ofx = getOfx() +DX; + for (list::iterator it = _outPorts.begin(); it!=_outPorts.end(); ++it) + { + if ((*it) == static_cast(child)) break; + else ofx += PX+ DX; + } + return ofx; +} + +// ---------------------------------------------------------------------------- + +ComposedNodeCanvasItem::ComposedNodeCanvasItem(CanvasItem *parent, QString label, Subject* subject) + : NodeCanvasItem(parent, label, subject) +{ + _children.clear(); +} + + +ComposedNodeCanvasItem::~ComposedNodeCanvasItem() +{ + DEBTRACE("ComposedNodeCanvasItem::~ComposedNodeCanvasItem " << _subject->getName()); + if (_parent) + { + ComposedNodeCanvasItem* cnci = dynamic_cast(_parent); + if (cnci) cnci->removeChild(this); + } +} + +int ComposedNodeCanvasItem::getLx() +{ + int lx = 0; + for (list::iterator it = _children.begin(); it!=_children.end(); ++it) + { + int val = (*it)->getLx(); + if (val > lx) lx = val; + } + if (lx == 0) lx = LX; + lx += 2*OX; + _lx = lx; + return _lx; +} + +int ComposedNodeCanvasItem::getLy() +{ + int ly = 0; + for (list::iterator it = _children.begin(); it!=_children.end(); ++it) + ly += (*it)->getLy() + OY; + if (ly == 0) ly = LY + OY; + ly += OY; + _ly = ly; + return _ly; +} + +int ComposedNodeCanvasItem::getOfyChild(CanvasItem *child) +{ + int oy = getOfy(); + for (list::iterator it = _children.begin(); it!=_children.end(); ++it) + { + if ((*it) == static_cast(child)) break; + else oy += (*it)->getLy() + OY; + } + oy += OY; + return oy; +} + + +void ComposedNodeCanvasItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("ComposedNodeCanvasItem::update"); + CanvasItem *item; + switch (event) + { + case YACS::HMI::ADD: + switch (type) + { + case YACS::HMI::BLOC: + case YACS::HMI::FORLOOP: + case YACS::HMI::WHILELOOP: + case YACS::HMI::SWITCH: + case YACS::HMI::FOREACHLOOP: + case YACS::HMI::OPTIMIZERLOOP: + item = new ComposedNodeCanvasItem(this, + son->getName(), + son); + _children.push_back(item); + _root->redraw(); + break; + case YACS::HMI::PYTHONNODE: + case YACS::HMI::PYFUNCNODE: + case YACS::HMI::CORBANODE: + case YACS::HMI::CPPNODE: + case YACS::HMI::SALOMENODE: + case YACS::HMI::SALOMEPYTHONNODE: + case YACS::HMI::XMLNODE: + case YACS::HMI::PRESETNODE: + case YACS::HMI::OUTNODE: + case YACS::HMI::STUDYINNODE: + case YACS::HMI::STUDYOUTNODE: + item = new ElementaryNodeCanvasItem(this, + son->getName(), + son); + _children.push_back(item); + _root->redraw(); + break; + case YACS::HMI::INPUTPORT: + case YACS::HMI::INPUTDATASTREAMPORT: + item = new InPortCanvasItem(this, + son->getName(), + son); + _inPorts.push_back(item); + _root->redraw(); + break; + case YACS::HMI::OUTPUTPORT: + case YACS::HMI::OUTPUTDATASTREAMPORT: + item = new OutPortCanvasItem(this, + son->getName(), + son); + _outPorts.push_back(item); + _root->redraw(); + break; + default: + DEBTRACE("ComposedNodeCanvasItem::update() ADD, type not handled:" << type); + } + break; + default: + DEBTRACE("ComposedNodeCanvasItem::update(), event not handled: << event"); + } +} + +void ComposedNodeCanvasItem::removeChild(CanvasItem* child) +{ + _children.remove(child); +} + +void ComposedNodeCanvasItem::redraw() +{ +// DEBTRACE(" ComposedNodeCanvasItem::redraw() "<getCanvas(); + drawNode(getOfx(), getOfy(), getLx(), getLy(), getLevel()); + for (list::iterator it = _children.begin(); it!=_children.end(); ++it) + (*it)->redraw(); + for (list::iterator it = _inPorts.begin(); it!=_inPorts.end(); ++it) + (*it)->redraw(); + for (list::iterator it = _outPorts.begin(); it!=_outPorts.end(); ++it) + (*it)->redraw(); + canvas->update(); +} + +QColor ComposedNodeCanvasItem::getNormalColor() +{ + return QColor(130,177,149); +} + +QColor ComposedNodeCanvasItem::getSelectedColor() +{ + return QColor(166,227,191); +} + +int ComposedNodeCanvasItem::getOfxInPort(CanvasItem *child) +{ + int ofx = getOfx() +DX; + for (list::iterator it = _inPorts.begin(); it!=_inPorts.end(); ++it) + { + if ((*it) == static_cast(child)) break; + else ofx += PX+ DX; + } + return ofx; +} + +int ComposedNodeCanvasItem::getOfxOutPort(CanvasItem *child) +{ + int ofx = getOfx() +DX; + for (list::iterator it = _outPorts.begin(); it!=_outPorts.end(); ++it) + { + if ((*it) == static_cast(child)) break; + else ofx += PX+ DX; + } + return ofx; +} + +// ---------------------------------------------------------------------------- + +InPortCanvasItem::InPortCanvasItem(CanvasItem *parent, QString label, Subject* subject) + : CanvasItem(parent, label, subject) +{ +} + +InPortCanvasItem::~InPortCanvasItem() +{ + DEBTRACE("InPortCanvasItem::~InPortCanvasItem " << _subject->getName()); + if(_parent) + { + NodeCanvasItem* nci = dynamic_cast(_parent); + if(nci) nci->removeInPort(this); + } +} + +QColor InPortCanvasItem::getNormalColor() +{ + return QColor(144,37,37); +} + +QColor InPortCanvasItem::getSelectedColor() +{ + return QColor(255,66,66); +} + +void InPortCanvasItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("InPortCanvasItem::update"); +} + +int InPortCanvasItem::getLx() +{ + return PX; +} + +int InPortCanvasItem::getLy() +{ + return PY; +} + +int InPortCanvasItem::getOfx() +{ + int ofx = 0; + if (_parent) + { + ofx = _parent->getOfxInPort(this); + } + _ofx = ofx; + return _ofx; +} + +int InPortCanvasItem::getOfy() +{ + int ofy = 0; + if (_parent) + ofy = _parent->getOfy() + DY; + _ofy = ofy; + return _ofy; +} + +void InPortCanvasItem::redraw() +{ +// DEBTRACE(" InportCanvasItem::redraw() "<getCanvas(); + drawNode(getOfx(), getOfy(), getLx(), getLy(), getLevel()); + canvas->update(); +} + +// ---------------------------------------------------------------------------- + +OutPortCanvasItem::OutPortCanvasItem(CanvasItem *parent, QString label, Subject* subject) + : CanvasItem(parent, label, subject) +{ +} + +OutPortCanvasItem::~OutPortCanvasItem() +{ + DEBTRACE("OutPortCanvasItem::~OutPortCanvasItem " << _subject->getName()); + if(_parent) + { + NodeCanvasItem* nci = dynamic_cast(_parent); + if(nci) nci->removeOutPort(this); + } +} + +QColor OutPortCanvasItem::getNormalColor() +{ + return QColor(144,37,37); +} + +QColor OutPortCanvasItem::getSelectedColor() +{ + return QColor(255,66,66); +} + +void OutPortCanvasItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("OutPortCanvasItem::update"); +} + +int OutPortCanvasItem::getLx() +{ + return PX; +} + +int OutPortCanvasItem::getLy() +{ + return PY; +} + +int OutPortCanvasItem::getOfx() +{ + int ofx = 0; + if (_parent) + { + ofx = _parent->getOfxOutPort(this); + } + _ofx = ofx; + return _ofx; +} + +int OutPortCanvasItem::getOfy() +{ + int ofy = 0; + if (_parent) + ofy = _parent->getOfy() + LY -(PY + DY); + _ofy = ofy; + return _ofy; +} + +void OutPortCanvasItem::redraw() +{ +// DEBTRACE(" OutportCanvasItem::redraw() "<getCanvas(); + drawNode(getOfx(), getOfy(), getLx(), getLy(), getLevel()); + canvas->update(); +} + diff --git a/src/hmi/editCanvas.h b/src/hmi/editCanvas.h new file mode 100644 index 000000000..b31db7433 --- /dev/null +++ b/src/hmi/editCanvas.h @@ -0,0 +1,145 @@ +#ifndef _EDITCANVAS_H_ +#define _EDITCANVAS_H_ + +#include "guiObservers.hxx" + +#include + +#include + +namespace YACS +{ + namespace HMI + { + class CanvasItem; + class ComposedNodeCanvasItem; + + class EditCanvas : public QCanvasView, public GuiObserver + { + Q_OBJECT + + public: + EditCanvas(YACS::HMI::Subject *context, + QCanvas* c, QWidget* parent=0, const char* name=0, WFlags f=0); + virtual void update(GuiEvent event, int type, Subject* son); + void setNewRoot(YACS::HMI::Subject *root); + + protected: + YACS::HMI::Subject *_context; + ComposedNodeCanvasItem *_rootItem; + void contentsMousePressEvent(QMouseEvent* e); + + signals: + + private: + }; + + class CanvasItem : public QCanvasRectangle, public GuiObserver + { + public: + CanvasItem(CanvasItem *parent, QString label, Subject* subject); + virtual ~CanvasItem(); + CanvasItem *getParent(); + CanvasItem *getRoot(); + virtual void select(bool isSelected); + virtual QColor getNormalColor(); + virtual QColor getSelectedColor(); + virtual Subject* getSubject(); + int getLevel(); + virtual int getOfx(); + virtual int getOfy(); + virtual int getLx(); + virtual int getLy(); + virtual int getOfxInPort(CanvasItem *child); + virtual int getOfxOutPort(CanvasItem *child); + virtual void redraw(); + virtual void drawNode(int ofx, int ofy, int lx, int ly, int level); + protected: + Subject* _subject; + CanvasItem *_parent; + CanvasItem *_root; + int _level; + int _ofx, _ofy, _lx, _ly; + QString _label; + }; + + class NodeCanvasItem: public CanvasItem + { + public: + NodeCanvasItem(CanvasItem *parent, QString label, Subject* subject); + virtual ~NodeCanvasItem(); + virtual void removeInPort(CanvasItem* inport); + virtual void removeOutPort(CanvasItem* outport); + std::list _inPorts; + std::list _outPorts; + }; + + class ElementaryNodeCanvasItem: public NodeCanvasItem + { + public: + ElementaryNodeCanvasItem(CanvasItem *parent, QString label, Subject* subject); + virtual ~ElementaryNodeCanvasItem(); + virtual QColor getNormalColor(); + virtual QColor getSelectedColor(); + virtual void update(GuiEvent event, int type, Subject* son); + virtual int getLx(); + virtual int getLy(); + virtual void redraw(); + virtual int getOfxInPort(CanvasItem *child); + virtual int getOfxOutPort(CanvasItem *child); + }; + + class ComposedNodeCanvasItem: public NodeCanvasItem + { + public: + ComposedNodeCanvasItem(CanvasItem *parent, QString label, Subject* subject); + virtual ~ComposedNodeCanvasItem(); + virtual QColor getNormalColor(); + virtual QColor getSelectedColor(); + virtual void update(GuiEvent event, int type, Subject* son); + virtual void removeChild(CanvasItem* child); + virtual int getLx(); + virtual int getLy(); + virtual int getOfyChild(CanvasItem *child); + virtual void redraw(); + virtual int getOfxInPort(CanvasItem *child); + virtual int getOfxOutPort(CanvasItem *child); + protected: + std::list _children; + }; + + class InPortCanvasItem: public CanvasItem + { + public: + InPortCanvasItem(CanvasItem *parent, QString label, Subject* subject); + virtual ~InPortCanvasItem(); + virtual QColor getNormalColor(); + virtual QColor getSelectedColor(); + virtual void update(GuiEvent event, int type, Subject* son); + virtual int getLx(); + virtual int getLy(); + virtual int getOfx(); + virtual int getOfy(); + virtual void redraw(); + }; + + class OutPortCanvasItem: public CanvasItem + { + public: + OutPortCanvasItem(CanvasItem *parent, QString label, Subject* subject); + virtual ~OutPortCanvasItem(); + virtual QColor getNormalColor(); + virtual QColor getSelectedColor(); + virtual void update(GuiEvent event, int type, Subject* son); + virtual int getLx(); + virtual int getLy(); + virtual int getOfx(); + virtual int getOfy(); + virtual void redraw(); + }; + + } +} + +#endif + diff --git a/src/hmi/editTree.cxx b/src/hmi/editTree.cxx new file mode 100644 index 000000000..7eef45844 --- /dev/null +++ b/src/hmi/editTree.cxx @@ -0,0 +1,1155 @@ + +#include "RuntimeSALOME.hxx" +#include "editTree.h" +#include "Proc.hxx" +#include "Node.hxx" +#include "guiContext.hxx" +#include "Catalog.hxx" +#include "browseCatalog.h" +#include "chooseName.h" +#include "ServiceNode.hxx" + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#include +#include +#include +#include +#include + + +#include +#include +#include + +using namespace std; + +using namespace YACS; +using namespace YACS::HMI; + + +/*! + * + */ + +ViewItem::ViewItem(QListView *parent, QString label, Subject* subject) + : QListViewItem(parent, label) +{ + _parent = parent; + _subject = subject; + _cf = Qt::black; + _subject->attach(this); +} + +/*! + * + */ + +ViewItem::ViewItem(ViewItem *parent, QString label, Subject* subject) + : GuiObserver(), QListViewItem(parent, label) +{ + _parent = parent->getParent(); + _subject = subject; + _cf = Qt::black; + _subject->attach(this); +} + +/*! + * + */ + +ViewItem::~ViewItem() +{ +} + +/*! + * + */ + +void ViewItem::setState(int state) +{ +} + +/*! + * + */ + +QListView *ViewItem::getParent() +{ + return _parent; +} + +/*! + * + */ + +Subject* ViewItem::getSubject() +{ + return _subject; +} + +/*! + * + */ + +void ViewItem::select(bool isSelected) +{ + DEBTRACE("ViewItem::select() "<< isSelected << " " << this); + _parent->setSelected(this, isSelected); + _parent->ensureItemVisible(this); +} + +void ViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("ViewItem::update"); + ViewItem *item = 0; + switch (event) + { + case RENAME: + DEBTRACE("ViewItem::update RENAME " << _subject->getName()); + setText(0,_subject->getName()); + break; + case ADDREF: + DEBTRACE("ViewItem::update ADDREF " << _subject->getName()); + item = new ReferenceViewItem(this, + son->getName(), + son); + break; + default: + DEBTRACE("ViewItem::update(), event not handled: " << event); + GuiObserver::update(event, type, son); + } +} + +/*! + * + */ + +void ViewItem::paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ) +{ + QColorGroup _cg( cg ); + QColor c = _cg.text(); + if (column == 1) _cg.setColor( QColorGroup::Text, _cf ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + if (column == 1) _cg.setColor( QColorGroup::Text, c ); +} + +// ---------------------------------------------------------------------------- + +/*! + * + */ + +NodeViewItem::NodeViewItem(ViewItem *parent, + QString label, + Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void NodeViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("NodeViewItem::update"); + ViewItem *item = 0; + switch (event) + { + case YACS::HMI::ADD: + switch (type) + { + case YACS::HMI::INPUTPORT: + case YACS::HMI::OUTPUTPORT: + case YACS::HMI::INPUTDATASTREAMPORT: + case YACS::HMI::OUTPUTDATASTREAMPORT: + item = new PortViewItem(this, + son->getName(), + son); + break; + default: + DEBTRACE("NodeViewItem::update(), ADD, type not handled: " << type); + } + break; + default: + DEBTRACE("NodeViewItem::update(), event not handled: " << event); + ViewItem::update(event, type, son); + } +} + +// ---------------------------------------------------------------------------- + +/*! + * + */ + +ComposedNodeViewItem::ComposedNodeViewItem(QListView *parent, + QString label, + Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +/*! + * + */ + + +ComposedNodeViewItem::ComposedNodeViewItem(ViewItem *parent, + QString label, + Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void ComposedNodeViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("ComposedNodeViewItem::update"); + ViewItem *item = 0; + switch (event) + { + case YACS::HMI::ADD: + switch (type) + { + case YACS::HMI::BLOC: + case YACS::HMI::FORLOOP: + case YACS::HMI::WHILELOOP: + case YACS::HMI::SWITCH: + case YACS::HMI::FOREACHLOOP: + case YACS::HMI::OPTIMIZERLOOP: + item = new ComposedNodeViewItem(this, + son->getName(), + son); + break; + case YACS::HMI::PYTHONNODE: + case YACS::HMI::PYFUNCNODE: + case YACS::HMI::CORBANODE: + case YACS::HMI::CPPNODE: + case YACS::HMI::SALOMENODE: + case YACS::HMI::SALOMEPYTHONNODE: + case YACS::HMI::XMLNODE: + case YACS::HMI::PRESETNODE: + case YACS::HMI::OUTNODE: + case YACS::HMI::STUDYINNODE: + case YACS::HMI::STUDYOUTNODE: + item = new NodeViewItem(this, + son->getName(), + son); + break; + case YACS::HMI::INPUTPORT: + case YACS::HMI::OUTPUTPORT: + case YACS::HMI::INPUTDATASTREAMPORT: + case YACS::HMI::OUTPUTDATASTREAMPORT: + item = new PortViewItem(this, + son->getName(), + son); + break; + case YACS::HMI::COMPONENT: + item = new ComponentViewItem(this, + son->getName(), + son); + break; + case YACS::HMI::CONTAINER: + item = new ContainerViewItem(this, + son->getName(), + son); + break; + case YACS::HMI::DATATYPE: + item = new DataTypeViewItem(this, + son->getName(), + son); + break; + default: + DEBTRACE("ComposedNodeViewItem::update() ADD, type not handled:" << type); + } + break; + case YACS::HMI::ADDLINK: + case YACS::HMI::ADDCONTROLLINK: + item = new LinkViewItem(this, + son->getName(), + son); + break; + default: + DEBTRACE("ComposedNodeViewItem::update(), event not handled: "<< event); + ViewItem::update(event, type, son); + } +} + +// ---------------------------------------------------------------------------- + +PortViewItem::PortViewItem(ViewItem *parent, QString label, Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void PortViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("PortViewItem::update"); + ViewItem::update(event, type, son); +} + +// ---------------------------------------------------------------------------- + +LinkViewItem::LinkViewItem(ViewItem *parent, QString label, Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void LinkViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("LinkViewItem::update"); + ViewItem::update(event, type, son); +} + +// ---------------------------------------------------------------------------- + +ComponentViewItem::ComponentViewItem(ViewItem *parent, QString label, Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void ComponentViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("ComponentViewItem::update"); + ViewItem::update(event, type, son); +} + +// ---------------------------------------------------------------------------- + +ContainerViewItem::ContainerViewItem(ViewItem *parent, QString label, Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void ContainerViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("ContainerViewItem::update"); + ViewItem::update(event, type, son); +} + +// ---------------------------------------------------------------------------- + +DataTypeViewItem::DataTypeViewItem(ViewItem *parent, QString label, Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void DataTypeViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("DataTypeViewItem::update"); + ViewItem::update(event, type, son); +} + +// ---------------------------------------------------------------------------- + +ReferenceViewItem::ReferenceViewItem(ViewItem *parent, QString label, Subject* subject) + : ViewItem::ViewItem(parent, label, subject) +{ +} + +void ReferenceViewItem::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("ReferenceViewItem::update"); + ViewItem::update(event, type, son); +} + +// ---------------------------------------------------------------------------- + + +/*! + * + */ + +editTree::editTree(YACS::HMI::Subject *context, + QWidget* parent, + const char* name, + WFlags fl) : GuiObserver(), wiEditTree(parent, name, fl) +{ + _context = context; + _parent = parent; + _root = 0; + _previousSelected = 0; + _selectedSubjectOutPort = 0; + _selectedSubjectNode = 0; + _selectedSubjectComponent = 0; + _selectedSubjectService = 0; + resetTreeNode(lv); + _context->attach(this); + connect( lv, SIGNAL(selectionChanged()), + this, SLOT(select()) ); +// connect( lv, SIGNAL(clicked(QListViewItem *)), +// this, SLOT(select()) ); +// connect( lv, SIGNAL(selectionChanged(QListViewItem *)), +// this, SLOT(select(QListViewItem *)) ); +// connect( lv, SIGNAL(clicked(QListViewItem *)), +// this, SLOT(select(QListViewItem *)) ); +} + +/*! + * + */ + +editTree::~editTree() +{ +} + +void editTree::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("editTree::update"); + switch (event) + { + case YACS::HMI::NEWROOT: + setNewRoot(son); + break; + default: + DEBTRACE("editTree::update(), event not handled: "<< event); + } +} + +void editTree::setNewRoot(YACS::HMI::Subject *root) +{ + _root=root; + _previousSelected=0; + resetTreeNode(lv); +} + +void editTree::addViewItemInMap(YACS::HMI::ViewItem* item, YACS::HMI::Subject* subject) +{ + _viewItemsMap[subject] = item; +} + +YACS::HMI::ViewItem* editTree::getViewItem(YACS::HMI::Subject* subject) +{ + return _viewItemsMap[subject]; +} + +/*! + * + */ + +void editTree::resetTreeNode(QListView *lv) +{ + lv->clear(); + lv->setColumnWidth(0,400); +// lv->addColumn( "state", 100); + lv->setRootIsDecorated( TRUE ); + if (_root) + { + string name = _root->getName(); + ViewItem *start = new ComposedNodeViewItem(lv, name, _root); + addViewItemInMap(start, _root); + } +} + +/*! + * + */ + +void editTree::printName() +{ + QListViewItem *it = lv->selectedItem(); + if (it) + { + DEBTRACE("my name is Bond, James Bond... "<< this); + } + else + { + DEBTRACE("nobody "<< this); + } +} + +YACS::HMI::Subject* editTree::getSelectedSubject() +{ + Subject *sub = 0; + QListViewItem *it = lv->selectedItem(); + if (it) + { + ViewItem *item = dynamic_cast (it); + if (item) sub = item->getSubject(); + } + return sub; +} + +void editTree::destroy() +{ + DEBTRACE("editTree::destroy"); + Subject *sub =getSelectedSubject(); + if (sub) + { + Subject *parent = sub->getParent(); + if (parent) + { + parent->destroy(sub); + } + } +} + +void editTree::addLink() +{ + DEBTRACE("editTree::addLink"); + Subject *sub =getSelectedSubject(); + if (sub) + { + if (dynamic_cast(sub) || dynamic_cast(sub)) + _selectedSubjectOutPort = static_cast(sub); + else if (dynamic_cast(sub)) + _selectedSubjectNode = static_cast(sub); + } +} + +void editTree::editPortProperties() +{ + DEBTRACE("editTree::editPortProperties"); + Subject *sub =getSelectedSubject(); + if (sub) + { + if (SubjectOutputDataStreamPort* subODS = dynamic_cast(sub)) + { + map properties = subODS->getProperties(); + properties["prop1"] = "val1"; + properties["prop2"] = "val2"; + subODS->setProperties(properties); + properties = subODS->getProperties(); + map::iterator it; + for (it = properties.begin(); it !=properties.end(); ++it) + DEBTRACE("OutputDataStreamPort property " << (*it).first << " " << (*it).second); + } + else if (SubjectInputDataStreamPort* subIDS = dynamic_cast(sub)) + { + map properties = subIDS->getProperties(); + properties["prop1"] = "val1"; + properties["prop2"] = "val2"; + subIDS->setProperties(properties); + properties = subIDS->getProperties(); + map::iterator it; + for (it = properties.begin(); it !=properties.end(); ++it) + DEBTRACE("InputDataStreamPort property " << (*it).first << " " << (*it).second); + } + } +} + +void editTree::addComponent() +{ + DEBTRACE("editTree::addComponent"); + stringstream name; + name << "component"; + name << "_" << GuiContext::getCurrent()->getNewId(); + ChooseName chooseName("root", "component", name.str()); + chooseName.exec(); + if (chooseName.isOk()) + { + string theName = chooseName.getChoosenName(); + bool ret = GuiContext::getCurrent()->getSubjectProc()->addComponent(theName); + if (!ret) QMessageBox::warning(this, "Component not Created", GuiContext::getCurrent()->_lastErrorMessage ); + } +} + +void editTree::addContainer() +{ + DEBTRACE("editTree::addContainer"); + std::stringstream name; + name << "container" << GuiContext::getCurrent()->getNewId(); + ChooseName chooseName("root", "container", name.str()); + chooseName.exec(); + if (chooseName.isOk()) + { + string theName = chooseName.getChoosenName(); + bool ret = GuiContext::getCurrent()->getSubjectProc()->addContainer(theName); + if (!ret) QMessageBox::warning(this, "Container not Created", GuiContext::getCurrent()->_lastErrorMessage ); + } +} + +void editTree::associateServiceToComponent() +{ + DEBTRACE("editTree::associateServiceToComponent"); + Subject *sub =getSelectedSubject(); + if (sub) + { + if (SubjectServiceNode *subserv = dynamic_cast(sub)) + _selectedSubjectService = subserv; + } +} + +void editTree::associateComponentToContainer() +{ + DEBTRACE("editTree::associateComponentToContainer"); + Subject *sub =getSelectedSubject(); + if (sub) + { + if (SubjectComponent *subcomp = dynamic_cast(sub)) + _selectedSubjectComponent = subcomp; + } +} + +void editTree::editContainerProperties() +{ + DEBTRACE("editTree::editContainerProperties"); + Subject *sub =getSelectedSubject(); + if (sub) + { + if (SubjectContainer *subcont = dynamic_cast(sub)) + { + map properties = subcont->getProperties(); + properties["prop1"] = "val1"; + properties["prop2"] = "val2"; + subcont->setProperties(properties); + properties = subcont->getProperties(); + map::iterator it; + for (it = properties.begin(); it !=properties.end(); ++it) + DEBTRACE("container property " << (*it).first << " " << (*it).second); + } + } +} + +void editTree::newNode(int key) +{ + DEBTRACE("editTree::newNode(Catalog* catalog, string type): "<< this); + YACS::ENGINE::Catalog* catalog = _catalogItemsMap[key].first; + std::string type = _catalogItemsMap[key].second; + Subject *sub =getSelectedSubject(); + if (sub) + { + YACS::HMI::SubjectComposedNode *subject = dynamic_cast< YACS::HMI::SubjectComposedNode*>(sub); + if (subject) + { + std::stringstream name; + name << type << GuiContext::getCurrent()->getNewId(); + YACS::HMI::SubjectSwitch *aSwitch = dynamic_cast< YACS::HMI::SubjectSwitch*>(subject); + if (aSwitch) + { + map bodyMap = aSwitch->getBodyMap(); + int swCase = 0; + if (bodyMap.empty()) swCase = 1; + else + { + map::reverse_iterator rit = bodyMap.rbegin(); + swCase = (*rit).first + 1; + } + aSwitch->addNode(catalog, "", type, name.str(), swCase); + } + else + subject->addNode(catalog, "", type, name.str()); + } + } + else DEBTRACE("editTree::newNode(Catalog* catalog, string type): no ComposedNode selected "<< this); +} + +void editTree::newNode(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::pair compoServ) +{ + DEBTRACE("editTree::newNode(catalog, subject, std::pair compoServ)"); + std::string compo = compoServ.first; + std::string service = compoServ.second; + std::stringstream name; + name << compo << "_" << service << GuiContext::getCurrent()->getNewId(); + YACS::HMI::SubjectComposedNode *subject = dynamic_cast< YACS::HMI::SubjectComposedNode*>(sub); + if (subject) + { + YACS::HMI::SubjectSwitch *aSwitch = dynamic_cast< YACS::HMI::SubjectSwitch*>(subject); + if (aSwitch) + { + map bodyMap = aSwitch->getBodyMap(); + int swCase = 0; + if (bodyMap.empty()) swCase = 1; + else + { + map::reverse_iterator rit = bodyMap.rbegin(); + swCase = (*rit).first + 1; + } + aSwitch->addNode(catalog, compo, service, name.str(), swCase); + } + else + subject->addNode(catalog, compo, service, name.str()); + } +} + +void editTree::newDataType(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName) +{ + DEBTRACE("editTree::newDataType " << sub->getName() << " " << typeName); + YACS::HMI::SubjectProc *subproc = GuiContext::getCurrent()->getSubjectProc(); + subproc->addDataType(catalog, typeName); +} + + +void editTree::newInputPort(int key) +{ + DEBTRACE("editTree::newInputPort(Catalog* catalog, string type): "<< this); + YACS::ENGINE::Catalog* catalog = _catalogItemsMap[key].first; + std::string type = _catalogItemsMap[key].second; + Subject *sub =getSelectedSubject(); + newDFInputPort(catalog, sub, type); +} + +void editTree::newOutputPort(int key) +{ + DEBTRACE("editTree::newOutputPort(Catalog* catalog, string type): "<< this); + YACS::ENGINE::Catalog* catalog = _catalogItemsMap[key].first; + std::string type = _catalogItemsMap[key].second; + Subject *sub =getSelectedSubject(); + newDFOutputPort(catalog, sub, type); +} + +void editTree::newDFInputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName) +{ + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + { + std::stringstream name; + name << "InDF_" << typeName << GuiContext::getCurrent()->getNewId(); + ChooseName chooseName(subject->getName(), typeName, name.str()); + chooseName.exec(); + if (chooseName.isOk()) + { + string theName = chooseName.getChoosenName(); + bool ret = subject->addInputPort(catalog, typeName, theName); + if (!ret) QMessageBox::warning(this, "Input Port not Created", GuiContext::getCurrent()->_lastErrorMessage ); + } + } + } +} + +void editTree::newDFOutputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName) +{ + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + { + std::stringstream name; + name << "OutDF_" << typeName << GuiContext::getCurrent()->getNewId(); + ChooseName chooseName(subject->getName(), typeName, name.str()); + chooseName.exec(); + if (chooseName.isOk()) + { + string theName = chooseName.getChoosenName(); + bool ret = subject->addOutputPort(catalog, typeName, theName); + if (!ret) QMessageBox::warning(this, "Output Port not Created", GuiContext::getCurrent()->_lastErrorMessage ); + } + } + } +} + +void editTree::newDSInputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName) +{ + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + { + std::stringstream name; + name << "InDS_" << typeName << GuiContext::getCurrent()->getNewId(); + ChooseName chooseName(subject->getName(), typeName, name.str()); + chooseName.exec(); + if (chooseName.isOk()) + { + string theName = chooseName.getChoosenName(); + bool ret = subject->addIDSPort(catalog, typeName, theName); + if (!ret) QMessageBox::warning(this, "Input Port not Created", GuiContext::getCurrent()->_lastErrorMessage ); + } + } + } +} + +void editTree::newDSOutputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName) +{ + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + { + std::stringstream name; + name << "OutDS_" << typeName << GuiContext::getCurrent()->getNewId(); + ChooseName chooseName(subject->getName(), typeName, name.str()); + chooseName.exec(); + if (chooseName.isOk()) + { + string theName = chooseName.getChoosenName(); + bool ret = subject->addODSPort(catalog, typeName, theName); + if (!ret) QMessageBox::warning(this, "Output Port not Created", GuiContext::getCurrent()->_lastErrorMessage ); + } + } + } +} + + +void editTree::newDFInputPort() +{ + DEBTRACE("editTree::newDFInputPort"); + Subject *sub =getSelectedSubject(); + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + catalog(CATALOGINPUTPORT); + } + +} + +void editTree::newDFOutputPort() +{ + DEBTRACE("editTree::newDFOutputPort"); + Subject *sub =getSelectedSubject(); + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + catalog(CATALOGOUTPUTPORT); + } +} +void editTree::newDSInputPort() +{ + DEBTRACE("editTree::newDSInputPort"); + Subject *sub =getSelectedSubject(); + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + catalog(CATALOGIDSPORT); + } + +} + +void editTree::newDSOutputPort() +{ + DEBTRACE("editTree::newDSOutputPort"); + Subject *sub =getSelectedSubject(); + if (sub) + { + YACS::HMI::SubjectElementaryNode *subject = dynamic_cast< YACS::HMI::SubjectElementaryNode*>(sub); + if (subject) + catalog(CATALOGODSPORT); + } +} + +void editTree::catalog(int cataType) +{ + Subject *sub =getSelectedSubject(); + if (sub) + { + BrowseCatalog *brCat = new BrowseCatalog(this, sub, cataType); + brCat->exec(); + } +} + +void editTree::setCatalog(int isproc) +{ + Subject *sub =getSelectedSubject(); + if (sub) + { + if (isproc) + { + QString fn = QFileDialog::getOpenFileName( QString::null, + tr( "XML-Files (*.xml);;All Files (*)" ), + this, + "load YACS scheme file dialog as catalog", + "Choose a filename to load" ); + if ( !fn.isEmpty() ) + { + YACS::ENGINE::Catalog* aCatalog = YACS::ENGINE::getSALOMERuntime()->loadCatalog( "proc", fn.latin1()); + GuiContext::getCurrent()->setProcCatalog(aCatalog); + GuiContext::getCurrent()->setCurrentCatalog(aCatalog); + } + } + else + { + GuiContext::getCurrent()->setCurrentCatalog(GuiContext::getCurrent()->getSessionCatalog()); + } + } +} + + +/*! + * + */ + +void editTree::select() +{ + DEBTRACE("editTree::select() "<< this); + QListViewItem *it =lv->selectedItem(); + ViewItem *item = 0; + if (it) // an item selected + { + if (it != _previousSelected) // a new item is selected + { + _previousSelected = it; + item = dynamic_cast (it); + } + } + else if (_previousSelected) // nothing selected, deselect previous + { + it = _previousSelected; + _previousSelected = 0; + item = dynamic_cast (it); + } + if (item) + { + item->getSubject()->select(it->isSelected()); + if (_selectedSubjectOutPort) + { + Subject *sub = item->getSubject(); + if (dynamic_cast(sub) || dynamic_cast(sub)) + { + SubjectDataPort *sdp = dynamic_cast(sub); + assert(sdp); + SubjectDataPort::tryCreateLink(_selectedSubjectOutPort, sdp); + _selectedSubjectOutPort = 0; + } + } + if (_selectedSubjectNode) + { + Subject *sub = item->getSubject(); + if (SubjectNode* subNode = dynamic_cast(sub)) + { + SubjectNode::tryCreateLink(_selectedSubjectNode, subNode); + _selectedSubjectNode = 0; + } + } + if (_selectedSubjectService) + { + Subject *sub = item->getSubject(); + if (SubjectComponent *subcomp = dynamic_cast(sub)) + { + _selectedSubjectService->associateToComponent(subcomp); + _selectedSubjectService = 0; + } + } + if (_selectedSubjectComponent) + { + Subject *sub = item->getSubject(); + if (SubjectContainer *subcont = dynamic_cast(sub)) + { + _selectedSubjectComponent->associateToContainer(subcont); + _selectedSubjectComponent = 0; + } + } + } +} + +/*! + * + */ + +void editTree::select(QListViewItem *it) +{ + DEBTRACE("editTree::select(QListViewItem *item) "<< this); + ViewItem *item = dynamic_cast (it); + if (item) item->getSubject()->select(it->isSelected()); +} + +/*! + * + */ + +void editTree::contextMenuEvent( QContextMenuEvent * ) +{ + QListViewItem *it =lv->selectedItem(); + ViewItem *item = 0; + if (it) + { + if (item = dynamic_cast (it)) + ComposedNodeContextMenu(); + else if (item = dynamic_cast (it)) + NodeContextMenu(); + else if (item = dynamic_cast (it)) + PortContextMenu(); + else if (item = dynamic_cast (it)) + LinkContextMenu(); + else if (item = dynamic_cast (it)) + ComponentContextMenu(); + else if (item = dynamic_cast (it)) + ContainerContextMenu(); + } +} + +/*! + * + */ + +void editTree::ComposedNodeContextMenu() +{ + DEBTRACE("editTree::ComposedNodeContextMenu"); + QPopupMenu* contextMenu = new QPopupMenu(); + Q_CHECK_PTR( contextMenu ); + QLabel *caption = new QLabel( "" + "ComposedNode Context Menu", + contextMenu ); + caption->setAlignment( Qt::AlignCenter ); + int id; + contextMenu->insertItem( caption ); + contextMenu->insertItem( "Message", this, SLOT(printName()) ); + contextMenu->insertItem( "Delete", this, SLOT(destroy()) ); + contextMenu->insertItem( "add control link to other node", this, SLOT(addLink()) ); + _keymap = 0; + _catalogItemsMap.clear(); + YACS::ENGINE::Catalog *builtinCatalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + { + map::iterator it; + for (it=builtinCatalog->_nodeMap.begin(); it!=builtinCatalog->_nodeMap.end(); ++it) + { + string nodeType = "new " + (*it).first; + //DEBTRACE(nodeType); + id =contextMenu->insertItem( nodeType.c_str(), this, + SLOT(newNode(int)) ); + std::pair p(builtinCatalog, (*it).first); + _catalogItemsMap[_keymap] = p; + contextMenu->setItemParameter(id, _keymap++); + } + } + { + map::iterator it; + for (it=builtinCatalog->_composednodeMap.begin(); it!=builtinCatalog->_composednodeMap.end(); ++it) + { + string nodeType = "new " + (*it).first; + //DEBTRACE(nodeType); + id =contextMenu->insertItem( nodeType.c_str(), this, + SLOT(newNode(int)) ); + std::pair p(builtinCatalog, (*it).first); + _catalogItemsMap[_keymap] = p; + contextMenu->setItemParameter(id, _keymap++); + } + } + id = contextMenu->insertItem( "set current catalog to session", this, SLOT(setCatalog(int)) ); + contextMenu->setItemParameter(id, 0); + id = contextMenu->insertItem( "set current catalog to proc", this, SLOT(setCatalog(int)) ); + contextMenu->setItemParameter(id, 1); + id = contextMenu->insertItem( "new node from current Catalog", this, SLOT(catalog(int)) ); + contextMenu->setItemParameter(id, CATALOGNODE); + contextMenu->exec( QCursor::pos() ); + delete contextMenu; +} + +/*! + * + */ + +void editTree::NodeContextMenu() +{ + QPopupMenu* contextMenu = new QPopupMenu(); + Q_CHECK_PTR( contextMenu ); + QLabel *caption = new QLabel( "" + "Elementary Node Context Menu", + contextMenu ); + caption->setAlignment( Qt::AlignCenter ); + contextMenu->insertItem( caption ); + contextMenu->insertItem( "Message", this, SLOT(printName()) ); + contextMenu->insertItem( "Delete", this, SLOT(destroy()) ); + contextMenu->insertItem( "add Component", this, SLOT(addComponent()) ); + contextMenu->insertItem( "associate to Component", this, SLOT(associateServiceToComponent()) ); + contextMenu->insertItem( "add control link to other node", this, SLOT(addLink()) ); + _keymap = 0; + _catalogItemsMap.clear(); + YACS::ENGINE::Catalog *builtinCatalog = YACS::ENGINE::getSALOMERuntime()->getBuiltinCatalog(); + { + int id; + map::iterator it; + for (it=builtinCatalog->_typeMap.begin(); it!=builtinCatalog->_typeMap.end(); ++it) + { + std::pair p(builtinCatalog, (*it).first); + { + string typeCode = "new input port " + (*it).first; + DEBTRACE(typeCode); + id =contextMenu->insertItem( typeCode.c_str(), this, + SLOT(newInputPort(int)) ); + _catalogItemsMap[_keymap] = p; + contextMenu->setItemParameter(id, _keymap++); + } + { + string typeCode = "new output port " + (*it).first; + DEBTRACE(typeCode); + id =contextMenu->insertItem( typeCode.c_str(), this, + SLOT(newOutputPort(int)) ); + _catalogItemsMap[_keymap] = p; + contextMenu->setItemParameter(id, _keymap++); + } + } + id = contextMenu->insertItem( "set current catalog to session", this, SLOT(setCatalog(int)) ); + contextMenu->setItemParameter(id, 0); + id = contextMenu->insertItem( "set current catalog to proc", this, SLOT(setCatalog(int)) ); + contextMenu->setItemParameter(id, 1); + id = contextMenu->insertItem( "new InputPort from catalog", this, SLOT(newDFInputPort())); + id = contextMenu->insertItem( "new OutputPort from catalog", this, SLOT(newDFOutputPort())); + id = contextMenu->insertItem( "new DataStream InputPort from catalog", this, SLOT(newDSInputPort())); + id = contextMenu->insertItem( "new DataStream OutputPort from catalog", this, SLOT(newDSOutputPort())); + id = contextMenu->insertItem( "add Data Type from current Catalog", this, SLOT(catalog(int)) ); + contextMenu->setItemParameter(id, CATALOGDATATYPE); + } + contextMenu->exec( QCursor::pos() ); + delete contextMenu; +} + +void editTree::PortContextMenu() +{ + QPopupMenu* contextMenu = new QPopupMenu(); + Q_CHECK_PTR( contextMenu ); + QLabel *caption = new QLabel( "" + "Port Context Menu", + contextMenu ); + caption->setAlignment( Qt::AlignCenter ); + contextMenu->insertItem( caption ); + contextMenu->insertItem( "Message", this, SLOT(printName()) ); + contextMenu->insertItem( "Delete", this, SLOT(destroy()) ); + contextMenu->insertItem( "Add link", this, SLOT(addLink()) ); + contextMenu->insertItem( "edit properties", this, SLOT(editPortProperties()) ); + contextMenu->exec( QCursor::pos() ); + delete contextMenu; +} + +void editTree::LinkContextMenu() +{ + QPopupMenu* contextMenu = new QPopupMenu(); + Q_CHECK_PTR( contextMenu ); + QLabel *caption = new QLabel( "" + "Link Context Menu", + contextMenu ); + caption->setAlignment( Qt::AlignCenter ); + contextMenu->insertItem( caption ); + contextMenu->insertItem( "Message", this, SLOT(printName()) ); + contextMenu->insertItem( "Delete", this, SLOT(destroy()) ); + contextMenu->exec( QCursor::pos() ); + delete contextMenu; +} + +void editTree::ComponentContextMenu() +{ + QPopupMenu* contextMenu = new QPopupMenu(); + Q_CHECK_PTR( contextMenu ); + QLabel *caption = new QLabel( "" + "Component Context Menu", + contextMenu ); + caption->setAlignment( Qt::AlignCenter ); + contextMenu->insertItem( caption ); + contextMenu->insertItem( "Message", this, SLOT(printName()) ); + contextMenu->insertItem( "add Container", this, SLOT(addContainer()) ); + contextMenu->insertItem( "associate to Container", this, SLOT(associateComponentToContainer()) ); + contextMenu->exec( QCursor::pos() ); + delete contextMenu; +} + +void editTree::ContainerContextMenu() +{ + QPopupMenu* contextMenu = new QPopupMenu(); + Q_CHECK_PTR( contextMenu ); + QLabel *caption = new QLabel( "" + "Container Context Menu", + contextMenu ); + caption->setAlignment( Qt::AlignCenter ); + contextMenu->insertItem( caption ); + contextMenu->insertItem( "Message", this, SLOT(printName()) ); + contextMenu->insertItem( "edit container properties", this, SLOT(editContainerProperties()) ); + contextMenu->exec( QCursor::pos() ); + delete contextMenu; +} diff --git a/src/hmi/editTree.h b/src/hmi/editTree.h new file mode 100644 index 000000000..30a8101fd --- /dev/null +++ b/src/hmi/editTree.h @@ -0,0 +1,188 @@ + +#ifndef _EDITTREE_H_ +#define _EDITTREE_H_ + +#include "guiObservers.hxx" + +#include "wiedittree.h" +#include + +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class Catalog; + } + + namespace HMI + { + + class ViewItem: public QListViewItem, public GuiObserver + { + public: + ViewItem(QListView *parent, QString label, Subject* subject); + ViewItem(ViewItem *parent, QString label, Subject* subject); + virtual ~ViewItem(); + void setState(int state); + virtual void paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ); + virtual QListView *getParent(); + virtual void select(bool isSelected); + virtual void update(GuiEvent event, int type, Subject* son); + virtual Subject* getSubject(); + protected: + int _state; + QColor _cf; + Subject* _subject; + QListView *_parent; + }; + + class editTree: public wiEditTree, public GuiObserver + { + Q_OBJECT + + public slots: + void printName(); + void newNode(int key); + void newNode(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::pair compoServ); + void newDataType(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName); + void newInputPort(int key); + void newOutputPort(int key); + void newDFInputPort(); + void newDFOutputPort(); + void newDSInputPort(); + void newDSOutputPort(); + void newDFInputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName); + void newDFOutputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName); + void newDSInputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName); + void newDSOutputPort(YACS::ENGINE::Catalog* catalog, + Subject* sub, + std::string typeName); + void select(); + void select(QListViewItem *it); + void destroy(); + void addLink(); + void editPortProperties(); + void addComponent(); + void associateServiceToComponent(); + void addContainer(); + void associateComponentToContainer(); + void editContainerProperties(); + void catalog(int cataType); + void setCatalog(int isproc); + public: + editTree(YACS::HMI::Subject *context, + QWidget* parent = 0, + const char* name = 0, + WFlags fl = 0 ); + virtual ~editTree(); + virtual void update(GuiEvent event, int type, Subject* son); + void setNewRoot(YACS::HMI::Subject *root); + void addViewItemInMap(YACS::HMI::ViewItem* item, YACS::HMI::Subject* subject); + YACS::HMI::ViewItem* getViewItem(YACS::HMI::Subject* subject); + YACS::HMI::Subject* getSelectedSubject(); + protected: + void contextMenuEvent ( QContextMenuEvent * ); + void ComposedNodeContextMenu(); + void NodeContextMenu(); + void PortContextMenu(); + void LinkContextMenu(); + void ComponentContextMenu(); + void ContainerContextMenu(); + void resetTreeNode(QListView *lv); + QWidget* _parent; + Subject *_context; + Subject *_root; + QListViewItem *_previousSelected; + SubjectDataPort *_selectedSubjectOutPort; + SubjectNode *_selectedSubjectNode; + SubjectComponent *_selectedSubjectComponent; + SubjectServiceNode *_selectedSubjectService; + std::map _viewItemsMap; + std::map > _catalogItemsMap; + int _keymap; + }; + + class NodeViewItem: public ViewItem + { + public: + NodeViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + + class ComposedNodeViewItem: public ViewItem + { + public: + ComposedNodeViewItem(QListView *parent, QString label, Subject* subject); + ComposedNodeViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + class PortViewItem: public ViewItem + { + public: + PortViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + class LinkViewItem: public ViewItem + { + public: + LinkViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + class ComponentViewItem: public ViewItem + { + public: + ComponentViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + class ContainerViewItem: public ViewItem + { + public: + ContainerViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + class DataTypeViewItem: public ViewItem + { + public: + DataTypeViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + class ReferenceViewItem: public ViewItem + { + public: + ReferenceViewItem(ViewItem *parent, QString label, Subject* subject); + virtual void update(GuiEvent event, int type, Subject* son); + protected: + }; + + } +} + +#endif diff --git a/src/hmi/guiContext.cxx b/src/hmi/guiContext.cxx new file mode 100644 index 000000000..9b539b266 --- /dev/null +++ b/src/hmi/guiContext.cxx @@ -0,0 +1,171 @@ + +#include "RuntimeSALOME.hxx" +#include "guiContext.hxx" +#include "Proc.hxx" +#include "Container.hxx" +#include "ComponentInstance.hxx" +#include "commandsProc.hxx" +#include "guiObservers.hxx" + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace std; + +using namespace YACS; +using namespace YACS::ENGINE; +using namespace YACS::HMI; + +GuiContext * GuiContext::_current = 0; + +GuiContext::GuiContext() + : Subject(0) +{ + _builtinCatalog = getSALOMERuntime()->getBuiltinCatalog(); + _sessionCatalog = 0; + _procCatalog = 0; + _currentCatalog = 0; + + _invoc = new ProcInvoc(); + _proc = 0; + _subjectProc = 0; + _numItem = 0; + _selectedCanvasItem = 0; + + _canvas = new QCanvas(800,2000); + _widgetStack = 0; + _mapOfSubjectNode.clear(); + _mapOfSubjectDataPort.clear(); + _mapOfSubjectLink.clear(); + _mapOfSubjectControlLink.clear(); + _mapOfSubjectComponent.clear(); + _mapOfSubjectContainer.clear(); + _mapOfSubjectDataType.clear(); + _lastErrorMessage =""; + _xmlSchema =""; + _YACSEngineContainer = pair("YACSServer","localhost"); +} + +GuiContext::~GuiContext() +{ + if (_invoc) delete _invoc; + _invoc = 0; + if (_subjectProc) + { + _subjectProc->clean(); + delete _subjectProc; + _subjectProc = 0; + } +} + +void GuiContext::setProc(YACS::ENGINE::Proc* proc) +{ + DEBTRACE("GuiContext::setProc "); + if (_subjectProc) + { + Subject::erase(_subjectProc); + _subjectProc = 0; + } + _proc = proc; + _mapOfSubjectNode.clear(); + _mapOfSubjectDataPort.clear(); + _mapOfSubjectLink.clear(); + _mapOfSubjectControlLink.clear(); + _mapOfSubjectComponent.clear(); + _mapOfSubjectContainer.clear(); + _mapOfSubjectDataType.clear(); + + _subjectProc = new SubjectProc(proc, this); + _mapOfSubjectNode[static_cast(proc)] = _subjectProc; + update(YACS::HMI::NEWROOT, 0, _subjectProc); + _subjectProc->loadProc(); +} + +long GuiContext::getNewId(YACS::HMI::TypeOfElem type) +{ + long anId = 0; + + if ( Proc* aProc = getProc() ) + { + set anIds; + + if ( type == CONTAINER ) + { + QString aTemplate("container"); + + map::const_iterator itCont = aProc->containerMap.begin(); + for ( ; itCont != aProc->containerMap.end(); ++itCont) + { + QString aName( (*itCont).second->getName() ); + if ( aName.length() > aTemplate.length() && !aName.left(aTemplate.length()).compare(aTemplate) ) + { + aName = aName.right(aName.length()-aTemplate.length()); + bool ok; + long aNum = aName.toLong(&ok); + if (ok) anIds.insert(aNum); + } + } + } + else if ( type == COMPONENT ) + { + QString aTemplate("component"); + + map, ComponentInstance*>::const_iterator itComp = + aProc->componentInstanceMap.begin(); + for ( ; itComp != aProc->componentInstanceMap.end(); ++itComp) + { + QString aName( (*itComp).second->getCompoName() ); + printf(">> component name : %s\n",aName.latin1()); + if ( aName.length() > aTemplate.length() && !aName.left(aTemplate.length()).compare(aTemplate) ) + { + aName = aName.right(aName.length()-aTemplate.length()); + bool ok; + long aNum = aName.toLong(&ok); + if (ok) anIds.insert(aNum); + } + } + } + else + { + list aNodes = aProc->getAllRecursiveConstituents(); + list::iterator it = aNodes.begin(); + for ( ; it != aNodes.end(); it++ ) + { + QString aName( (*it)->getName() ); + + if ( ProcInvoc::getTypeOfNode(*it) != type ) continue; + + QString aTemplate; + switch(type) + { + case BLOC: aTemplate= QString("Bloc"); break; + case FOREACHLOOP: aTemplate= QString("ForEachLoopDouble"); break; + case FORLOOP: aTemplate= QString("ForLoop"); break; + case WHILELOOP: aTemplate= QString("WhileLoop"); break; + case SWITCH: aTemplate= QString("Switch"); break; + case PYTHONNODE: aTemplate= QString("PyScript"); break; + case PYFUNCNODE: aTemplate= QString("PyFunction"); break; + case CORBANODE: aTemplate= QString("CORBANode"); break; + case SALOMENODE: aTemplate= QString("SalomeNode"); break; + case CPPNODE: aTemplate= QString("CppNode"); break; + case SALOMEPYTHONNODE: aTemplate= QString("SalomePythonNode"); break; + case XMLNODE: aTemplate= QString("XmlNode"); break; + default: break; + } + + if ( aName.length() > aTemplate.length() && !aName.left(aTemplate.length()).compare(aTemplate) ) + { + aName = aName.right(aName.length()-aTemplate.length()); + bool ok; + long aNum = aName.toLong(&ok); + if (ok) anIds.insert(aNum); + } + } + } + + if ( !anIds.empty() ) + anId = (*anIds.rbegin()) + 1; + } + + return anId; +} diff --git a/src/hmi/guiContext.hxx b/src/hmi/guiContext.hxx new file mode 100644 index 000000000..cfa2e6410 --- /dev/null +++ b/src/hmi/guiContext.hxx @@ -0,0 +1,83 @@ + +#ifndef _GUICONTEXT_HXX_ +#define _GUICONTEXT_HXX_ + +#include "Proc.hxx" +#include "Catalog.hxx" +#include "commandsProc.hxx" +#include "guiObservers.hxx" + +#include +#include +#include +#include + +namespace YACS +{ + namespace HMI + { +// class Subject; + + class GuiContext: public Subject + { + public: + GuiContext(); + virtual ~GuiContext(); + void setProc(YACS::ENGINE::Proc* proc); + long getNewId(YACS::HMI::TypeOfElem type); + + inline YACS::ENGINE::Catalog* getBuiltinCatalog() {return _builtinCatalog; }; + inline YACS::ENGINE::Catalog* getSessionCatalog() {return _sessionCatalog; }; + inline YACS::ENGINE::Catalog* getProcCatalog() {return _procCatalog; }; + inline YACS::ENGINE::Catalog* getCurrentCatalog() {return _currentCatalog; }; + + inline YACS::ENGINE::Proc* getProc() {return _proc; }; + inline YACS::HMI::ProcInvoc* getInvoc() {return _invoc; }; + inline YACS::HMI::SubjectProc* getSubjectProc() {return _subjectProc; }; + inline QCanvas* getCanvas() {return _canvas; }; + inline QCanvasItem* getSelectedCanvasItem() {return _selectedCanvasItem; }; + inline long getNewId() {return _numItem++; }; + inline QWidgetStack* getWidgetStack() {return _widgetStack; }; + inline std::string getXMLSchema() {return _xmlSchema; }; + inline std::pair getYACSCont() {return _YACSEngineContainer; } + + inline void setSelectedCanvasItem(QCanvasItem *c) {_selectedCanvasItem = c; }; + inline void setWidgetStack(QWidgetStack* ws) {_widgetStack = ws; }; + inline void setSessionCatalog(YACS::ENGINE::Catalog* cata) {_sessionCatalog = cata; }; + inline void setProcCatalog(YACS::ENGINE::Catalog* cata) {_procCatalog = cata; }; + inline void setCurrentCatalog(YACS::ENGINE::Catalog* cata) {_currentCatalog = cata; }; + inline void setXMLSchema(std::string xmlSchema) {_xmlSchema = xmlSchema; }; + inline void setYACSContainer(std::pair yc) {_YACSEngineContainer = yc; }; + + inline static GuiContext* getCurrent() {return _current; }; + inline static void setCurrent(GuiContext* context) { _current=context; }; + + std::map _mapOfSubjectNode; + std::map _mapOfSubjectDataPort; + std::map,YACS::HMI::SubjectLink*> _mapOfSubjectLink; + std::map,YACS::HMI::SubjectControlLink*> _mapOfSubjectControlLink; + std::map _mapOfSubjectComponent; + std::map _mapOfSubjectContainer; + std::map _mapOfSubjectDataType; + std::string _lastErrorMessage; + + protected: + YACS::ENGINE::Catalog* _builtinCatalog; + YACS::ENGINE::Catalog* _sessionCatalog; + YACS::ENGINE::Catalog* _procCatalog; + YACS::ENGINE::Catalog* _currentCatalog; + YACS::ENGINE::Proc* _proc; + YACS::HMI::ProcInvoc* _invoc; + YACS::HMI::SubjectProc *_subjectProc; + long _numItem; + static GuiContext* _current; + QCanvas *_canvas; + QCanvasItem *_selectedCanvasItem; + QWidgetStack* _widgetStack; + std::string _xmlSchema; + std::pair _YACSEngineContainer; // --- + + }; + } +} +#endif diff --git a/src/hmi/guiObservers.cxx b/src/hmi/guiObservers.cxx new file mode 100644 index 000000000..74000fd96 --- /dev/null +++ b/src/hmi/guiObservers.cxx @@ -0,0 +1,2774 @@ + +#include +#include "guiObservers.hxx" +#include "commandsProc.hxx" +#include "Node.hxx" +#include "ComposedNode.hxx" +#include "Bloc.hxx" +#include "Proc.hxx" +#include "ElementaryNode.hxx" +#include "InlineNode.hxx" +#include "ServiceNode.hxx" +#include "PythonNode.hxx" +#include "CORBANode.hxx" +#include "CppNode.hxx" +#include "XMLNode.hxx" +#include "SalomePythonNode.hxx" +#include "DataNode.hxx" +#include "PresetNode.hxx" +#include "OutNode.hxx" +#include "StudyNodes.hxx" +#include "ForLoop.hxx" +#include "ForEachLoop.hxx" +#include "WhileLoop.hxx" +#include "Switch.hxx" +#include "OptimizerLoop.hxx" +#include "InputPort.hxx" +#include "OutputPort.hxx" +#include "InputDataStreamPort.hxx" +#include "OutputDataStreamPort.hxx" +#include "SalomeContainer.hxx" +#include "SalomeComponent.hxx" +#include "ComponentDefinition.hxx" +#include "TypeCode.hxx" + +#include "guiContext.hxx" + +#include +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace std; + +using namespace YACS; +using namespace YACS::HMI; +using namespace YACS::ENGINE; + +// ---------------------------------------------------------------------------- + +void Subject::erase(Subject* sub) +{ + sub->clean(); + delete sub; +} + +// ---------------------------------------------------------------------------- + +Subject::Subject(Subject *parent) : _parent(parent) +{ + _destructible = true; +} + +/*! + * Destructor must only be called by Subject::erase to clean + * completely the context (detach observers), before the delete + * process itself. Some actions involving dynamic_cast can't be done + * in destructor. + */ +Subject::~Subject() +{ + DEBTRACE("Subject::~Subject " << this << " "<< getName()); +} + +/*! + * Clean process prior to delete is redefined in derived classes: a local clean + * treatment relative to the derived class, then a call to the parent class clean + * method. + */ +void Subject::clean() +{ + localClean(); +} + +/*! + * the local clean method of base class of subjects take care of Observers. + * Remaining Observers in the list are detached, if an abserver has no more + * Subject to observe, it can be deleted. + */ +void Subject::localClean() +{ + DEBTRACE("Subject::localClean "); + set::iterator it; + set copySet = _setObs; + for (it = copySet.begin(); it != copySet.end(); ++it) + { + GuiObserver* anObs = (*it); + detach(anObs); + int nbsub = anObs->getNbSubjects(); + DEBTRACE("nbSubjects=" << nbsub); + if (nbsub <= 0) delete anObs ; + } + _setObs.clear(); +} + +void Subject::attach(GuiObserver *obs) +{ + _setObs.insert(obs); + obs->incrementSubjects(this); +} + +void Subject::detach(GuiObserver *obs) +{ + DEBTRACE("Subject::detach " << obs); + obs->decrementSubjects(this); + _setObs.erase(obs); +} + +std::string Subject::getName() +{ + return "generic"; +} + +bool Subject::setName(std::string name) +{ + return false; +} + +void Subject::select(bool isSelected) +{ + DEBTRACE("Subject::select " << isSelected << " " << this); + for (set::iterator it = _setObs.begin(); it != _setObs.end(); ++it) + { + GuiObserver* currOb = *it; + currOb->select(isSelected); + } +} + +void Subject::update(GuiEvent event,int type, Subject* son) +{ + DEBTRACE("Subject::update " << type << "," << event << "," << son); + for (set::iterator it = _setObs.begin(); it != _setObs.end(); ++it) + { + DEBTRACE("Subject::update " << *it); + (*it)->update(event, type, son); + } +} + +Subject* Subject::getParent() +{ + return _parent; +} + +bool Subject::destroy(Subject *son) +{ + string toDestroy = son->getName(); + DEBTRACE("Subject::destroy " << toDestroy); + Proc *proc = GuiContext::getCurrent()->getProc(); + string position = ""; + + if (dynamic_cast(son)) + position = proc->getName(); + else + { + if (SubjectNode *subNode = dynamic_cast(son)) + { + if (subNode->getNode()->getFather() ) + position = proc->getChildName(subNode->getNode()); + } + else if (dynamic_cast(son)) + { + SubjectNode *subNodep = dynamic_cast(son->getParent()); + if (dynamic_cast(subNodep)) + position = proc->getName(); + else + position = proc->getChildName(subNodep->getNode()); + } + else if (dynamic_cast(son)) + { + SubjectNode *subNodep = dynamic_cast(son->getParent()); + if (dynamic_cast(subNodep)) + position = proc->getName(); + else + position = proc->getChildName(subNodep->getNode()); + } + } + if (son->isDestructible()) + { + CommandDestroy* command = new CommandDestroy(position, son); + if (command->execute()) + { + DEBTRACE("Destruction done: " << toDestroy); + return true; + } + else delete command; + } + return false; +} + +void Subject::loadChildren() +{ +} + +void Subject::loadLinks() +{ +} + +void Subject::addSubjectReference(Subject *ref) +{ + DEBTRACE("Subject::addSubjectReference " << getName() << " " << ref->getName()); + SubjectReference *son = new SubjectReference(ref, this); + update(ADDREF, 0, son); +} + +// ---------------------------------------------------------------------------- + +GuiObserver::GuiObserver() +{ + DEBTRACE("GuiObserver::GuiObserver " << this); + _subjectSet.clear(); +} + +GuiObserver::~GuiObserver() +{ + DEBTRACE("GuiObserver::~GuiObserver " << this); +} + +void GuiObserver::select(bool isSelected) +{ + DEBTRACE("GuiObserver::select() " << isSelected); +} + +void GuiObserver::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("GuiObserver::update, event not handled " << event << " " << type ); +} + +/*! + * only called by subject when attach to subject. + * @see Subject::attach + */ +void GuiObserver::incrementSubjects(Subject *subject) +{ + if (_subjectSet.count(subject)) + DEBTRACE("subject " << subject << " is already a subject of observer " << this << "---------------------------"); + _subjectSet.insert(subject); + //DEBTRACE(this << " " << _subjectSet.size()); +} + +/*! + * only called by subject when detach from subject. + * @see Subject::detach + */ +void GuiObserver::decrementSubjects(Subject *subject) +{ + if (_subjectSet.count(subject)) + _subjectSet.erase(subject); + else + DEBTRACE("subject " << subject << " is not a subject of observer " << this << "---------------------------"); + //DEBTRACE(this << " " << _subjectSet.size()); +} + +/*! + * Gets the number of subjects observed. + * used by subject. When the subject is erased (Subject::erase), + * remaining observers are detached from subjects. If an observer has no + * more subject, it can be deleted. + * @see Subject::erase Subject::localClean + */ +int GuiObserver::getNbSubjects() +{ + return _subjectSet.size(); +} + +// ---------------------------------------------------------------------------- + +SubjectReference::SubjectReference(Subject* ref, Subject *parent) + : Subject(parent), _reference(ref) +{ +} + +SubjectReference::~SubjectReference() +{ +} + +void SubjectReference::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectReference::localClean() +{ + DEBTRACE("SubjectReference::localClean "); +} + +std::string SubjectReference::getName() +{ + std::stringstream name; + name << "ref-->" << _reference->getName(); + return name.str(); +} + +Subject* SubjectReference::getReference() const +{ + return _reference; +} + +// ---------------------------------------------------------------------------- + +SubjectNode::SubjectNode(YACS::ENGINE::Node *node, Subject *parent) + : Subject(parent), _node(node) +{ + _listSubjectInputPort.clear(); + _listSubjectOutputPort.clear(); + _listSubjectIDSPort.clear(); + _listSubjectODSPort.clear(); + _listSubjectLink.clear(); + _listSubjectControlLink.clear(); + Dispatcher* d=Dispatcher::getDispatcher(); + d->addObserver(this,node,"status"); +} + +/*! + * all destruction is done in generic class SubjectNode + */ +SubjectNode::~SubjectNode() +{ + DEBTRACE("SubjectNode::~SubjectNode " << getName()); + Dispatcher::getDispatcher()->removeObserver(this,_node,"status"); + + ComposedNode* father = _node->getFather(); + if (father) + try + { + Bloc *bloc = dynamic_cast(father); + if (bloc) bloc->edRemoveChild(_node); + else + { + Loop *loop = dynamic_cast(father); + if (loop) loop->edRemoveChild(_node); + else + { + ForEachLoop *feloop = dynamic_cast(father); + if (feloop && getName() != ForEachLoop::NAME_OF_SPLITTERNODE) { + DEBTRACE("SubjectNode::localClean: remove for each loop body"); + feloop->edRemoveChild(_node); + } + else + { + Switch *aSwitch = dynamic_cast(father); + if (aSwitch) aSwitch->edRemoveChild(_node); + } + } + } + } + catch (YACS::Exception &e) + { + DEBTRACE("------------------------------------------------------------------------------"); + DEBTRACE("SubjectNode::localClean: father->edRemoveChild: YACS exception " << e.what()); + DEBTRACE("------------------------------------------------------------------------------"); + } +} + +void SubjectNode::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectNode::localClean() +{ + DEBTRACE("SubjectNode::localClean "); + removeExternalLinks(); + { + list::iterator its; + list cpll = _listSubjectLink; + for (its = cpll.begin(); its != cpll.end(); ++its) + erase(*its); + } + { + list::iterator its; + list cplcl = _listSubjectControlLink; + for (its = cplcl.begin(); its != cplcl.end(); ++its) + erase(*its); + } + { + list::iterator iti; + list cpli = _listSubjectInputPort; + for(iti = cpli.begin(); iti != cpli.end(); ++iti) + erase(*iti); + } + { + list::iterator ito; + list cplo = _listSubjectOutputPort; + for(ito = cplo.begin(); ito != cplo.end(); ++ito) + erase(*ito); + } + { + list::iterator itid; + list cplid = _listSubjectIDSPort; + for(itid = cplid.begin(); itid != cplid.end(); ++itid) + erase(*itid); + } + { + list::iterator itod; + list cplod = _listSubjectODSPort; + for(itod = cplod.begin(); itod != cplod.end(); ++itod) + erase(*itod); + } + if (_parent) + { + if( SubjectBloc* sb = dynamic_cast(_parent) ) + sb->removeNode(this); + else if( SubjectForLoop* sfl = dynamic_cast(_parent) ) + sfl->completeChildrenSubjectList( 0 ); + else if( SubjectWhileLoop* swl = dynamic_cast(_parent) ) + swl->completeChildrenSubjectList( 0 ); + else if( SubjectForEachLoop* sfel = dynamic_cast(_parent) ) + sfel->completeChildrenSubjectList( 0 ); + } +} + +void SubjectNode::reparent(Subject* parent) +{ + // remove this node from children list of an old parent + if (_parent) + { + if( SubjectBloc* sb = dynamic_cast(_parent) ) + sb->removeNode(this); + } + + // reparent + _parent = parent; + + // add this node into the children list of a new parent + if (_parent) + { + if( SubjectBloc* sb = dynamic_cast(_parent) ) + sb->completeChildrenSubjectList(this); + else if( SubjectSwitch* ss = dynamic_cast(_parent) ) + ss->completeChildrenSubjectList(this); + } +} + +std::string SubjectNode::getName() +{ + return _node->getName(); +} + +YACS::ENGINE::Node* SubjectNode::getNode() +{ + return _node; +} + +bool SubjectNode::setName(std::string name) +{ + DEBTRACE("SubjectNode::setName " << name); + Proc *proc = GuiContext::getCurrent()->getProc(); + string position = ""; + if (proc != dynamic_cast(_node)) + position = proc->getChildName(_node); + else + position = _node->getName(); + CommandRenameNode* command = new CommandRenameNode(position, name); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + update(RENAME, 0, this); + return true; + } + else delete command; + return false; +} +void SubjectNode::notifyObserver(Node* object,const std::string& event) +{ + DEBTRACE("SubjectNode::notifyObserver " << object->getName() << " " << event); + TypeOfElem ntyp = ProcInvoc::getTypeOfNode(object); + update(UPDATE, ntyp , 0 ); +} + +SubjectInputPort* SubjectNode::addSubjectInputPort(YACS::ENGINE::InputPort *port, + std::string name) +{ + string theName = name; + if (name.empty()) theName =port->getName(); + DEBTRACE("SubjectNode::addSubjectInputPort "<< theName); + SubjectInputPort *son = new SubjectInputPort(port, this); + GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast(port)] = son; + _listSubjectInputPort.push_back(son); + if (!name.empty()) son->setName(name); + update(ADD, INPUTPORT ,son); + YACS::ENGINE::TypeCode *typcod = port->edGetType(); + GuiContext::getCurrent()->getSubjectProc()->addSubjectDataType(typcod); + return son; +} + +void SubjectNode::update( GuiEvent event, int type, Subject* son ) +{ + Subject::update( event, type, son ); + + // remove subject data type if necessary + YACS::HMI::SubjectDataPort* aSPort = dynamic_cast< YACS::HMI::SubjectDataPort* >( son ); + if ( aSPort && event == REMOVE ) + { + YACS::ENGINE::DataPort* aEPort = aSPort->getPort(); + if ( aEPort ) + { + YACS::ENGINE::TypeCode* aTypeCode = aEPort->edGetType(); + if ( aTypeCode ) + GuiContext::getCurrent()->getSubjectProc()->removeSubjectDataType( aTypeCode ); + } + } +} + +SubjectOutputPort* SubjectNode::addSubjectOutputPort(YACS::ENGINE::OutputPort *port, + std::string name) +{ + string theName = name; + if (name.empty()) theName =port->getName(); + DEBTRACE("SubjectNode::addSubjectOutputPort "<< theName); + SubjectOutputPort *son = new SubjectOutputPort(port, this); + GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast(port)] = son; + _listSubjectOutputPort.push_back(son); + if (!name.empty()) son->setName(name); + update(ADD, OUTPUTPORT ,son); + YACS::ENGINE::TypeCode *typcod = port->edGetType(); + GuiContext::getCurrent()->getSubjectProc()->addSubjectDataType(typcod); + return son; +} + +SubjectInputDataStreamPort* SubjectNode::addSubjectIDSPort(YACS::ENGINE::InputDataStreamPort *port, + std::string name) +{ + string theName = name; + if (name.empty()) theName =port->getName(); + DEBTRACE("SubjectNode::addSubjectIDSPort "<< theName); + SubjectInputDataStreamPort *son = new SubjectInputDataStreamPort(port, this); + GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast(port)] = son; + _listSubjectIDSPort.push_back(son); + if (!name.empty()) son->setName(name); + update(ADD, INPUTDATASTREAMPORT ,son); + YACS::ENGINE::TypeCode *typcod = port->edGetType(); + GuiContext::getCurrent()->getSubjectProc()->addSubjectDataType(typcod); + return son; +} + + +SubjectOutputDataStreamPort* SubjectNode::addSubjectODSPort(YACS::ENGINE::OutputDataStreamPort *port, + std::string name) +{ + string theName = name; + if (name.empty()) theName =port->getName(); + DEBTRACE("SubjectNode::addSubjectODSPort "<< theName); + SubjectOutputDataStreamPort *son = new SubjectOutputDataStreamPort(port, this); + GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast(port)] = son; + _listSubjectODSPort.push_back(son); + if (!name.empty()) son->setName(name); + update(ADD, OUTPUTDATASTREAMPORT ,son); + YACS::ENGINE::TypeCode *typcod = port->edGetType(); + GuiContext::getCurrent()->getSubjectProc()->addSubjectDataType(typcod); + return son; +} + +bool SubjectNode::tryCreateLink(SubjectNode *subOutNode, SubjectNode *subInNode) +{ + DEBTRACE("SubjectNode::tryCreateLink " << subOutNode->getName() << " " << subInNode->getName()); + Proc *proc = GuiContext::getCurrent()->getProc(); + Node *outNode = subOutNode->getNode(); + string outNodePos = proc->getChildName(outNode); + Node *inNode = subInNode->getNode(); + string inNodePos = proc->getChildName(inNode); + CommandAddControlLink *command = new CommandAddControlLink(outNodePos, inNodePos); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + ComposedNode *cla = ComposedNode::getLowestCommonAncestor(outNode->getFather(), + inNode->getFather()); + SubjectComposedNode *scla = dynamic_cast(subOutNode->getParent()); + ComposedNode *ancestor = outNode->getFather(); + while (ancestor && ancestor != cla) + { + ancestor = ancestor->getFather(); + scla = dynamic_cast(scla->getParent()); + assert(scla); + } + DEBTRACE(scla->getName()); + scla->addSubjectControlLink(subOutNode,subInNode); + return true; + } + else + { + delete command; + return false; + } +} + +void SubjectNode::removeExternalLinks() +{ + DEBTRACE("SubjectNode::removeExternalLinks " << getName()); + std::vector< std::pair > listLeaving = getNode()->getSetOfLinksLeavingCurrentScope(); + std::vector< std::pair > listIncoming = getNode()->getSetOfLinksComingInCurrentScope(); + std::vector< std::pair > globalList = listLeaving; + std::vector< std::pair >::iterator it1; + for (it1 = listIncoming.begin(); it1 != listIncoming.end(); ++it1) + { + std::pair outin = std::pair((*it1).second, (*it1).first); + globalList.push_back(outin); + } + std::vector< std::pair >::iterator it2; + for (it2 = globalList.begin(); it2 != globalList.end(); ++it2) + { + SubjectLink* subject = 0; + if (GuiContext::getCurrent()->_mapOfSubjectLink.count(*it2)) + { + subject = GuiContext::getCurrent()->_mapOfSubjectLink[*it2]; + assert(subject); + DEBTRACE("link to remove " << subject->getName()); + erase(subject); + GuiContext::getCurrent()->_mapOfSubjectLink.erase(*it2); + } + else + { + DEBTRACE("------------------------------------------------------------------------------"); + DEBTRACE("SubjectNode::removeExternalLinks(): an external link not in map..."); + DEBTRACE("------------------------------------------------------------------------------"); + } + } + +} + +// ---------------------------------------------------------------------------- + +SubjectComposedNode::SubjectComposedNode(YACS::ENGINE::ComposedNode *composedNode, + Subject *parent) + : SubjectNode(composedNode, parent), _composedNode(composedNode) +{ +} + +/*! + * all generic destruction is done in generic class SubjectNode + */ +SubjectComposedNode::~SubjectComposedNode() +{ + DEBTRACE("SubjectComposedNode::~SubjectComposedNode " << getName()); +} + +void SubjectComposedNode::clean() +{ + localClean(); + SubjectNode::clean(); +} + +void SubjectComposedNode::localClean() +{ + DEBTRACE("SubjectComposedNode::localClean "); +} + +SubjectNode* SubjectComposedNode::addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name) +{ + DEBTRACE("SubjectComposedNode::addNode("<getProc(); + string position = ""; + if (proc != dynamic_cast(_node)) position = proc->getChildName(_node); + CommandAddNodeFromCatalog *command = new CommandAddNodeFromCatalog(catalog, + compo, + type, + position, + name, + swCase); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + Node * node = command->getNode(); + SubjectNode *son = addSubjectNode(node,"",catalog,compo,type); + son->loadChildren(); + son->loadLinks(); + return son; + } + else delete command; + return 0; +} + +SubjectNode *SubjectComposedNode::addSubjectNode(YACS::ENGINE::Node * node, + std::string name, + YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type) +{ + string theName = name; + if (name.empty()) theName =node->getName(); + DEBTRACE("SubjectComposedNode::addSubjectNode "<< theName); + TypeOfElem ntyp = ProcInvoc::getTypeOfNode(node); + DEBTRACE("TypeOfNode: " << ntyp); + SubjectNode *son = 0; + switch(ntyp) + { + case BLOC: + son = new SubjectBloc(dynamic_cast(node), this); + break; + case PYTHONNODE: + son = new SubjectPythonNode(dynamic_cast(node), this); + break; + case PYFUNCNODE: + son = new SubjectPyFuncNode(dynamic_cast(node), this); + break; + case CORBANODE: + son = new SubjectCORBANode(dynamic_cast(node), this); + break; + case CPPNODE: + son = new SubjectCppNode(dynamic_cast(node), this); + break; + case SALOMENODE: + son = new SubjectSalomeNode(dynamic_cast(node), this); + break; + case SALOMEPYTHONNODE: + son = new SubjectSalomePythonNode(dynamic_cast(node), this); + break; + case XMLNODE: + son = new SubjectXmlNode(dynamic_cast(node), this); + break; + case SPLITTERNODE: + son = new SubjectSplitterNode(dynamic_cast(node), this); + break; + case PRESETNODE: + son = new SubjectPresetNode(dynamic_cast(node), this); + break; + case OUTNODE: + son = new SubjectOutNode(dynamic_cast(node), this); + break; + case STUDYINNODE: + son = new SubjectStudyInNode(dynamic_cast(node), this); + break; + case STUDYOUTNODE: + son = new SubjectStudyOutNode(dynamic_cast(node), this); + break; + case FORLOOP: + son = new SubjectForLoop(dynamic_cast(node), this); + break; + case WHILELOOP: + son = new SubjectWhileLoop(dynamic_cast(node), this); + break; + case SWITCH: + son = new SubjectSwitch(dynamic_cast(node), this); + break; + case FOREACHLOOP: + son = new SubjectForEachLoop(dynamic_cast(node), this); + break; + case OPTIMIZERLOOP: + son = new SubjectOptimizerLoop(dynamic_cast(node), this); + break; + default: + throw YACS::Exception("Not implemented"); + //assert(0); + } + assert(son); + GuiContext::getCurrent()->_mapOfSubjectNode[static_cast(node)] = son; + if (!name.empty()) son->setName(name); + completeChildrenSubjectList(son); + update(ADD, ntyp ,son); + if (SubjectServiceNode *service = dynamic_cast(son)) + if (catalog && !compo.empty() && !type.empty()) // --- clone from catalog: set component + service->setComponentFromCatalog(catalog,compo,type); + else + service->setComponent(); + return son; +} + +void SubjectComposedNode::completeChildrenSubjectList(SubjectNode *son) +{ +} + +void SubjectComposedNode::loadChildren() +{ + list setOfNode= _composedNode->edGetDirectDescendants(); + if (ForEachLoop *feloop = dynamic_cast(_composedNode)) + { + Node *node2Insert=feloop->getChildByName(ForEachLoop::NAME_OF_SPLITTERNODE); + if(find(setOfNode.begin(),setOfNode.end(),node2Insert)==setOfNode.end()) + setOfNode.push_back(node2Insert); + } + for(list::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + { + try + { + SubjectNode * son = addSubjectNode(*iter); + son->loadChildren(); + } + catch(YACS::Exception& ex) + { + std::cerr << "Unknown type of node" << std::endl; + } + } + list listInputPorts = _composedNode->getLocalInputPorts(); + list listOutputPorts = _composedNode->getLocalOutputPorts(); + list listIDSPorts = _composedNode->getSetOfInputDataStreamPort(); + list listODSPorts = _composedNode->getSetOfOutputDataStreamPort(); + list::const_iterator iti; + for (iti = listInputPorts.begin(); iti != listInputPorts.end(); ++iti) + addSubjectInputPort(*iti); + list::const_iterator ito; + for (ito = listOutputPorts.begin(); ito != listOutputPorts.end(); ++ito) + addSubjectOutputPort(*ito); +} + +SubjectLink* SubjectComposedNode::addSubjectLink(SubjectNode *sno, + SubjectDataPort *spo, + SubjectNode *sni, + SubjectDataPort *spi) +{ + DEBTRACE("SubjectComposedNode::addSubjectLink"); + SubjectLink *son = new SubjectLink(sno, spo, sni, spi, this); + OutPort *outp = sno->getNode()->getOutPort(spo->getName()); + InPort *inp = sni->getNode()->getInPort(spi->getName()); + pair keyLink(outp,inp); + GuiContext::getCurrent()->_mapOfSubjectLink[keyLink] = son; + _listSubjectLink.push_back(son); + spo->addSubjectLink(son); + spi->addSubjectLink(son); + update(ADDLINK, DATALINK, son); + DEBTRACE("addSubjectLink: " << getName() << " " << son->getName()); + return son; +} + +void SubjectComposedNode::removeLink(SubjectLink* link) +{ + DEBTRACE("removeSubjectLink: " << getName()); + link->getSubjectOutPort()->removeSubjectLink(link); + link->getSubjectInPort()->removeSubjectLink(link); + _listSubjectLink.remove(link); +} + +SubjectControlLink* SubjectComposedNode::addSubjectControlLink(SubjectNode *sno, + SubjectNode *sni) +{ + SubjectControlLink *son = new SubjectControlLink(sno, sni, this); + Node *outn = sno->getNode(); + Node *inn = sni->getNode(); + pair keyLink(outn,inn); + + GuiContext::getCurrent()->_mapOfSubjectControlLink[keyLink] = son; + _listSubjectControlLink.push_back(son); + sno->addSubjectControlLink(son); + sni->addSubjectControlLink(son); + update(ADDCONTROLLINK, CONTROLLINK, son); + DEBTRACE("addSubjectControlLink: " << getName() << " " << son->getName()); + return son; +} + +void SubjectComposedNode::removeControlLink(SubjectControlLink* link) +{ + DEBTRACE("removeSubjectControlLink: " << getName()); + link->getSubjectOutNode()->removeSubjectControlLink(link); + link->getSubjectInNode()->removeSubjectControlLink(link); + _listSubjectControlLink.remove(link); +} + +/*! + * loadLinks is used when an existing scheme has been loaded in memory, to create gui representation. + * Gui representation of links is done after node representation (loadChildren). + * Proc is explored recursively to find the composedNodes and create the corresponding links + * representation, from bottom to top. + * For each composedNode, data links representation are created first and stored in a map to avoid + * double represention. Then control links representation are created. + */ +void SubjectComposedNode::loadLinks() +{ + list setOfNode= _composedNode->edGetDirectDescendants(); + for(list::iterator iter=setOfNode.begin();iter!=setOfNode.end();iter++) + { + ComposedNode *cnSon = dynamic_cast(*iter); + if (cnSon) + { + SubjectNode *subSon = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast(*iter)]; + assert(subSon); + SubjectComposedNode *subCnSon = dynamic_cast(subSon); + assert (subCnSon); + subCnSon->loadLinks(); + } + } + + std::vector > setOfLinks = _composedNode->getSetOfInternalLinks(); + std::vector >::iterator itp; + for (itp = setOfLinks.begin(); itp != setOfLinks.end(); ++itp) + if (!GuiContext::getCurrent()->_mapOfSubjectLink.count(*itp)) + { + OutPort *outp = (*itp).first; + InPort *inp = (*itp).second; + Node *outn = outp->getNode(); + Node *inn = inp->getNode(); + DEBTRACE(outn->getName()<<"."<getName()<<"->"<getName()<<"."<getName()); + SubjectNode *sno = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast(outn)]; + SubjectNode *sni = GuiContext::getCurrent()->_mapOfSubjectNode[static_cast(inn)]; + SubjectDataPort *spo = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast(outp)]; + SubjectDataPort *spi = GuiContext::getCurrent()->_mapOfSubjectDataPort[static_cast(inp)]; + addSubjectLink(sno,spo,sni,spi); + } + + std::list setOfNodes = _composedNode->edGetDirectDescendants(); + std::list::const_iterator itn; + for(itn = setOfNodes.begin(); itn != setOfNodes.end(); ++itn) + { + SubjectNode* sno = GuiContext::getCurrent()->_mapOfSubjectNode[*itn]; + OutGate* outgate = (*itn)->getOutGate(); + std::set setIngate = outgate->edSetInGate(); + std::set::const_iterator itg; + for(itg = setIngate.begin(); itg != setIngate.end(); ++itg) + { + Node* inNode = (*itg)->getNode(); + SubjectNode* sni = GuiContext::getCurrent()->_mapOfSubjectNode[inNode]; + addSubjectControlLink(sno,sni); + } + } +} + +//! Retrieves the lowest common ancestor of 2 nodes +/*! + * + * \note Retrieves the lowest common ancestor of 'node1' AND 'node2'. + * If 'node1' or 'node2' are both or indiscriminately instances of ComposedNode and that + * 'node1' is in descendance of 'node2' (resp. 'node2' in descendance of 'node1') + * 'node2' is returned (resp. 'node1'). + * \exception Exception : if 'node1' and 'node2' do not share the same genealogy. + * \return The lowest common ancestor if it exists. + * + */ +SubjectComposedNode* SubjectComposedNode::getLowestCommonAncestor(SubjectNode* snode1, SubjectNode* snode2) +{ + Node* node1 = snode1->getNode(); + Node* node2 = snode2->getNode(); + + ComposedNode *node = ComposedNode::getLowestCommonAncestor(node1->getFather(), node2->getFather()); + SubjectComposedNode* snode = dynamic_cast( GuiContext::getCurrent()->_mapOfSubjectNode[node] ); + return snode; +} + +// ---------------------------------------------------------------------------- + +SubjectBloc::SubjectBloc(YACS::ENGINE::Bloc *bloc, Subject *parent) + : SubjectComposedNode(bloc, parent), _bloc(bloc) +{ + _children.clear(); +} + +/*! + * all generic destruction is done in generic class SubjectNode + */ +SubjectBloc::~SubjectBloc() +{ + DEBTRACE("SubjectBloc::~SubjectBloc " << getName()); +} + +void SubjectBloc::clean() +{ + localClean(); + SubjectComposedNode::clean(); +} + +void SubjectBloc::localClean() +{ + DEBTRACE("SubjectBloc::localClean "); + set::iterator it; + set copyChildren = _children; + for (it = copyChildren.begin(); it !=copyChildren.end(); ++it) + erase(*it); +} + +SubjectNode* SubjectBloc::addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name) +{ + DEBTRACE("SubjectBloc::addNode( " << catalog << ", " << compo << ", " << type << ", " << name << " )"); + SubjectNode* child = createNode(catalog, compo, type, name); + return child; +} + +void SubjectBloc::completeChildrenSubjectList(SubjectNode *son) +{ + _children.insert(son); +} + +void SubjectBloc::removeNode(SubjectNode* child) +{ + _children.erase(child); +} + +SubjectNode* SubjectBloc::getChild(YACS::ENGINE::Node* node) const +{ + SubjectNode* aChild = 0; + + if (node) + { + set::iterator it = _children.begin(); + for ( ; it != _children.end(); it++ ) + if ( (*it)->getNode() == node ) + { + aChild = (*it); + break; + } + } + + return aChild; +} + +// ---------------------------------------------------------------------------- + +SubjectProc::SubjectProc(YACS::ENGINE::Proc *proc, Subject *parent) + : SubjectBloc(proc, parent), _proc(proc) +{ +} + +SubjectProc::~SubjectProc() +{ + DEBTRACE("SubjectProc::~SubjectProc " << getName()); +} + +void SubjectProc::clean() +{ + localClean(); + SubjectBloc::clean(); +} + +void SubjectProc::localClean() +{ + DEBTRACE("SubjectProc::localClean "); +} + +void SubjectProc::loadProc() +{ + DEBTRACE("SubjectProc::loadProc " << getName()); + loadChildren(); + loadLinks(); + loadComponents(); + loadContainers(); +} + +/*! + * loadComponents is used when an existing scheme has been loaded in memory, + * to create subjects for components stored in the schema file, but are not + * associated with any service nodes. Note, that if such component is associated + * to any container, the subject for this container is also created, if it is not + * exist yet. + */ +void SubjectProc::loadComponents() +{ + Proc* aProc = GuiContext::getCurrent()->getProc(); + for (map, ComponentInstance*>::const_iterator itComp = aProc->componentInstanceMap.begin(); + itComp != aProc->componentInstanceMap.end(); ++itComp) + if ( GuiContext::getCurrent()->_mapOfSubjectComponent.find((*itComp).second) + == + GuiContext::getCurrent()->_mapOfSubjectComponent.end() ) + { // engine object for component already exists => add only a subject for it + addSubjectComponent((*itComp).second); + } +} + +/*! + * loadContainers is used when an existing scheme has been loaded in memory, + * to create subjects for containers stored in the schema file, but are not + * associated with components. + */ +void SubjectProc::loadContainers() +{ + Proc* aProc = GuiContext::getCurrent()->getProc(); + for (map::const_iterator itCont = aProc->containerMap.begin(); + itCont != aProc->containerMap.end(); ++itCont) + if ( GuiContext::getCurrent()->_mapOfSubjectContainer.find((*itCont).second) + == + GuiContext::getCurrent()->_mapOfSubjectContainer.end() ) + // engine object for container already exists => add only a subject for it + addSubjectContainer((*itCont).second, (*itCont).second->getName()); +} + +SubjectComponent* SubjectProc::addComponent(std::string name) +{ + DEBTRACE("SubjectProc::addComponent " << name); + CommandAddComponentInstance *command = new CommandAddComponentInstance(name); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + ComponentInstance *compo = command->getComponentInstance(); + SubjectComponent *son = addSubjectComponent(compo); + return son; + } + else delete command; + return 0; +} + +SubjectContainer* SubjectProc::addContainer(std::string name, std::string ref) +{ + DEBTRACE("SubjectProc::addContainer " << name << " " << ref); + if (! GuiContext::getCurrent()->getProc()->containerMap.count(name)) + { + CommandAddContainer *command = new CommandAddContainer(name,ref); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + Container *cont = command->getContainer(); + SubjectContainer *son = addSubjectContainer(cont, name); + GuiContext::getCurrent()->getProc()->containerMap[name] = cont; + return son; + } + else + delete command; + } + else GuiContext::getCurrent()->_lastErrorMessage = "There is already a container with that name"; + return 0; +} + +SubjectDataType* SubjectProc::addDataType(YACS::ENGINE::Catalog* catalog, std::string typeName) +{ + DEBTRACE("SubjectProc::addDataType " << typeName); + CommandAddDataTypeFromCatalog *command = new CommandAddDataTypeFromCatalog(catalog, typeName); + if (command->execute()) + { + DEBTRACE("new datatype " << typeName); + GuiContext::getCurrent()->getInvoc()->add(command); + SubjectDataType *son = addSubjectDataType(command->getTypeCode()); + return son; + } + else delete command; + return 0; +} + +SubjectComponent* SubjectProc::addSubjectComponent(YACS::ENGINE::ComponentInstance* compo) +{ + DEBTRACE("SubjectProc::addSubjectComponent " << compo->getInstanceName()); + SubjectComponent *son = new SubjectComponent(compo, this); + GuiContext::getCurrent()->_mapOfSubjectComponent[compo] = son; + update(ADD, COMPONENT, son); + son->setContainer(); + return son; +} + +SubjectContainer* SubjectProc::addSubjectContainer(YACS::ENGINE::Container* cont, + std::string name) +{ + DEBTRACE("SubjectProc::addSubjectContainer " << name); + SubjectContainer *son = new SubjectContainer(cont, this); + GuiContext::getCurrent()->_mapOfSubjectContainer[cont] = son; + update(ADD, CONTAINER, son); + return son; +} + +SubjectDataType* SubjectProc::addSubjectDataType(YACS::ENGINE::TypeCode *type) +{ + string typeName = type->name(); + DEBTRACE("SubjectProc::addSubjectDataType " << typeName); + Proc* proc = GuiContext::getCurrent()->getProc(); + SubjectDataType* son = 0; + if (! proc->typeMap.count(typeName)) + proc->typeMap[ typeName ] = type->clone(); + else + proc->typeMap[ typeName ]->incrRef(); + if (! GuiContext::getCurrent()->_mapOfSubjectDataType.count(typeName)) + { + son = new SubjectDataType(type, this); + GuiContext::getCurrent()->_mapOfSubjectDataType[typeName] = son; + update(ADD, DATATYPE, son); + } + else + GuiContext::getCurrent()->_lastErrorMessage = "Typecode " + typeName + " already had added in proc"; + return son; +} + +void SubjectProc::removeSubjectDataType( YACS::ENGINE::TypeCode* theType ) +{ + if ( !theType ) + return; + + YACS::HMI::GuiContext* aContext = GuiContext::getCurrent(); + if ( !aContext ) + return; + + YACS::ENGINE::Proc* aProc = aContext->getProc(); + if ( !aProc ) + return; + + string typeName = theType->name(); + if ( !aProc->typeMap.count( typeName ) ) + return; + + YACS::ENGINE::TypeCode* aTypeCode = aProc->typeMap[ typeName ]; + if ( !aTypeCode ) + return; + + if ( !aContext->_mapOfSubjectDataType.count( typeName ) ) + return; + + YACS::HMI::SubjectDataType* aSDataType = aContext->_mapOfSubjectDataType[ typeName ]; + if ( !aSDataType ) + return; + + unsigned int aRefCnt = aTypeCode->getRefCnt(); + if ( aRefCnt == 1 ) + { + update( REMOVE, DATATYPE, aSDataType ); + aContext->_mapOfSubjectDataType.erase( typeName ); + aProc->typeMap.erase( typeName ); + } + + aTypeCode->decrRef(); +} + +// ---------------------------------------------------------------------------- + +SubjectElementaryNode::SubjectElementaryNode(YACS::ENGINE::ElementaryNode *elementaryNode, + Subject *parent) + : SubjectNode(elementaryNode, parent), _elementaryNode(elementaryNode) +{ +} + +/*! + * all generic destruction is done in generic class SubjectNode + */ +SubjectElementaryNode::~SubjectElementaryNode() +{ + DEBTRACE("SubjectElementaryNode::~SubjectElementaryNode " << getName()); +} + +void SubjectElementaryNode::clean() +{ + localClean(); + SubjectNode::clean(); +} + +void SubjectElementaryNode::localClean() +{ + DEBTRACE("SubjectElementaryNode::localClean "); +} + + +SubjectDataPort* SubjectElementaryNode::addInputPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name) +{ + DEBTRACE("SubjectElementaryNode::addInputPort( " << catalog << ", " << type << ", " << name << " )"); + Proc *proc = GuiContext::getCurrent()->getProc(); + string position = ""; + if (proc != dynamic_cast(_node)) position = proc->getChildName(_node); + else assert(0); + CommandAddInputPortFromCatalog *command = new CommandAddInputPortFromCatalog(catalog, + type, + position, + name); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + InputPort * port = command->getInputPort(); + SubjectInputPort *son = addSubjectInputPort(port, name); + return son; + } + else delete command; + return 0; +} + +SubjectDataPort* SubjectElementaryNode::addOutputPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name) +{ + DEBTRACE("SubjectElementaryNode::addOutputPort( " << catalog << ", " << type << ", " << name << " )"); + Proc *proc = GuiContext::getCurrent()->getProc(); + string position = ""; + if (proc != dynamic_cast(_node)) position = proc->getChildName(_node); + else assert(0); + CommandAddOutputPortFromCatalog *command = new CommandAddOutputPortFromCatalog(catalog, + type, + position, + name); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + OutputPort * port = command->getOutputPort(); + SubjectOutputPort *son = addSubjectOutputPort(port, name); + return son; + } + else delete command; + return 0; +} + +SubjectDataPort* SubjectElementaryNode::addIDSPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name) +{ + DEBTRACE("SubjectElementaryNode::addIDSPort( " << catalog << ", " << type << ", " << name << " )"); + Proc *proc = GuiContext::getCurrent()->getProc(); + string position = ""; + if (proc != dynamic_cast(_node)) position = proc->getChildName(_node); + else assert(0); + CommandAddIDSPortFromCatalog *command = new CommandAddIDSPortFromCatalog(catalog, + type, + position, + name); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + InputDataStreamPort * port = command->getIDSPort(); + SubjectInputDataStreamPort *son = addSubjectIDSPort(port, name); + return son; + } + else delete command; + return 0; +} + +SubjectDataPort* SubjectElementaryNode::addODSPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name) +{ + DEBTRACE("SubjectElementaryNode::addODSPort( " << catalog << ", " << type << ", " << name << " )"); + Proc *proc = GuiContext::getCurrent()->getProc(); + string position = ""; + if (proc != dynamic_cast(_node)) position = proc->getChildName(_node); + else assert(0); + CommandAddODSPortFromCatalog *command = new CommandAddODSPortFromCatalog(catalog, + type, + position, + name); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + OutputDataStreamPort * port = command->getODSPort(); + SubjectOutputDataStreamPort *son = addSubjectODSPort(port, name); + return son; + } + else delete command; + return 0; +} + +void SubjectElementaryNode::removePort(SubjectDataPort* port) +{ + DEBTRACE("SubjectElementaryNode::removePort " << port->getName()); + if (SubjectInputPort* inp = dynamic_cast(port)) + { + DEBTRACE("-"); + _listSubjectInputPort.remove(inp); + } + else if(SubjectOutputPort* outp = dynamic_cast(port)) + { + DEBTRACE("--"); + _listSubjectOutputPort.remove(outp); + } + if (SubjectInputDataStreamPort* idsp = dynamic_cast(port)) + { + DEBTRACE("---"); + _listSubjectIDSPort.remove(idsp); + } + else if(SubjectOutputDataStreamPort* odsp = dynamic_cast(port)) + { + DEBTRACE("----"); + _listSubjectODSPort.remove(odsp); + } +} + +void SubjectElementaryNode::loadChildren() +{ + list listInputPorts = _elementaryNode->getLocalInputPorts(); + list listOutputPorts = _elementaryNode->getLocalOutputPorts(); + list listIDSPorts = _elementaryNode->getSetOfInputDataStreamPort(); + list listODSPorts = _elementaryNode->getSetOfOutputDataStreamPort(); + if (SplitterNode *splitterNode = dynamic_cast(_elementaryNode)) + listInputPorts.push_back(splitterNode->getFather()->getInputPort("SmplsCollection")); + list::const_iterator iti; + for (iti = listInputPorts.begin(); iti != listInputPorts.end(); ++iti) + addSubjectInputPort(*iti); + list::const_iterator ito; + for (ito = listOutputPorts.begin(); ito != listOutputPorts.end(); ++ito) + addSubjectOutputPort(*ito); + list::const_iterator itids; + for (itids = listIDSPorts.begin(); itids != listIDSPorts.end(); ++itids) + addSubjectIDSPort(*itids); + list::const_iterator itods; + for (itods = listODSPorts.begin(); itods != listODSPorts.end(); ++itods) + addSubjectODSPort(*itods); +} + +// ---------------------------------------------------------------------------- + + +SubjectInlineNode::SubjectInlineNode(YACS::ENGINE::InlineNode *inlineNode, Subject *parent) + : SubjectElementaryNode(inlineNode, parent), _inlineNode(inlineNode) +{ +} + +SubjectInlineNode::~SubjectInlineNode() +{ + DEBTRACE("SubjectInlineNode::~SubjectInlineNode " << getName()); +} + +bool SubjectInlineNode::setScript(std::string script) +{ + Proc *proc = GuiContext::getCurrent()->getProc(); + CommandSetInlineNodeScript *command = + new CommandSetInlineNodeScript(proc->getChildName(_node), script); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + return true; + } + else delete command; + return false; +} + +std::string SubjectInlineNode::getScript() +{ + return _inlineNode->getScript(); +} + +void SubjectInlineNode::clean() +{ + localClean(); + SubjectElementaryNode::clean(); +} + +void SubjectInlineNode::localClean() +{ + DEBTRACE("SubjectInlineNode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectServiceNode::SubjectServiceNode(YACS::ENGINE::ServiceNode *serviceNode, Subject *parent) + : SubjectElementaryNode(serviceNode, parent), _serviceNode(serviceNode) +{ + _subjectReference=0; +} + +SubjectServiceNode::~SubjectServiceNode() +{ + DEBTRACE("SubjectServiceNode::~SubjectServiceNode " << getName()); +} + +void SubjectServiceNode::clean() +{ + localClean(); + SubjectElementaryNode::clean(); +} + +void SubjectServiceNode::localClean() +{ + DEBTRACE("SubjectServiceNode::localClean "); + if (_subjectReference) + { + update( REMOVE, REFERENCE, _subjectReference ); + erase( _subjectReference ); + _subjectReference = 0; + } +} + + +/*! + * When cloning a service node from a catalog, create the component associated to the node, + * if not already existing, and create the corresponding subject. + */ +void SubjectServiceNode::setComponentFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string service) +{ + DEBTRACE("SubjectServiceNode::setComponent " << compo); + if (catalog->_componentMap.count(compo)) + { + YACS::ENGINE::ComponentDefinition* compodef = catalog->_componentMap[compo]; + if (compodef->_serviceMap.count(service)) + { + Proc* proc = GuiContext::getCurrent()->getProc(); + ComponentInstance *instance = 0; + instance = new SalomeComponent(compo); + pair key = pair(compo, instance->getNumId()); + proc->componentInstanceMap[key] = instance; + SubjectComponent* subCompo = GuiContext::getCurrent()->getSubjectProc()->addSubjectComponent(instance); + assert(subCompo); + addSubjectReference(subCompo); + _serviceNode->setComponent(instance); + } + } +} + +/*! + * When loading scheme from file, get the component associated to the node, if any, + * and create the corresponding subject. + */ +void SubjectServiceNode::setComponent() +{ + ComponentInstance *instance = _serviceNode->getComponent(); + if (instance) + { + Proc* proc = GuiContext::getCurrent()->getProc(); + string compo = instance->getCompoName(); + SubjectComponent* subCompo = 0; + if (! GuiContext::getCurrent()->_mapOfSubjectComponent.count(instance)) + { + DEBTRACE("SubjectServiceNode::setComponent : create subject for compo = " << compo.c_str()); + pair key = pair(compo, instance->getNumId()); + proc->componentInstanceMap[key] = instance; + subCompo = + GuiContext::getCurrent()->getSubjectProc()->addSubjectComponent(instance); + } + else + { + DEBTRACE("SubjectServiceNode::setComponent : get already created subject for compo = " <_mapOfSubjectComponent[instance]; + } + assert(subCompo); + addSubjectReference(subCompo); + } +} + +void SubjectServiceNode::associateToComponent(SubjectComponent *subcomp) +{ + DEBTRACE("SubjectServiceNode::associateToComponent " << getName() << " " << subcomp->getName()); + SubjectReference* oldSReference = _subjectReference; + string aName = GuiContext::getCurrent()->getProc()->getChildName(_serviceNode); + CommandAssociateServiceToComponent *command = + new CommandAssociateServiceToComponent(aName, subcomp->getKey()); + if (command->execute()) + { + if (oldSReference) removeSubjectReference(oldSReference); + GuiContext::getCurrent()->getInvoc()->add(command); + addSubjectReference(subcomp); + } + else delete command; +} + +void SubjectServiceNode::removeSubjectReference(Subject *ref) +{ + DEBTRACE("Subject::removeSubjectReference " << getName() << " " << ref->getName()); + update( REMOVE, REFERENCE, ref ); + erase( ref ); +} + +void SubjectServiceNode::addSubjectReference(Subject *ref) +{ + DEBTRACE("Subject::addSubjectReference " << getName() << " " << ref->getName()); + SubjectReference *son = new SubjectReference(ref, this); + _subjectReference = son; + update(ADDREF, 0, son); +} + +SubjectReference* SubjectServiceNode::getSubjectReference() +{ + return _subjectReference; +} + +// ---------------------------------------------------------------------------- + +SubjectPythonNode::SubjectPythonNode(YACS::ENGINE::PythonNode *pythonNode, Subject *parent) + : SubjectInlineNode(pythonNode, parent), _pythonNode(pythonNode) +{ +} + +SubjectPythonNode::~SubjectPythonNode() +{ + DEBTRACE("SubjectPythonNode::~SubjectPythonNode " << getName()); +} + +void SubjectPythonNode::clean() +{ + localClean(); + SubjectInlineNode::clean(); +} + +void SubjectPythonNode::localClean() +{ + DEBTRACE("SubjectPythonNode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectPyFuncNode::SubjectPyFuncNode(YACS::ENGINE::PyFuncNode *pyFuncNode, Subject *parent) + : SubjectInlineNode(pyFuncNode, parent), _pyFuncNode(pyFuncNode) +{ +} + +SubjectPyFuncNode::~SubjectPyFuncNode() +{ + DEBTRACE("SubjectPyFuncNode::~SubjectPyFuncNode " << getName()); +} + +bool SubjectPyFuncNode::setFunctionName(std::string funcName) +{ + Proc *proc = GuiContext::getCurrent()->getProc(); + CommandSetFuncNodeFunctionName *command = + new CommandSetFuncNodeFunctionName(proc->getChildName(_node), funcName); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + return true; + } + else delete command; + return false; +} + +void SubjectPyFuncNode::clean() +{ + localClean(); + SubjectInlineNode::clean(); +} + +void SubjectPyFuncNode::localClean() +{ + DEBTRACE("SubjectPyFuncNode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectCORBANode::SubjectCORBANode(YACS::ENGINE::CORBANode *corbaNode, Subject *parent) + : SubjectServiceNode(corbaNode, parent), _corbaNode(corbaNode) +{ +} + +SubjectCORBANode::~SubjectCORBANode() +{ + DEBTRACE("SubjectCORBANode::~SubjectCORBANode " << getName()); +} + +void SubjectCORBANode::clean() +{ + localClean(); + SubjectServiceNode::clean(); +} + +void SubjectCORBANode::localClean() +{ + DEBTRACE("SubjectCORBANode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectCppNode::SubjectCppNode(YACS::ENGINE::CppNode *cppNode, Subject *parent) + : SubjectServiceNode(cppNode, parent), _cppNode(cppNode) +{ +} + +SubjectCppNode::~SubjectCppNode() +{ + DEBTRACE("SubjectCppNode::~SubjectCppNode " << getName()); +} + +void SubjectCppNode::clean() +{ + localClean(); + SubjectServiceNode::clean(); +} + +void SubjectCppNode::localClean() +{ + DEBTRACE("SubjectCppNode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectSalomeNode::SubjectSalomeNode(YACS::ENGINE::SalomeNode *salomeNode, Subject *parent) + : SubjectServiceNode(salomeNode, parent), _salomeNode(salomeNode) +{ +} + +SubjectSalomeNode::~SubjectSalomeNode() +{ + DEBTRACE("SubjectSalomeNode::~SubjectSalomeNode " << getName()); +} + +void SubjectSalomeNode::clean() +{ + localClean(); + SubjectServiceNode::clean(); +} + +void SubjectSalomeNode::localClean() +{ + DEBTRACE("SubjectSalomeNode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectSalomePythonNode::SubjectSalomePythonNode(YACS::ENGINE::SalomePythonNode *salomePythonNode, + Subject *parent) + : SubjectServiceNode(salomePythonNode, parent), _salomePythonNode(salomePythonNode) +{ +} + +SubjectSalomePythonNode::~SubjectSalomePythonNode() +{ + DEBTRACE("SubjectSalomePythonNode::~SubjectSalomePythonNode " << getName()); +} + +void SubjectSalomePythonNode::clean() +{ + localClean(); + SubjectServiceNode::clean(); +} + +void SubjectSalomePythonNode::localClean() +{ + DEBTRACE("SubjectSalomePythonNode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectXmlNode::SubjectXmlNode(YACS::ENGINE::XmlNode *xmlNode, Subject *parent) + : SubjectServiceNode(xmlNode, parent), _xmlNode(xmlNode) +{ +} + +SubjectXmlNode::~SubjectXmlNode() +{ + DEBTRACE("SubjectXmlNode::~SubjectXmlNode " << getName()); +} + +void SubjectXmlNode::clean() +{ + localClean(); + SubjectServiceNode::clean(); +} + +void SubjectXmlNode::localClean() +{ + DEBTRACE("SubjectXmlNode::localClean "); +} + + +// ---------------------------------------------------------------------------- + +SubjectSplitterNode::SubjectSplitterNode(YACS::ENGINE::SplitterNode *splitterNode, Subject *parent) + : SubjectElementaryNode(splitterNode, parent), _splitterNode(splitterNode) +{ + _destructible = false; +} + +SubjectSplitterNode::~SubjectSplitterNode() +{ + DEBTRACE("SubjectSplitterNode::~SubjectSplitterNode " << getName()); +} + +void SubjectSplitterNode::clean() +{ + localClean(); + SubjectElementaryNode::clean(); +} + +void SubjectSplitterNode::localClean() +{ + DEBTRACE("SubjectSplitterNode::localClean "); +} + + +std::string SubjectSplitterNode::getName() +{ + return "splitter"; +} + +// ---------------------------------------------------------------------------- + +SubjectDataNode::SubjectDataNode(YACS::ENGINE::DataNode *dataNode, Subject *parent) + : SubjectElementaryNode(dataNode, parent), _dataNode(dataNode) +{ + _destructible = true; +} + +SubjectDataNode::~SubjectDataNode() +{ + DEBTRACE("SubjectDataNode::~SubjectDataNode " << getName()); +} + +void SubjectDataNode::clean() +{ + localClean(); + SubjectElementaryNode::clean(); +} + +void SubjectDataNode::localClean() +{ + DEBTRACE("SubjectDataNode::localClean "); +} + +// ---------------------------------------------------------------------------- + +SubjectPresetNode::SubjectPresetNode(YACS::ENGINE::PresetNode *presetNode, Subject *parent) + : SubjectDataNode(presetNode, parent), _presetNode(presetNode) +{ + _destructible = true; +} + +SubjectPresetNode::~SubjectPresetNode() +{ + DEBTRACE("SubjectPresetNode::~SubjectPresetNode " << getName()); +} + +void SubjectPresetNode::clean() +{ + localClean(); + SubjectDataNode::clean(); +} + +void SubjectPresetNode::localClean() +{ + DEBTRACE("SubjectPresetNode::localClean "); +} + +// ---------------------------------------------------------------------------- + +SubjectOutNode::SubjectOutNode(YACS::ENGINE::OutNode *outNode, Subject *parent) + : SubjectDataNode(outNode, parent), _outNode(outNode) +{ + _destructible = true; +} + +SubjectOutNode::~SubjectOutNode() +{ + DEBTRACE("SubjectOutNode::~SubjectOutNode " << getName()); +} + +void SubjectOutNode::clean() +{ + localClean(); + SubjectDataNode::clean(); +} + +void SubjectOutNode::localClean() +{ + DEBTRACE("SubjectOutNode::localClean "); +} + +// ---------------------------------------------------------------------------- + +SubjectStudyInNode::SubjectStudyInNode(YACS::ENGINE::StudyInNode *studyInNode, Subject *parent) + : SubjectDataNode(studyInNode, parent), _studyInNode(studyInNode) +{ + _destructible = true; +} + +SubjectStudyInNode::~SubjectStudyInNode() +{ + DEBTRACE("SubjectStudyInNode::~SubjectStudyInNode " << getName()); +} + +void SubjectStudyInNode::clean() +{ + localClean(); + SubjectDataNode::clean(); +} + +void SubjectStudyInNode::localClean() +{ + DEBTRACE("SubjectStudyInNode::localClean "); +} + +// ---------------------------------------------------------------------------- + +SubjectStudyOutNode::SubjectStudyOutNode(YACS::ENGINE::StudyOutNode *studyOutNode, Subject *parent) + : SubjectDataNode(studyOutNode, parent), _studyOutNode(studyOutNode) +{ + _destructible = true; +} + +SubjectStudyOutNode::~SubjectStudyOutNode() +{ + DEBTRACE("SubjectStudyOutNode::~SubjectStudyOutNode " << getName()); +} + +void SubjectStudyOutNode::clean() +{ + localClean(); + SubjectDataNode::clean(); +} + +void SubjectStudyOutNode::localClean() +{ + DEBTRACE("SubjectStudyOutNode::localClean "); +} + +// ---------------------------------------------------------------------------- + +SubjectForLoop::SubjectForLoop(YACS::ENGINE::ForLoop *forLoop, Subject *parent) + : SubjectComposedNode(forLoop, parent), _forLoop(forLoop) +{ + _body = 0; +} + +SubjectForLoop::~SubjectForLoop() +{ + DEBTRACE("SubjectForLoop::~SubjectForLoop " << getName()); +} + +void SubjectForLoop::clean() +{ + localClean(); + SubjectComposedNode::clean(); +} + +void SubjectForLoop::localClean() +{ + DEBTRACE("SubjectForLoop::localClean "); + if (_body) + erase(_body); +} + + +SubjectNode* SubjectForLoop::addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name) +{ + DEBTRACE("SubjectForLoop::addNode(catalog, compo, type, name)"); + SubjectNode* body = 0; + if (_body) return body; + body = createNode(catalog, compo, type, name); + return body; +} + +void SubjectForLoop::completeChildrenSubjectList(SubjectNode *son) +{ + _body = son; +} + +// ---------------------------------------------------------------------------- + +SubjectWhileLoop::SubjectWhileLoop(YACS::ENGINE::WhileLoop *whileLoop, Subject *parent) + : SubjectComposedNode(whileLoop, parent), _whileLoop(whileLoop) +{ + _body = 0; +} + +SubjectWhileLoop::~SubjectWhileLoop() +{ + DEBTRACE("SubjectWhileLoop::~SubjectWhileLoop " << getName()); +} + +void SubjectWhileLoop::clean() +{ + localClean(); + SubjectComposedNode::clean(); +} + +void SubjectWhileLoop::localClean() +{ + DEBTRACE("SubjectWhileLoop::localClean "); + if (_body) + erase(_body); +} + +SubjectNode* SubjectWhileLoop::addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name) +{ + DEBTRACE("SubjectWhileLoop::addNode(catalog, compo, type, name)"); + SubjectNode* body = 0; + if (_body) return body; + body = createNode(catalog, compo, type, name); + return body; +} + +void SubjectWhileLoop::completeChildrenSubjectList(SubjectNode *son) +{ + _body = son; +} + +// ---------------------------------------------------------------------------- + +SubjectSwitch::SubjectSwitch(YACS::ENGINE::Switch *aSwitch, Subject *parent) + : SubjectComposedNode(aSwitch, parent), _switch(aSwitch) +{ + _bodyMap.clear(); +} + +SubjectSwitch::~SubjectSwitch() +{ + DEBTRACE("SubjectSwitch::~SubjectSwitch " << getName()); +} + +void SubjectSwitch::clean() +{ + localClean(); + SubjectComposedNode::clean(); +} + +void SubjectSwitch::localClean() +{ + DEBTRACE("SubjectSwitch::localClean "); + map::iterator it; + for (it = _bodyMap.begin(); it != _bodyMap.end(); ++it) + erase((*it).second); +} + +SubjectNode* SubjectSwitch::addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name, + int swCase, + bool replace) +{ + DEBTRACE("SubjectSwitch::addNode("<getName()<<")"); + if (son) + { + int id; + bool isFound = false; + map::const_iterator it; + for (it = _bodyMap.begin(); it != _bodyMap.end(); ++it) + { + if ( (*it).second == son ) + { + isFound = true; + id = (*it).first; + break; + } + } + if (isFound) + { + DEBTRACE("id = "< SubjectSwitch::getBodyMap() +{ + return _bodyMap; +} + +void SubjectSwitch::completeChildrenSubjectList(SubjectNode *son) +{ + _bodyMap[_switch->getRankOfNode(son->getNode())] = son; +} + +SubjectNode* SubjectSwitch::getChild(YACS::ENGINE::Node* node) const +{ + SubjectNode* aChild = 0; + + if (node) + { + map::const_iterator it; + for (it = _bodyMap.begin(); it != _bodyMap.end(); ++it) + if ( (*it).second->getNode() == node ) + { + aChild = (*it).second; + break; + } + } + + return aChild; +} + +// ---------------------------------------------------------------------------- + +SubjectForEachLoop::SubjectForEachLoop(YACS::ENGINE::ForEachLoop *forEachLoop, Subject *parent) + : SubjectComposedNode(forEachLoop, parent), _forEachLoop(forEachLoop) +{ + _body = 0; + _splitter = 0; +} + +SubjectForEachLoop::~SubjectForEachLoop() +{ + DEBTRACE("SubjectForEachLoop::~SubjectForEachLoop " << getName()); +} + +void SubjectForEachLoop::clean() +{ + Node* aSplitterEngine = 0; + if (_splitter) aSplitterEngine = _splitter->getNode(); + + localClean(); + SubjectComposedNode::clean(); + + if (_forEachLoop && aSplitterEngine) + { + DEBTRACE("SubjectForEachLoop::clean: remove for each loop splitter"); + _forEachLoop->edRemoveChild(aSplitterEngine); + } +} + +void SubjectForEachLoop::localClean() +{ + DEBTRACE("SubjectForEachLoop::localClean "); + if (_body) + { + DEBTRACE(_body->getName()); + erase(_body); + } + if (_splitter) + { + DEBTRACE(_splitter->getName()); + erase(_splitter); + } +} + + +SubjectNode* SubjectForEachLoop::addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name) +{ + DEBTRACE("SubjectForEachLoop::addNode(catalog, compo, type, name)"); + SubjectNode* body = 0; + if (_body) return body; + body = createNode(catalog, compo, type, name); + return body; +} + +void SubjectForEachLoop::completeChildrenSubjectList(SubjectNode *son) +{ + if ( !son ) + { + _body = son; + return; + } + + string name = son->getName(); + DEBTRACE("SubjectForEachLoop::completeChildrenSubjectList " << name); + if (name == ForEachLoop::NAME_OF_SPLITTERNODE) + _splitter = son; + else + _body = son; +} + + +// ---------------------------------------------------------------------------- + +SubjectOptimizerLoop::SubjectOptimizerLoop(YACS::ENGINE::OptimizerLoop *optimizerLoop, + Subject *parent) + : SubjectComposedNode(optimizerLoop, parent), _optimizerLoop(optimizerLoop) +{ + _body = 0; +} + +SubjectOptimizerLoop::~SubjectOptimizerLoop() +{ + DEBTRACE("SubjectOptimizerLoop::~SubjectOptimizerLoop " << getName()); +} + +void SubjectOptimizerLoop::clean() +{ + localClean(); + SubjectComposedNode::clean(); +} + +void SubjectOptimizerLoop::localClean() +{ + DEBTRACE("SubjectOptimizerLoop::localClean "); + if (_body) + erase(_body); +} + +SubjectNode* SubjectOptimizerLoop::addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name) +{ + DEBTRACE("SubjectOptimizerLoop::addNode(catalog, compo, type, name)"); + SubjectNode* body = 0; + if (_body) return body; + body = createNode(catalog, compo, type, name); + return body; +} + +void SubjectOptimizerLoop::completeChildrenSubjectList(SubjectNode *son) +{ + _body = son; +} + +// ---------------------------------------------------------------------------- + +SubjectDataPort::SubjectDataPort(YACS::ENGINE::DataPort* port, Subject *parent) + : Subject(parent), _dataPort(port) +{ + _listSubjectLink.clear(); +} + +SubjectDataPort::~SubjectDataPort() +{ + DEBTRACE("SubjectDataPort::~SubjectDataPort " << getName()); + if (isDestructible()) + { + Node* node = _dataPort->getNode(); + assert(node); + ElementaryNode * father = dynamic_cast(node); + if (father) + { + DEBTRACE("father->edRemovePort(_dataPort)"); + try + { + father->edRemovePort(_dataPort); + } + catch (YACS::Exception &e) + { + DEBTRACE("------------------------------------------------------------------------------"); + DEBTRACE("SubjectDataPort::~SubjectDataPort: father->edRemovePort: YACS exception " << e.what()); + DEBTRACE("------------------------------------------------------------------------------"); + } + } + } +} + +void SubjectDataPort::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectDataPort::localClean() +{ + DEBTRACE("SubjectDataPort::localClean "); + list lsl = getListOfSubjectLink(); + for (list::iterator it = lsl.begin(); it != lsl.end(); ++it) + erase(*it); +} + +std::string SubjectDataPort::getName() +{ + return _dataPort->getName(); +} + +YACS::ENGINE::DataPort* SubjectDataPort::getPort() +{ + return _dataPort; +} + +bool SubjectDataPort::tryCreateLink(SubjectDataPort *subOutport, SubjectDataPort *subInport) +{ + DEBTRACE("SubjectDataPort::tryCreateLink"); + Proc *proc = GuiContext::getCurrent()->getProc(); + + string outNodePos = ""; + SubjectNode *sno = dynamic_cast(subOutport->getParent()); + assert(sno); + Node *outNode = sno->getNode(); + outNodePos = proc->getChildName(outNode); + string outportName = subOutport->getName(); + + string inNodePos = ""; + SubjectNode *sni = dynamic_cast(subInport->getParent()); + assert(sni); + Node *inNode = sni->getNode(); + inNodePos = proc->getChildName(inNode); + string inportName = subInport->getName(); + + CommandAddLink *command = new CommandAddLink(outNodePos, outportName, + inNodePos, inportName); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + + ComposedNode *cla = ComposedNode::getLowestCommonAncestor(outNode->getFather(), + inNode->getFather()); + SubjectComposedNode *scla = dynamic_cast(sno->getParent()); + ComposedNode *ancestor = outNode->getFather(); + while (ancestor && ancestor != cla) + { + ancestor = ancestor->getFather(); + scla = dynamic_cast(scla->getParent()); + assert(scla); + } + DEBTRACE(scla->getName()); + scla->addSubjectLink(sno, subOutport, sni, subInport); + return true; + } + else + { + delete command; + return false; + } +} + +// ---------------------------------------------------------------------------- + +SubjectInputPort::SubjectInputPort(YACS::ENGINE::InputPort *port, Subject *parent) + : SubjectDataPort(port, parent), _inputPort(port) +{ + Node *node = _inputPort->getNode(); + if (ForLoop* forloop = dynamic_cast(node)) + { + if (_inputPort->getName() == "nsteps") _destructible = false; + } + else if (WhileLoop* whileloop = dynamic_cast(node)) + { + if (_inputPort->getName() == "condition") _destructible = false; + } + else if (Switch* aSwitch = dynamic_cast(node)) + { + if (_inputPort->getName() == "select") _destructible = false; + } + else if (ForEachLoop* foreach = dynamic_cast(node)) + { + if (_inputPort->getName() == "nbBranches") _destructible = false; + } + else if (OptimizerLoop* optil = dynamic_cast(node)) + { + if (_inputPort->getName() == "nbBranches") _destructible = false; + } + else if (SplitterNode* split = dynamic_cast(node)) + { + if (_inputPort->getName() == "SmplsCollection") _destructible = false; + } + +} + +SubjectInputPort::~SubjectInputPort() +{ + DEBTRACE("SubjectInputPort::~SubjectInputPort " << getName()); +} + +void SubjectInputPort::clean() +{ + localClean(); + SubjectDataPort::clean(); +} + +void SubjectInputPort::localClean() +{ + DEBTRACE("SubjectInputPort::localClean "); + if (_parent) + { + SubjectElementaryNode* elem = dynamic_cast(_parent); + if (elem) elem->removePort(this); + } +} + +// ---------------------------------------------------------------------------- + +SubjectOutputPort::SubjectOutputPort(YACS::ENGINE::OutputPort *port, Subject *parent) + : SubjectDataPort(port, parent), _outputPort(port) +{ + Node *node = _outputPort->getNode(); + if (ForEachLoop* foreach = dynamic_cast(node)) + { + if (_outputPort->getName() == "SmplPrt") _destructible = false; + } + else if (OptimizerLoop* optil = dynamic_cast(node)) + { + if (_outputPort->getName() == "SmplPrt") _destructible = false; + } +} + +SubjectOutputPort::~SubjectOutputPort() +{ + DEBTRACE("SubjectOutputPort::~SubjectOutputPort " << getName()); +} + +void SubjectOutputPort::clean() +{ + localClean(); + SubjectDataPort::clean(); +} + +void SubjectOutputPort::localClean() +{ + DEBTRACE("SubjectOutputPort::localClean "); + if (_parent) + { + SubjectElementaryNode* elem = dynamic_cast(_parent); + if (elem) elem->removePort(this); + } +} + +// ---------------------------------------------------------------------------- + +SubjectInputDataStreamPort::SubjectInputDataStreamPort(YACS::ENGINE::InputDataStreamPort *port, + Subject *parent) + : SubjectDataPort(port, parent), _inputDataStreamPort(port) +{ +} + +SubjectInputDataStreamPort::~SubjectInputDataStreamPort() +{ + DEBTRACE("SubjectInputDataStreamPort::~SubjectInputDataStreamPort " << getName()); +} + +std::map SubjectInputDataStreamPort::getProperties() +{ + return _inputDataStreamPort->getPropertyMap(); +} + +bool SubjectInputDataStreamPort::setProperties(std::map properties) +{ + Proc *proc = GuiContext::getCurrent()->getProc(); + CommandSetDSPortProperties *command = + new CommandSetDSPortProperties(proc->getChildName(getPort()->getNode()), getName(), true, properties); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + return true; + } + else delete command; + return false; +} + +void SubjectInputDataStreamPort::clean() +{ + localClean(); + SubjectDataPort::clean(); +} + +void SubjectInputDataStreamPort::localClean() +{ + DEBTRACE("SubjectInputDataStreamPort::localClean "); +} + +// ---------------------------------------------------------------------------- + +SubjectOutputDataStreamPort::SubjectOutputDataStreamPort(YACS::ENGINE::OutputDataStreamPort *port, + Subject *parent) + : SubjectDataPort(port, parent), _outputDataStreamPort(port) +{ +} + +SubjectOutputDataStreamPort::~SubjectOutputDataStreamPort() +{ + DEBTRACE("SubjectOutputDataStreamPort::~SubjectOutputDataStreamPort " << getName()); +} + +std::map SubjectOutputDataStreamPort::getProperties() +{ + return _outputDataStreamPort->getPropertyMap(); +} + +bool SubjectOutputDataStreamPort::setProperties(std::map properties) +{ + Proc *proc = GuiContext::getCurrent()->getProc(); + CommandSetDSPortProperties *command = + new CommandSetDSPortProperties(proc->getChildName(getPort()->getNode()), getName(), false, properties); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + return true; + } + else delete command; + return false; +} + +void SubjectOutputDataStreamPort::clean() +{ + localClean(); + SubjectDataPort::clean(); +} + +void SubjectOutputDataStreamPort::localClean() +{ + DEBTRACE("SubjectOutputDataStreamPort::localClean "); +} + +// ---------------------------------------------------------------------------- + +SubjectLink::SubjectLink(SubjectNode* subOutNode, + SubjectDataPort* outPort, + SubjectNode* subInNode, + SubjectDataPort* inPort, + Subject *parent) + : Subject(parent), + _subOutNode(subOutNode), _outPort(outPort), _subInNode(subInNode), _inPort(inPort) +{ + _name = ""; + ComposedNode *cla = ComposedNode::getLowestCommonAncestor(_subOutNode->getNode()->getFather(), + _subInNode->getNode()->getFather()); + DEBTRACE(_subOutNode->getName() << "." << _outPort->getName()); + DEBTRACE(_subInNode->getName() << "." << _inPort->getName()); + DEBTRACE(cla->getName()); + _name += cla->getChildName(_subOutNode->getNode()); + _name += "." + _outPort->getName(); + _name += "->"; + _name += cla->getChildName(_subInNode->getNode()); + _name += "." + _inPort->getName(); + DEBTRACE("SubjectLink::SubjectLink " << _name); +} + +SubjectLink::~SubjectLink() +{ + DEBTRACE("SubjectLink::~SubjectLink " << getName()); +} + +void SubjectLink::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectLink::localClean() +{ + DEBTRACE("SubjectLink::localClean "); + if (_parent) + { + DEBTRACE("clean link: " << _parent->getName() << " " << getName()); + SubjectComposedNode* father = dynamic_cast(_parent); + assert(father); + father->removeLink(this); // --- clean subjects first + _cla = dynamic_cast(father->getNode()); + assert(_cla); + _outp = dynamic_cast(_outPort->getPort()); + assert(_outp); + _inp = dynamic_cast(_inPort->getPort()); + assert(_inp); + if (isDestructible()) + _cla->edRemoveLink(_outp, _inp); + } +} + +std::string SubjectLink::getName() +{ + return _name; +} +// ---------------------------------------------------------------------------- + +SubjectControlLink::SubjectControlLink(SubjectNode* subOutNode, + SubjectNode* subInNode, + Subject *parent) + : Subject(parent), + _subOutNode(subOutNode), _subInNode(subInNode) +{ + _name = ""; + ComposedNode *cla = ComposedNode::getLowestCommonAncestor(_subOutNode->getNode()->getFather(), + _subInNode->getNode()->getFather()); + DEBTRACE(_subOutNode->getName()); + DEBTRACE(_subInNode->getName()); + DEBTRACE(cla->getName()); + _name += cla->getChildName(_subOutNode->getNode()); + _name += "-->>"; + _name += cla->getChildName(_subInNode->getNode()); + DEBTRACE("SubjectControlLink::SubjectControlLink " << _name); +} + +SubjectControlLink::~SubjectControlLink() +{ + DEBTRACE("SubjectControlLink::~SubjectControlLink " << getName()); + if (isDestructible()) + { + try + { + + _cla->edRemoveCFLink(_subOutNode->getNode(), _subInNode->getNode()); + } + catch (YACS::Exception &e) + { + DEBTRACE("------------------------------------------------------------------------------"); + DEBTRACE("SubjectControlLink::~SubjectControlLink: edRemoveLink YACS exception " << e.what()); + DEBTRACE("------------------------------------------------------------------------------"); + } + } +} + +void SubjectControlLink::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectControlLink::localClean() +{ + DEBTRACE("SubjectControlLink::localClean "); + if (_parent) + { + DEBTRACE("clean control link: " << _parent->getName() << " " << getName()); + SubjectComposedNode* father = dynamic_cast(_parent); + assert(father); + father->removeControlLink(this); // --- clean subjects first + _cla = dynamic_cast(father->getNode()); + assert(_cla); + } +} + +std::string SubjectControlLink::getName() +{ + return _name; +} + +// ---------------------------------------------------------------------------- + +SubjectComponent::SubjectComponent(YACS::ENGINE::ComponentInstance* component, Subject *parent) + : Subject(parent), _compoInst(component) +{ + _compoInst->incrRef(); +} + +SubjectComponent::~SubjectComponent() +{ + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( aProc ) + { + pair key = pair(_compoInst->getCompoName(),_compoInst->getNumId()); + aProc->componentInstanceMap.erase(key); + + std::map::iterator it = aProc->serviceMap.begin(); + for ( ; it!=aProc->serviceMap.end(); it++ ) + if ( (*it).second->getComponent() == _compoInst ) + (*it).second->setComponent(0); + + GuiContext::getCurrent()->_mapOfSubjectComponent.erase(_compoInst); + + //if ( SalomeComponent* aSalomeCompo = static_cast(_compoInst) ) + //delete aSalomeCompo; + } + _compoInst->decrRef(); +} + +void SubjectComponent::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectComponent::localClean() +{ + DEBTRACE("SubjectComponent::localClean "); +} + +std::string SubjectComponent::getName() +{ + DEBTRACE("SubjectComponent::getName()********************************************************************************"); + return _compoInst->getInstanceName(); +} + +std::pair SubjectComponent::getKey() +{ + std::pair key = std::pair(_compoInst->getCompoName(), _compoInst->getNumId()); + return key; +} + +YACS::ENGINE::ComponentInstance* SubjectComponent::getComponent() const +{ + return _compoInst; +} + +/*! + * When loading scheme from file, get the container associated to the component, if any, + * and create the corresponding subject. + */ +void SubjectComponent::setContainer() +{ + DEBTRACE("SubjectComponent::setContainer " << getName()); + Container* container = _compoInst->getContainer(); + if (container) + { + SubjectContainer *subContainer; + if (GuiContext::getCurrent()->_mapOfSubjectContainer.find(container) + == + GuiContext::getCurrent()->_mapOfSubjectContainer.end()) + subContainer = + GuiContext::getCurrent()->getSubjectProc()->addSubjectContainer(container, container->getName()); + else + subContainer = GuiContext::getCurrent()->_mapOfSubjectContainer[container]; + addSubjectReference(subContainer); + } +} + +void SubjectComponent::associateToContainer(SubjectContainer* subcont) +{ + DEBTRACE("SubjectComponent::associateToContainer " << getName() << subcont->getName()); + CommandAssociateComponentToContainer *command = + new CommandAssociateComponentToContainer(getKey(), subcont->getName()); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + addSubjectReference(subcont); + } + else delete command; +} + +// ---------------------------------------------------------------------------- + +SubjectContainer::SubjectContainer(YACS::ENGINE::Container* container, Subject *parent) + : Subject(parent), _container(container) +{ +} + +SubjectContainer::~SubjectContainer() +{ + Proc* aProc = GuiContext::getCurrent()->getProc(); + if ( aProc ) + { + aProc->containerMap.erase(_container->getName()); + + map::iterator it = GuiContext::getCurrent()->_mapOfSubjectComponent.begin(); + for ( ; it!=GuiContext::getCurrent()->_mapOfSubjectComponent.end(); it++ ) + if ( (*it).first && (*it).first->getContainer() == _container ) + { + (*it).first->setContainer(0); + GuiContext::getCurrent()->getSubjectProc()->destroy((*it).second); + } + + GuiContext::getCurrent()->_mapOfSubjectContainer.erase(_container); + } +} + +std::map SubjectContainer::getProperties() +{ + return _container->getProperties(); +} + +bool SubjectContainer::setProperties(std::map properties) +{ + CommandSetContainerProperties *command = new CommandSetContainerProperties(getName(), properties); + if (command->execute()) + { + GuiContext::getCurrent()->getInvoc()->add(command); + return true; + } + else delete command; + return false; +} + +void SubjectContainer::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectContainer::localClean() +{ + DEBTRACE("SubjectContainer::localClean "); +} + +std::string SubjectContainer::getName() +{ + return _container->getName(); +} + +YACS::ENGINE::Container* SubjectContainer::getContainer() const +{ + return _container; +} + +// ---------------------------------------------------------------------------- + +SubjectDataType::SubjectDataType(YACS::ENGINE::TypeCode *typeCode, Subject *parent) + : Subject(parent), _typeCode(typeCode) +{ +} + +SubjectDataType::~SubjectDataType() +{ +} + +void SubjectDataType::clean() +{ + localClean(); + Subject::clean(); +} + +void SubjectDataType::localClean() +{ + DEBTRACE("SubjectDataType::localClean "); +} + +std::string SubjectDataType::getName() +{ + return _typeCode->name(); +} + +YACS::ENGINE::TypeCode* SubjectDataType::getTypeCode() +{ + return _typeCode; +} + +// ---------------------------------------------------------------------------- diff --git a/src/hmi/guiObservers.hxx b/src/hmi/guiObservers.hxx new file mode 100644 index 000000000..8bf18ff35 --- /dev/null +++ b/src/hmi/guiObservers.hxx @@ -0,0 +1,706 @@ + +#ifndef _GUIOBSERVERS_HXX_ +#define _GUIOBSERVERS_HXX_ + +#include +#include +#include +#include +#include "Dispatcher.hxx" + +namespace YACS +{ + namespace ENGINE + { + class Node; + class ComposedNode; + class Bloc; + class Proc; + class ForLoop; + class ForEachLoop; + class WhileLoop; + class Switch; + class OptimizerLoop; + class ElementaryNode; + class InlineNode; + class ServiceNode; + class PythonNode; + class PyFuncNode; + class CORBANode; + class CppNode; + class SalomeNode; + class SalomePythonNode; + class XmlNode; + class SplitterNode; + class DataNode; + class PresetNode; + class OutNode; + class StudyInNode; + class StudyOutNode; + class DataPort; + class InputPort; + class OutputPort; + class InPort; + class OutPort; + class InputDataStreamPort; + class OutputDataStreamPort; + class Catalog; + class ComponentInstance; + class Container; + class TypeCode; + } + + namespace HMI + { + + typedef enum + { + ADD, + REMOVE, + CUT, + PASTE, + EDIT, + UPDATE, + UPDATEPROGRESS, + UP, + DOWN, + RENAME, + NEWROOT, + ADDLINK, + ADDCONTROLLINK, + ADDREF, + } GuiEvent; + + class ProcInvoc; + class GuiObserver; + + class SubjectReference; + class Subject: public YACS::ENGINE::Observer + { + public: + Subject(Subject *parent); + virtual ~Subject(); + virtual void attach(GuiObserver *obs); + virtual void detach(GuiObserver *obs); + virtual void select(bool isSelected); + virtual void update(GuiEvent event, int type, Subject* son); + virtual std::string getName(); + virtual bool setName(std::string name); + virtual Subject* getParent(); + virtual bool destroy(Subject *son); + virtual void loadChildren(); + virtual void loadLinks(); + virtual void addSubjectReference(Subject *ref); + virtual void clean(); + void localClean(); + bool isDestructible() { return _destructible; }; + static void erase(Subject* sub); + protected: + std::set _setObs; + Subject *_parent; + bool _destructible; + }; + + class GuiObserver + { + public: + GuiObserver(); + virtual ~GuiObserver(); + virtual void select(bool isSelected); + virtual void update(GuiEvent event, int type, Subject* son); + void incrementSubjects(Subject *subject); + void decrementSubjects(Subject *subject); + int getNbSubjects(); + protected: + std::set _subjectSet; + }; + + class SubjectReference: public Subject + { + public: + SubjectReference(Subject* ref, Subject *parent); + virtual ~SubjectReference(); + virtual std::string getName(); + virtual Subject* getReference() const; + virtual void clean(); + void localClean(); + protected: + Subject* _reference; + }; + + class SubjectLink; + class SubjectControlLink; + class SubjectDataPort: public Subject + { + public: + SubjectDataPort(YACS::ENGINE::DataPort* port, Subject *parent); + virtual ~SubjectDataPort(); + virtual std::string getName(); + virtual YACS::ENGINE::DataPort* getPort(); + static bool tryCreateLink(SubjectDataPort *subOutport, SubjectDataPort *subInport); + virtual void clean(); + void localClean(); + void addSubjectLink(SubjectLink* subject) { _listSubjectLink.push_back(subject); }; + void removeSubjectLink(SubjectLink* subject) { _listSubjectLink.remove(subject); }; + std::list getListOfSubjectLink() { return _listSubjectLink; }; + protected: + YACS::ENGINE::DataPort *_dataPort; + std::list _listSubjectLink; + }; + + class SubjectInputPort: public SubjectDataPort + { + public: + SubjectInputPort(YACS::ENGINE::InputPort *port, Subject *parent); + virtual ~SubjectInputPort(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::InputPort *_inputPort; + }; + + class SubjectOutputPort: public SubjectDataPort + { + public: + SubjectOutputPort(YACS::ENGINE::OutputPort *port, Subject *parent); + virtual ~SubjectOutputPort(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::OutputPort *_outputPort; + }; + + class SubjectInputDataStreamPort: public SubjectDataPort + { + public: + SubjectInputDataStreamPort(YACS::ENGINE::InputDataStreamPort *port, Subject *parent); + virtual ~SubjectInputDataStreamPort(); + virtual bool setProperties(std::map properties); + virtual std::map getProperties(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::InputDataStreamPort *_inputDataStreamPort; + }; + + class SubjectOutputDataStreamPort: public SubjectDataPort + { + public: + SubjectOutputDataStreamPort(YACS::ENGINE::OutputDataStreamPort *port, Subject *parent); + virtual ~SubjectOutputDataStreamPort(); + virtual bool setProperties(std::map properties); + virtual std::map getProperties(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::OutputDataStreamPort *_outputDataStreamPort; + }; + + + class SubjectNode: public Subject + { + public: + SubjectNode(YACS::ENGINE::Node *node, Subject *parent); + virtual ~SubjectNode(); + virtual void reparent(Subject* parent); + virtual std::string getName(); + virtual bool setName(std::string name); + virtual YACS::ENGINE::Node* getNode(); + virtual void clean(); + SubjectControlLink* addSubjectControlLink(SubjectControlLink *sub) { _listSubjectControlLink.push_back(sub); }; + void removeSubjectControlLink(SubjectControlLink* sub) { _listSubjectControlLink.remove(sub); }; + std::list getSubjectLinks() const { return _listSubjectLink; }; + std::list getSubjectControlLinks() const { return _listSubjectControlLink; }; + std::list getSubjectInputPorts() const { return _listSubjectInputPort; }; + std::list getSubjectOutputPorts() const { return _listSubjectOutputPort; }; + std::list getSubjectInputDataStreamPorts() const { return _listSubjectIDSPort; }; + std::list getSubjectOutputDataStreamPorts() const { return _listSubjectODSPort; }; + void localClean(); + virtual void update(GuiEvent event, int type, Subject* son); + static bool tryCreateLink(SubjectNode *subOutNode, SubjectNode *subInNode); + //protected: // a temporary solution while SessionCataLoader use loadTypesOld(...) + // method instead of a new loadTypes(...) method + virtual SubjectInputPort* addSubjectInputPort(YACS::ENGINE::InputPort *port, + std::string name = ""); + virtual SubjectOutputPort* addSubjectOutputPort(YACS::ENGINE::OutputPort *port, + std::string name = ""); + virtual SubjectInputDataStreamPort* addSubjectIDSPort(YACS::ENGINE::InputDataStreamPort *port, + std::string name = ""); + virtual SubjectOutputDataStreamPort* addSubjectODSPort(YACS::ENGINE::OutputDataStreamPort *port, + std::string name = ""); + virtual void notifyObserver(YACS::ENGINE::Node* object,const std::string& event); + protected: + virtual void removeExternalLinks(); + YACS::ENGINE::Node *_node; + std::list _listSubjectInputPort; + std::list _listSubjectOutputPort; + std::list _listSubjectIDSPort; + std::list _listSubjectODSPort; + std::list _listSubjectLink; + std::list _listSubjectControlLink; + }; + + class SubjectComposedNode: public SubjectNode + { + public: + SubjectComposedNode(YACS::ENGINE::ComposedNode *composedNode, Subject *parent); + virtual ~SubjectComposedNode(); + virtual SubjectNode* addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name); + virtual SubjectNode* getChild(YACS::ENGINE::Node* node=0) const { return 0; } + virtual void loadChildren(); + virtual void loadLinks(); + virtual void completeChildrenSubjectList(SubjectNode *son); + SubjectLink* addSubjectLink(SubjectNode *sno, + SubjectDataPort *spo, + SubjectNode *sni, + SubjectDataPort *spi); + SubjectControlLink* addSubjectControlLink(SubjectNode *sno, + SubjectNode *sni); + virtual void removeLink(SubjectLink* link); + virtual void removeControlLink(SubjectControlLink* link); + virtual void clean(); + void localClean(); + static SubjectComposedNode* getLowestCommonAncestor(SubjectNode* snode1, SubjectNode* snode2); + protected: + virtual SubjectNode *createNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name, + int swCase=0); + virtual SubjectNode* addSubjectNode(YACS::ENGINE::Node * node, + std::string name = "", + YACS::ENGINE::Catalog *catalog = 0, + std::string compo = "", + std::string type =""); + YACS::ENGINE::ComposedNode *_composedNode; + }; + + class SubjectBloc: public SubjectComposedNode + { + public: + SubjectBloc(YACS::ENGINE::Bloc *bloc, Subject *parent); + virtual ~SubjectBloc(); + virtual SubjectNode* addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name); + virtual void removeNode(SubjectNode* child); + virtual void completeChildrenSubjectList(SubjectNode *son); + virtual SubjectNode* getChild(YACS::ENGINE::Node* node=0) const; + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::Bloc *_bloc; + std::set _children; + }; + + class SubjectContainer: public Subject + { + public: + SubjectContainer(YACS::ENGINE::Container* container, Subject *parent); + virtual ~SubjectContainer(); + virtual std::string getName(); + virtual std::map getProperties(); + virtual bool setProperties(std::map properties); + virtual void clean(); + void localClean(); + YACS::ENGINE::Container* getContainer() const; + protected: + YACS::ENGINE::Container* _container; + }; + + class SubjectComponent: public Subject + { + public: + SubjectComponent(YACS::ENGINE::ComponentInstance* component, Subject *parent); + virtual ~SubjectComponent(); + virtual std::string getName(); + virtual void setContainer(); + virtual void associateToContainer(SubjectContainer* subcont); + virtual std::pair getKey(); + virtual void clean(); + void localClean(); + YACS::ENGINE::ComponentInstance* getComponent() const; + protected: + int _id; + YACS::ENGINE::ComponentInstance* _compoInst; + }; + + class SubjectDataType: public Subject + { + public: + SubjectDataType(YACS::ENGINE::TypeCode *typeCode, Subject *parent); + virtual ~SubjectDataType(); + virtual std::string getName(); + virtual YACS::ENGINE::TypeCode* getTypeCode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::TypeCode *_typeCode; + }; + + class SubjectProc: public SubjectBloc + { + public: + SubjectProc(YACS::ENGINE::Proc *proc, Subject *parent); + virtual ~SubjectProc(); + void loadProc(); + void loadComponents(); + void loadContainers(); + virtual SubjectComponent* addComponent(std::string name); + virtual SubjectContainer* addContainer(std::string name, std::string ref=""); + virtual SubjectDataType* addDataType(YACS::ENGINE::Catalog* catalog, std::string typeName); + SubjectComponent* addSubjectComponent(YACS::ENGINE::ComponentInstance* compo); + SubjectContainer* addSubjectContainer(YACS::ENGINE::Container* cont, + std::string name = ""); + SubjectDataType* addSubjectDataType(YACS::ENGINE::TypeCode *type); + void removeSubjectDataType(YACS::ENGINE::TypeCode *type); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::Proc *_proc; + }; + + class SubjectForLoop: public SubjectComposedNode + { + public: + SubjectForLoop(YACS::ENGINE::ForLoop *forLoop, Subject *parent); + virtual ~SubjectForLoop(); + virtual SubjectNode* addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name); + virtual void completeChildrenSubjectList(SubjectNode *son); + virtual SubjectNode* getChild(YACS::ENGINE::Node* node=0) const { return _body; } + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::ForLoop *_forLoop; + SubjectNode* _body; + }; + + class SubjectWhileLoop: public SubjectComposedNode + { + public: + SubjectWhileLoop(YACS::ENGINE::WhileLoop *whileLoop, Subject *parent); + virtual ~SubjectWhileLoop(); + virtual SubjectNode* addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name); + virtual void completeChildrenSubjectList(SubjectNode *son); + virtual SubjectNode* getChild(YACS::ENGINE::Node* node=0) const { return _body; } + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::WhileLoop *_whileLoop; + SubjectNode* _body; + }; + + class SubjectSwitch: public SubjectComposedNode + { + public: + SubjectSwitch(YACS::ENGINE::Switch *aSwitch, Subject *parent); + virtual ~SubjectSwitch(); + virtual SubjectNode* addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name, + int swCase, + bool replace = false); + virtual void removeNode(SubjectNode* son); + std::map getBodyMap(); + virtual void completeChildrenSubjectList(SubjectNode *son); + virtual SubjectNode* getChild(YACS::ENGINE::Node* node=0) const; + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::Switch *_switch; + std::map _bodyMap; + }; + + class SubjectForEachLoop: public SubjectComposedNode + { + public: + SubjectForEachLoop(YACS::ENGINE::ForEachLoop *forEachLoop, Subject *parent); + virtual ~SubjectForEachLoop(); + virtual SubjectNode* addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name); + virtual void completeChildrenSubjectList(SubjectNode *son); + virtual SubjectNode* getChild(YACS::ENGINE::Node* node=0) const { return _body; } + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::ForEachLoop *_forEachLoop; + SubjectNode* _body; + SubjectNode* _splitter; + }; + + class SubjectOptimizerLoop: public SubjectComposedNode + { + public: + SubjectOptimizerLoop(YACS::ENGINE::OptimizerLoop *optimizerLoop, Subject *parent); + virtual ~SubjectOptimizerLoop(); + virtual SubjectNode* addNode(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string type, + std::string name); + virtual void completeChildrenSubjectList(SubjectNode *son); + virtual SubjectNode* getChild(YACS::ENGINE::Node* node=0) const { return _body; } + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::OptimizerLoop *_optimizerLoop; + SubjectNode* _body; + }; + + class SubjectElementaryNode: public SubjectNode + { + public: + SubjectElementaryNode(YACS::ENGINE::ElementaryNode *elementaryNode, Subject *parent); + virtual ~SubjectElementaryNode(); + virtual SubjectDataPort* addInputPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name); + virtual SubjectDataPort* addOutputPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name); + virtual SubjectDataPort* addIDSPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name); + virtual SubjectDataPort* addODSPort(YACS::ENGINE::Catalog *catalog, std::string type, std::string name); + virtual void removePort(SubjectDataPort* port); + virtual void loadChildren(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::ElementaryNode *_elementaryNode; + }; + + class SubjectInlineNode: public SubjectElementaryNode + { + public: + SubjectInlineNode(YACS::ENGINE::InlineNode *inlineNode, Subject *parent); + virtual ~SubjectInlineNode(); + virtual bool setScript(std::string script); + virtual std::string getScript(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::InlineNode *_inlineNode; + }; + + class SubjectPythonNode: public SubjectInlineNode + { + public: + SubjectPythonNode(YACS::ENGINE::PythonNode *pythonNode, Subject *parent); + virtual ~SubjectPythonNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::PythonNode *_pythonNode; + }; + + class SubjectPyFuncNode: public SubjectInlineNode + { + public: + SubjectPyFuncNode(YACS::ENGINE::PyFuncNode *pyFuncNode, Subject *parent); + virtual ~SubjectPyFuncNode(); + virtual bool setFunctionName(std::string funcName); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::PyFuncNode *_pyFuncNode; + }; + + class SubjectServiceNode: public SubjectElementaryNode + { + public: + SubjectServiceNode(YACS::ENGINE::ServiceNode *serviceNode, Subject *parent); + virtual ~SubjectServiceNode(); + virtual void setComponentFromCatalog(YACS::ENGINE::Catalog *catalog, + std::string compo, + std::string service); + virtual void setComponent(); + virtual void associateToComponent(SubjectComponent *subcomp); + virtual void removeSubjectReference(Subject *ref); + virtual void addSubjectReference(Subject *ref); + virtual SubjectReference* getSubjectReference(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::ServiceNode *_serviceNode; + SubjectReference* _subjectReference; + }; + + class SubjectCORBANode: public SubjectServiceNode + { + public: + SubjectCORBANode(YACS::ENGINE::CORBANode *corbaNode, Subject *parent); + virtual ~SubjectCORBANode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::CORBANode *_corbaNode; + }; + + class SubjectCppNode: public SubjectServiceNode + { + public: + SubjectCppNode(YACS::ENGINE::CppNode *cppNode, Subject *parent); + virtual ~SubjectCppNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::CppNode *_cppNode; + }; + + class SubjectSalomeNode: public SubjectServiceNode + { + public: + SubjectSalomeNode(YACS::ENGINE::SalomeNode *salomeNode, Subject *parent); + virtual ~SubjectSalomeNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::SalomeNode *_salomeNode; + }; + + class SubjectSalomePythonNode: public SubjectServiceNode + { + public: + SubjectSalomePythonNode(YACS::ENGINE::SalomePythonNode *salomePythonNode, + Subject *parent); + virtual ~SubjectSalomePythonNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::SalomePythonNode *_salomePythonNode; + }; + + class SubjectXmlNode: public SubjectServiceNode + { + public: + SubjectXmlNode(YACS::ENGINE::XmlNode *xmlNode, Subject *parent); + virtual ~SubjectXmlNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::XmlNode *_xmlNode; + }; + + class SubjectSplitterNode: public SubjectElementaryNode + { + public: + SubjectSplitterNode(YACS::ENGINE::SplitterNode *splitterNode, Subject *parent); + virtual ~SubjectSplitterNode(); + virtual std::string getName(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::SplitterNode *_splitterNode; + }; + + class SubjectDataNode: public SubjectElementaryNode + { + public: + SubjectDataNode(YACS::ENGINE::DataNode *dataNode, Subject *parent); + virtual ~SubjectDataNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::DataNode *_dataNode; + }; + + class SubjectPresetNode: public SubjectDataNode + { + public: + SubjectPresetNode(YACS::ENGINE::PresetNode *presetNode, Subject *parent); + virtual ~SubjectPresetNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::PresetNode *_presetNode; + }; + + class SubjectOutNode: public SubjectDataNode + { + public: + SubjectOutNode(YACS::ENGINE::OutNode *outNode, Subject *parent); + virtual ~SubjectOutNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::OutNode *_outNode; + }; + + class SubjectStudyInNode: public SubjectDataNode + { + public: + SubjectStudyInNode(YACS::ENGINE::StudyInNode *studyInNode, Subject *parent); + virtual ~SubjectStudyInNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::StudyInNode *_studyInNode; + }; + + class SubjectStudyOutNode: public SubjectDataNode + { + public: + SubjectStudyOutNode(YACS::ENGINE::StudyOutNode *studyOutNode, Subject *parent); + virtual ~SubjectStudyOutNode(); + virtual void clean(); + void localClean(); + protected: + YACS::ENGINE::StudyOutNode *_studyOutNode; + }; + + class SubjectLink: public Subject + { + public: + SubjectLink(SubjectNode* subOutNode, + SubjectDataPort* outPort, + SubjectNode* subInNode, + SubjectDataPort* inPort, + Subject *parent); + virtual ~SubjectLink(); + virtual std::string getName(); + virtual void clean(); + void localClean(); + SubjectNode* getSubjectOutNode() { return _subOutNode; }; + SubjectNode* getSubjectInNode() { return _subInNode; }; + SubjectDataPort* getSubjectOutPort() { return _outPort; }; + SubjectDataPort* getSubjectInPort() { return _inPort; }; + protected: + SubjectNode* _subOutNode; + SubjectDataPort* _outPort; + SubjectNode* _subInNode; + SubjectDataPort* _inPort; + std::string _name; + YACS::ENGINE::ComposedNode *_cla; + YACS::ENGINE::OutPort *_outp; + YACS::ENGINE::InPort *_inp; + }; + + class SubjectControlLink: public Subject + { + public: + SubjectControlLink(SubjectNode* subOutNode, + SubjectNode* subInNode, + Subject *parent); + virtual ~SubjectControlLink(); + virtual std::string getName(); + virtual void clean(); + void localClean(); + SubjectNode* getSubjectOutNode() { return _subOutNode; }; + SubjectNode* getSubjectInNode() { return _subInNode; }; + protected: + SubjectNode* _subOutNode; + SubjectNode* _subInNode; + std::string _name; + YACS::ENGINE::ComposedNode *_cla; + }; + + } +} +#endif diff --git a/src/hmi/main.cxx b/src/hmi/main.cxx new file mode 100644 index 000000000..8ea41a31e --- /dev/null +++ b/src/hmi/main.cxx @@ -0,0 +1,305 @@ + +#include "RuntimeSALOME.hxx" +#include "Proc.hxx" + +#include "mainempty.h" +#include "editTree.h" +#include "editCanvas.h" +#include "guiObservers.hxx" +#include "commandsProc.hxx" +#include "guiContext.hxx" +#include "nodeEdition.h" +#include "parsers.hxx" +#include "Logger.hxx" +#include "LinkInfo.hxx" +#include "VisitorSaveSalomeSchema.hxx" + +#include "SALOME_NamingService.hxx" +#include "SALOME_ModuleCatalog.hxx" +#include "SALOME_ModuleCatalog.hh" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" +using namespace std; + +void AttachDebugger() +{ + if(getenv ("DEBUGGER")) + { + std::stringstream exec; + exec << "$DEBUGGER guidemo " << getpid() << "&"; + std::cerr << exec.str() << std::endl; + system(exec.str().c_str()); + while(1); + } +} + +void terminateHandler(void) +{ + std::cerr << "Terminate: not managed exception !" << std::endl; + AttachDebugger(); +} + +void unexpectedHandler(void) +{ + std::cerr << "Unexpected: unexpected exception !" << std::endl; + AttachDebugger(); +} + +class myMainform: public mainform +{ +public: + myMainform(QWidget* parent = 0, const char* name = 0, WFlags fl = 0); + virtual ~myMainform(); + virtual void fileExit(); + virtual void fileOpen(); + virtual void fileNew(); + virtual void fileSave(); + virtual void fileSaveAs(); + virtual void fileCheckLoad(); + virtual void addTree(Qt::Dock pos); + virtual void setCanvas(); + virtual void setStackOfWidgets(); +protected: + virtual void load(const QString &f); + YACS::ENGINE::Proc* _proc; + YACS::YACSLoader *_loader; +}; + + +myMainform::myMainform(QWidget* parent, const char* name, WFlags fl) + : mainform(parent, name, fl) +{ + YACS::ENGINE::RuntimeSALOME::setRuntime(); + _loader = new YACS::YACSLoader(); + _loader->registerProcCataLoader(); + YACS::HMI::GuiContext* context = new YACS::HMI::GuiContext(); + YACS::HMI::GuiContext::setCurrent(context); + setMinimumWidth(1260); + setMinimumHeight(800); + setCanvas(); + addTree(Qt::DockLeft); + addTree(Qt::DockRight); + // addTree(Qt::DockLeft); + setStackOfWidgets(); + + try + { + YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime(); + CORBA::ORB_ptr orb = runTime->getOrb(); + if (orb) + { + SALOME_NamingService namingService(orb); + CORBA::Object_ptr obj = namingService.Resolve("/Kernel/ModulCatalog"); + SALOME_ModuleCatalog::ModuleCatalog_var aModuleCatalog = + SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj); + if (! CORBA::is_nil(aModuleCatalog)) + { + DEBTRACE("SALOME_ModuleCatalog::ModuleCatalog found"); + std::string anIOR = orb->object_to_string( aModuleCatalog ); + YACS::ENGINE::Catalog* aCatalog = runTime->loadCatalog( "session", anIOR ); + YACS::HMI::GuiContext::getCurrent()->setSessionCatalog(aCatalog); + std::map< std::string, YACS::ENGINE::ComponentDefinition * >::iterator it; + for (it = aCatalog->_componentMap.begin();it != aCatalog->_componentMap.end(); ++it) + DEBTRACE("Component: " <<(*it).first); + } + } + } + catch(ServiceUnreachable& e) + { + DEBTRACE("Caught Exception. "<createProc("newSchema"); + YACS::HMI::GuiContext::getCurrent()->setProc(_proc); +} + +void myMainform::setCanvas() +{ + QCanvas * canvas = YACS::HMI::GuiContext::getCurrent()->getCanvas(); + YACS::HMI::EditCanvas *editor + = new YACS::HMI::EditCanvas(YACS::HMI::GuiContext::getCurrent(), canvas, this); + canvas->setBackgroundColor(QColor(204,237,239)); + setCentralWidget(editor); +} + +void myMainform::addTree(Qt::Dock pos) +{ + QDockWindow *dw = new QDockWindow( QDockWindow::InDock, this ); + dw->setResizeEnabled( TRUE ); + dw->setVerticalStretchable( TRUE ); + addDockWindow( dw, pos ); + setDockEnabled( dw, DockTop, FALSE ); + setDockEnabled( dw, DockBottom, FALSE ); + dw->setCloseMode( QDockWindow::Never ); + + YACS::HMI::editTree *dbtree = + new YACS::HMI::editTree(YACS::HMI::GuiContext::getCurrent(), dw); + dw->setWidget(dbtree); + dw->setCaption( tr("edit tree")); +} + +void myMainform::setStackOfWidgets() +{ + QDockWindow *dw = new QDockWindow( QDockWindow::InDock, this ); + dw->setResizeEnabled( TRUE ); + dw->setVerticalStretchable( TRUE ); + addDockWindow( dw, DockRight ); + setDockEnabled( dw, DockTop, FALSE ); + setDockEnabled( dw, DockBottom, FALSE ); + dw->setCloseMode( QDockWindow::Never ); + + QWidgetStack *ws = new QWidgetStack(dw); + YACS::HMI::GuiContext::getCurrent()->setWidgetStack(ws); + QWidget* WStackPage = new QWidget( ws, "WStackPage" ); + QHBoxLayout* wiEditionsLayout = new QHBoxLayout( this, 11, 6, "wiEditionsLayout"); + ws->addWidget( WStackPage, 0 ); + wiEditionsLayout->addWidget( ws ); + + dw->setWidget(ws); + dw->setCaption( tr("edit stack")); + + YACS::HMI::Subject* context = YACS::HMI::GuiContext::getCurrent(); + YACS::HMI::NodeEdition* rootEdit = new YACS::HMI::NodeEdition(context, + ws, + context->getName().c_str()); +} + +void myMainform::fileOpen() +{ + QString fn = QFileDialog::getOpenFileName( QString::null, + tr( "XML-Files (*.xml);;All Files (*)" ), + this, + "load YACS scheme file dialog", + "Choose a filename to load" ); + if ( !fn.isEmpty() ) + { + DEBTRACE("***************************************************************************"); + DEBTRACE("file loaded : " <load(fn.latin1()); + YACS::ENGINE::Logger* logger= _proc->getLogger("parser"); + if(!logger->isEmpty()) + { + DEBTRACE(logger->getStr()); + } + YACS::HMI::GuiContext::getCurrent()->setProc(_proc); + } +} + +void myMainform::fileExit() +{ + close(); +} + +void myMainform::fileSave() +{ + fileSaveAs(); +} + +void myMainform::fileSaveAs() +{ + QString fn = QFileDialog::getSaveFileName(QString::null, + tr( "XML-Files (*.xml)" ), + this, + "save YACS scheme file dialog", + "Choose a filename to save under" ); + if ( !fn.isEmpty() ) + { + YACS::ENGINE::Proc* proc = YACS::HMI::GuiContext::getCurrent()->getProc(); + YACS::ENGINE::LinkInfo info(YACS::ENGINE::LinkInfo::ALL_DONT_STOP); + proc->checkConsistency(info); + if (info.areWarningsOrErrors()) + DEBTRACE(info.getGlobalRepr()); + YACS::ENGINE::VisitorSaveSalomeSchema vss(proc); + vss.openFileSchema(fn.latin1()); + proc->accept(&vss); + vss.closeFileSchema(); + } +} + +/*! + * Select several xml files in a directory to check load and delete of all the files. + * Mainly used do test delete mechanism. + */ +void myMainform::fileCheckLoad() +{ + QStringList files = QFileDialog::getOpenFileNames(tr( "XML-Files (*.xml)" ), + QString::null, + this, + "check load on samples xml files", + "Select one or more files to load" ); + QStringList list = files; + QStringList::Iterator it = list.begin(); + while( it != list.end() ) + { + QString fn = *it; + if ( !fn.isEmpty() ) + { + DEBTRACE("***************************************************************************"); + DEBTRACE("file loaded : " <load(fn.latin1()); + YACS::ENGINE::Logger* logger= _proc->getLogger("parser"); + if(!logger->isEmpty()) + { + DEBTRACE(logger->getStr()); + } + YACS::HMI::GuiContext::getCurrent()->setProc(_proc); + } + ++it; + } + } + +/*! + * Not used any more ? + */ +void myMainform::load(const QString &f) +{ + if (!QFile::exists(f)) + return; + QFile file(f); + if (!file.open(IO_ReadOnly)) + return; + QTextStream ts(&file); + QString txt = ts.read(); + } + +int main( int argc, char **argv ) +{ + if(getenv ("DEBUGGER")) + { +// setsig(SIGSEGV,&Handler); + set_terminate(&terminateHandler); + set_unexpected(&unexpectedHandler); + } + QApplication a( argc, argv ); + myMainform *myAppli =new myMainform(); + myAppli->show(); + a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) ); + return a.exec(); +} + diff --git a/src/hmi/mainempty.ui b/src/hmi/mainempty.ui new file mode 100644 index 000000000..92a948cdb --- /dev/null +++ b/src/hmi/mainempty.ui @@ -0,0 +1,444 @@ + +mainform + + + mainform + + + + 0 + 0 + 600 + 480 + + + + Check widget + + + + + MenuBar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + toolBar + + + Tools + + + + + + + + + + + + + + + + fileNewAction + + + filenew.png + + + New + + + &New + + + Ctrl+N + + + + + fileOpenAction + + + fileopen.png + + + Open + + + &Open... + + + Ctrl+O + + + + + fileSaveAction + + + filesave.png + + + Save + + + &Save + + + Ctrl+S + + + + + fileSaveAsAction + + + filenew.png + + + Save As + + + Save &As... + + + + + + + + filePrintAction + + + print.png + + + Print + + + &Print... + + + Ctrl+P + + + + + fileExitAction + + + Exit + + + E&xit + + + + + + + + editUndoAction + + + undo.png + + + Undo + + + &Undo + + + Ctrl+Z + + + + + editRedoAction + + + redo.png + + + Redo + + + &Redo + + + Ctrl+Y + + + + + editCutAction + + + editcut.png + + + Cut + + + Cu&t + + + Ctrl+X + + + + + editCopyAction + + + editcopy.png + + + Copy + + + &Copy + + + Ctrl+C + + + + + editPasteAction + + + editpaste.png + + + Paste + + + &Paste + + + Ctrl+V + + + + + editFindAction + + + searchfind.png + + + Find + + + &Find... + + + Ctrl+F + + + + + helpContentsAction + + + Contents + + + &Contents... + + + + + + + + helpIndexAction + + + Index + + + &Index... + + + + + + + + helpAboutAction + + + About + + + &About + + + + + + + + checkLoadAction + + + check Load + + + check Load + + + + + + fileNewAction + activated() + mainform + fileNew() + + + fileOpenAction + activated() + mainform + fileOpen() + + + fileSaveAction + activated() + mainform + fileSave() + + + fileSaveAsAction + activated() + mainform + fileSaveAs() + + + filePrintAction + activated() + mainform + filePrint() + + + fileExitAction + activated() + mainform + fileExit() + + + editUndoAction + activated() + mainform + editUndo() + + + editRedoAction + activated() + mainform + editRedo() + + + editCutAction + activated() + mainform + editCut() + + + editCopyAction + activated() + mainform + editCopy() + + + editPasteAction + activated() + mainform + editPaste() + + + editFindAction + activated() + mainform + editFind() + + + helpIndexAction + activated() + mainform + helpIndex() + + + helpContentsAction + activated() + mainform + helpContents() + + + helpAboutAction + activated() + mainform + helpAbout() + + + checkLoadAction + activated() + mainform + fileCheckLoad() + + + + fileNew() + fileOpen() + fileSave() + fileSaveAs() + filePrint() + fileExit() + editUndo() + editRedo() + editCut() + editCopy() + editPaste() + editFind() + helpIndex() + helpContents() + helpAbout() + fileCheckLoad() + + + + diff --git a/src/hmi/nodeEdition.cxx b/src/hmi/nodeEdition.cxx new file mode 100644 index 000000000..20f0409ad --- /dev/null +++ b/src/hmi/nodeEdition.cxx @@ -0,0 +1,351 @@ + +#include "nodeEdition.h" +#include "guiContext.hxx" +#include "Port.hxx" +#include "InlineNode.hxx" +#include "TypeCode.hxx" + +#include +#include +#include +#include + +#ifdef HAVE_QEXTSCINTILLA_H +#include +#include +#endif + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#include +#include + +using namespace std; + +using namespace YACS; +using namespace YACS::HMI; + +#ifdef HAVE_QEXTSCINTILLA_H +class myQextScintilla: public QextScintilla +{ +public: + myQextScintilla(QWidget *parent=0, const char *name=0, WFlags f=0) + : QextScintilla(parent, name, f) {}; + ~myQextScintilla(){}; + virtual QSize sizeHint() const { return QSize(350, 150); }; +}; +#endif + +itemEdition::itemEdition(Subject* subject) + : GuiObserver(), _subject(subject) +{ + _subject->attach(this); + _stackId = -1; + _name = _subject->getName(); + _type = "Unknown"; + _category = "Unknown"; + ProcInvoc* invoc = GuiContext::getCurrent()->getInvoc(); + if (SubjectNode * sub = dynamic_cast(_subject)) + { + _category = "Node"; + _type = invoc->getTypeName(invoc->getTypeOfNode(sub->getNode())); + } + else if (SubjectDataPort * sub = dynamic_cast(_subject)) + { + _category = "Port"; + _type = invoc->getTypeName(invoc->getTypeOfPort(sub->getPort())); + } + else if (SubjectLink * sub = dynamic_cast(_subject)) + { + _category = "Link"; + _type = "Link"; + } + else if (SubjectControlLink * sub = dynamic_cast(_subject)) + { + _category = "ControlLink"; + _type = "Control Link"; + } + else if (SubjectDataType * sub = dynamic_cast(_subject)) + { + _category = "Data"; + switch (sub->getTypeCode()->kind()) + { + case YACS::ENGINE::Double: _type = "Double"; break; + case YACS::ENGINE::Int: _type = "Int"; break; + case YACS::ENGINE::String: _type = "String"; break; + case YACS::ENGINE::Bool: _type = "Bool"; break; + case YACS::ENGINE::Objref: _type = "Objref"; break; + case YACS::ENGINE::Sequence: _type = "Sequence"; break; + case YACS::ENGINE::Array: _type = "Array"; break; + case YACS::ENGINE::Struct: _type = "Struct"; break; + default: _type = "None or Unknown"; + } + } + else if (SubjectComponent * sub = dynamic_cast(_subject)) + { + _category = "Component"; + _type = "Salome Component"; + } + else if (SubjectContainer * sub = dynamic_cast(_subject)) + { + _category = "Container"; + _type = "Salome Container"; + } +} + +itemEdition::~itemEdition() +{ +} + +void itemEdition::select(bool isSelected) +{ + DEBTRACE("NodeEdition::select " << isSelected); + if (isSelected) + GuiContext::getCurrent()->getWidgetStack()->raiseWidget(_stackId); +} + + +void itemEdition::update(GuiEvent event, int type, Subject* son) +{ +} + +Subject* itemEdition::getSubject() +{ + return _subject; +} + + +NodeEdition::NodeEdition(Subject* subject, + QWidget* parent, + const char* name, + WFlags fl) + : wiNodeEdition(parent, name, fl), itemEdition(subject) +{ + DEBTRACE("NodeEdition::NodeEdition " << name); + string category = _category + " type:"; + laNodeType->setText(category.c_str()); + category = _category + " name:"; + laNodeName->setText(category.c_str()); + liNodeType->setText(_type); + liNodeName->setText(_name.c_str()); + liNodeType->setText(_type); + setEdited(false); + _haveScript = false; + _sci = 0; + _subInlineNode = 0; + _subFuncNode = 0; + _funcName =""; + _liFuncName = 0; + if (_subFuncNode = dynamic_cast(_subject)) + if (YACS::ENGINE::InlineFuncNode *pyFuncNode + = dynamic_cast(_subFuncNode->getNode())) + { + _funcName = pyFuncNode->getFname(); + QLabel* laFuncName = new QLabel( this, "laFuncName" ); + layout5->addWidget( laFuncName ); + laFuncName->setText("Function Name:"); + _liFuncName = new QLineEdit( this, "liFuncName" ); + layout5->addWidget( _liFuncName ); + _liFuncName->setText(_funcName); + connect(_liFuncName, SIGNAL(textChanged(const QString&)), this, SLOT(onFuncNameModified(const QString&))); + } + else assert(0); + if (_subInlineNode = dynamic_cast(_subject)) + { + _haveScript = true; +#ifdef HAVE_QEXTSCINTILLA_H + _sci = new myQextScintilla( this, "Python Editor" ); +#else + _sci = new QTextEdit( this, "Python Editor" ); +#endif + wiNodeEditionLayout->removeItem(spacer2); + layout5->addWidget( _sci ); +#ifdef HAVE_QEXTSCINTILLA_H + _sci->setUtf8(1); + QextScintillaLexerPython *lex = new QextScintillaLexerPython(_sci); + _sci->setLexer(lex); + _sci->setBraceMatching(QextScintilla::SloppyBraceMatch); + _sci->setAutoIndent(1); + _sci->setIndentationWidth(4); + _sci->setIndentationGuides(1); + _sci->setIndentationsUseTabs(0); + _sci->setAutoCompletionThreshold(2); +#endif + if (YACS::ENGINE::InlineNode* pyNode = dynamic_cast(_subInlineNode->getNode())) + { + _sci->append(pyNode->getScript()); + } + connect(_sci, SIGNAL(textChanged()), this, SLOT(onScriptModified())); + } + _stackId = GuiContext::getCurrent()->getWidgetStack()->addWidget(this); + DEBTRACE("_stackId " << _stackId); + //GuiContext::getCurrent()->getWidgetStack()->raiseWidget(_stackId); +} + +NodeEdition::~NodeEdition() +{ +} + +void NodeEdition::setName(std::string name) +{ + _name = name; + setEdited(false); +} + +void NodeEdition::onApply() +{ + string name = liNodeName->text().latin1(); + bool nameEdited = false; + if (name != _name) + { + nameEdited = true; + bool ret = _subject->setName(name); + if (ret) + { + nameEdited = false; + _name = name; + } + } + bool funcNameEdited = false; + if (_subFuncNode) + { + funcNameEdited = true; + string funcName = _liFuncName->text().latin1(); + if (funcName != _funcName) + { + bool ret = _subFuncNode->setFunctionName(funcName); + if (ret) + { + funcNameEdited = false; + _funcName = funcName; + } + } + } + bool scriptEdited = false; + if (_haveScript) + { + if (_sci->isModified()) + { + scriptEdited = true; + bool ret = _subInlineNode->setScript(_sci->text().latin1()); + if (ret) + { + scriptEdited = false; + } + } + } + bool edited = nameEdited || funcNameEdited || scriptEdited; + setEdited(edited); +} + +void NodeEdition::onCancel() +{ + liNodeName->setText(_name.c_str()); + if (_haveScript) + _sci->setText(_subInlineNode->getScript()); + if (_subFuncNode) + _liFuncName->setText(_funcName); + setEdited(false); +} + +void NodeEdition::onModify(const QString &text) +{ + if (_name != text.latin1()) setEdited(true); +} + +void NodeEdition::onFuncNameModified(const QString &text) +{ + if (_funcName != text.latin1()) setEdited(true); +} + +void NodeEdition::onScriptModified() +{ + setEdited(true); +} + +void NodeEdition::setEdited(bool isEdited) +{ + btApply->setEnabled(isEdited); + btCancel->setEnabled(isEdited); +} + +void NodeEdition::update(GuiEvent event, int type, Subject* son) +{ + DEBTRACE("NodeEdition::update "); + NodeEdition *item = 0; + switch (event) + { + case NEWROOT: + item = new NodeEdition(son, + GuiContext::getCurrent()->getWidgetStack(), + son->getName().c_str()); + break; + case ADD: + switch (type) + { + case YACS::HMI::SALOMEPROC: + case YACS::HMI::BLOC: + case YACS::HMI::FOREACHLOOP: + case YACS::HMI::OPTIMIZERLOOP: + case YACS::HMI::FORLOOP: + case YACS::HMI::WHILELOOP: + case YACS::HMI::SWITCH: + case YACS::HMI::PYTHONNODE: + case YACS::HMI::PYFUNCNODE: + case YACS::HMI::CORBANODE: + case YACS::HMI::SALOMENODE: + case YACS::HMI::CPPNODE: + case YACS::HMI::SALOMEPYTHONNODE: + case YACS::HMI::XMLNODE: + case YACS::HMI::PRESETNODE: + case YACS::HMI::OUTNODE: + case YACS::HMI::STUDYINNODE: + case YACS::HMI::STUDYOUTNODE: + case YACS::HMI::SPLITTERNODE: + case YACS::HMI::DFTODSFORLOOPNODE: + case YACS::HMI::DSTODFFORLOOPNODE: + case YACS::HMI::INPUTPORT: + case YACS::HMI::OUTPUTPORT: + case YACS::HMI::INPUTDATASTREAMPORT: + case YACS::HMI::OUTPUTDATASTREAMPORT: + case YACS::HMI::CONTAINER: + case YACS::HMI::COMPONENT: + case YACS::HMI::REFERENCE: + case YACS::HMI::DATATYPE: + item = new NodeEdition(son, + GuiContext::getCurrent()->getWidgetStack(), + son->getName().c_str()); + break; + default: + DEBTRACE("NodeEdition::update() ADD, type not handled:" << type); + } + break; + case ADDLINK: + switch (type) + { + case YACS::HMI::DATALINK: + item = new NodeEdition(son, + GuiContext::getCurrent()->getWidgetStack(), + son->getName().c_str()); + break; + default: + DEBTRACE("NodeEdition::update() ADDLINK, type not handled:" << type); + } + break; + case ADDCONTROLLINK: + switch (type) + { + case YACS::HMI::CONTROLLINK: + item = new NodeEdition(son, + GuiContext::getCurrent()->getWidgetStack(), + son->getName().c_str()); + break; + default: + DEBTRACE("NodeEdition::update() ADDCONTROLLINK, type not handled:" << type); + } + break; + default: + DEBTRACE("NodeEdition::update(), event not handled: " << event); + } +} diff --git a/src/hmi/nodeEdition.h b/src/hmi/nodeEdition.h new file mode 100644 index 000000000..337815fc0 --- /dev/null +++ b/src/hmi/nodeEdition.h @@ -0,0 +1,74 @@ +#ifndef _NODEEDITION_H_ +#define _NODEEDITION_H_ + +#include "yacsconfig.h" +#include +#include "guiObservers.hxx" + +#include "winodeedition.h" + +#ifdef HAVE_QEXTSCINTILLA_H +class QextScintilla; +#endif + +namespace YACS +{ + namespace HMI + { + + class itemEdition: public GuiObserver + { + public: + itemEdition(Subject* subject); + virtual ~itemEdition(); + virtual void select(bool isSelected); + virtual void update(GuiEvent event, int type, Subject* son); + virtual Subject* getSubject(); + protected: + Subject* _subject; + int _stackId; + std::string _name; + std::string _type; + std::string _category; + }; + + class NodeEdition: public wiNodeEdition, public itemEdition + { + Q_OBJECT + + public slots: + virtual void onApply(); + virtual void onCancel(); + virtual void onModify(const QString &text); + virtual void onFuncNameModified(const QString &text); + virtual void onScriptModified(); + public: + NodeEdition(Subject* subject, + QWidget* parent = 0, + const char* name = 0, + WFlags fl = 0 ); + virtual ~NodeEdition(); + virtual void setName(std::string name); + virtual void update(GuiEvent event, int type, Subject* son); + + protected: + virtual void setEdited(bool isEdited); + bool _isEdited; + bool _haveScript; +#ifdef HAVE_QEXTSCINTILLA_H + QextScintilla* _sci; +#else + QTextEdit* _sci; +#endif + SubjectInlineNode *_subInlineNode; + SubjectPyFuncNode* _subFuncNode; + std::string _funcName; + QLineEdit* _liFuncName; + }; + + } +} + + + +#endif diff --git a/src/hmi/resources/editcopy.png b/src/hmi/resources/editcopy.png new file mode 100644 index 0000000000000000000000000000000000000000..9f5f0c6d6080310f30298e1c9ef7342b3ea6d730 GIT binary patch literal 248 zcmV8)K_!M|q-f$D!~PiL(ntzbb5bwl(@8 z=N&es9gnom8?xp}+`s>Wjcrw^%rVoHBX@rATu_h=uZn41(Gq`$DQ>Aj)t|HMkE~=r mHNVj|zqvMk%l-FP=KTJyzh=gXGo3)!FnGH9xvXIv!|eR5UJM`E&#MFT3@SaYnPiGgMYxo7PjOTTV(f*absDL zo7_ck-bcVkGTmNV%r)@IcVe!1c{be7brV;9dGw4+C#nwa|xb^rhX07*qoM6N<$g6c_g82|tP literal 0 HcmV?d00001 diff --git a/src/hmi/resources/filenew.png b/src/hmi/resources/filenew.png new file mode 100644 index 0000000000000000000000000000000000000000..138cd8c36cf6cdf473c5a4c79347b76d999a048a GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fC7v#hAr`%FuO8$)puod=A^)XW zqmIC)|94w21-EWnInjfk)t*D@gQk$c4~?TMZyvcf?X32!o39xd()jcr915IadE`5f zk4tV`wyDMWNlmU#HhudbvSwBPEm{AAOG~7c*yqm`l%4jfYoboYLGE`c&)6lu)=gqw X>#D_a#xFntXg`CetDnm{r-UW|Gn7G> literal 0 HcmV?d00001 diff --git a/src/hmi/resources/fileopen.png b/src/hmi/resources/fileopen.png new file mode 100644 index 0000000000000000000000000000000000000000..6d47e005551b1c940050616ab035a4a6746e3ad1 GIT binary patch literal 210 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fGd*1#Lo9mVPI2UGRp4=n?>uf+ zpSY(yR>Nb7M#BGdH$%Gj^$D}s$xdo4|I)Zn`Hr^9w=Y$;k9MT4Xt8%-oT0^S8=rKv znPHXGb=ClvSv#+?FE3uPWS9S>MfZ(uQjS@_-rMwa$J%?R&r~S9c1k;DSrYrJ;dB1_ zv}5@T=h%1XZz*`gdiKD+3l)>U^@)p2N{-LSv3vh*mreg&v)m>y@$Te{cXD$>8bg K=d#Wzp$P!t9#|{@ literal 0 HcmV?d00001 diff --git a/src/hmi/resources/filesave.png b/src/hmi/resources/filesave.png new file mode 100644 index 0000000000000000000000000000000000000000..241479c2f713a6cd0633ebc793c57aaf35f512a9 GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4f3p`yMLo9l)PW9z#P!MRHf6*=D zVehk~OGq}>=~znUgY6&NKYo;PXVp^dE7M(j`}e$=-@^JEwwigjcAPVH zVPSZ|W!dxM=LC~WnmUJT`t}C%zmBkCeHmgR-^Em|Rcj^Bxxdx-=+&FSt1R>UElzEm z`RLL^j@1vte&`uYuRrbE|I_Ju?7n@M9y(98n*8n5TH8dyFW$BOP5eI(u+82oclNDe RPYlql44$rjF6*2UngHR&TR;E+ literal 0 HcmV?d00001 diff --git a/src/hmi/resources/print.png b/src/hmi/resources/print.png new file mode 100644 index 0000000000000000000000000000000000000000..de962684641cdc832d8ff0751f40414cea3d8c89 GIT binary patch literal 725 zcmV;`0xJE9P)*-+47HZ)9_!(x^|hb3=NKSE()0vqPCge6d6E{owpnMrJhZNW;i z{CCUPoQN)HQ|z1+CmAdtO3^UAoL=J66jcLL zj%+algq%-4cx7r+(yx@~muLJ}{QA_CY;+MppPqh&vM9s<#8>zVqc92*B#go+tk>)C z@kzuH#Z-QApZ_b^gYE}4=e%$PAAk4a=mX$8-}UZ|>ybdb_F z!22T3qZx=0Ye?-jI9ycR6vXjh-?_mvv>|`kfEnp<7}sle`ejkzMWUW&w7xlrF4mnm z0~H|V1n{=Sh-Zl3Y+6qo^|&<&YXGr!C=`n|bZ=)nInsFA2}S86U}fh8t;u#b8XyXG zxZ*G?srzhtV=|fY4ePLM$!dJG`nm_|nr$^`4Oq)L7z|h}?jmFFePb1fK_x&HoimFt z(y+1}7(2}|Lj;z~CG+{b*Uz$ykGBtgzrCSq#Pdhk8$Rhg%MP;bv!15qa>?W4V-Grq z&}y{`tJNFZ`v0Y9ZOYD>-CqM#%XnWIlj(%p+gtAM?_0dT(e|DUKkOui00000NkvXX Hu0mjfR9jK@ literal 0 HcmV?d00001 diff --git a/src/hmi/resources/redo.png b/src/hmi/resources/redo.png new file mode 100644 index 0000000000000000000000000000000000000000..44109228e8b94cd7871385b9e510c8e612e59e73 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fC7v#hAr`%FCmrNEpupjfdtcYO z<^Nm0#SvL*7gHZJ^DVV&W$~!qZ{x3E^`ugq5q*WIez3^JK=zG9jp^_f{3#%uqq*pLR X=4os!v3F|&+RxzW>gTe~DWM4fctAv? literal 0 HcmV?d00001 diff --git a/src/hmi/resources/searchfind.png b/src/hmi/resources/searchfind.png new file mode 100644 index 0000000000000000000000000000000000000000..1a9836f04a46117de8dacd11b3f5e51ff831169f GIT binary patch literal 662 zcmV;H0%`q;P)o?m5QaZz3RdjIB6!ecHj|*j9B9_U<_+>1fq@Y;l$pX*s4|;X@ZgEvv0J7Bx1DB^ z)|s}`nf~Z*XXo30ckkeT)8fZV*LAaV4(~lt6#yfGwH9kFS65ey7b(92w{1HQhXc7S zSgzM#1OV?G+4s+7vG?5+frTERPVL`s47VliV`(4>^j6No6Y7`&M*4D zpNGRh{oy^!O^vFePDt(&#)3Eq!3UO`8j76b@%XAyTsY^*t);4K0K{JsoM+M_lZ=Sw z$Y9YJvDK2%Il8W!&x5ClWwl08G=Li&E+0unz~fK}WC-dNM3BPZy+7|*Q^MqipaGvv zg!P0NL4#tjK#q$e$s|w^lQB)xS@0Wxm=qBpB@{pv@s>;rycM1f$8ISXC@+}+*Hj)1A&LIOzW1cV4y@IC^NeR7m# z$+}wOMu#!xr=R5lV6|Fd0>th>rin~5^2-dd22m&!`1qN!EV;S4S-8>h`1nZEG_-B| z;+y_nt?&E!csw#XhZuqEv>*);QK;*h?RL8W7=~f)x{m#Rk1>YrcFStDdgA_B8(r7U z-g{zo-EMB02Jby}T|X)Q$LjljzP-Jjt+jJmmh=7n{rsZi-_^sz w!`w6t(=@T!Z2le?PGj8f_oS5mCiWlc3%pETS=JQF^Z)<=07*qoM6N<$f*>tFwg3PC literal 0 HcmV?d00001 diff --git a/src/hmi/resources/undo.png b/src/hmi/resources/undo.png new file mode 100644 index 0000000000000000000000000000000000000000..f314aa538b915d184730ca958cee32dd2a876d54 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4f#hxyXAr`%FCmrN#P~dRb_&!Zm z=D%-y){2gWWtl(C_%-ZqFeH48bc(ks{A$MZpl_x&X9wd2jS%syC-sWwEN<6Y$>HJ1EYI{Y@JAvvan?%<;O#CtBp1XwHxux^&%{w~Zf+1;* W#>U6j8E*ouXYh3Ob6Mw<&;$T*phAQI literal 0 HcmV?d00001 diff --git a/src/hmi/wiedittree.ui b/src/hmi/wiedittree.ui new file mode 100644 index 000000000..ab01bdf7d --- /dev/null +++ b/src/hmi/wiedittree.ui @@ -0,0 +1,49 @@ + +wiEditTree + + + wiEditTree + + + + 0 + 0 + 328 + 346 + + + + YACS Tree + + + + unnamed + + + + + Column 1 + + + true + + + true + + + + + New Item + + + + + + + lv + + + + + + diff --git a/src/hmi/winodeedition.ui b/src/hmi/winodeedition.ui new file mode 100644 index 000000000..0bdfd4f68 --- /dev/null +++ b/src/hmi/winodeedition.ui @@ -0,0 +1,161 @@ + +wiNodeEdition + + + wiNodeEdition + + + + 0 + 0 + 270 + 255 + + + + + 0 + 0 + + + + Node Edition + + + + unnamed + + + + spacer2 + + + Vertical + + + Expanding + + + + 21 + 81 + + + + + + layout1 + + + + unnamed + + + + btApply + + + apply + + + + + spacer1 + + + Horizontal + + + Expanding + + + + 20 + 20 + + + + + + btCancel + + + cancel edition + + + + + + + layout5 + + + + unnamed + + + + laNodeType + + + node type: + + + + + liNodeType + + + LineEditPanel + + + Sunken + + + node + + + + + laNodeName + + + node name: + + + + + liNodeName + + + + + + + + + btApply + clicked() + wiNodeEdition + onApply() + + + btCancel + clicked() + wiNodeEdition + onCancel() + + + liNodeName + textChanged(const QString&) + wiNodeEdition + onModify(const QString&) + + + + onApply() + onCancel() + onModify(const QString &text) + + + diff --git a/src/lineconn2d/Makefile.am b/src/lineconn2d/Makefile.am index 2957dae9a..85d9c9cd6 100644 --- a/src/lineconn2d/Makefile.am +++ b/src/lineconn2d/Makefile.am @@ -30,7 +30,9 @@ LIBHEADERS = \ LineConn2d_Port.h \ LineConn2d_Segment.h \ LineConn2d_SegmentIterator.h \ - LineConn2d_ZInterval.h + LineConn2d_ZInterval.h \ + LineConn2dAfx.h + # MOC-generated files MOCSOURCES = @@ -41,8 +43,8 @@ LIBPOFILES = LIBICONS = # Add "resources" subdirectory to resource file names -POFILES = $(LIBPOFILES) -ICONS = $(LIBICONS) +POFILES += $(LIBPOFILES) +ICONS += $(LIBICONS) libLineConn2d_la_SOURCES = $(LIBSOURCES) $(LIBHEADERS) nodist_libLineConn2d_la_SOURCES = $(MOCSOURCES) diff --git a/src/prs/Makefile.am b/src/prs/Makefile.am index f9d629079..61613fd1f 100644 --- a/src/prs/Makefile.am +++ b/src/prs/Makefile.am @@ -6,6 +6,7 @@ lib_LTLIBRARIES = libYACSPrs.la # Implementation files LIBSOURCES = \ YACSPrs_ElementaryNode.cxx \ + YACSPrs_toString.cxx \ YACSPrs_ServiceNode.cxx \ YACSPrs_InlineNode.cxx \ YACSPrs_IfNode.cxx \ @@ -17,7 +18,9 @@ LIBSOURCES = \ # Headers LIBHEADERS = \ + YACSPrs_Def.h \ YACSPrs_ElementaryNode.h \ + YACSPrs_toString.h \ YACSPrs_ServiceNode.h \ YACSPrs_InlineNode.h \ YACSPrs_IfNode.h \ @@ -38,6 +41,8 @@ LIBPOFILES = \ LIBICONS = \ no_status.png \ + ledgreen.png \ + ledred.png \ disabled.png \ running.png \ waiting.png \ @@ -49,8 +54,8 @@ LIBICONS = \ left_arrows.png # Add "resources" subdirectory to resource file names -POFILES = $(LIBPOFILES:%=resources/%) -ICONS = $(LIBICONS:%=resources/%) +POFILES += $(LIBPOFILES:%=resources/%) +ICONS += $(LIBICONS:%=resources/%) libYACSPrs_la_SOURCES = $(LIBSOURCES) $(LIBHEADERS) nodist_libYACSPrs_la_SOURCES = $(MOCSOURCES) @@ -58,18 +63,25 @@ nodist_libYACSPrs_la_SOURCES = $(MOCSOURCES) # List all generated files here BUILT_SOURCES = $(MOCSOURCES) +libYACSPrs_la_LDFLAGS = \ + @GUI_LDFLAGS@ @PYTHON_LDFLAGS@ @QT_MT_LDFLAGS@ + libYACSPrs_la_LIBADD = \ - ../engine/libYACSEngine.la \ + ../engine/libYACSlibEngine.la \ ../runtime/libYACSRuntimeSALOME.la \ - @QT_MT_LIBS@ @GUI_LDFLAGS@ -lQxGraph @PYTHON_LDFLAGS@ + ../hmi/libHMI.la \ + @QT_MT_LIBADD@ -lQxGraph $(LIBXML_LIBS) libYACSPrs_la_CXXFLAGS = \ $(THREAD_DEF) \ $(PYTHON_CPPFLAGS) \ + $(OMNIORB_INCLUDES) \ + $(LIBXML_INCLUDES) \ -I$(KERNEL_ROOT_DIR)/include/salome \ -I$(srcdir)/../bases \ -I$(srcdir)/../engine \ -I$(srcdir)/../runtime \ + -I$(srcdir)/../hmi \ @QT_INCLUDES@ @GUI_CXXFLAGS@ include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/prs/YACSPrs_BlocNode.cxx b/src/prs/YACSPrs_BlocNode.cxx index 3cfe7a38a..5a047c5cf 100644 --- a/src/prs/YACSPrs_BlocNode.cxx +++ b/src/prs/YACSPrs_BlocNode.cxx @@ -26,9 +26,16 @@ #include "SUIT_ResourceMgr.h" +#include +#include + #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; +using namespace YACS::HMI; void drawText4(QPainter& thePainter, const QString& theText, const QRect& theRect, int theHAlign = Qt::AlignAuto) @@ -66,16 +73,17 @@ void drawText4(QPainter& thePainter, const QString& theText, * =========================== YACSPrs_BlocNode =========================== !*/ -YACSPrs_BlocNode::YACSPrs_BlocNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode, +YACSPrs_BlocNode::YACSPrs_BlocNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, + YACS::HMI::SubjectNode* theSNode, DisplayMode theDisplayMode, int theZ, int theLeft, int theTop, int theWidth, int theHeight): - YACSPrs_ElementaryNode(theMgr, theCanvas, theNode), + YACSPrs_ElementaryNode(theMgr, theCanvas, theSNode), myDisplayMode(theDisplayMode) { - printf("YACSPrs_BlocNode::YACSPrs_BlocNode\n"); - setX(theLeft); - setY(theTop); - + DEBTRACE("YACSPrs_BlocNode::YACSPrs_BlocNode"); + //setX(theLeft); + //setY(theTop); + setNodeColor(BLOCNODE_COLOR); setNodeSubColor(BLOCNODE_SUBCOLOR); @@ -87,12 +95,13 @@ YACSPrs_BlocNode::YACSPrs_BlocNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, myWidth = theWidth; myHeight = theHeight; + myArea = QRect(100, 100, theWidth, theHeight); if ( myDisplayMode == Expanded ) { if ( myPointMaster ) myWidth = myPointMaster->width() > theWidth ? myPointMaster->width() : theWidth; else myWidth = theWidth; - + int anEmptyHeight = getTitleHeight() + getGateHeight() + 2*BLOCNODE_MARGIN; myHeight = ( (anEmptyHeight > theHeight) ? anEmptyHeight : theHeight); @@ -102,8 +111,9 @@ YACSPrs_BlocNode::YACSPrs_BlocNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, myBoundColor = BLOCNODERECT_COLOR; setZ(theZ); - + updateGates(); + } else { @@ -114,6 +124,8 @@ YACSPrs_BlocNode::YACSPrs_BlocNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, // not yet implemented } + + moveBy(2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN,2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN); } YACSPrs_BlocNode::~YACSPrs_BlocNode() @@ -123,35 +135,111 @@ YACSPrs_BlocNode::~YACSPrs_BlocNode() myChildren.clear(); } +void YACSPrs_BlocNode::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSPrs_BlocNode::update"); + switch (event) + { + case YACS::HMI::RENAME: + if ( canvas() ) + { + canvas()->setChanged(getTitleRect()); + canvas()->update(); + } + break; + /* + case YACS::HMI::EDIT: + { + int anOldHeight = maxHeight(); + updateHeight(); + + bool needToCanvasUpdate = true; + if ( anOldHeight != maxHeight() ) + { + //emit portsChanged(); + + YACS::HMI::SubjectBloc* aParentSubj = dynamic_cast( getSEngine()->getParent() ); + if ( aParentSubj && !dynamic_cast( aParentSubj ) ) + { + aParentSubj->update( event, YACS::HMI::BLOC, getSEngine() ); + needToCanvasUpdate = false; + } + } + + if ( needToCanvasUpdate && canvas() ) + { + QRect aRect((int)x(),(int)y(),maxWidth(),maxHeight()); + canvas()->setChanged(aRect); + canvas()->update(); + } + } + break; + */ + case ADDLINK: + case ADDCONTROLLINK: + { + DEBTRACE(">> In prs : ADDLINK"); + // add link is treated in YACSGui_Graph + } + break; + case REMOVE: + switch (type) + { + case CONTROLLINK: + { + DEBTRACE(">> In prs: REMOVE link"); + removeLinkPrs(son); + } + break; + } + break; + default: + GuiObserver::update(event, type, son); + } +} + void YACSPrs_BlocNode::setChildren(std::set& theChildren) { if ( myDisplayMode == Expanded ) { - myChildren = theChildren; + std::set aNodesToStayOnItsPlaces; + for ( std::set::iterator it = theChildren.begin(); it != theChildren.end(); it++ ) + if ( myChildren.find(*it) != myChildren.end() ) aNodesToStayOnItsPlaces.insert(*it); + + //myChildren = theChildren; + if ( !myChildren.empty() ) myChildren.clear(); + for ( std::set::iterator it = theChildren.begin(); it != theChildren.end(); it++ ) + myChildren.insert(*it); + // resize bounding rectangle if needed int aMaxWidth=0, aMaxHeight=0; int aX = (int)x(); int aY = (int)y() + getTitleHeight(); - bool hasBlocChild = false; for ( std::set::iterator it = myChildren.begin(); it != myChildren.end(); it++ ) { if ( aMaxWidth < (*it)->maxWidth() ) aMaxWidth = (*it)->maxWidth(); if ( aMaxHeight < (*it)->maxHeight() ) aMaxHeight = (*it)->maxHeight(); - YACSPrs_LoopNode* aLoop = dynamic_cast( *it ); - if ( aLoop ) - (*it)->moveBy( aX - (*it)->boundingRect().x() + (( 2*HOOKPOINT_SIZE > 3*TITLE_HEIGHT/2 ) ? ( 2*HOOKPOINT_SIZE - 3*TITLE_HEIGHT/2 ) : 0) + BLOCNODE_MARGIN, - aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN ); - else + + if ( aNodesToStayOnItsPlaces.find(*it) == aNodesToStayOnItsPlaces.end() ) { - YACSPrs_BlocNode* aBloc = dynamic_cast( *it ); - if ( aBloc ) { - (*it)->moveBy( aX - (*it)->boundingRect().x() + HOOKPOINTGATE_SIZE + BLOCNODE_MARGIN, aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN ); - hasBlocChild = true; - } - else - (*it)->moveBy( aX - (*it)->boundingRect().x() + 2*HOOKPOINT_SIZE + BLOCNODE_MARGIN, + YACSPrs_LoopNode* aLoop = dynamic_cast( *it ); + if ( aLoop ) + (*it)->moveBy( aX - (*it)->boundingRect().x() + + (( 2*HOOKPOINT_SIZE > 3*TITLE_HEIGHT/2 ) ? ( 2*HOOKPOINT_SIZE - 3*TITLE_HEIGHT/2 ) : 0) + + BLOCNODE_MARGIN, aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN ); + else + { + YACSPrs_BlocNode* aBloc = dynamic_cast( *it ); + if ( aBloc ) + (*it)->moveBy( aX - (*it)->boundingRect().x() + HOOKPOINTGATE_SIZE + BLOCNODE_MARGIN, + aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN ); + else + (*it)->moveBy( aX - (*it)->boundingRect().x() + 2*HOOKPOINT_SIZE + BLOCNODE_MARGIN, + aY - (*it)->boundingRect().y() + BLOCNODE_MARGIN ); + } } + (*it)->setIsInBloc(true); } if ( aMaxWidth > myWidth ) myWidth = aMaxWidth + 2*BLOCNODE_MARGIN; @@ -160,8 +248,8 @@ void YACSPrs_BlocNode::setChildren(std::set& theChildre setZ(z()); updateGates(); - printf("Parent : %s. Number of children : %d\n",myEngine->getName().c_str(),myChildren.size()); - } + DEBTRACE("Parent : " << getEngine()->getName() << ". Number of children : " << myChildren.size()); + } } void YACSPrs_BlocNode::setCanvas(QCanvas* theCanvas) @@ -287,7 +375,7 @@ void YACSPrs_BlocNode::resize(QPoint thePoint) } break; case 2: // top edge - if ( yP < minYContent() ) { + if ( yP < minYContent() - getTitleHeight() ) { myHeight += (int)y() - yP; setY(yP); } @@ -297,7 +385,7 @@ void YACSPrs_BlocNode::resize(QPoint thePoint) myWidth += xP - (int)x() - myWidth; break; case 4: // bottom edge - if ( yP > maxYContent() && checkArea(0,0,aBottomP) ) + if ( yP > maxYContent() + getGateHeight() && checkArea(0,0,aBottomP) ) myHeight += yP - (int)y() - myHeight; break; case 5: // left and top edges @@ -307,7 +395,7 @@ void YACSPrs_BlocNode::resize(QPoint thePoint) myWidth += (int)x() - xP; setX(xP); } - if ( yP < minYContent() ) { + if ( yP < minYContent() - getTitleHeight() ) { myHeight += (int)y() - yP; setY(yP); } @@ -318,7 +406,7 @@ void YACSPrs_BlocNode::resize(QPoint thePoint) { if ( xP > maxXContent() ) myWidth += xP - (int)x() - myWidth; - if ( yP < minYContent() ) { + if ( yP < minYContent() - getTitleHeight() ) { myHeight += (int)y() - yP; setY(yP); } @@ -329,7 +417,7 @@ void YACSPrs_BlocNode::resize(QPoint thePoint) { if ( xP > maxXContent() ) myWidth += xP - (int)x() - myWidth; - if ( yP > maxYContent() ) + if ( yP > maxYContent() + getGateHeight() ) myHeight += yP - (int)y() - myHeight; } break; @@ -340,7 +428,7 @@ void YACSPrs_BlocNode::resize(QPoint thePoint) myWidth += (int)x() - xP; setX(xP); } - if ( yP > maxYContent() ) + if ( yP > maxYContent() + getGateHeight() ) myHeight += yP - (int)y() - myHeight; } break; @@ -348,7 +436,7 @@ void YACSPrs_BlocNode::resize(QPoint thePoint) break; } QPoint aPnt = getConnectionMasterPoint(); - myPointMaster->setCoords(aPnt.x(), aPnt.y()); + if ( myPointMaster ) myPointMaster->setCoords(aPnt.x(), aPnt.y()); updateGates(); @@ -384,6 +472,7 @@ int YACSPrs_BlocNode::rtti() const void YACSPrs_BlocNode::setVisible(bool b) { + DEBTRACE("YACSPrs_BlocNode::setVisible " << b); QCanvasPolygonalItem::setVisible(b); if ( myDisplayMode == Expanded ) @@ -405,7 +494,7 @@ void YACSPrs_BlocNode::setVisible(bool b) } // set visibility to master point - myPointMaster->setVisible(b); + if ( myPointMaster ) myPointMaster->setVisible(b); updateLabelLink(); } @@ -484,8 +573,8 @@ void YACSPrs_BlocNode::moveBy(double dx, double dy) aPort->moveBy(xx, yy); } - myPointMaster->moveBy(dx, dy); - if ( myLabelLink ) myLabelLink->moveByNode(this, (int)dx, (int)dy); + if ( myPointMaster ) myPointMaster->moveBy(dx, dy); + if ( myLabelLink ) myLabelLink->moveByNode(this); if ( isSelected() && canvas() && isMoving() ) { @@ -500,6 +589,7 @@ void YACSPrs_BlocNode::moveBy(double dx, double dy) void YACSPrs_BlocNode::setZ(double z) { + DEBTRACE("YACSPrs_BlocNode::setZ: " << z); QCanvasItem::setZ(z); if ( myDisplayMode == Expanded ) @@ -520,6 +610,23 @@ void YACSPrs_BlocNode::setZ(double z) if ( myPointMaster ) myPointMaster->setZ(z); } +void YACSPrs_BlocNode::setX(int x) +{ + QCanvasPolygonalItem::setX(x); + myArea = boundingRect(); +} + +void YACSPrs_BlocNode::setY(int y) +{ + QCanvasPolygonalItem::setY(y); + myArea = boundingRect(); +} + +void YACSPrs_BlocNode::update() +{ + YACSPrs_ElementaryNode::update(); +} + void YACSPrs_BlocNode::updateGates() { bool aDisp = isVisible(); @@ -538,14 +645,14 @@ void YACSPrs_BlocNode::updateGates() if ( myPortList.isEmpty() ) { // create (and update) // input Gate - YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr,canvas(),myEngine->getInGate(),this); + YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr,canvas(),getEngine()->getInGate(),this); anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); anInPort->setColor(nodeSubColor()); anInPort->setStoreColor(nodeSubColor()); myPortList.append(anInPort); // output Gate - YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),myEngine->getOutGate(),this); + YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),getEngine()->getOutGate(),this); anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT)); anOutPort->setColor(nodeSubColor()); anOutPort->setStoreColor(nodeSubColor()); @@ -598,7 +705,7 @@ void YACSPrs_BlocNode::resize(int theWidth, int theHeight) myHeight = theHeight; QPoint aPnt = getConnectionMasterPoint(); - myPointMaster->setCoords(aPnt.x(), aPnt.y()); + if ( myPointMaster ) myPointMaster->setCoords(aPnt.x(), aPnt.y()); updateGates(); @@ -618,15 +725,27 @@ void YACSPrs_BlocNode::resize(int theWidth, int theHeight) } } +void YACSPrs_BlocNode::updateHeight() +{ + if ( myDisplayMode == Expanded ) + { + int aMinY = minYContent(); + int aMaxY = maxYContent(); + myHeight = aMaxY - aMinY + getTitleHeight() + getGateHeight() + (myPointMaster ? myPointMaster->height()/2 : 0 ); + + resize( myWidth, myHeight ); + } +} + int YACSPrs_BlocNode::minXContent() { if ( myDisplayMode == Expanded ) { - int aMinX = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().left()) : boundingRect().left() + 2*BLOCNODE_MARGIN; + int aMinX = (!myChildren.empty()) ? (*myChildren.begin())->minX() : boundingRect().left() + 2*BLOCNODE_MARGIN; for ( std::set::iterator it = myChildren.begin(); it != myChildren.end(); it++ ) - if ( aMinX > (*it)->boundingRect().left() ) aMinX = (int)( (*it)->boundingRect().left() ); + if ( aMinX > (*it)->minX() ) aMinX = (*it)->minX(); - aMinX -= 2*HOOKPOINT_SIZE + BLOCNODE_MARGIN; + aMinX -= BLOCNODE_MARGIN; return aMinX; } return 0; @@ -636,11 +755,11 @@ int YACSPrs_BlocNode::maxXContent() { if ( myDisplayMode == Expanded ) { - int aMaxX = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().right()) : boundingRect().right() - 2*BLOCNODE_MARGIN; + int aMaxX = (!myChildren.empty()) ? (*myChildren.begin())->maxX() : boundingRect().right() - 2*BLOCNODE_MARGIN; for ( std::set::iterator it = myChildren.begin(); it != myChildren.end(); it++ ) - if ( aMaxX < (*it)->boundingRect().right() ) aMaxX = (int)( (*it)->boundingRect().right() ); + if ( aMaxX < (*it)->maxX() ) aMaxX = (*it)->maxX(); - aMaxX += 2*HOOKPOINT_SIZE + BLOCNODE_MARGIN; + aMaxX += BLOCNODE_MARGIN; return aMaxX; } return 0; @@ -650,11 +769,11 @@ int YACSPrs_BlocNode::minYContent() { if ( myDisplayMode == Expanded ) { - int aMinY = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().top()) : (int)x(); + int aMinY = (!myChildren.empty()) ? (*myChildren.begin())->minY() : boundingRect().top(); for ( std::set::iterator it = myChildren.begin(); it != myChildren.end(); it++ ) - if ( aMinY > (*it)->boundingRect().top() ) aMinY = (int)( (*it)->boundingRect().top() ); - - aMinY -= getTitleHeight() + BLOCNODE_MARGIN; + if ( aMinY > (*it)->minY() ) aMinY = (*it)->minY(); + + aMinY -= BLOCNODE_MARGIN; return aMinY; } return 0; @@ -664,11 +783,11 @@ int YACSPrs_BlocNode::maxYContent() { if ( myDisplayMode == Expanded ) { - int aMaxY = (!myChildren.empty()) ? (int)((*myChildren.begin())->boundingRect().bottom()) : (int)x(); + int aMaxY = (!myChildren.empty()) ? (*myChildren.begin())->maxY() : boundingRect().bottom(); for ( std::set::iterator it = myChildren.begin(); it != myChildren.end(); it++ ) - if ( aMaxY < (*it)->boundingRect().bottom() ) aMaxY = (int)( (*it)->boundingRect().bottom() ); + if ( aMaxY < (*it)->maxY() ) aMaxY = (*it)->maxY(); - aMaxY += getGateHeight() + (myPointMaster ? myPointMaster->height()/2 : 0 ) + BLOCNODE_MARGIN; + aMaxY += BLOCNODE_MARGIN; return aMaxY; } return 0; @@ -753,6 +872,21 @@ int YACSPrs_BlocNode::maxHeight() const } } +int YACSPrs_BlocNode::minX() const +{ + return boundingRect().left() - HOOKPOINTGATE_SIZE; +} + +int YACSPrs_BlocNode::maxX() const +{ + return boundingRect().right() + HOOKPOINTGATE_SIZE; +} + +QRect YACSPrs_BlocNode::getRect() const +{ + return QRect((int)x(), (int)y(), width(), height()); +} + QRect YACSPrs_BlocNode::getTitleRect() const { if ( myDisplayMode == Expanded ) @@ -811,6 +945,12 @@ void YACSPrs_BlocNode::drawShape(QPainter& thePainter) drawFrame(thePainter); drawTitle(thePainter); drawGate(thePainter); + + if ( isControlDMode() && myPointMaster) + { + myPointMaster->setVisible(false); + myPointMaster->setCanvas(0); + } } else { @@ -834,7 +974,7 @@ void YACSPrs_BlocNode::drawTitle(QPainter& thePainter) thePainter.drawRoundRect(aRoundRect,myXRnd,myYRnd); thePainter.setPen(Qt::white); - drawText4(thePainter, QString(myEngine->getName()), aRoundRect, Qt::AlignHCenter); + drawText4(thePainter, QString(getEngine()->getName()), aRoundRect, Qt::AlignHCenter); thePainter.setBrush(savedB); thePainter.setPen(savedP); diff --git a/src/prs/YACSPrs_BlocNode.h b/src/prs/YACSPrs_BlocNode.h index bd9f425f3..7f62681a2 100644 --- a/src/prs/YACSPrs_BlocNode.h +++ b/src/prs/YACSPrs_BlocNode.h @@ -31,13 +31,15 @@ class YACSPrs_BlocNode : public YACSPrs_ElementaryNode { public: typedef enum { Collapsed, Expanded } DisplayMode; - YACSPrs_BlocNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node*, + YACSPrs_BlocNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode*, DisplayMode theDisplayMode=Expanded, int theZ=0, int theLeft=0, int theTop=0, int theWidth=0, int theHeight=0); virtual ~YACSPrs_BlocNode(); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + DisplayMode getDisplayMode() const { return myDisplayMode; } void setChildren(std::set& theChildren); @@ -63,12 +65,16 @@ class YACSPrs_BlocNode : public YACSPrs_ElementaryNode { virtual QPointArray constructAreaPoints(int theW, int theH) const; void moveBy(double dx, double dy); void setZ(double z); + void setX(int x); + void setY(int y); + virtual void update(); virtual void updateGates(); virtual int width() const; virtual int height() const; void resize(int theWidth, int theHeight); + void updateHeight(); int minXContent(); int maxXContent(); @@ -81,7 +87,11 @@ class YACSPrs_BlocNode : public YACSPrs_ElementaryNode { virtual int maxWidth() const; virtual int maxHeight() const; + + virtual int minX() const; + virtual int maxX() const; + virtual QRect getRect() const; virtual QRect getTitleRect() const; virtual QRect getGateRect() const; diff --git a/src/prs/YACSPrs_Def.h b/src/prs/YACSPrs_Def.h index a34990404..5a042ffc3 100644 --- a/src/prs/YACSPrs_Def.h +++ b/src/prs/YACSPrs_Def.h @@ -70,8 +70,9 @@ #define LINKPOINT_SIZE 5 #define LINKEDGE_WIDTH 2 #define LINKDRAW_COLOR QColor(0,0,127) +#define STREAMLINKDRAW_COLOR QColor(222,0,0) #define LINK_HILIGHT_COLOR QColor(222,222,222) -#define LINK_SELECT_COLOR QColor(0,0,0) +#define LINK_SELECT_COLOR Qt::magenta #define LABELLINKDRAW_COLOR QColor(170,0,0) diff --git a/src/prs/YACSPrs_ElementaryNode.cxx b/src/prs/YACSPrs_ElementaryNode.cxx index 96ea85bdf..c04118cba 100644 --- a/src/prs/YACSPrs_ElementaryNode.cxx +++ b/src/prs/YACSPrs_ElementaryNode.cxx @@ -21,10 +21,17 @@ #include "YACSPrs_ElementaryNode.h" +#include "YACSPrs_toString.h" #include "YACSPrs_Link.h" #include "YACSPrs_Def.h" +#include + +#include +#include + #include "SUIT_ResourceMgr.h" +#include "SUIT_Session.h" #include //#include // for states animation @@ -40,10 +47,16 @@ #include // for SeqAnyInputPort #include #include +#include #include #include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" using namespace YACS::ENGINE; +using namespace YACS::HMI; using namespace std; #include @@ -81,240 +94,47 @@ void drawText(QPainter& thePainter, const QString& theText, } } -char * toString(CORBA::Any* theAny, QString& theRetStr) -{ - if ( !theAny ) theRetStr += QString("< ? >"); - else - { - CORBA::Any anAny = *theAny; - if ( !anAny.value() ) theRetStr += QString("< ? >"); - else - { - ostringstream astr; - const char * retstr; - int startstr = 0; - switch ( anAny.type()->kind() ) - { - case CORBA::tk_string: { - anAny >>= retstr; - theRetStr += QString(retstr); - break; - } - case CORBA::tk_long: { - CORBA::Long l; - anAny >>= l; - astr << l << ends; - theRetStr += QString(astr.str()); - break; - } - case CORBA::tk_double: { - double d; - anAny >>= d; - astr << d << ends; - //astr << setw(25) << setprecision(18) << d << ends; - QString aRetStr = QString(astr.str()); - int i = 0; - while ( i < (int ) theRetStr.length() && theRetStr.at(i++) == ' ' ) { - startstr = i; - } - theRetStr += aRetStr.mid(startstr,aRetStr.length()); - break; - } - case CORBA::tk_sequence: { - theRetStr += QString("["); - - CORBA::Long aSeqLength = 0; - *(anAny.type()->parameter(1)) >>= aSeqLength; - - if ( aSeqLength == 0 ) - { - theRetStr += QString(" ]"); - break; - } - - // TO DO : implement recursion for the sequence type - /*CORBA::TypeCode* aType; - *(anAny.type()->parameter(0)) >>= aType; - switch ( aType->kind() ) - { - case CORBA::tk_string: { - printf("StringElem\n"); - CORBA::StringSeq* aStringSeq; - anAny >>= aStringSeq; - for (int i=0; i < aSeqLength; i++) - { - CORBA::Any anArg; - anArg <<= aStringSeq[i]; - toString( &anArg, theRetStr ); - if ( i < aSeqLength-1 ) theRetStr += QString(","); - } - break; - } - case CORBA::tk_double: { - printf("DoubleElem\n"); - CORBA::DoubleSeq* aDoubleSeq; - anAny >>= aDoubleSeq; - for (int i=0; i < aSeqLength; i++) - { - CORBA::Any anArg; - anArg <<= aDoubleSeq[i]; - toString( &anArg, theRetStr ); - if ( i < aSeqLength-1 ) theRetStr += QString(","); - } - break; - } - case CORBA::tk_sequence: { - printf("SequenceElem\n"); - CORBA::Any* aSequenceSeq; - anAny >>= aSequenceSeq; - for (int i=0; i < aSeqLength; i++) - { - CORBA::Any anArg; - anArg <<= aSequenceSeq[i]; - toString( &anArg, theRetStr ); - if ( i < aSeqLength-1 ) theRetStr += QString(","); - } - break; - } - default: { - printf("DefaultElem\n"); - theRetStr += QString("< ? >"); - break; - } - }*/ - theRetStr += QString("]"); - break; - } - case CORBA::tk_objref: { - /*CORBA::Object_ptr obj; - try { - anAny >>= (CORBA::Any::to_object ) obj; - theRetStr += QString( _Orb->object_to_string( obj ) ); - } - catch ( ... ) { - theRetStr += QString("object_to_string catched "); - }*/ - theRetStr += QString("Objref"); - break; - } - default: { - theRetStr += QString("< ? >"); - break; - } - } - } - } -} - -void toString(PyObject* theObject, QString& theRetStr) -{ - if ( !theObject ) theRetStr += QString("< ? >"); - - ostringstream aStr; - if ( PyString_CheckExact(theObject) ) - theRetStr += QString( PyString_AsString(theObject) ); - else if ( PyLong_CheckExact(theObject) ) - { - long aVal = PyLong_AsLong(theObject); - aStr << aVal << ends; - theRetStr += QString( aStr.str() ); - } - else if ( PyInt_CheckExact(theObject) ) - { - long aVal = PyInt_AsLong(theObject); - aStr << aVal << ends; - theRetStr += QString( aStr.str() ); - } - else if ( PyBool_Check(theObject) ) - theRetStr += QString( (theObject == Py_True) ? "true" : "false" ); - else if ( PyFloat_CheckExact(theObject) ) - { - double aVal = PyFloat_AsDouble(theObject); - aStr << aVal << ends; - theRetStr += QString( aStr.str() ); - } - else if ( PyList_CheckExact(theObject) ) - { - theRetStr += QString("["); - for (int i=0; i < PyList_Size(theObject); i++) - { - toString( PyList_GetItem(theObject, i), theRetStr ); - if ( i < PyList_Size(theObject)-1 ) theRetStr += QString(","); - } - theRetStr += QString("]"); - } - //else if ( ... ) // objref case - else - theRetStr += QString("< ? >"); -} - -void toString(Any* theAny, QString& theValue) -{ - if ( !theAny ) theValue += QString("< ? >"); - else if ( theAny->getType() ) - { - DynType aKind = theAny->getType()->kind(); - switch (aKind) - { - case Double: - theValue += QString::number(theAny->getDoubleValue()); - break; - case Int: - theValue += QString::number(theAny->getIntValue()); - break; - case String: - theValue += QString(theAny->getStringValue()); - break; - case Bool: - theValue += QString(theAny->getBoolValue()?"true":"false"); - break; - case Objref: - theValue += QString("Objref"); /// ? - break; - case Sequence: { - SequenceAny* aSeqAny = dynamic_cast( theAny ); - if ( aSeqAny ) - { - theValue += QString("["); - for (int i=0; i < aSeqAny->size(); i++) - { - toString( (*aSeqAny)[i], theValue ); - if ( i < aSeqAny->size()-1 ) theValue += QString(","); - } - theValue += QString("]"); - } - break; - } - case None: - default: - theValue += QString(""); - break; - } - } -} - /*! * =========================== YACSPrs_ElementaryNode =========================== !*/ -YACSPrs_ElementaryNode::YACSPrs_ElementaryNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode): +YACSPrs_ElementaryNode::YACSPrs_ElementaryNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::HMI::SubjectNode* theSNode): QxGraph_ActiveItem(), QCanvasPolygonalItem(theCanvas), + GuiObserver(), myMgr(theMgr), - myEngine(theNode), + mySEngine(theSNode), myLabelLink(0), myHilightedPort(0), mySelectedPort(0) { - printf("YACSPrs_ElementaryNode::YACSPrs_ElementaryNode\n"); - myWidth = NODE_WIDTH; - if (2*(PORT_WIDTH+PORT_MARGIN) > myWidth) - myWidth = 2*(PORT_WIDTH+PORT_MARGIN); + DEBTRACE("YACSPrs_ElementaryNode::YACSPrs_ElementaryNode : " << mySEngine->getName()); + if ( mySEngine ) mySEngine->attach(this); + + QxGraph_Canvas* aCanvas = dynamic_cast(canvas()); + if ( aCanvas && aCanvas->getPrs() ) + myViewMode = aCanvas->getPrs()->getDMode(); + else + myViewMode = 0; + + if ( isFullDMode() ) + { + myWidth = NODE_WIDTH; + if (2*(PORT_WIDTH+PORT_MARGIN) > myWidth) + myWidth = 2*(PORT_WIDTH+PORT_MARGIN); + } + else if ( isControlDMode() ) + myWidth = NODE_WIDTH/2-2; + else + myWidth = 0; myTitleHeight = TITLE_HEIGHT; myStatusHeight = TITLE_HEIGHT; myTimeHeight = TITLE_HEIGHT; - myPortHeight = 2*PORT_MARGIN; + if ( isFullDMode() ) + myPortHeight = 2*PORT_MARGIN; + else + myPortHeight = 0; myGateHeight = PORT_HEIGHT + 2*PORT_MARGIN; myStoreColor = myColor = myMgr->colorValue("QxGraph", "NodeBody", NODE_COLOR); @@ -348,7 +168,10 @@ YACSPrs_ElementaryNode::YACSPrs_ElementaryNode(SUIT_ResourceMgr* theMgr, QCanvas mySprite->setZ(1); mySprite->show();*/ - myPointMaster = new YACSPrs_Hook(myMgr, canvas(), this, false, false, true); + if ( isFullDMode() ) + myPointMaster = new YACSPrs_Hook(myMgr, canvas(), this, false, false, true); + else + myPointMaster = 0; setZ(2); //updatePorts(); // create presentations for all ports of node, @@ -360,10 +183,217 @@ YACSPrs_ElementaryNode::YACSPrs_ElementaryNode(SUIT_ResourceMgr* theMgr, QCanvas YACSPrs_ElementaryNode::~YACSPrs_ElementaryNode() { - myPortList.setAutoDelete(true); + setCanvas(0); + + myPortList.setAutoDelete(false); + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if ( aPort ) + { + if ( YACSPrs_InOutPort* anIOP = dynamic_cast(aPort) ) + delete anIOP; + else if ( YACSPrs_LabelPort* aLP = dynamic_cast(aPort) ) + delete aLP; + } + } myPortList.clear(); - if (myPointMaster) delete myPointMaster; + if (myPointMaster) + { + myPointMaster = 0; + delete myPointMaster; + } + + mySEngine->detach(this); +} + +void YACSPrs_ElementaryNode::select( bool isSelected ) +{ + DEBTRACE(">> YACSPrs_ElementaryNode::select " << isSelected << " " << mySEngine->getName()); + setSelected(isSelected); + + // Unselect gates. They cannot be selected/unselected in tree view + // so unselect them here + if ( !isSelected ) + { + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); + if ( anIOPort && anIOPort->isGate() ) + anIOPort->setSelected( false ); + } + } +} + +void YACSPrs_ElementaryNode::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSPrs_ElementaryNode::update"); + switch (event) + { + case RENAME: + if ( canvas() ) + { + canvas()->setChanged(getTitleRect()); + canvas()->update(); + } + break; + case EDIT: + if ( isFullDMode() ) + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + if ( canvas() ) + if ( SubjectDataPort* aDP = dynamic_cast(son) ) + if ( YACSPrs_InOutPort* aPPrs = getPortPrs(aDP->getPort()) ) + { + DEBTRACE(">> In prs : EDIT"); + aPPrs->update(); + canvas()->update(); + } + } + break; + default: + { + int anOldHeight = maxHeight(); + updatePorts(true); + + bool needToCanvasUpdate = true; + if ( anOldHeight != maxHeight() ) + { + //emit portsChanged(); + + SubjectBloc* aParentSubj = dynamic_cast( mySEngine->getParent() ); + if ( aParentSubj && !dynamic_cast( aParentSubj ) ) + { + aParentSubj->update( event, BLOC, mySEngine ); + needToCanvasUpdate = false; + } + } + + if ( needToCanvasUpdate && canvas() ) + { + QRect aRect((int)x(),(int)y(),maxWidth(),maxHeight()); + canvas()->setChanged(aRect); + canvas()->update(); + } + } + break; + } + break; + case ADD: + if ( isFullDMode() ) + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + if ( SubjectDataPort* aDP = dynamic_cast(son) ) + { + DEBTRACE(">> In prs : ADD"); + addPortPrs(aDP->getPort()); + } + } + break; + default: + break; + } + break; + case REMOVE: + if ( isFullDMode() ) + switch (type) + { + case DATALINK: + case CONTROLLINK: + { + DEBTRACE(">> In prs: REMOVE link"); + removeLinkPrs(son); + } + break; + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + if ( SubjectDataPort* aDP = dynamic_cast(son) ) + { + DEBTRACE(">> In prs : REMOVE"); + removePortPrs(aDP->getPort()); + } + } + break; + default: + break; + } + break; + case UPDATE: + if ( isFullDMode() && canvas() ) + { + DEBTRACE(">> In prs : UPDATE"); + updatePorts(); + canvas()->update(); + } + break; + case UP: + if ( isFullDMode() ) + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + if ( SubjectDataPort* aDP = dynamic_cast(son) ) + { + DEBTRACE(">> In prs : UP"); + moveUp(aDP->getPort()); + } + } + break; + default: + break; + } + break; + case DOWN: + if ( isFullDMode() ) + switch (type) + { + case INPUTPORT: + case OUTPUTPORT: + case INPUTDATASTREAMPORT: + case OUTPUTDATASTREAMPORT: + { + if ( SubjectDataPort* aDP = dynamic_cast(son) ) + { + DEBTRACE(">> In prs : DOWN"); + moveDown(aDP->getPort()); + } + } + break; + default: + break; + } + break; + case ADDLINK: + case ADDCONTROLLINK: + { + DEBTRACE(">> In prs : ADDLINK"); + // add link is treated in YACSGui_Graph + } + break; + default: + GuiObserver::update(event, type, son); + } +} + +YACS::ENGINE::Node* YACSPrs_ElementaryNode::getEngine() const +{ + return ( mySEngine ? mySEngine->getNode() : 0 ); } YACSPrs_InOutPort* YACSPrs_ElementaryNode::getPortPrs(YACS::ENGINE::Port* thePort) @@ -378,8 +408,242 @@ YACSPrs_InOutPort* YACSPrs_ElementaryNode::getPortPrs(YACS::ENGINE::Port* thePor return aRetPort; } +void YACSPrs_ElementaryNode::sortPorts() +{ + DEBTRACE("YACSPrs_ElementaryNode::sortPorts"); + ElementaryNode* aNode = dynamic_cast(getEngine()); + if ( !aNode ) return; + + QPtrList aSortedPortList; + + list anInPortsEngine = aNode->getSetOfInPort(); + list::iterator itIn = anInPortsEngine.begin(); + for ( ; itIn != anInPortsEngine.end(); itIn++ ) + aSortedPortList.append( getPortPrs(*itIn) ); + + list anOutPortsEngine = aNode->getSetOfOutPort(); + list::iterator itOut = anOutPortsEngine.begin(); + for ( ; itOut != anOutPortsEngine.end(); itOut++ ) + aSortedPortList.append( getPortPrs(*itOut) ); + + aSortedPortList.append( getPortPrs(aNode->getInGate()) ); + aSortedPortList.append( getPortPrs(aNode->getOutGate()) ); + + myPortList = aSortedPortList; +} + +void YACSPrs_ElementaryNode::moveUp(YACS::ENGINE::Port* thePort) +{ + if ( !thePort ) return; + + YACSPrs_InOutPort* aPortToMoveUp = getPortPrs(thePort); + int anId = myPortList.find(aPortToMoveUp); + if ( anId > -1 ) + { + myPortList.take(anId); + anId--; + myPortList.insert(anId,aPortToMoveUp); + } +} + +void YACSPrs_ElementaryNode::moveDown(YACS::ENGINE::Port* thePort) +{ + if ( !thePort ) return; + + YACSPrs_InOutPort* aPortToMoveDown = getPortPrs(thePort); + int anId = myPortList.find(aPortToMoveDown); + if ( anId > -1 ) + { + myPortList.take(anId); + anId++; + myPortList.insert(anId,aPortToMoveDown); + } +} + +void YACSPrs_ElementaryNode::addPortPrs(YACS::ENGINE::Port* thePort) +{ + DEBTRACE("YACSPrs_ElementaryNode::addPortPrs"); + if ( !thePort ) return; + + if ( getPortPrs(thePort) ) return; + + ElementaryNode* aNode = dynamic_cast(getEngine()); + if ( !aNode ) return; + + int anIPNum = aNode->getNumberOfInputPorts(); + int anOPNum = aNode->getNumberOfOutputPorts(); + + bool isInput = true; + if ( dynamic_cast(thePort) ) + isInput = false; + + bool aDisp = isVisible(); + if (aDisp) hide(); + + QRect r = getBodyRect(); + int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; + if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; + + int ix = r.x() + PORT_MARGIN + 1; + int iy; + if ( anIPNum > 1 ) + iy = r.y() + PORT_MARGIN + (PORT_HEIGHT+PORT_SPACE)*(anIPNum-1); + else + iy = r.y() + PORT_MARGIN; + + int ox = ix + aPRectWidth + 2*PORT_MARGIN; + int oy; + if ( anOPNum > 1 ) + oy = r.y() + PORT_MARGIN + (PORT_HEIGHT+PORT_SPACE)*(anOPNum-1); + else + oy = r.y() + PORT_MARGIN; + + YACSPrs_InOutPort* aPortPrs = new YACSPrs_InOutPort(myMgr, canvas(), thePort, this); + aPortPrs->setPortRect(QRect( (isInput ? ix : ox), + (isInput ? iy : oy), + aPRectWidth, + PORT_HEIGHT )); // commented + aPortPrs->setColor(nodeSubColor()); + aPortPrs->setStoreColor(nodeSubColor()); + + YACSPrs_InOutPort* aPort; + DEBTRACE(aPortPrs->getName() << "," << aPortPrs->isGate() << "," << aPortPrs->isInput()); + for (aPort = (YACSPrs_InOutPort*)(myPortList.first()); + aPort; + aPort = (YACSPrs_InOutPort*)(myPortList.next())) + { + if ( aPortPrs->isInput() && !aPort->isInput() ) + { + myPortList.insert( myPortList.find(aPort), aPortPrs ); + break; + } + if ( !aPortPrs->isInput() && aPort->isGate() ) + { + myPortList.insert( myPortList.find(aPort), aPortPrs ); + break; + } + } + + if ( (isInput && anIPNum > anOPNum) || (!isInput && anIPNum < anOPNum) ) + myPortHeight += PORT_HEIGHT+PORT_SPACE; + + updateGates(false); + //updatePorts(); + + if (myPointMaster) + { + QPoint aPnt = getConnectionMasterPoint(); + myPointMaster->setCoords(aPnt.x(), aPnt.y()); + } + + if (aDisp) show(); + + if ( canvas() ) + { + canvas()->setChanged(getRect()); + canvas()->update(); + } +} + +void YACSPrs_ElementaryNode::removePortPrs(YACS::ENGINE::Port* thePort) +{ + DEBTRACE("YACSPrs_ElementaryNode::removePortPrs"); + if ( YACSPrs_InOutPort* aPort = getPortPrs(thePort) ) + { + ElementaryNode* aNode = dynamic_cast(getEngine()); + if ( !aNode ) return; + + int anIPNum = aNode->getNumberOfInputPorts(); + int anOPNum = aNode->getNumberOfOutputPorts(); + + bool aDisp = isVisible(); + if (aDisp) hide(); + + bool isInput = true; + if ( dynamic_cast(thePort) ) + isInput = false; + + if ( ElementaryNode* aNode = dynamic_cast(getEngine()) ) + if ( (isInput && anIPNum > anOPNum) || (!isInput && anIPNum < anOPNum) ) + myPortHeight -= PORT_HEIGHT+PORT_SPACE; + + myPortList.setAutoDelete(false); + myPortList.remove(aPort); + if ( mySelectedPort == aPort ) mySelectedPort = 0; + delete aPort; + + //updateGates(false); + updatePorts(); + + if (myPointMaster) + { + QPoint aPnt = getConnectionMasterPoint(); + myPointMaster->setCoords(aPnt.x(), aPnt.y()); + } + + if (aDisp) show(); + + if ( canvas() ) + { + canvas()->setChanged(getRect()); + canvas()->update(); + } + } +} + +void YACSPrs_ElementaryNode::removeLabelPortPrs(YACSPrs_LabelPort* thePort) +{ + DEBTRACE("YACSPrs_ElementaryNode::removeLabelPortPrs"); + if ( !thePort ) return; + + ComposedNode* aNode = dynamic_cast(getEngine()); + if ( !aNode ) return; + + bool aDisp = isVisible(); + if (aDisp) hide(); + + int anIPNum = aNode->getNumberOfInputPorts(); + int anOPNum = aNode->getNumberOfOutputPorts(); + if ( anOPNum > 1 && anIPNum < anOPNum ) + myPortHeight -= PORT_HEIGHT+PORT_SPACE; + + myPortList.setAutoDelete(false); + myPortList.remove(thePort); + if ( mySelectedPort == thePort ) mySelectedPort = 0; + delete thePort; + + updatePorts(); + + if (myPointMaster) + { + QPoint aPnt = getConnectionMasterPoint(); + myPointMaster->setCoords(aPnt.x(), aPnt.y()); + } + + if (aDisp) show(); + + if ( canvas() ) + { + canvas()->setChanged(getRect()); + canvas()->update(); + } +} + +void YACSPrs_ElementaryNode::erasePortPrs(YACSPrs_Port* thePort) +{ + DEBTRACE("YACSPrs_ElementaryNode::erasePortPrs"); + if ( !myPortList.isEmpty() ) + { + bool anADFlag = myPortList.autoDelete(); + myPortList.setAutoDelete(false); + if ( myPortList.contains(thePort) ) myPortList.remove(thePort); + myPortList.setAutoDelete(anADFlag); + } +} + void YACSPrs_ElementaryNode::setCanvas(QCanvas* theCanvas) { + DEBTRACE("YACSPrs_ElementaryNode::setCanvas"); QCanvasItem::setCanvas(theCanvas); // set canvas to all ports @@ -410,8 +674,43 @@ void YACSPrs_ElementaryNode::updateLabelLink() if ( myLabelLink ) myLabelLink->moveByNode(this); } +void YACSPrs_ElementaryNode::removeLinkPrs(YACS::HMI::Subject* theSLink) +{ + YACSPrs_PortLink* aLinkPrs = 0; + + if ( SubjectLink* aSLink = dynamic_cast(theSLink) ) + { //remove data link presentation (this node is an out node for the given link) + if ( aSLink->getSubjectOutNode() != mySEngine ) return; + + YACSPrs_InOutPort* anOPPrs = + dynamic_cast(getPortPrs(aSLink->getSubjectOutPort()->getPort())); + if ( !anOPPrs ) return; + + aLinkPrs = anOPPrs->getLink(aSLink); + } + else if ( SubjectControlLink* aSCLink = dynamic_cast(theSLink) ) + { //remove control link presentation (this node is an out node for the given link) + if ( aSCLink->getSubjectOutNode() != mySEngine ) return; + + YACSPrs_InOutPort* anOPPrs = + dynamic_cast(getPortPrs(getEngine()->getOutGate())); + if ( !anOPPrs ) return; + + aLinkPrs = anOPPrs->getLink(aSCLink); + } + + if ( !aLinkPrs ) return; + + aLinkPrs->setSelected(false); + DEBTRACE(">> Delete link presentation"); + delete aLinkPrs; + + if ( canvas() ) canvas()->update(); +} + void YACSPrs_ElementaryNode::beforeMoving() { + DEBTRACE("YACSPrs_ElementaryNode::beforeMoving"); myZ = z(); setMoving(true); setZ(myZ+100); @@ -419,13 +718,15 @@ void YACSPrs_ElementaryNode::beforeMoving() void YACSPrs_ElementaryNode::afterMoving() { + DEBTRACE("YACSPrs_ElementaryNode::afterMoving"); setMoving(false); setZFromLinks(myZ); - canvas()->update(); + if ( canvas() ) canvas()->update(); } void YACSPrs_ElementaryNode::hilight(const QPoint& theMousePos, const bool toHilight) { + //DEBTRACE("YACSPrs_ElementaryNode::hilight " << toHilight); // process the hilighting for node and ports if (toHilight) { @@ -491,6 +792,7 @@ void YACSPrs_ElementaryNode::hilight(const QPoint& theMousePos, const bool toHil void YACSPrs_ElementaryNode::select(const QPoint& theMousePos, const bool toSelect) { + DEBTRACE("YACSPrs_ElementaryNode::select " << toSelect); if ( toSelect ) { // unhilight the item under the mouse cursor @@ -510,15 +812,20 @@ void YACSPrs_ElementaryNode::select(const QPoint& theMousePos, const bool toSele { mySelectedPort->setSelected(false); mySelectedPort->setColor(mySelectedPort->storeColor(), false, true, true); + synchronize( mySelectedPort, false ); } else { setSelected(false); + DEBTRACE(">>>## 4"); + getSEngine()->select(false); + setNodeSubColor( myStoreSubColor, true ); } aPort->setSelected(true); aPort->setColor(aPort->Color().dark(130), false, true, true); mySelectedPort = aPort; + synchronize( mySelectedPort, true ); } break; } @@ -530,15 +837,19 @@ void YACSPrs_ElementaryNode::select(const QPoint& theMousePos, const bool toSele if ( mySelectedPort ) { mySelectedPort->setSelected(false); + synchronize( mySelectedPort, false ); mySelectedPort = 0; } - if ( myStoreSubColor.dark(130) != mySubColor ) + //if ( myStoreSubColor.dark(130) != mySubColor ) { - myStoreSubColor = mySubColor; + //myStoreSubColor = mySubColor; setSelected(true); - setNodeSubColor( nodeSubColor().dark(130), true ); + DEBTRACE(">>>## 5"); + getSEngine()->select(true); + + //setNodeSubColor( nodeSubColor().dark(130), true ); } } } @@ -547,10 +858,14 @@ void YACSPrs_ElementaryNode::select(const QPoint& theMousePos, const bool toSele if ( mySelectedPort ) { mySelectedPort->setSelected(false); mySelectedPort->setColor(mySelectedPort->storeColor(), false, true, true); + synchronize( mySelectedPort, false ); mySelectedPort = 0; } else { setSelected(false); + DEBTRACE(">>>## 6"); + getSEngine()->select(false); + setNodeSubColor( myStoreSubColor, true ); } } @@ -580,7 +895,7 @@ QString YACSPrs_ElementaryNode::getToolTipText(const QPoint& theMousePos, QRect& aText += QString(" data stream"); aText += QString(" port \"") + anIOPort->getName() + QString("\", "); aText += anIOPort->getType(true) + QString(", "); - aText += QString("value = ") + anIOPort->getValue(); + aText += QString("value = ") + anIOPort->getCurrentValue(); } else aText += QString(" gate port"); @@ -619,15 +934,21 @@ int YACSPrs_ElementaryNode::rtti() const void YACSPrs_ElementaryNode::setVisible(bool b) { + DEBTRACE("YACSPrs_ElementaryNode::setVisible " << b); QCanvasPolygonalItem::setVisible(b); // set visibility to all ports YACSPrs_Port* aPort; - for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) - if (aPort->isVisible()) aPort->setVisible(b); - + //using iterator is more robust than using myPortList.next() when it can be called + //from within a loop on myPortList + QPtrListIterator it( myPortList ); + while ( (aPort = it.current()) != 0 ) + { + ++it; + if (aPort->isVisible()) aPort->setVisible(b); + } // set visibility to master point - myPointMaster->setVisible(b); + if ( myPointMaster ) myPointMaster->setVisible(b); updateLabelLink(); // set visibility to in/out points @@ -646,7 +967,7 @@ QPointArray YACSPrs_ElementaryNode::areaPoints() const QPointArray YACSPrs_ElementaryNode::maxAreaPoints() const { int w = width(); - int h = maxHeight()+1; // add pen width + int h = height() + ( myPointMaster ? myPointMaster->height()/2 : 0 ) + 1; // add pen width return constructAreaPoints(w,h); } @@ -663,6 +984,7 @@ QPointArray YACSPrs_ElementaryNode::constructAreaPoints(int theW, int theH) cons void YACSPrs_ElementaryNode::moveBy(double dx, double dy) { + DEBTRACE("YACSPrs_ElementaryNode::moveBy " << dx << "," << dy); // for constraint nodes' moving inside the Bloc--> if ( isCheckAreaNeeded() && !checkArea(dx,dy) ) return; // <-- @@ -695,9 +1017,9 @@ void YACSPrs_ElementaryNode::moveBy(double dx, double dy) //for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) // aPort->moveBy(xx, yy); - myPointMaster->moveBy(dx, dy); - if ( myLabelLink ) myLabelLink->moveByNode(this, (int)dx, (int)dy); - + if ( myPointMaster ) myPointMaster->moveBy(dx, dy); + if ( myLabelLink ) myLabelLink->moveByNode(this); + //if (!myCellPrs) { // myPointIn->moveBy(dx, dy); // myPointOut->moveBy(dx, dy); @@ -717,6 +1039,7 @@ void YACSPrs_ElementaryNode::moveBy(double dx, double dy) void YACSPrs_ElementaryNode::setZ(double z) { + DEBTRACE("YACSPrs_ElementaryNode::setZ: " << z); QCanvasItem::setZ(z); // update port's @@ -729,6 +1052,7 @@ void YACSPrs_ElementaryNode::setZ(double z) void YACSPrs_ElementaryNode::setZFromLinks(double z) { + DEBTRACE("YACSPrs_ElementaryNode::setZFromLinks: " << z); // find the maximum Z on all links of this node double aMaxLinkZ = 0; YACSPrs_Port* aPort; @@ -757,17 +1081,23 @@ void YACSPrs_ElementaryNode::setZFromLinks(double z) */ void YACSPrs_ElementaryNode::update() { - if ( !myEngine ) return; + DEBTRACE("==> YACSPrs_ElementaryNode::update()"); + + if ( !getEngine() ) return; // update state - setState( myEngine->getState() ); + setState( getEngine()->getState() ); // update ports values YACSPrs_Port* aPort = 0; for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) { YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); - if ( anIOPort && !anIOPort->isGate() ) anIOPort->update(); + if ( anIOPort && !anIOPort->isGate() ) + { + DEBTRACE("==> update port : " << aPort->getName().latin1()); + anIOPort->update(); + } } // update progress bar @@ -776,6 +1106,8 @@ void YACSPrs_ElementaryNode::update() // update execution time updateExecTime(); + mySEngine->update( UPDATEPROGRESS, 0, mySEngine ); + if ( canvas() ) { canvas()->setChanged(getRect()); canvas()->update(); @@ -792,7 +1124,9 @@ void YACSPrs_ElementaryNode::update() */ void YACSPrs_ElementaryNode::updateForEachLoopBody(YACS::ENGINE::Node* theEngine) { - if ( !myEngine || !theEngine ) return; + DEBTRACE("==> YACSPrs_ElementaryNode::updateForEachLoopBody()"); + + if ( !getEngine() || !theEngine ) return; // update state setState( theEngine->getState() ); @@ -818,41 +1152,57 @@ void YACSPrs_ElementaryNode::updateForEachLoopBody(YACS::ENGINE::Node* theEngine myPercentage = getPercentage(theEngine); + mySEngine->update( UPDATEPROGRESS, 0, mySEngine ); + if ( canvas() ) { canvas()->setChanged(getRect()); canvas()->update(); } } -void YACSPrs_ElementaryNode::updatePorts() +void YACSPrs_ElementaryNode::updatePorts(bool theForce) { + DEBTRACE("YACSPrs_ElementaryNode::updatePorts"); bool aDisp = isVisible(); if (aDisp) hide(); + + if (theForce) + { + if ( isFullDMode() ) + myPortHeight = 2*PORT_MARGIN; + else + myPortHeight = 0; + myPortList.setAutoDelete(true); + myPortList.clear(); + } - // iterates on all engine ports of the engine node myEngine, + // iterates on all engine ports of the engine node getEngine(), // create (if not already exists) for each engine port YACSPrs_InOutPort object and // set the rectangle for it bool withCreate = false; if ( myPortList.isEmpty() ) withCreate = true; - QRect r = getBodyRect(); - int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; - if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; - - int ix = r.x() + PORT_MARGIN + 1; - int iy = r.y() + PORT_MARGIN;// + 1; - int ox = ix + aPRectWidth + 2*PORT_MARGIN; - int oy = r.y() + PORT_MARGIN;// + 1; - - if ( withCreate ) - { // create (and update) - - // input ports - list anInPortsEngine = myEngine->getSetOfInPort(); - list::iterator anInPortsIter = anInPortsEngine.begin(); - int heightIncr = 0; - for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) + if ( isFullDMode() ) + { + QRect r = getBodyRect(); + int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; + if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; + + int ix = r.x() + PORT_MARGIN + 1; + int iy = r.y() + PORT_MARGIN;// + 1; + int ox = ix + aPRectWidth + 2*PORT_MARGIN; + int oy = r.y() + PORT_MARGIN;// + 1; + + if ( withCreate ) + { // create (and update) + DEBTRACE("YACSPrs_ElementaryNode::updatePorts"); + + // input ports + list anInPortsEngine = getEngine()->getSetOfInPort(); + list::iterator anInPortsIter = anInPortsEngine.begin(); + int heightIncr = 0; + for( ;anInPortsIter!=anInPortsEngine.end();anInPortsIter++) { YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr, canvas(), *anInPortsIter, this); anInPort->setPortRect(QRect(ix, iy+heightIncr, aPRectWidth, PORT_HEIGHT)); @@ -861,12 +1211,12 @@ void YACSPrs_ElementaryNode::updatePorts() myPortList.append(anInPort); heightIncr += PORT_HEIGHT+PORT_SPACE; } - - // output ports - list anOutPortsEngine = myEngine->getSetOfOutPort(); - list::iterator anOutPortsIter = anOutPortsEngine.begin(); - heightIncr = 0; - for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) + + // output ports + list anOutPortsEngine = getEngine()->getSetOfOutPort(); + list::iterator anOutPortsIter = anOutPortsEngine.begin(); + heightIncr = 0; + for( ;anOutPortsIter!=anOutPortsEngine.end();anOutPortsIter++) { YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr, canvas(), *anOutPortsIter, this); anOutPort->setPortRect(QRect(ox, oy+heightIncr, aPRectWidth, PORT_HEIGHT)); @@ -875,39 +1225,54 @@ void YACSPrs_ElementaryNode::updatePorts() myPortList.append(anOutPort); heightIncr += PORT_HEIGHT+PORT_SPACE; } - - int aPortsIncrement = - anInPortsEngine.size()>anOutPortsEngine.size()?anInPortsEngine.size():anOutPortsEngine.size(); - myPortHeight += PORT_HEIGHT*aPortsIncrement + (aPortsIncrement-1)*PORT_SPACE; - } - else - { // only update - YACSPrs_InOutPort* aPort; - for (aPort = (YACSPrs_InOutPort*)(myPortList.first()); - aPort && !aPort->isGate(); - aPort = (YACSPrs_InOutPort*)(myPortList.next())) - { - if ( aPort->isInput() ) - { // test input ports - aPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); - iy += PORT_HEIGHT+PORT_SPACE; - } - else - { // test output ports - aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); - oy += PORT_HEIGHT+PORT_SPACE; - } + + int aPortsIncrement = + anInPortsEngine.size()>anOutPortsEngine.size()?anInPortsEngine.size():anOutPortsEngine.size(); + myPortHeight += PORT_HEIGHT*aPortsIncrement + (aPortsIncrement-1)*PORT_SPACE; + } + else + { // only update + YACSPrs_Port* aPort; + QPtrListIterator it( myPortList ); + while ( (aPort = it.current()) != 0 ) + { + ++it; + DEBTRACE(aPort); + YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); + if ( !anIOPort )continue; + DEBTRACE(anIOPort->getName()<<","<isGate()<<","<isInput()); + if ( !anIOPort->isGate() ) + if ( anIOPort->isInput() ) + { // test input ports + DEBTRACE(ix<<","<< iy<<","<< aPRectWidth<<","<< PORT_HEIGHT); + anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); + iy += PORT_HEIGHT+PORT_SPACE; + } + else + { // test output ports + DEBTRACE(ox<<","<< oy<<","<< aPRectWidth<<","<< PORT_HEIGHT); + anIOPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); + oy += PORT_HEIGHT+PORT_SPACE; + } + } } } - + // can update gates only after body height will be defined updateGates(withCreate); + if (theForce && myPointMaster) + { + QPoint aPnt = getConnectionMasterPoint(); + myPointMaster->setCoords(aPnt.x(), aPnt.y()); + } + if (aDisp) show(); } void YACSPrs_ElementaryNode::updateGates(bool theCreate) { + DEBTRACE("YACSPrs_ElementaryNode::updateGates " << theCreate << "," << isVisible()); bool aDisp = isVisible(); if (aDisp) hide(); @@ -923,14 +1288,14 @@ void YACSPrs_ElementaryNode::updateGates(bool theCreate) if ( theCreate ) { // create (and update) // input Gate - YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr,canvas(),myEngine->getInGate(),this); + YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr,canvas(),getEngine()->getInGate(),this); anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); anInPort->setColor(nodeSubColor()); anInPort->setStoreColor(nodeSubColor()); myPortList.append(anInPort); // output Gate - YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),myEngine->getOutGate(),this); + YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),getEngine()->getOutGate(),this); anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT)); anOutPort->setColor(nodeSubColor()); anOutPort->setStoreColor(nodeSubColor()); @@ -939,15 +1304,23 @@ void YACSPrs_ElementaryNode::updateGates(bool theCreate) else { // only update YACSPrs_Port* aPort; - for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) + QPtrListIterator it( myPortList ); + while ( (aPort = it.current()) != 0 ) { + ++it; YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); if ( anIOPort && anIOPort->isGate() ) { if ( anIOPort->isInput() ) // test input ports - anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); + { + DEBTRACE(ix<<","<< iy<<","<< aPRectWidth<<","<< PORT_HEIGHT); + anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); + } else // test output ports - anIOPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); + { + DEBTRACE(ox<<","<< oy<<","<< aPRectWidth<<","<< PORT_HEIGHT); + anIOPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !mySelfMoving, myArea); + } } } } @@ -1008,6 +1381,26 @@ int YACSPrs_ElementaryNode::maxHeight() const return boundingRect().height() + ( myPointMaster ? myPointMaster->height()/2 : 0 ); } +int YACSPrs_ElementaryNode::minX() const +{ + return boundingRect().left() - 2*HOOKPOINT_SIZE; +} + +int YACSPrs_ElementaryNode::maxX() const +{ + return boundingRect().right() + 2*HOOKPOINT_SIZE; +} + +int YACSPrs_ElementaryNode::minY() const +{ + return boundingRect().top(); +} + +int YACSPrs_ElementaryNode::maxY() const +{ + return boundingRect().bottom() + (myPointMaster ? myPointMaster->height()/2 : 0 ); +} + int YACSPrs_ElementaryNode::getInfoHeight() const { return myTitleHeight; @@ -1090,17 +1483,17 @@ QRect YACSPrs_ElementaryNode::getGateRect() const void YACSPrs_ElementaryNode::nextTimeIteration(YACS::ENGINE::Node* theEngine) { bool nullifyOnToActivate = false; - if ( !theEngine ) theEngine = myEngine; + if ( !theEngine ) theEngine = getEngine(); else nullifyOnToActivate = true; if ( theEngine && - ( theEngine->getState() == YACS::INITED || theEngine->getEffectiveState() == YACS::INITED + ( theEngine->getState() == YACS::READY /*|| theEngine->getEffectiveState() == YACS::READY*/ || ( nullifyOnToActivate && ( theEngine->getState() == YACS::TOACTIVATE || theEngine->getEffectiveState() == YACS::TOACTIVATE) ) ) ) myTimeIteration = 0.; else if ( theEngine && - theEngine->getState() != YACS::INITED && theEngine->getEffectiveState() != YACS::INITED && + theEngine->getState() != YACS::READY /*&& theEngine->getEffectiveState() != YACS::READY*/ && !myFinished ) { const double aGoodTime = 0.02 * 100; // estimated time to run, s myTimeIteration += 1./aGoodTime; @@ -1113,25 +1506,27 @@ void YACSPrs_ElementaryNode::nextTimeIteration(YACS::ENGINE::Node* theEngine) * * \param theEngine : the engine of clone node from which we have to update presentation of this node. */ -double YACSPrs_ElementaryNode::getPercentage(YACS::ENGINE::Node* theEngine) const +int YACSPrs_ElementaryNode::getPercentage(YACS::ENGINE::Node* theEngine) const { bool nullifyOnToActivate = false; - if ( !theEngine ) theEngine = myEngine; + if ( !theEngine ) theEngine = getEngine(); else nullifyOnToActivate = true; - if ( !theEngine ) return 0.; + if ( !theEngine ) return 0; - if ( theEngine->getState() == YACS::INITED || theEngine->getEffectiveState() == YACS::INITED || + if ( theEngine->getState() == YACS::READY || /*theEngine->getEffectiveState() == YACS::READY ||*/ theEngine->getState() == YACS::TOLOAD || theEngine->getEffectiveState() == YACS::TOLOAD || theEngine->getState() == YACS::DISABLED || theEngine->getEffectiveState() == YACS::DISABLED || ( nullifyOnToActivate && ( theEngine->getState() == YACS::TOACTIVATE || theEngine->getEffectiveState() == YACS::TOACTIVATE) ) ) - return 0.; + return 0; + if ( theEngine->getState() == YACS::DONE ) - return 100.; + return 100; + // progress bar is manipulated at logarithmic scale: // iteration=1 -> 1%, iteration==goodtime -> 50%, iteration=infinite -> 99% - return ( 0.499 + 99. * ( myTimeIteration * myTimeIteration / ( 1. + myTimeIteration * myTimeIteration ) ) ); + return (int)( 0.499 + 99. * ( myTimeIteration * myTimeIteration / ( 1. + myTimeIteration * myTimeIteration ) ) ); } //! Updates execution time. @@ -1143,7 +1538,7 @@ double YACSPrs_ElementaryNode::getPercentage(YACS::ENGINE::Node* theEngine) cons void YACSPrs_ElementaryNode::updateExecTime(YACS::ENGINE::Node* theEngine) { bool nullifyOnToActivate = false; - if ( !theEngine ) theEngine = myEngine; + if ( !theEngine ) theEngine = getEngine(); else nullifyOnToActivate = true; if ( !theEngine ) return; @@ -1154,13 +1549,13 @@ void YACSPrs_ElementaryNode::updateExecTime(YACS::ENGINE::Node* theEngine) return; } - if ( theEngine->getState() == YACS::INITED || theEngine->getEffectiveState() == YACS::INITED + if ( theEngine->getState() == YACS::READY /*|| theEngine->getEffectiveState() == YACS::READY*/ || ( nullifyOnToActivate && ( theEngine->getState() == YACS::TOACTIVATE || theEngine->getEffectiveState() == YACS::TOACTIVATE) ) ) { myTime = QString("00:00:00"); myStarted = false; - if ( theEngine->getState() == YACS::INITED ) return; + if ( theEngine->getState() == YACS::READY ) return; } if ( !myTime.compare(QString("00:00:00")) && !myStarted ) { @@ -1169,7 +1564,7 @@ void YACSPrs_ElementaryNode::updateExecTime(YACS::ENGINE::Node* theEngine) myFinished = false; } - if ( theEngine->getState() != YACS::INITED && theEngine->getState() != YACS::DONE && + if ( theEngine->getState() != YACS::READY && theEngine->getState() != YACS::DONE && theEngine->getState() != YACS::FAILED && theEngine->getState() != YACS::ERROR ) { int aMS = myStartTime.elapsed(); @@ -1203,9 +1598,13 @@ void YACSPrs_ElementaryNode::setState(YACS::StatesForNode theState) { switch ( theState ) { - case YACS::INITED: - myStatus = QString("Inited"); - myStatePixmap = myMgr->loadPixmap( "YACSPrs", QObject::tr( "ICON_STATUS_NO" )); + case YACS::INVALID: + myStatus = QString("Invalid"); + myStatePixmap = myMgr->loadPixmap( "YACSPrs", QObject::tr( "ICON_STATUS_INVALID" )); + break; + case YACS::READY: + myStatus = QString("Ready"); + myStatePixmap = myMgr->loadPixmap( "YACSPrs", QObject::tr( "ICON_STATUS_READY" )); break; case YACS::TOLOAD: myStatus = QString("To Load"); @@ -1268,14 +1667,23 @@ void YACSPrs_ElementaryNode::drawShape(QPainter& thePainter) { drawFrame(thePainter); drawTitle(thePainter); - drawPort(thePainter); + + if ( isFullDMode() ) + drawPort(thePainter); + drawGate(thePainter); + + if ( isControlDMode() && myPointMaster) + { + myPointMaster->setVisible(false); + myPointMaster->setCanvas(0); + } } void YACSPrs_ElementaryNode::drawTitleShape(QPainter& thePainter) { thePainter.drawRoundRect(getTitleRect(),myXRnd,myYRnd); - drawText(thePainter, QString(myEngine->getName()), getTitleRect(), Qt::AlignHCenter); + drawText(thePainter, QString(getEngine()->getName()), getTitleRect(), Qt::AlignHCenter); } void YACSPrs_ElementaryNode::drawTitle(QPainter& thePainter) @@ -1316,6 +1724,10 @@ void YACSPrs_ElementaryNode::drawGate(QPainter& thePainter) { QRect aRect = getRect(); QRect aBRect = getBodyRect(); + + if ( isControlDMode() ) + thePainter.drawLine(aBRect.left(), aBRect.bottom(), aBRect.right(), aBRect.bottom()); + int x0 = (aRect.left() + aRect.right())/2; thePainter.drawLine(x0, aBRect.bottom(), x0, aRect.bottom()); @@ -1376,6 +1788,7 @@ void YACSPrs_ElementaryNode::setMasterPointColor(QColor theColor) bool YACSPrs_ElementaryNode::checkArea(double dx, double dy) { + DEBTRACE("YACSPrs_ElementaryNode::checkArea " << dx << "," << dy); // for constraint nodes' moving inside the Bloc--> if ( !myIsInBloc ) return true; @@ -1388,6 +1801,33 @@ bool YACSPrs_ElementaryNode::checkArea(double dx, double dy) // <-- } +bool YACSPrs_ElementaryNode::isFullDMode() const +{ + if ( myViewMode == 0 ) return true; + return false; +} + +bool YACSPrs_ElementaryNode::isControlDMode() const +{ + if ( myViewMode == 1 ) return true; + return false; +} + +void YACSPrs_ElementaryNode::setSelected( bool b ) +{ + mySelected = b; + if (mySelected) + setNodeSubColor( myStoreSubColor.dark(130), true ); + else + setNodeSubColor( myStoreSubColor, true ); +} + +bool YACSPrs_ElementaryNode::synchronize( YACSPrs_Port* port, const bool toSelect ) +{ + DEBTRACE("YACSPrs_ElementaryNode::synchronize"); + return YACSPrs_InOutPort::synchronize( port, toSelect ); +} + /*! * =========================== YACSPrs_Port =========================== !*/ @@ -1408,23 +1848,62 @@ YACSPrs_Port::YACSPrs_Port( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACSPr YACSPrs_Port::~YACSPrs_Port() { - if (myPoint) delete myPoint; + DEBTRACE(">> YACSPrs_Port::~YACSPrs_Port()"); + //if ( getNode() ) getNode()->erasePortPrs(this); - for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) { - if ( YACSPrs_PortLink* aPL = dynamic_cast( *it ) ) { - aPL->setInputPort(0); - aPL->setOutputPort(0); - } - else if ( YACSPrs_LabelLink* aLL = dynamic_cast( *it ) ) { - aLL->setOutputPort(0); - aLL->setSlaveNode(0); + if (myPoint) + { + delete myPoint; + myPoint = 0; + } + + for(list::iterator it = myLinks.begin(); it != myLinks.end(); ++it) { + YACSPrs_Link* aLink = *it; + if( aLink ) + { + if ( YACSPrs_PortLink* aPL = dynamic_cast( aLink ) ) + { + // detach port link presentation from HMI + YACS::HMI::Subject* aSub = aPL->getSubject(); + if ( aSub ) + aSub->detach(aPL); + + if ( aPL->getInputPort() == this ) + aPL->setInputPort(0); + else if ( aPL->getOutputPort() == this ) + aPL->setOutputPort(0); + + delete aPL; + aPL = 0; + } + else if ( YACSPrs_LabelLink* aLL = dynamic_cast( aLink ) ) + { + if ( aLL->getOutputPort() == this ) + aLL->setOutputPort(0); + delete aLL; + aLL = 0; + } } } + myLinks.clear(); +} + +YACSPrs_PortLink* YACSPrs_Port::getLink(YACS::HMI::Subject* theSLink) +{ + YACSPrs_PortLink* aRet = 0; + + if ( !theSLink ) return aRet; - //for(list::iterator it = myLinks.begin(); it != myLinks.end(); ++it) { - // delete (*it); - //} - //myLinks.clear(); + for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) + { + YACSPrs_PortLink* aPLink = dynamic_cast(*it); + if ( !aPLink ) continue; + + if ( aPLink->getSubject() == theSLink ) + return aPLink; + } + + return aRet; } void YACSPrs_Port::setCanvas(QCanvas* theCanvas) @@ -1433,10 +1912,15 @@ void YACSPrs_Port::setCanvas(QCanvas* theCanvas) // set canvas to hook if (myPoint) myPoint->setCanvas(theCanvas); + + // set canvas for all ports links + for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) + (*it)->setCanvas(theCanvas); } void YACSPrs_Port::updateLinks(bool theMoveInternalLinkPoints, QRect theArea) { + DEBTRACE("YACSPrs_Port::updateLinks"); for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) (*it)->moveByPort(this, theMoveInternalLinkPoints, theArea); } @@ -1448,8 +1932,18 @@ QString YACSPrs_Port::getName() const void YACSPrs_Port::setVisible(bool b) { + DEBTRACE("YACSPrs_Port::setVisible " <setVisible(b); - if (b) updateLinks(); + + if (b) + { + updateLinks(); + for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) + (*it)->show(); + } + else + for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) + (*it)->hide(); } void YACSPrs_Port::setColor(const QColor& theColor, bool theUpdatePointColor, @@ -1478,6 +1972,7 @@ void YACSPrs_Port::moveBy(int dx, int dy) void YACSPrs_Port::setZ(double z, bool storeOldZ) { + DEBTRACE("YACSPrs_Port::setZ: " << z); if (myPoint) myPoint->setZ(z); for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) { if ( storeOldZ ) (*it)->setMyZ((*it)->z()); @@ -1516,6 +2011,7 @@ YACSPrs_LabelPort::~YACSPrs_LabelPort() void YACSPrs_LabelPort::setPortRect(const QRect& theRect, bool theMoveInternalLinkPoints, QRect theArea) { + DEBTRACE("YACSPrs_LabelPort::setPortRect"); myNameRect = theRect; myNameRect.setWidth(theRect.width()-3); @@ -1541,6 +2037,7 @@ void YACSPrs_LabelPort::setColor(const QColor& theColor, bool theUpdatePointColo void YACSPrs_LabelPort::moveBy(int dx, int dy) { + DEBTRACE("YACSPrs_LabelPort::moveBy " << dx << "," << dy); myNameRect.moveBy(dx, dy); if (myPoint) myPoint->moveBy(dx, dy); @@ -1549,9 +2046,11 @@ void YACSPrs_LabelPort::moveBy(int dx, int dy) QPoint YACSPrs_LabelPort::getConnectionPoint() const { + DEBTRACE("YACSPrs_LabelPort::getConnectionPoint"); int x, y; x = myNameRect.right() + PORT_MARGIN + 2 + 3*HOOKPOINT_SIZE/2; y = (int)(myNameRect.top() + myNameRect.bottom())/2; + DEBTRACE(x << "," << y); return QPoint(x, y); } @@ -1591,6 +2090,7 @@ void YACSPrs_LabelPort::draw(QPainter& thePainter, int theXRnd, int theYRnd) !*/ YACSPrs_InOutPort::YACSPrs_InOutPort( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Port* thePort, YACSPrs_ElementaryNode* theNodePrs ): + GuiObserver(), YACSPrs_Port(theMgr, theCanvas, theNodePrs), myEngine(thePort) { @@ -1613,15 +2113,32 @@ YACSPrs_InOutPort::YACSPrs_InOutPort( SUIT_ResourceMgr* theMgr, QCanvas* theCanv if ( !myGate ) { myType = getType(); myValue = getValue(); + DEBTRACE("Set VAL 0"); } myColor = myMgr->colorValue( "QxGraph", "Title", TITLE_COLOR ); myPoint = new YACSPrs_Hook(theMgr, theCanvas, this, myInput, myGate); + + // attach to HMI myself + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->attach( this ); } YACSPrs_InOutPort::~YACSPrs_InOutPort() { + DEBTRACE(">> YACSPrs_InOutPort::~YACSPrs_InOutPort() detach this from HMI"); + // detach from HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->detach(this); +} + +void YACSPrs_InOutPort::select( bool isSelected ) +{ + DEBTRACE(">> YACSPrs_InOutPort::select( " << isSelected ); + setSelected( isSelected ); } //! Updates a port presentation during execution. @@ -1632,6 +2149,7 @@ YACSPrs_InOutPort::~YACSPrs_InOutPort() */ void YACSPrs_InOutPort::update(bool theForce, YACS::ENGINE::Port* theEngine) { + DEBTRACE("YACSPrs_InOutPort::update"); QString aNewName = getName(); if (theForce || myName.compare(aNewName) != 0) { myName = aNewName; @@ -1640,18 +2158,39 @@ void YACSPrs_InOutPort::update(bool theForce, YACS::ENGINE::Port* theEngine) if ( !myGate ) { QString aNewType = getType(); - QString aNewValue = getValue(theEngine); if (theForce || myType.compare(aNewType) != 0) { myType = aNewType; if (myCanvas) myCanvas->setChanged(myTypeRect); } - if (theForce || myValue.compare(aNewValue) != 0) { - myValue = aNewValue; - if (myCanvas) myCanvas->setChanged(myValueRect); + + if ( getNode()->getEngine()->getState() == YACS::READY || getNode()->getEngine()->getState() == YACS::INVALID) //edition + { + QString aNewValue = getValue(theEngine); // !!! during execution the value updated by events from YACSORB engine + if (theForce || myValue.compare(aNewValue) != 0) { + DEBTRACE(myValue<<","<setChanged(myValueRect); + } } } } +//! Updates a port value during execution. +/*! + * \param theValue : the new port value to be set for port presentation. + */ +void YACSPrs_InOutPort::updateValue( QString theValue ) +{ + DEBTRACE("YACSPrs_InOutPort::updateValue"); + if ( !myGate ) + if ( myValue.compare(theValue) != 0 ) { + myValue = theValue; + DEBTRACE("Set VAL 2"); + if (myCanvas) myCanvas->setChanged(myValueRect); + } +} + bool YACSPrs_InOutPort::isHilight() const { //Port aPort = myPort->getEngine(); @@ -1738,6 +2277,7 @@ QString YACSPrs_InOutPort::getType(const bool forToolTip) const */ QString YACSPrs_InOutPort::getValue(YACS::ENGINE::Port* theEngine) const { + DEBTRACE("YACSPrs_InOutPort::getValue"); if ( !theEngine ) theEngine = myEngine; QString aValue; @@ -1751,48 +2291,59 @@ QString YACSPrs_InOutPort::getValue(YACS::ENGINE::Port* theEngine) const { if ( SeqAnyInputPort* aSeqAnyP = dynamic_cast(theEngine) ) { // check if theEngine is SeqAnyInputPort - //printf("SeqAnyInputPort : %s\n",getName().latin1()); + DEBTRACE("SeqAnyInputPort : " << getName().latin1()); anAny = aSeqAnyP->getValue(); if ( !anAny ) aValue = QString("[ ? ]"); else toString(anAny, aValue); } else if ( AnyInputPort* anAnyP = dynamic_cast(theEngine) ) { // check if theEngine is AnyInputPort - //printf("AnyInputPort : %s\n",getName().latin1()); - toString(anAnyP->getValue(), aValue); + DEBTRACE("AnyInputPort : " << getName().latin1()); + if ( !anAnyP->edIsManuallyInitialized() ) + aValue = QString::number(0); + else + toString(anAnyP->getValue(), aValue); } else if ( ConditionInputPort* aConditionP = dynamic_cast(theEngine) ) { // check if theEngine is ConditionInputPort - //printf("ConditionInputPort : %s\n",getName().latin1()); + DEBTRACE("ConditionInputPort : " << getName().latin1()); aValue = QString( aConditionP->getValue() ? "true" : "false" ); } else if ( InputCorbaPort* aCorbaP = dynamic_cast(theEngine) ) { // check if theEngine is InputCorbaPort - //printf("InputCorbaPort : %s\n",getName().latin1()); + DEBTRACE("InputCorbaPort : " << getName().latin1()); + DEBTRACE(aCorbaP->dump()); toString( aCorbaP->getAny(), aValue ); } else if ( InputPyPort* aPyP = dynamic_cast(theEngine) ) { // check if theEngine is InputPyPort - //printf("InputPyPort : %s\n",getName().latin1()); + DEBTRACE("InputPyPort : " << getName().latin1()); toString( aPyP->getPyObj(), aValue ); } + else if(InputStudyPort* aPort=dynamic_cast(theEngine)) + { + DEBTRACE( aPort->getData()); + aValue=aPort->getData(); + } else if ( InputXmlPort* aXmlP = dynamic_cast(theEngine) ) { // check if theEngine is InputXmlPort - //printf("InputXmlPort : %s\n",getName().latin1()); + DEBTRACE("InputXmlPort : " << getName().latin1()); + DEBTRACE( aXmlP->dump()); + toString(aXmlP->dump(),aXmlP->edGetType(),aValue); } else if ( InputCalStreamPort* aCalStreamP = dynamic_cast(theEngine) ) { // check if theEngine is InputCalStreamPort - //printf("InputCalStreamPort : %s\n",getName().latin1()); + DEBTRACE("InputCalStreamPort : " << getName().latin1()); aValue = QString("data stream"); } else if ( InputDataStreamPort* aDataStreamP = dynamic_cast(theEngine) ) { // check if theEngine is InputDataStreamPort - //printf("InputDataStreamPort : %s\n",getName().latin1()); + DEBTRACE("InputDataStreamPort : " << getName().latin1()); aValue = QString("data stream"); } else if ( InputPort* anInputP = dynamic_cast(theEngine) ) { // check if theEngine is InputPort - //printf("InputPort : %s\n",getName().latin1()); + DEBTRACE("InputPort : " << getName().latin1()); } } else @@ -1801,36 +2352,43 @@ QString YACSPrs_InOutPort::getValue(YACS::ENGINE::Port* theEngine) const if ( AnyOutputPort* anAnyP = dynamic_cast(theEngine) ) { // check if theEngine is AnyOutputPort - //printf("AnyOutputPort : %s\n",getName().latin1()); + DEBTRACE("AnyOutputPort : " << getName().latin1()); toString(anAnyP->getValue(), aValue); } else if ( OutputCorbaPort* aCorbaP = dynamic_cast(theEngine) ) { // check if theEngine is OutputCorbaPort - //printf("OutputCorbaPort : %s\n",getName().latin1()); + DEBTRACE("OutputCorbaPort : " << getName().latin1()); toString( aCorbaP->getAny(), aValue ); } else if ( OutputPyPort* aPyP = dynamic_cast(theEngine) ) { // check if theEngine is OutputPyPort - //printf("OutputPyPort : %s\n",getName().latin1()); + DEBTRACE("OutputPyPort : " << getName().latin1()); toString( aPyP->get(), aValue ); } + else if(OutputStudyPort* aPort=dynamic_cast(theEngine)) + { + DEBTRACE( aPort->getData()); + aValue=aPort->getData(); + } else if ( OutputXmlPort* aXmlP = dynamic_cast(theEngine)) { // check if theEngine is OutputXmlPort - //printf("OutputXmlPort : %s\n",getName().latin1()); + DEBTRACE("OutputXmlPort : " << getName().latin1()); + DEBTRACE( aXmlP->dump()); + toString(aXmlP->dump(),aXmlP->edGetType(),aValue); } else if ( OutputCalStreamPort* aCalStreamP = dynamic_cast(theEngine) ) { // check if theEngine is OutputCalStreamPort - //printf("OutputCalStreamPort : %s\n",getName().latin1()); + DEBTRACE("OutputCalStreamPort : " << getName().latin1()); aValue = QString("data stream"); } else if ( OutputDataStreamPort* aCalStreamP = dynamic_cast(theEngine) ) { // check if theEngine is OutputDataStreamPort - //printf("OutputDataStreamPort : %s\n",getName().latin1()); + DEBTRACE("OutputDataStreamPort : " << getName().latin1()); aValue = QString("data stream"); } else if ( OutputPort* anOutputP = dynamic_cast(theEngine) ) { // check if theEngine is OutputPort - //printf("OutputPort : %s\n",getName().latin1()); + DEBTRACE("OutputPort : " << getName().latin1()); } } } @@ -1849,9 +2407,11 @@ int YACSPrs_InOutPort::getAlignment() const void YACSPrs_InOutPort::setPortRect(const QRect& theRect, bool theMoveInternalLinkPoints, QRect theArea) { + DEBTRACE("YACSPrs_InOutPort::setPortRect " << getName()); if ( !myGate ) { int aRectWidth = (theRect.right() - theRect.left() - 2*(PORT_SPACE))/3; + DEBTRACE(theRect.left()<<","<< theRect.top()<<","<setZ(z); for(list::iterator it = myLinks.begin(); it != myLinks.end(); it++) { if ( storeOldZ ) (*it)->setMyZ((*it)->z()); @@ -1915,6 +2478,7 @@ void YACSPrs_InOutPort::setZ(double z, bool storeOldZ) QPoint YACSPrs_InOutPort::getConnectionPoint() const { + DEBTRACE("YACSPrs_InOutPort::getConnectionPoint"); int x, y; if ( myGate ) { @@ -1998,6 +2562,60 @@ void YACSPrs_InOutPort::draw(QPainter& thePainter, int theXRnd, int theYRnd) } } +YACS::HMI::Subject* YACSPrs_InOutPort::getSubject() const +{ + YACS::HMI::Subject* aSub = 0; + + DataPort* aDataPort = dynamic_cast( myEngine ); + if ( aDataPort ) + { + GuiContext* aContext = GuiContext::getCurrent(); + if ( aContext ) + { + if ( aContext->_mapOfSubjectDataPort.find( aDataPort ) != aContext->_mapOfSubjectDataPort.end() ) + aSub = aContext->_mapOfSubjectDataPort[ aDataPort ]; + } + } + + return aSub; +} + +bool YACSPrs_InOutPort::synchronize( YACSPrs_Port* port, const bool toSelect ) +{ + DEBTRACE("YACSPrs_InOutPort::synchronize"); + YACSPrs_InOutPort* anInOutPort = dynamic_cast< YACSPrs_InOutPort* >( port ); + if ( !anInOutPort ) + return false; + + if ( !anInOutPort->isGate() ) + { + YACS::HMI::Subject* aSub = anInOutPort->getSubject(); + if ( aSub ) + { + DEBTRACE(">>>## 7"); + aSub->select( toSelect ); + return true; + } + } + else + { + // try to synchronize port with parent prs + YACSPrs_ElementaryNode* aNodePrs = anInOutPort->getNode(); + if ( aNodePrs ) + { + YACS::HMI::SubjectNode* aSub = aNodePrs->getSEngine(); + if ( aSub ) + { + DEBTRACE(">>>## 8"); + aSub->select( toSelect ); + return true; + } + } + } + + return false; +} + /*! * =========================== YACSPrs_Hook =========================== !*/ @@ -2068,6 +2686,7 @@ void YACSPrs_Hook::setCanvas(QCanvas* theCanvas) void YACSPrs_Hook::hilight(const QPoint& theMousePos, const bool toHilight) { + //DEBTRACE("YACSPrs_Hook::hilight "<< toHilight); if ( mySelected ) return; // process the hilighting for hook: @@ -2110,9 +2729,9 @@ void YACSPrs_Hook::hilight(const QPoint& theMousePos, const bool toHilight) } else if (YACSPrs_PortLink* aPortLink = dynamic_cast(aLink)) { - if (aPortLink->getInputPort() != myPortPrs) + if (aPortLink->getInputPort() && aPortLink->getInputPort() != myPortPrs) aPortLink->getInputPort()->GetHook()->setColor(aDefinedColor); - else + else if (aPortLink->getOutputPort()) aPortLink->getOutputPort()->GetHook()->setColor(aDefinedColor); } } @@ -2123,6 +2742,7 @@ void YACSPrs_Hook::hilight(const QPoint& theMousePos, const bool toHilight) void YACSPrs_Hook::select(const QPoint& theMousePos, const bool toSelect) { + DEBTRACE("YACSPrs_Hook::select " << toSelect); // unhilight the item under the mouse cursor hilight(theMousePos, false); @@ -2292,3 +2912,4 @@ void YACSPrs_Hook::drawShape(QPainter& thePainter) } } } + diff --git a/src/prs/YACSPrs_ElementaryNode.h b/src/prs/YACSPrs_ElementaryNode.h index b38dcafa3..dcb9be33d 100644 --- a/src/prs/YACSPrs_ElementaryNode.h +++ b/src/prs/YACSPrs_ElementaryNode.h @@ -21,6 +21,7 @@ #include #include +#include #include "QxGraph_ActiveItem.h" @@ -92,6 +93,7 @@ class YACSPrs_Hook : public QxGraph_ActiveItem, public QCanvasEllipse }; class YACSPrs_Link; +class YACSPrs_PortLink; class YACSPrs_ElementaryNode; class YACSPrs_Port { @@ -100,6 +102,7 @@ class YACSPrs_Port { ~YACSPrs_Port(); std::list getLinks() const { return myLinks; } + YACSPrs_PortLink* getLink(YACS::HMI::Subject* theSLink); YACSPrs_ElementaryNode* getNode() const { return myNode; } void setCanvas(QCanvas* theCanvas); @@ -135,6 +138,8 @@ class YACSPrs_Port { virtual QPoint getConnectionPoint() const = 0; virtual void draw(QPainter& thePainter, int theXRnd, int theYRnd) = 0; + static bool synchronize( YACSPrs_Port* port, const bool toSelect ); + protected: SUIT_ResourceMgr* myMgr; @@ -165,6 +170,7 @@ class YACSPrs_LabelPort : public YACSPrs_Port { ~YACSPrs_LabelPort(); YACS::ENGINE::Node* getSlaveNode() const { return mySlaveNode; } + void setSlaveNode( YACS::ENGINE::Node* theNode ) { mySlaveNode = theNode; } void setName(QString theName) { myName = theName; } @@ -184,7 +190,9 @@ class YACSPrs_LabelPort : public YACSPrs_Port { // the node inside the loop body for Loop) }; -class YACSPrs_InOutPort : public YACSPrs_Port { +class YACSPrs_InOutPort : public YACSPrs_Port , + public YACS::HMI::GuiObserver +{ public: YACSPrs_InOutPort( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Port*, YACSPrs_ElementaryNode* ); @@ -196,6 +204,10 @@ class YACSPrs_InOutPort : public YACSPrs_Port { bool isGate() const { return myGate; } virtual void update(bool theForce = false, YACS::ENGINE::Port* theEngine = 0); + void updateValue( QString theValue ); + + // redefined from GuiObserver + virtual void select( bool isSelected ); virtual bool isHilight() const; virtual bool isAlert() const; @@ -203,6 +215,7 @@ class YACSPrs_InOutPort : public YACSPrs_Port { virtual QString getName() const; virtual QString getType(const bool forToolTip = false) const; virtual QString getValue(YACS::ENGINE::Port* theEngine = 0) const; + virtual QString getCurrentValue() const { return myValue; } virtual int getAlignment() const; @@ -215,6 +228,10 @@ class YACSPrs_InOutPort : public YACSPrs_Port { virtual QPoint getConnectionPoint() const; virtual void draw(QPainter& thePainter, int theXRnd, int theYRnd); + YACS::HMI::Subject* getSubject() const; + + static bool synchronize( YACSPrs_Port* port, const bool toSelect ); + private: YACS::ENGINE::Port* myEngine; // port engine @@ -229,22 +246,38 @@ class YACSPrs_InOutPort : public YACSPrs_Port { }; class YACSPrs_LabelLink; -class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygonalItem { +class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, + public QCanvasPolygonalItem, + public YACS::HMI::GuiObserver { public: - YACSPrs_ElementaryNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node* ); + YACSPrs_ElementaryNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode* ); virtual ~YACSPrs_ElementaryNode(); - YACS::ENGINE::Node* getEngine() const { return myEngine; } + virtual void select( bool isSelected ); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); - QPtrList getPortList() const { return myPortList; } + YACS::ENGINE::Node* getEngine() const; + YACS::HMI::SubjectNode* getSEngine() const { return mySEngine; } + QPtrList getPortList() const { return myPortList; } YACSPrs_InOutPort* getPortPrs(YACS::ENGINE::Port* thePort); + void sortPorts(); + void moveUp(YACS::ENGINE::Port* thePort); + void moveDown(YACS::ENGINE::Port* thePort); + void addPortPrs(YACS::ENGINE::Port* thePort); + void removePortPrs(YACS::ENGINE::Port* thePort); + + void removeLabelPortPrs(YACSPrs_LabelPort* thePort); + + void erasePortPrs(YACSPrs_Port* thePort); + virtual void setCanvas(QCanvas* theCanvas); void addLabelLink(YACSPrs_LabelLink* theLink) { myLabelLink = theLink; } void removeLabelLink(); void updateLabelLink(); + void removeLinkPrs(YACS::HMI::Subject* theSLink); YACSPrs_LabelLink* getLabelLink() const { return myLabelLink; } /* reimplement functions from QxGraph_ActiveItem */ @@ -262,7 +295,7 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona void setSelfMoving(bool b) { mySelfMoving = b; } bool isSelfMoving() const { return mySelfMoving; } - void setSelected(bool b) { mySelected = b; } + void setSelected(bool b); bool isSelected() const { return mySelected; } virtual int rtti() const; @@ -279,7 +312,7 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona virtual void update(); virtual void updateForEachLoopBody(YACS::ENGINE::Node* theEngine=0); - virtual void updatePorts(); + virtual void updatePorts(bool theForce=false); virtual void updateGates(bool theCreate); virtual void setNodeColor(const QColor& theColor); @@ -300,6 +333,12 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona virtual int maxWidth() const; virtual int maxHeight() const; + virtual int minX() const; + virtual int maxX() const; + + virtual int minY() const; + virtual int maxY() const; + virtual int getTitleHeight() const { return myTitleHeight; } void setTitleHeight(int theTitleHeight) { myTitleHeight = theTitleHeight; } @@ -326,8 +365,8 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona double getStoredPercentage() const { return myPercentage; } - virtual void nextTimeIteration(YACS::ENGINE::Node* theEngine=0); - virtual double getPercentage(YACS::ENGINE::Node* theEngine=0) const; + virtual void nextTimeIteration(YACS::ENGINE::Node* theEngine=0); + virtual int getPercentage(YACS::ENGINE::Node* theEngine=0) const; void updateExecTime(YACS::ENGINE::Node* theEngine=0); bool isFinished() const { return myFinished; } @@ -349,6 +388,14 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona bool isCheckAreaNeeded() const { return myIsCheckAreaNeeded; } void setIsCheckAreaNeeded(bool theValue) { myIsCheckAreaNeeded = theValue; } + bool isFullDMode() const; + bool isControlDMode() const; + + bool synchronize( YACSPrs_Port* port, const bool toSelect ); + + //signals: + //void portsChanged(); + protected: void draw(QPainter& thePainter); virtual void drawShape(QPainter& thePainter); @@ -363,7 +410,7 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona SUIT_ResourceMgr* myMgr; - YACS::ENGINE::Node* myEngine; // node engine + YACS::HMI::SubjectNode* mySEngine; // node subject QPixmap myStatePixmap; //QCanvasSprite* mySprite; // for states animation @@ -387,6 +434,9 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona YACSPrs_Hook* myPointMaster; YACSPrs_LabelLink* myLabelLink; + bool mySelfMoving; // field to indicate if node is moving itself + // or as a content of moving Bloc node + // for constraint nodes' moving inside the Bloc--> bool myIsInBloc; QRect myArea; @@ -409,8 +459,6 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona YACSPrs_Hook* myPointOut; bool myMoving; - bool mySelfMoving; // field to indicate if node is moving itself - // or as a content of moving Bloc node bool mySelected; // for update node geometry after import from XML file @@ -424,6 +472,8 @@ class YACSPrs_ElementaryNode : public QxGraph_ActiveItem, public QCanvasPolygona QTime myStartTime; bool myStarted; bool myFinished; + + int myViewMode; }; #endif diff --git a/src/prs/YACSPrs_ForEachLoopNode.cxx b/src/prs/YACSPrs_ForEachLoopNode.cxx index b590e826a..e81d37bd8 100644 --- a/src/prs/YACSPrs_ForEachLoopNode.cxx +++ b/src/prs/YACSPrs_ForEachLoopNode.cxx @@ -31,11 +31,11 @@ using namespace YACS::ENGINE; /*! Constructor */ -YACSPrs_ForEachLoopNode::YACSPrs_ForEachLoopNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode ): - YACSPrs_LoopNode(theMgr, theCanvas, theNode, false) +YACSPrs_ForEachLoopNode::YACSPrs_ForEachLoopNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::HMI::SubjectNode* theSNode ): + YACSPrs_LoopNode(theMgr, theCanvas, theSNode, false) { //updatePorts(); // will be called in moveBy(...) function - moveBy(3*TITLE_HEIGHT/2, 3*TITLE_HEIGHT/2); + moveBy(3*TITLE_HEIGHT/2+NODEBOUNDARY_MARGIN, 3*TITLE_HEIGHT/2+NODEBOUNDARY_MARGIN); } /*! @@ -50,11 +50,37 @@ int YACSPrs_ForEachLoopNode::rtti() const return 0;//YACSPrs_Canvas::Rtti_ForEachLoopNode; } -void YACSPrs_ForEachLoopNode::updatePorts() +void YACSPrs_ForEachLoopNode::updatePorts(bool theForce) { bool aDisp = isVisible(); if (aDisp) hide(); + bool withCreate = theForce; + + if (theForce) + { + if ( isFullDMode() ) + myPortHeight = 2*PORT_MARGIN; + else + myPortHeight = 0; + + myPortList.setAutoDelete(true); + //myPortList.clear(); + + QPtrList aDeletePortList; + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ) ) + { + aDeletePortList.append( aLabelPort ); + withCreate = true; + } + } + + for (YACSPrs_Port* aPort = aDeletePortList.first(); aPort; aPort = aDeletePortList.next()) + myPortList.remove( aPort ); + } + // ForEachLoop has 2 input ports and 2 output ports. // Input ports : 1) 'nbBranches' port, its type is 'int', its value is a number of iterations; // 2) 'SmplsCollection' port, its type is 'sequence' of elelmnts of the given type, @@ -64,94 +90,138 @@ void YACSPrs_ForEachLoopNode::updatePorts() // 2) 'Body' label port, this 'label' port connects with help of label link to // 'Master' hook of the node, which is set as an internal node of the loop. - bool withCreate = false; if ( myPortList.isEmpty() ) withCreate = true; - QRect r = getBodyRect(); - int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; - if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; - - int ix = r.x() + PORT_MARGIN + 1; - int iy = r.y() + PORT_MARGIN;// + 1; - int ox = ix + aPRectWidth + 2*PORT_MARGIN; - int oy = r.y() + PORT_MARGIN;// + 1; - - if ( withCreate ) - { // create (and update) - ForEachLoop* aFELoop = dynamic_cast( myEngine ); - if ( aFELoop ) - { // create 2 input and 1 output ports - // 'nbBranches' - YACSPrs_InOutPort* anIn1Port = new YACSPrs_InOutPort(myMgr,canvas(),aFELoop->edGetNbOfBranchesPort(),this); - anIn1Port->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); - anIn1Port->setColor(nodeSubColor()); - anIn1Port->setStoreColor(nodeSubColor()); - myPortList.append(anIn1Port); - // 'SmplsCollection' - YACSPrs_InOutPort* anIn2Port = new YACSPrs_InOutPort(myMgr,canvas(),aFELoop->edGetSeqOfSamplesPort(),this); - anIn2Port->setPortRect(QRect(ix, iy+PORT_HEIGHT+PORT_SPACE, aPRectWidth, PORT_HEIGHT)); - anIn2Port->setColor(nodeSubColor()); - anIn2Port->setStoreColor(nodeSubColor()); - myPortList.append(anIn2Port); - - myPortHeight += 2*PORT_HEIGHT+PORT_SPACE; - - // 'SmplPtr' - YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),aFELoop->edGetSamplePort(),this); - anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT)); - anOutPort->setColor(nodeSubColor()); - anOutPort->setStoreColor(nodeSubColor()); - myPortList.append(anOutPort); + if ( isFullDMode() ) + { + QRect r = getBodyRect(); + int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; + if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; + + int ix = r.x() + PORT_MARGIN + 1; + int iy = r.y() + PORT_MARGIN;// + 1; + int ox = ix + aPRectWidth + 2*PORT_MARGIN; + int oy = r.y() + PORT_MARGIN;// + 1; + + if ( withCreate ) + { // create (and update) + ForEachLoop* aFELoop = dynamic_cast( getEngine() ); + if ( aFELoop ) + { // create 2 input and 1 output ports + bool isBranchesPortCreated = false; + bool isSeqOfSamplesPortCreated = false; + bool isSamplePortCreated = false; + InputPort* aBranchesPort = aFELoop->edGetNbOfBranchesPort(); + InputPort* aSeqOfSamplesPort = aFELoop->edGetSeqOfSamplesPort(); + OutputPort* aSamplePort = aFELoop->edGetSamplePort(); + + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( !aPort->getName().compare( QString( aBranchesPort->getName() ) ) ) + isBranchesPortCreated = true; + else if( !aPort->getName().compare( QString( aSeqOfSamplesPort->getName() ) ) ) + isSeqOfSamplesPortCreated = true; + else if( !aPort->getName().compare( QString( aSamplePort->getName() ) ) ) + isSamplePortCreated = true; + } + + if( !isBranchesPortCreated ) + { + // 'nbBranches' + YACSPrs_InOutPort* anIn1Port = new YACSPrs_InOutPort(myMgr,canvas(),aBranchesPort,this); + anIn1Port->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); + anIn1Port->setColor(nodeSubColor()); + anIn1Port->setStoreColor(nodeSubColor()); + myPortList.append(anIn1Port); + } + if( !isSeqOfSamplesPortCreated ) + { + // 'SmplsCollection' + YACSPrs_InOutPort* anIn2Port = new YACSPrs_InOutPort(myMgr,canvas(),aSeqOfSamplesPort,this); + anIn2Port->setPortRect(QRect(ix, iy+PORT_HEIGHT+PORT_SPACE, aPRectWidth, PORT_HEIGHT)); + anIn2Port->setColor(nodeSubColor()); + anIn2Port->setStoreColor(nodeSubColor()); + myPortList.append(anIn2Port); + } + + myPortHeight += 2*PORT_HEIGHT; + myPortHeight += PORT_SPACE; + + if( !isSamplePortCreated ) + { + // 'SmplPtr' + YACSPrs_InOutPort* anOutPort = new YACSPrs_InOutPort(myMgr,canvas(),aSamplePort,this); + anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT)); + anOutPort->setColor(nodeSubColor()); + anOutPort->setStoreColor(nodeSubColor()); + myPortList.append(anOutPort); + } - // get a set of internal loop nodes (in fact ForEachLoop has 2 internal nodes: _node and _initNode, - // but only _node was initialized in engine, in all examples _initNode is null) - std::set aNodes = aFELoop->edGetDirectDescendants(); - std::set::iterator aNodesIter = aNodes.begin(); - for (; aNodesIter != aNodes.end(); aNodesIter++) - { // output label port - YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aNodesIter,this); - anOutPort->setPortRect(QRect(ox, oy+PORT_HEIGHT+PORT_SPACE, aPRectWidth, PORT_HEIGHT)); - anOutPort->setColor(nodeSubColor().dark(140)); - anOutPort->setStoreColor(nodeSubColor().dark(140)); - myPortList.append(anOutPort); - oy += PORT_HEIGHT+PORT_SPACE; + // get a set of internal loop nodes (in fact ForEachLoop has 2 internal nodes: _node and _initNode, + // but only _node was initialized in engine, in all examples _initNode is null) + std::list aNodes = aFELoop->edGetDirectDescendants(); + std::list::iterator aNodesIter = aNodes.begin(); + for (; aNodesIter != aNodes.end(); aNodesIter++) + { // output label port + YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aNodesIter,this); + anOutPort->setPortRect(QRect(ox, oy+PORT_HEIGHT+PORT_SPACE, aPRectWidth, PORT_HEIGHT)); + anOutPort->setColor(nodeSubColor().dark(140)); + anOutPort->setStoreColor(nodeSubColor().dark(140)); + myPortList.append(anOutPort); + } } - if ( aNodes.size() > 1 ) - myPortHeight += (aNodes.size()-1)*PORT_HEIGHT + (aNodes.size()-2)*PORT_SPACE; } - } - else - { // only update - YACSPrs_Port* aPort; - for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) - { - YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); - if ( anIOPort ) - { - if ( !anIOPort->isGate() ) - { - if ( anIOPort->isInput() ) - { // input data (i.e. not Gate) ports - anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); - iy += PORT_HEIGHT+PORT_SPACE; - } - else - { // output data (i.e. not Gate) ports - anIOPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); - oy += PORT_HEIGHT+PORT_SPACE; + else + { // only update + YACSPrs_Port* aPort; + for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); + if ( anIOPort ) + { + if ( !anIOPort->isGate() ) + { + if ( anIOPort->isInput() ) + { // input data (i.e. not Gate) ports + anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); + iy += PORT_HEIGHT+PORT_SPACE; + } + else + { // output data (i.e. not Gate) ports + anIOPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); + oy += PORT_HEIGHT+PORT_SPACE; + } } } - } - else - { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort (output!) => we not need to dynamic cast - aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); - oy += PORT_HEIGHT+PORT_SPACE; + else + { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort (output!) => we not need to dynamic cast + aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); + oy += PORT_HEIGHT+PORT_SPACE; + } } } } - + // can update gates only after body height will be defined - updateGates(withCreate); + bool createGates = withCreate; + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ) ) + { + if ( anIOPort->isGate() ) + { // gate ports are already created - we should only update them + createGates = false; + break; + } + } + } + updateGates(createGates); + + if (theForce && myPointMaster) + { + QPoint aPnt = getConnectionMasterPoint(); + myPointMaster->setCoords(aPnt.x(), aPnt.y()); + } if (aDisp) show(); } @@ -165,17 +235,17 @@ void YACSPrs_ForEachLoopNode::updatePorts() void YACSPrs_ForEachLoopNode::nextTimeIteration(YACS::ENGINE::Node* theEngine) { bool nullifyOnToActivate = false; - if ( !theEngine ) theEngine = myEngine; + if ( !theEngine ) theEngine = getEngine(); else nullifyOnToActivate = true; if ( theEngine && - ( theEngine->getState() == YACS::INITED || theEngine->getEffectiveState() == YACS::INITED + ( theEngine->getState() == YACS::READY /*|| theEngine->getEffectiveState() == YACS::READY*/ || ( nullifyOnToActivate && ( theEngine->getState() == YACS::TOACTIVATE || theEngine->getEffectiveState() == YACS::TOACTIVATE) ) ) ) setTimeIteration( 0. ); else if ( theEngine && - theEngine->getState() != YACS::INITED && theEngine->getEffectiveState() != YACS::INITED && + theEngine->getState() != YACS::READY /*&& theEngine->getEffectiveState() != YACS::READY*/ && !isFinished() ) { if ( ForEachLoop* aLoop = dynamic_cast( theEngine ) ) setTimeIteration( aLoop->getExecCurrentId()-1. >= 0 ? aLoop->getExecCurrentId()-1. : 0. ); @@ -188,21 +258,21 @@ void YACSPrs_ForEachLoopNode::nextTimeIteration(YACS::ENGINE::Node* theEngine) * * \param theEngine : the engine of clone node from which we have to update presentation of this node. */ -double YACSPrs_ForEachLoopNode::getPercentage(YACS::ENGINE::Node* theEngine) const +int YACSPrs_ForEachLoopNode::getPercentage(YACS::ENGINE::Node* theEngine) const { - if ( !theEngine ) theEngine = myEngine; + if ( !theEngine ) theEngine = getEngine(); - if ( !theEngine ) return 0.; + if ( !theEngine ) return 0; - if ( theEngine->getState() == YACS::INITED || theEngine->getEffectiveState() == YACS::INITED || + if ( theEngine->getState() == YACS::READY || /*theEngine->getEffectiveState() == YACS::READY ||*/ theEngine->getState() == YACS::TOLOAD || theEngine->getEffectiveState() == YACS::TOLOAD ) - return 0.; + return 0; if ( theEngine->getState() == YACS::DONE ) - return 100.; + return 100; if ( ForEachLoop* aLoop = dynamic_cast( theEngine ) ) { SeqAnyInputPort* aCollection = dynamic_cast( aLoop->edGetSeqOfSamplesPort() ); if ( aCollection && !aCollection->isEmpty() ) - return 100. / aCollection->getNumberOfElements() * getTimeIteration(); + return (int)( 100. / aCollection->getNumberOfElements() * getTimeIteration() ); } - return 0.; + return 0; } diff --git a/src/prs/YACSPrs_ForEachLoopNode.h b/src/prs/YACSPrs_ForEachLoopNode.h index 18b20a78e..a8657050a 100644 --- a/src/prs/YACSPrs_ForEachLoopNode.h +++ b/src/prs/YACSPrs_ForEachLoopNode.h @@ -23,7 +23,7 @@ class YACSPrs_ForEachLoopNode : public YACSPrs_LoopNode { public: - YACSPrs_ForEachLoopNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node*); + YACSPrs_ForEachLoopNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode*); virtual ~YACSPrs_ForEachLoopNode(); /* reimplement functions from QxGraph_ActiveItem */ @@ -31,10 +31,10 @@ class YACSPrs_ForEachLoopNode : public YACSPrs_LoopNode { virtual int rtti() const; - virtual void updatePorts(); + virtual void updatePorts(bool theForce=false); - virtual void nextTimeIteration(YACS::ENGINE::Node* theEngine=0); - virtual double getPercentage(YACS::ENGINE::Node* theEngine=0) const; + virtual void nextTimeIteration(YACS::ENGINE::Node* theEngine=0); + virtual int getPercentage(YACS::ENGINE::Node* theEngine=0) const; }; #endif diff --git a/src/prs/YACSPrs_IfNode.cxx b/src/prs/YACSPrs_IfNode.cxx index 4d40396f4..e0743bd8d 100644 --- a/src/prs/YACSPrs_IfNode.cxx +++ b/src/prs/YACSPrs_IfNode.cxx @@ -27,8 +27,8 @@ /*! Constructor */ -YACSPrs_IfNode::YACSPrs_IfNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode ): - YACSPrs_InlineNode(theMgr, theCanvas, theNode) +YACSPrs_IfNode::YACSPrs_IfNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::HMI::SubjectNode* theSNode ): + YACSPrs_InlineNode(theMgr, theCanvas, theSNode) { setNodeColor(IFNODE_COLOR); setNodeSubColor(IFNODE_SUBCOLOR); diff --git a/src/prs/YACSPrs_IfNode.h b/src/prs/YACSPrs_IfNode.h index 089b62005..0a0aa5044 100644 --- a/src/prs/YACSPrs_IfNode.h +++ b/src/prs/YACSPrs_IfNode.h @@ -23,7 +23,7 @@ class YACSPrs_IfNode : public YACSPrs_InlineNode { public: - YACSPrs_IfNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node* ); + YACSPrs_IfNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode* ); virtual ~YACSPrs_IfNode(); /* reimplement functions from QxGraph_ActiveItem */ diff --git a/src/prs/YACSPrs_InlineNode.cxx b/src/prs/YACSPrs_InlineNode.cxx index 101f5517f..58104733b 100644 --- a/src/prs/YACSPrs_InlineNode.cxx +++ b/src/prs/YACSPrs_InlineNode.cxx @@ -58,8 +58,9 @@ void drawText2(QPainter& thePainter, const QString& theText, /*! Constructor */ -YACSPrs_InlineNode::YACSPrs_InlineNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode, const bool& thePortUpdate): - YACSPrs_ElementaryNode(theMgr, theCanvas, theNode) +YACSPrs_InlineNode::YACSPrs_InlineNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, + YACS::HMI::SubjectNode* theSNode, const bool& thePortUpdate): + YACSPrs_ElementaryNode(theMgr, theCanvas, theSNode) { setNodeColor(INLINENODE_COLOR); setNodeSubColor(INLINENODE_SUBCOLOR); @@ -73,7 +74,7 @@ YACSPrs_InlineNode::YACSPrs_InlineNode(SUIT_ResourceMgr* theMgr, QCanvas* theCan if ( thePortUpdate ) { //updatePorts(); // will be called in moveBy(...) function - moveBy(2*HOOKPOINT_SIZE,0); + moveBy(2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN,2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN); } update(); @@ -107,6 +108,10 @@ QPointArray YACSPrs_InlineNode::constructAreaPoints(int theW, int theH) const int YACSPrs_InlineNode::getInfoHeight() const { + if ( isControlDMode() ) + return getTitleHeight() + NODE_SPACE; + + // Full view by default return getTitleHeight() + NODE_SPACE + getStatusHeight() + NODE_SPACE + getTimeHeight(); @@ -114,6 +119,11 @@ int YACSPrs_InlineNode::getInfoHeight() const QRect YACSPrs_InlineNode::getTitleRect() const { + if ( isControlDMode() ) + return QRect((int)x()+NODE_MARGIN+getCorner(), (int)y()+NODE_MARGIN, + width()-2*NODE_MARGIN-getCorner(), getTitleHeight()); + + // Full view by default return QRect((int)x()+NODE_MARGIN+getCorner(), (int)y()+NODE_MARGIN, width()-3*NODE_MARGIN-getCorner()-getPixMapWidth(), getTitleHeight()); } @@ -149,55 +159,70 @@ int YACSPrs_InlineNode::getCorner() const void YACSPrs_InlineNode::drawTitleShape(QPainter& thePainter) { // draw information: title, status, time + QBrush savedB = thePainter.brush(); + QPen savedP = thePainter.pen(); thePainter.setPen(thePainter.brush().color().dark(140)); // title thePainter.drawRoundRect(getTitleRect(),myXRnd,myYRnd); - // status - thePainter.drawRoundRect(getStatusRect(),myXRnd,myYRnd); - // time - thePainter.drawRoundRect(getTimeRect(),myXRnd,myYRnd); - // draw progress bar - thePainter.setPen(NoPen); - - QBrush savedB = thePainter.brush(); - - thePainter.setBrush(savedB.color().light(130)); - thePainter.drawRect(getWholeRect()); - - if ( getPercentRect().width() > 1 ) { - thePainter.setBrush(savedB.color().dark(160)); - thePainter.drawRect(getPercentRect()); + if ( isFullDMode() ) + { + // status + thePainter.drawRoundRect(getStatusRect(),myXRnd,myYRnd); + // time + thePainter.drawRoundRect(getTimeRect(),myXRnd,myYRnd); + + // draw progress bar + thePainter.setPen(NoPen); + + //savedB = thePainter.brush(); + + thePainter.setBrush(savedB.color().light(130)); + thePainter.drawRect(getWholeRect()); + + if ( getPercentRect().width() > 1 ) { + thePainter.setBrush(savedB.color().dark(160)); + thePainter.drawRect(getPercentRect()); + } + + thePainter.setBrush(savedB); } - - thePainter.setBrush(savedB); // draw texts thePainter.setPen(Qt::white); - drawText2(thePainter, QString(myEngine->getName()), getTitleRect(), Qt::AlignLeft); - drawText2(thePainter, myStatus, getStatusRect(), Qt::AlignLeft); - drawText2(thePainter, myTime, getTimeRect(), Qt::AlignLeft); - drawText2(thePainter, QString::number(( (getStoredPercentage() < 0) ? getPercentage() : getStoredPercentage() ))+QString("%"), getTimeRect(), Qt::AlignRight); // percentage - + if ( isControlDMode() ) + drawText2(thePainter, QString(getEngine()->getName()), getTitleRect(), Qt::AlignHCenter); + else if ( isFullDMode() ) + { + drawText2(thePainter, QString(getEngine()->getName()), getTitleRect(), Qt::AlignLeft); + drawText2(thePainter, myStatus, getStatusRect(), Qt::AlignLeft); + drawText2(thePainter, myTime, getTimeRect(), Qt::AlignLeft); + drawText2(thePainter, QString::number(( (getStoredPercentage() < 0) ? getPercentage() : getStoredPercentage() ), 'g', 4)+QString("%"), + getTimeRect(), Qt::AlignRight); // percentage + } + thePainter.setPen(savedP); - // draw pixmap - thePainter.setBrush(NoBrush); - - int aXRnd = getTitleRect().width()*myXRnd/getPixmapRect().width(); - int aYRnd = getTitleRect().height()*myYRnd/getPixmapRect().height(); - thePainter.drawRoundRect(getPixmapRect(),aXRnd,aYRnd); - QRect aPRect = getPixmapRect(); - aPRect.setX(aPRect.x()+PIXMAP_MARGIN+2); - aPRect.setY(aPRect.y()+PIXMAP_MARGIN); - aPRect.setWidth(aPRect.width()-2*PIXMAP_MARGIN); - aPRect.setHeight(aPRect.height()-2*PIXMAP_MARGIN); - thePainter.drawPixmap(aPRect,myStatePixmap); - - thePainter.setBrush(savedB); + if ( isFullDMode() ) + { + // draw pixmap + thePainter.setBrush(NoBrush); + + int aXRnd = getTitleRect().width()*myXRnd/getPixmapRect().width(); + int aYRnd = getTitleRect().height()*myYRnd/getPixmapRect().height(); + thePainter.drawRoundRect(getPixmapRect(),aXRnd,aYRnd); + QRect aPRect = getPixmapRect(); + aPRect.setX(aPRect.x()+PIXMAP_MARGIN+2); + aPRect.setY(aPRect.y()+PIXMAP_MARGIN); + aPRect.setWidth(aPRect.width()-2*PIXMAP_MARGIN); + aPRect.setHeight(aPRect.height()-2*PIXMAP_MARGIN); + thePainter.drawPixmap(aPRect,myStatePixmap); + + thePainter.setBrush(savedB); + } } void YACSPrs_InlineNode::drawFrame(QPainter& thePainter) diff --git a/src/prs/YACSPrs_InlineNode.h b/src/prs/YACSPrs_InlineNode.h index d581a905a..55e04e902 100644 --- a/src/prs/YACSPrs_InlineNode.h +++ b/src/prs/YACSPrs_InlineNode.h @@ -23,7 +23,7 @@ class YACSPrs_InlineNode : public YACSPrs_ElementaryNode { public: - YACSPrs_InlineNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node*, const bool& thePortUpdate=true ); + YACSPrs_InlineNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode*, const bool& thePortUpdate=true ); virtual ~YACSPrs_InlineNode(); /* reimplement functions from QxGraph_ActiveItem */ diff --git a/src/prs/YACSPrs_Link.cxx b/src/prs/YACSPrs_Link.cxx index 76073e623..9898cea10 100644 --- a/src/prs/YACSPrs_Link.cxx +++ b/src/prs/YACSPrs_Link.cxx @@ -22,12 +22,29 @@ #include "YACSPrs_Link.h" #include "YACSPrs_Def.h" +#include "guiContext.hxx" + #include "SUIT_ResourceMgr.h" #include "SUIT_Session.h" #include "CAM_Application.h" +#include "InGate.hxx" +#include "InPort.hxx" +#include "OutGate.hxx" +#include "OutPort.hxx" +#include + #include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::HMI; +using namespace YACS::ENGINE; + +using namespace std; /*! * =========================== YACSPrs_Link =========================== @@ -47,17 +64,20 @@ YACSPrs_Link::YACSPrs_Link( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas ): YACSPrs_Link::~YACSPrs_Link() { - // TO DO : check commented code if link is deleted - //for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) { - //(*it)->hide(); - //delete *it; - //} + DEBTRACE("YACSPrs_Link::~YACSPrs_Link"); + // remove presentation objects (points and edges) + for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) { + (*it)->setCanvas(0); + delete *it; + } + myPrs.clear(); myPoints.clear(); } void YACSPrs_Link::show() { + DEBTRACE("YACSPrs_Link::show"); if (myPrs.isEmpty()) createPrs(); for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) { @@ -65,8 +85,19 @@ void YACSPrs_Link::show() } } +void YACSPrs_Link::hide() +{ + DEBTRACE("YACSPrs_Link::hide"); + if (myPrs.isEmpty()) return; + + for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) { + (*it)->hide(); + } +} + void YACSPrs_Link::merge() { + DEBTRACE("YACSPrs_Link::merge"); // save z of the link double aZ = ( !myPrs.isEmpty() ? myPrs.first()->z()-1 : 0 ); // the first item is a point @@ -84,6 +115,15 @@ void YACSPrs_Link::merge() setZ(aZ); } +void YACSPrs_Link::setCanvas(QCanvas* theCanvas) +{ + myCanvas = theCanvas; + + // set canvas for all prs items + for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) + (*it)->setCanvas(theCanvas); +} + void YACSPrs_Link::updatePoints(QCanvasItem* thePointItem) { if ( thePointItem == myPrs.first() || thePointItem == myPrs.last() ) return; @@ -91,7 +131,7 @@ void YACSPrs_Link::updatePoints(QCanvasItem* thePointItem) YACSPrs_Point* aPoint = dynamic_cast( thePointItem ); if ( aPoint ) { - std::list::iterator it; + list::iterator it; int id = 1; for ( it = myPoints.begin(); it != myPoints.end(); it++, id++ ) if ( id == aPoint->getIndex() ) { @@ -113,7 +153,7 @@ void YACSPrs_Link::setHilighted(bool state) for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) { (*it)->hide(); (*it)->show(); } - myCanvas->update(); + if (myCanvas) myCanvas->update(); } } } @@ -130,7 +170,7 @@ void YACSPrs_Link::setSelected(bool state) else if ( YACSPrs_Edge* anEdge = dynamic_cast( *it ) ) anEdge->setSelected(state); (*it)->hide(); (*it)->show(); } - myCanvas->update(); + if (myCanvas) myCanvas->update(); } } } @@ -164,6 +204,7 @@ void YACSPrs_Link::remove() { } void YACSPrs_Link::addPoint() { + DEBTRACE("YACSPrs_Link::addPoint"); if ( mySelected ) setSelected(false); YACSPrs_Edge* anEdge = dynamic_cast( mySelectedItem ); @@ -183,7 +224,7 @@ void YACSPrs_Link::addPoint() { if ( myPoints.empty() ) myPoints.push_back(mySelectedPoint); else { - std::list::iterator it; + list::iterator it; int id = 0; for ( it = myPoints.begin(); it != myPoints.end(); it++, id++ ) if ( id == anIndex-1 ) break; @@ -191,7 +232,14 @@ void YACSPrs_Link::addPoint() { } merge(); - myCanvas->update(); + if (myCanvas) myCanvas->update(); + + /* + GuiContext* aContext = GuiContext::getCurrent(); + if ( aContext ) + if ( aContext->getSubjectProc() ) + aContext->getSubjectProc()->update( EDIT, DATALINK, 0 ); + */ } } @@ -205,7 +253,14 @@ void YACSPrs_Link::removePoint() { myPoints.remove(aP); merge(); - myCanvas->update(); + if (myCanvas) myCanvas->update(); + + /* + GuiContext* aContext = GuiContext::getCurrent(); + if ( aContext ) + if ( aContext->getSubjectProc() ) + aContext->getSubjectProc()->update( EDIT, DATALINK, 0 ); + */ } } @@ -239,9 +294,18 @@ double YACSPrs_Link::getMyZ() void YACSPrs_Link::setZ(double z) { + DEBTRACE("YACSPrs_Link::setZ: " << z); for (QCanvasItemList::Iterator it = myPrs.begin(); it != myPrs.end(); ++it) - if ( dynamic_cast( *it ) ) (*it)->setZ(z+1); - else if ( dynamic_cast( *it ) ) (*it)->setZ(z); + if ( YACSPrs_Point* pt=dynamic_cast( *it ) ) + { + DEBTRACE("YACSPrs_Link::setZ: " << z); + pt->setZ(z+1); + } + else if (YACSPrs_Edge* ed= dynamic_cast( *it ) ) + { + DEBTRACE("YACSPrs_Link::setZ: " << z); + ed->setZ(z); + } } double YACSPrs_Link::z() @@ -252,6 +316,7 @@ double YACSPrs_Link::z() QPoint YACSPrs_Link::getConnectionPoint(YACSPrs_Port* thePort) { + DEBTRACE("YACSPrs_Link::getConnectionPoint"); QPoint aCP; YACSPrs_InOutPort* anIOPort = dynamic_cast( thePort ); @@ -273,6 +338,7 @@ QPoint YACSPrs_Link::getConnectionPoint(YACSPrs_Port* thePort) void YACSPrs_Link::addPoint(const QPoint& thePoint, const int& theIndex) { + DEBTRACE("YACSPrs_Link::addPoint"); YACSPrs_Point* aPoint; if (myPrs.empty()) { aPoint = new YACSPrs_Point(myCanvas, this, theIndex); @@ -310,23 +376,101 @@ YACSPrs_PortLink::YACSPrs_PortLink( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACSPrs_InOutPort* theInputPort, YACSPrs_InOutPort* theOutputPort ): + GuiObserver(), YACSPrs_Link(theMgr, theCanvas), myInputPort(theInputPort), myOutputPort(theOutputPort) { - printf("Construct YACSPrs_PortLink\n"); + DEBTRACE("Construct YACSPrs_PortLink"); + //change color if datastream link + if ( dynamic_cast(theInputPort->getEngine())) + myColor = myMgr->colorValue("YACSGui", "stream_link_draw_color", STREAMLINKDRAW_COLOR); + if (myInputPort) myInputPort->addLink(this); if (myOutputPort) myOutputPort->addLink(this); + + // attach to HMI myself + Subject* aSub = getSubject(); + if ( aSub ) + aSub->attach( this ); } YACSPrs_PortLink::~YACSPrs_PortLink() { - if (myInputPort) myInputPort->removeLink(this); - if (myOutputPort) myOutputPort->removeLink(this); + // detach from HMI + YACS::HMI::Subject* aSub = getSubject(); + if ( aSub ) + aSub->detach(this); + + if (myInputPort) { + myInputPort->removeLink(this); + myInputPort = 0; + } + if (myOutputPort) { + myOutputPort->removeLink(this); + myOutputPort = 0; + } +} + +void YACSPrs_PortLink::select( bool isSelected ) +{ + DEBTRACE(">> YACSPrs_PortLink::select"); + setSelected(isSelected); +} + +void YACSPrs_PortLink::update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son) +{ + DEBTRACE(">> YACSPrs_PortLink::update"); +} + +YACS::HMI::Subject* YACSPrs_PortLink::getSubject() const +{ + Subject* aSub = 0; + + if ( !myOutputPort || !myInputPort ) return aSub; + + if ( !myOutputPort->isGate() && !myInputPort->isGate() ) // data link + { + OutPort* anOP = dynamic_cast( myOutputPort->getEngine() ); + InPort* anIP = dynamic_cast( myInputPort->getEngine() ); + if ( anOP && anIP ) + { + GuiContext* aContext = GuiContext::getCurrent(); + if ( aContext ) + { + pair aPair(anOP,anIP); + if ( aContext->_mapOfSubjectLink.find( aPair ) != aContext->_mapOfSubjectLink.end() ) + aSub = aContext->_mapOfSubjectLink[ aPair ]; + } + } + } + else // control link + { + OutGate* anOG = dynamic_cast( myOutputPort->getEngine() ); + InGate* anIG = dynamic_cast( myInputPort->getEngine() ); + if ( anOG && anIG ) + { + Node* anON = anOG->getNode(); + Node* anIN = anIG->getNode(); + if ( anON && anIN ) + { + GuiContext* aContext = GuiContext::getCurrent(); + if ( aContext ) + { + pair aPair(anON,anIN); + if ( aContext->_mapOfSubjectControlLink.find( aPair ) != aContext->_mapOfSubjectControlLink.end() ) + aSub = aContext->_mapOfSubjectControlLink[ aPair ]; + } + } + } + } + + return aSub; } void YACSPrs_PortLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLinkPoints, QRect theArea) { + DEBTRACE("YACSPrs_PortLink::moveByPort"); YACSPrs_InOutPort* aPort = dynamic_cast( thePort ); if ( aPort ) { @@ -335,10 +479,10 @@ void YACSPrs_PortLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLin if ( theMoveInternalLinkPoints ) { // choose and collect only those points from myPoints, which is inside of theArea - std::map anIndex2MovePointMap; + map anIndex2MovePointMap; int id = 1; - for ( std::list::iterator it = myPoints.begin(); it != myPoints.end(); it++, id++) - if ( theArea.contains(*it,true) ) anIndex2MovePointMap.insert(std::make_pair(id,*it)); + for ( list::iterator it = myPoints.begin(); it != myPoints.end(); it++, id++) + if ( theArea.contains(*it,true) ) anIndex2MovePointMap.insert(make_pair(id,*it)); if ( !anIndex2MovePointMap.empty() ) { @@ -379,6 +523,7 @@ void YACSPrs_PortLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLin void YACSPrs_PortLink::moveByPort(YACSPrs_Port* thePort, int dx, int dy) { + DEBTRACE("YACSPrs_PortLink::moveByPort " << dx << "," << dy); YACSPrs_InOutPort* aPort = dynamic_cast( thePort ); if ( aPort ) { @@ -420,16 +565,17 @@ void YACSPrs_PortLink::remove() { aPort->setValue(aValue); }*/ - myCanvas->update(); + if (myCanvas) myCanvas->update(); } void YACSPrs_PortLink::createPrs() { + DEBTRACE("YACSPrs_PortLink::createPrs"); // create without internal points now if ( myInputPort ) addPoint(getConnectionPoint(myInputPort),0); int i = 1; - for ( std::list::iterator it = myPoints.begin(); it != myPoints.end(); it++, i++ ) + for ( list::iterator it = myPoints.begin(); it != myPoints.end(); it++, i++ ) addPoint(*it, i); if ( myOutputPort ) addPoint(getConnectionPoint(myOutputPort),myPoints.size()+1); @@ -499,7 +645,7 @@ YACSPrs_LabelLink::YACSPrs_LabelLink( SUIT_ResourceMgr* theMgr, myOutputPort(theOutputPort), mySlaveNode(theSlaveNode) { - printf("Construct YACSPrs_LabelLink\n"); + DEBTRACE("Construct YACSPrs_LabelLink"); if (myOutputPort) myOutputPort->addLink(this); if (mySlaveNode) { @@ -511,12 +657,19 @@ YACSPrs_LabelLink::YACSPrs_LabelLink( SUIT_ResourceMgr* theMgr, YACSPrs_LabelLink::~YACSPrs_LabelLink() { - if (myOutputPort) myOutputPort->removeLink(this); - if (mySlaveNode) mySlaveNode->removeLabelLink(); + if (myOutputPort) { + myOutputPort->removeLink(this); + myOutputPort = 0; + } + if (mySlaveNode) { + mySlaveNode->removeLabelLink(); + mySlaveNode = 0; + } } void YACSPrs_LabelLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLinkPoints, QRect theArea) { + DEBTRACE("YACSPrs_LabelLink::moveByPort"); YACSPrs_LabelPort* aPort = dynamic_cast( thePort ); if ( aPort ) { @@ -525,10 +678,10 @@ void YACSPrs_LabelLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLi if ( theMoveInternalLinkPoints ) { // choose and collect only those points from myPoints, which is inside of theArea - std::map anIndex2MovePointMap; + map anIndex2MovePointMap; int id = 1; - for ( std::list::iterator it = myPoints.begin(); it != myPoints.end(); it++, id++) - if ( theArea.contains(*it,true) ) anIndex2MovePointMap.insert(std::make_pair(id,*it)); + for ( list::iterator it = myPoints.begin(); it != myPoints.end(); it++, id++) + if ( theArea.contains(*it,true) ) anIndex2MovePointMap.insert(make_pair(id,*it)); if ( !anIndex2MovePointMap.empty() ) { @@ -557,6 +710,7 @@ void YACSPrs_LabelLink::moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLi void YACSPrs_LabelLink::moveByPort(YACSPrs_Port* thePort, int dx, int dy) { + DEBTRACE("YACSPrs_LabelLink::moveByPort " << dx << "," << dy); YACSPrs_LabelPort* aPort = dynamic_cast( thePort ); if ( aPort ) { @@ -598,7 +752,7 @@ void YACSPrs_LabelLink::remove() { // TO DO : remove slave node from the switch case or loop body YACSPrs_Link::remove(); - myCanvas->update(); + if (myCanvas) myCanvas->update(); } QPoint YACSPrs_LabelLink::getConnectionMasterPoint() @@ -615,7 +769,7 @@ void YACSPrs_LabelLink::createPrs() if ( mySlaveNode ) addPoint(getConnectionMasterPoint(),0); int i = 1; - for ( std::list::iterator it = myPoints.begin(); it != myPoints.end(); it++, i++ ) + for ( list::iterator it = myPoints.begin(); it != myPoints.end(); it++, i++ ) addPoint(*it, i); if ( myOutputPort ) addPoint(getConnectionPoint(myOutputPort),myPoints.size()+1); @@ -705,7 +859,16 @@ void YACSPrs_Point::select(const QPoint& theMousePos, const bool toSelect) hilight(theMousePos, false); if (YACSPrs_Link* aLink = getLink()) + { aLink->setSelected(toSelect); + + YACSPrs_PortLink* aPLink = dynamic_cast(aLink); + if ( !aPLink ) return; + + Subject* aSub = aPLink->getSubject(); + if ( aSub ) + aSub->select(toSelect); + } } void YACSPrs_Point::showPopup(QWidget* theParent, QMouseEvent* theEvent, const QPoint& theMousePos) @@ -771,7 +934,7 @@ void YACSPrs_Point::moveBy(double dx, double dy) if (myInEdge) myInEdge->setFromPoint(this); if (myOutEdge) myOutEdge->setToPoint(this); - if ( getLink() && !getLink()->isEmptyPrs() ) { + if ( canvas() && getLink() && !getLink()->isEmptyPrs() ) { //resize canvas view if mouse is outside int w = (int)(x()+dx) + width() + GRAPH_MARGIN; int h = (int)(y()+dy) + height() + GRAPH_MARGIN; @@ -799,9 +962,17 @@ YACSPrs_Edge::YACSPrs_Edge(QCanvas* theCanvas, myLink(theLink), myStartPoint(0), myEndPoint(0), mySelected(false) { + myArrow=new QCanvasPolygon(theCanvas); setZ(-2); } +YACSPrs_Edge::~YACSPrs_Edge() +{ + DEBTRACE("YACSPrs_Edge::~YACSPrs_Edge"); + myArrow->setCanvas(0); + delete myArrow; +} + bool YACSPrs_Edge::isMoveable() { if ( myStartPoint && ( myLink->isFirst(myStartPoint) || myLink->isLast(myStartPoint) ) @@ -826,7 +997,16 @@ void YACSPrs_Edge::select(const QPoint& theMousePos, const bool toSelect) hilight(theMousePos, false); if (YACSPrs_Link* aLink = getLink()) + { aLink->setSelected(toSelect); + + YACSPrs_PortLink* aPLink = dynamic_cast(aLink); + if ( !aPLink ) return; + + Subject* aSub = aPLink->getSubject(); + if ( aSub ) + aSub->select(toSelect); + } } void YACSPrs_Edge::showPopup(QWidget* theParent, QMouseEvent* theEvent, const QPoint& theMousePos) @@ -873,23 +1053,29 @@ int YACSPrs_Edge::rtti() const void YACSPrs_Edge::setFromPoint(YACSPrs_Point* thePoint) { + DEBTRACE("YACSPrs_Edge::setFromPoint"); myStartPoint = thePoint; setPoints((int)(thePoint->x()), (int)(thePoint->y()), endPoint().x(), endPoint().y()); + setArrow(); } void YACSPrs_Edge::setToPoint(YACSPrs_Point* thePoint) { + DEBTRACE("YACSPrs_Edge::setToPoint"); myEndPoint = thePoint; setPoints(startPoint().x(), startPoint().y(), (int)(thePoint->x()), (int)(thePoint->y())); + setArrow(); } void YACSPrs_Edge::setColor(const QColor& theColor) { setPen(QPen(theColor, LINKEDGE_WIDTH)); + myArrow->setBrush(theColor); } void YACSPrs_Edge::moveBy(double dx, double dy) { + DEBTRACE("YACSPrs_Edge::moveBy " << dx << "," << dy); // for moving segment of link if (myStartPoint && myEndPoint) { myStartPoint->setMoving(true); @@ -898,4 +1084,59 @@ void YACSPrs_Edge::moveBy(double dx, double dy) myEndPoint->setMoving(true); myEndPoint->moveBy(dx,dy); } + setArrow(); +} + +void YACSPrs_Edge::setZ(double z) +{ + DEBTRACE("YACSPrs_Edge::setZ: " << z); + QCanvasLine::setZ(z); + myArrow->setZ(z); +} + +void YACSPrs_Edge::setVisible(bool on) +{ + DEBTRACE("YACSPrs_Edge::setVisible " << this << ","<setVisible(on); +} + +void YACSPrs_Edge::setArrow() +{ + DEBTRACE("YACSPrs_Edge::setArrow"); + int x1=startPoint().x(); + int y1=startPoint().y(); + int x2=endPoint().x(); + int y2=endPoint().y(); + DEBTRACE(x1 << "," << y1 << "," << x2 << "," << y2 ); + double d=hypot(x2-x1,y2-y1); + double x=(x1+x2)/2.; + double y=(y1+y2)/2.; + + //size of arrow + double l=0.,e=0.; + double sina=0.; + double cosa=1.; + if(d > 12) + { + l=12.; + e=6.; + sina=(y2-y1)/d; + cosa=(x2-x1)/d; + } + DEBTRACE(x << "," << y << "," << sina << "," << cosa ); + + QPointArray pa=QPointArray(3); + pa.setPoint(0, QPoint((int)(x+l*cosa),(int)(y+l*sina))); + pa.setPoint(1, QPoint((int)(x-e*sina),(int)(y+e*cosa))); + pa.setPoint(2, QPoint((int)(x+e*sina),(int)(y-e*cosa))); + myArrow->setPoints(pa); + myArrow->setZ(z()); +} + +void YACSPrs_Edge::setCanvas(QCanvas* theCanvas) +{ + DEBTRACE("YACSPrs_Edge::setCanvas"); + QCanvasLine::setCanvas(theCanvas); + myArrow->setCanvas(theCanvas); } diff --git a/src/prs/YACSPrs_Link.h b/src/prs/YACSPrs_Link.h index 0a8d8f006..f8ee4d7d4 100644 --- a/src/prs/YACSPrs_Link.h +++ b/src/prs/YACSPrs_Link.h @@ -20,6 +20,8 @@ #ifndef YACSPRS_LINK_H #define YACSPRS_LINK_H +#include + #include "QxGraph_ActiveItem.h" #include @@ -40,8 +42,11 @@ class YACSPrs_Link : public QObject { virtual ~YACSPrs_Link(); void show(); + void hide(); void merge(); + void setCanvas(QCanvas* theCanvas); + std::list getPoints() const { return myPoints; } void setPoints(std::list thePoints) { myPoints = thePoints; } void updatePoints(QCanvasItem* thePointItem); @@ -101,12 +106,17 @@ class YACSPrs_Link : public QObject { double myZ; }; -class YACSPrs_PortLink : public YACSPrs_Link { +class YACSPrs_PortLink : public YACSPrs_Link, public YACS::HMI::GuiObserver { public: YACSPrs_PortLink(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACSPrs_InOutPort* theInputPort, YACSPrs_InOutPort* theOutputPort); virtual ~YACSPrs_PortLink(); + virtual void select( bool isSelected ); + virtual void update( YACS::HMI::GuiEvent event, int type, YACS::HMI::Subject* son); + + YACS::HMI::Subject* getSubject() const; + virtual void moveByPort(YACSPrs_Port* thePort, bool theMoveInternalLinkPoints=false, QRect theArea=QRect()); virtual void moveByPort(YACSPrs_Port* thePort, int dx, int dy); @@ -220,7 +230,7 @@ class YACSPrs_Edge : public QxGraph_ActiveItem, public QCanvasLine { public: YACSPrs_Edge(QCanvas* theCanvas, YACSPrs_Link* theLink); - ~YACSPrs_Edge() {} + ~YACSPrs_Edge(); /* reimplement functions from QxGraph_ActiveItem */ virtual bool isMoveable(); @@ -231,6 +241,7 @@ class YACSPrs_Edge : public QxGraph_ActiveItem, public QCanvasLine { virtual void showPopup(QWidget* theParent, QMouseEvent* theEvent, const QPoint& theMousePos = QPoint()); virtual QString getToolTipText(const QPoint& theMousePos, QRect& theRect) const; virtual bool arePartsOfOtherItem(QxGraph_ActiveItem* theSecondItem); + void setCanvas(QCanvas* theCanvas); YACSPrs_Link* getLink() const { return myLink; } @@ -244,6 +255,9 @@ class YACSPrs_Edge : public QxGraph_ActiveItem, public QCanvasLine { bool isMoving() const { return myMoving; } void setSelected(bool b) { mySelected = b; } + virtual void setArrow(); + virtual void setVisible ( bool ) ; + virtual void setZ ( double z ); virtual int rtti() const; @@ -256,6 +270,7 @@ class YACSPrs_Edge : public QxGraph_ActiveItem, public QCanvasLine { YACSPrs_Point* myEndPoint; bool mySelected; + QCanvasPolygon* myArrow; }; #endif diff --git a/src/prs/YACSPrs_LoopNode.cxx b/src/prs/YACSPrs_LoopNode.cxx index bfc8387be..6485e14fa 100644 --- a/src/prs/YACSPrs_LoopNode.cxx +++ b/src/prs/YACSPrs_LoopNode.cxx @@ -32,8 +32,9 @@ using namespace YACS::ENGINE; /*! Constructor */ -YACSPrs_LoopNode::YACSPrs_LoopNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode, const bool& thePortUpdate ): - YACSPrs_InlineNode(theMgr, theCanvas, theNode, false) +YACSPrs_LoopNode::YACSPrs_LoopNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, + YACS::HMI::SubjectNode* theSNode, const bool& thePortUpdate ): + YACSPrs_InlineNode(theMgr, theCanvas, theSNode, false) { setNodeColor(LOOPNODE_COLOR); setNodeSubColor(LOOPNODE_SUBCOLOR); @@ -48,7 +49,10 @@ YACSPrs_LoopNode::YACSPrs_LoopNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas if ( thePortUpdate ) { //updatePorts(); // will be called in moveBy(...) function - moveBy(3*TITLE_HEIGHT/2, 3*TITLE_HEIGHT/2); + if ( isFullDMode() ) + moveBy(3*TITLE_HEIGHT/2+NODEBOUNDARY_MARGIN, 3*TITLE_HEIGHT/2+NODEBOUNDARY_MARGIN); + else if ( isControlDMode() ) + moveBy(2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN,2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN); } } @@ -80,16 +84,20 @@ void YACSPrs_LoopNode::select(const QPoint& theMousePos, const bool toSelect) { mySelectedPort->setSelected(false); mySelectedPort->setColor(mySelectedPort->storeColor(), false, true, true); + synchronize( mySelectedPort, false ); } else { setSelected(false); + getSEngine()->select(false); + setBracketColor( myStoreBracketColor ); setNodeSubColor( storeSubColor(), true ); } aPort->setSelected(true); aPort->setColor(aPort->Color().dark(130), false, true, true); mySelectedPort = aPort; + synchronize( mySelectedPort, true ); } break; } @@ -101,6 +109,7 @@ void YACSPrs_LoopNode::select(const QPoint& theMousePos, const bool toSelect) if ( mySelectedPort ) { mySelectedPort->setSelected(false); + synchronize( mySelectedPort, false ); mySelectedPort = 0; } @@ -110,6 +119,8 @@ void YACSPrs_LoopNode::select(const QPoint& theMousePos, const bool toSelect) setStoreSubColor( nodeSubColor() ); setSelected(true); + getSEngine()->select(true); + setBracketColor( bracketColor().dark(130) ); setNodeSubColor( nodeSubColor().dark(130), true ); } @@ -120,10 +131,13 @@ void YACSPrs_LoopNode::select(const QPoint& theMousePos, const bool toSelect) if ( mySelectedPort ) { mySelectedPort->setSelected(false); mySelectedPort->setColor(mySelectedPort->storeColor(), false, true, true); + synchronize( mySelectedPort, false ); mySelectedPort = 0; } else { setSelected(false); + getSEngine()->select(false); + setBracketColor( myStoreBracketColor ); setNodeSubColor( storeSubColor(), true ); } @@ -137,21 +151,35 @@ int YACSPrs_LoopNode::rtti() const QPointArray YACSPrs_LoopNode::constructAreaPoints(int theW, int theH) const { - int h = theH-1; - - int aCorner = 3*TITLE_HEIGHT/2; - - QPointArray aPnts(8); - QPoint p((int)x(), (int)y()); - p = p + QPoint(-NODEBOUNDARY_MARGIN,0); - aPnts[0] = p; - aPnts[1] = p + QPoint(aCorner, -aCorner) + QPoint(NODEBOUNDARY_MARGIN,-NODEBOUNDARY_MARGIN); - aPnts[2] = aPnts[1] + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); - aPnts[3] = p + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); - aPnts[4] = aPnts[3] + QPoint(0, h) + QPoint(0,-NODEBOUNDARY_MARGIN/2); - aPnts[5] = aPnts[4] + QPoint(-aCorner, aCorner) + QPoint(-NODEBOUNDARY_MARGIN,NODEBOUNDARY_MARGIN); - aPnts[6] = aPnts[5] + QPoint(-theW, 0) + QPoint(-NODEBOUNDARY_MARGIN,0); - aPnts[7] = p + QPoint(0, h) + QPoint(0,-NODEBOUNDARY_MARGIN/2); + QPointArray aPnts; + + if ( isControlDMode() ) + { + aPnts = QPointArray(4); + aPnts[0] = QPoint((int)x(), (int)y()) + QPoint(-NODEBOUNDARY_MARGIN,-NODEBOUNDARY_MARGIN); + aPnts[1] = aPnts[0] + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); + aPnts[2] = aPnts[1] + QPoint(0, theH) + QPoint(0,NODEBOUNDARY_MARGIN); + aPnts[3] = aPnts[0] + QPoint(0, theH) + QPoint(0,NODEBOUNDARY_MARGIN); + } + else if ( isFullDMode() ) + { + int h = theH-1; + + int aCorner = 3*TITLE_HEIGHT/2; + + aPnts = QPointArray(8); + QPoint p((int)x(), (int)y()); + p = p + QPoint(-NODEBOUNDARY_MARGIN,0); + aPnts[0] = p; + aPnts[1] = p + QPoint(aCorner, -aCorner) + QPoint(NODEBOUNDARY_MARGIN,-NODEBOUNDARY_MARGIN); + aPnts[2] = aPnts[1] + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); + aPnts[3] = p + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); + aPnts[4] = aPnts[3] + QPoint(0, h) + QPoint(0,-NODEBOUNDARY_MARGIN/2); + aPnts[5] = aPnts[4] + QPoint(-aCorner, aCorner) + QPoint(-NODEBOUNDARY_MARGIN,NODEBOUNDARY_MARGIN); + aPnts[6] = aPnts[5] + QPoint(-theW, 0) + QPoint(-NODEBOUNDARY_MARGIN,0); + aPnts[7] = p + QPoint(0, h) + QPoint(0,-NODEBOUNDARY_MARGIN/2); + } + return aPnts; } @@ -165,11 +193,37 @@ void YACSPrs_LoopNode::setBracketColor(const QColor& theColor, bool theUpdate) } } -void YACSPrs_LoopNode::updatePorts() +void YACSPrs_LoopNode::updatePorts(bool theForce) { bool aDisp = isVisible(); if (aDisp) hide(); - + + bool withCreate = theForce; + + if (theForce) + { + if ( isFullDMode() ) + myPortHeight = 2*PORT_MARGIN; + else + myPortHeight = 0; + + myPortList.setAutoDelete(true); + //myPortList.clear(); + + QPtrList aDeletePortList; + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ) ) + { + aDeletePortList.append( aLabelPort ); + withCreate = true; + } + } + + for (YACSPrs_Port* aPort = aDeletePortList.first(); aPort; aPort = aDeletePortList.next()) + myPortList.remove( aPort ); + } + // ForLoop and WhileLoop nodes have only 1 input port. // ForLoop : its name is 'nsteps' , // its type is 'int', @@ -181,92 +235,148 @@ void YACSPrs_LoopNode::updatePorts() // name 'Body'. This 'label' port connects with help of 'case' link to 'Master' hook // of the node, which is set as an internal node of the loop. - bool withCreate = false; if ( myPortList.isEmpty() ) withCreate = true; - QRect r = getBodyRect(); - int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; - if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; - - int ix = r.x() + PORT_MARGIN + 1; - int iy = r.y() + PORT_MARGIN;// + 1; - int ox = ix + aPRectWidth + 2*PORT_MARGIN; - int oy = r.y() + PORT_MARGIN;// + 1; - - ForLoop* aFLoop = dynamic_cast( myEngine ); - WhileLoop* aWLoop = 0; - - if ( withCreate ) - { // create (and update) - // 'nsteps'/'condition' input port (name, type (and value) of the port will set in YACSPrs_InOutPort from port engine) - YACSPrs_InOutPort* anInPort = 0; - - if ( aFLoop ) - anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aFLoop->edGetNbOfTimesInputPort(),this); - else - { - aWLoop = dynamic_cast( myEngine ); - if ( aWLoop ) - anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aWLoop->edGetConditionPort(),this); - } + if ( isFullDMode() ) + { + QRect r = getBodyRect(); + int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; + if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; - if ( anInPort ) - { - anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); - anInPort->setColor(nodeSubColor()); - anInPort->setStoreColor(nodeSubColor()); - myPortList.append(anInPort); - } + int ix = r.x() + PORT_MARGIN + 1; + int iy = r.y() + PORT_MARGIN;// + 1; + int ox = ix + aPRectWidth + 2*PORT_MARGIN; + int oy = r.y() + PORT_MARGIN;// + 1; - if ( aFLoop || aWLoop ) - { - // get a set of internal loop nodes (in fact in ForLoop and WhileLoop we have only one internal node) - std::set aNodes = aFLoop ? aFLoop->edGetDirectDescendants() : aWLoop->edGetDirectDescendants(); - std::set::iterator aNodesIter = aNodes.begin(); - for (; aNodesIter != aNodes.end(); aNodesIter++) - { // output label port - YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aNodesIter,this); - anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT)); - anOutPort->setColor(nodeSubColor().dark(140)); - anOutPort->setStoreColor(nodeSubColor().dark(140)); - myPortList.append(anOutPort); - myPortHeight += PORT_HEIGHT; + ForLoop* aFLoop = dynamic_cast( getEngine() ); + WhileLoop* aWLoop = dynamic_cast( getEngine() ); + + if ( withCreate ) + { // create (and update) + // 'nsteps'/'condition' input port (name, type (and value) of the port will set in YACSPrs_InOutPort from port engine) + bool isConditionPortCreated = false; + InputPort* aConditionPort = 0; + if( aFLoop ) + aConditionPort = aFLoop->edGetNbOfTimesInputPort(); + else if( aWLoop ) + aConditionPort = aWLoop->edGetConditionPort(); + + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( !aPort->getName().compare( QString( aConditionPort->getName() ) ) ) + { + isConditionPortCreated = true; + break; + } + } + if( !isConditionPortCreated ) + { + YACSPrs_InOutPort* anInPort = 0; + if ( aFLoop ) + anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aFLoop->edGetNbOfTimesInputPort(),this); + else if ( aWLoop ) + anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aWLoop->edGetConditionPort(),this); + + if ( anInPort ) + { + anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); + anInPort->setColor(nodeSubColor()); + anInPort->setStoreColor(nodeSubColor()); + myPortList.append(anInPort); + } + } + + if ( aFLoop || aWLoop ) + { + // get a set of internal loop nodes (in fact in ForLoop and WhileLoop we have only one internal node) + std::list aNodes = aFLoop ? aFLoop->edGetDirectDescendants() : aWLoop->edGetDirectDescendants(); + if ( aNodes.empty() ) + myPortHeight += PORT_HEIGHT; + else + { + std::list::iterator aNodesIter = aNodes.begin(); + for (; aNodesIter != aNodes.end(); aNodesIter++) + { // output label port + YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aNodesIter,this); + anOutPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT)); + anOutPort->setColor(nodeSubColor().dark(140)); + anOutPort->setStoreColor(nodeSubColor().dark(140)); + myPortList.append(anOutPort); + myPortHeight += PORT_HEIGHT; + } + } } } - } - else - { // only update - YACSPrs_Port* aPort; - for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) - { - YACSPrs_InOutPort* anInPort = dynamic_cast( aPort ); - if ( anInPort ) + else + { // only update + YACSPrs_Port* aPort; + for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) { - if ( !anInPort->isGate() && anInPort->isInput() ) - { // input data (i.e. not Gate) ports - anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); - iy += PORT_HEIGHT+PORT_SPACE; + YACSPrs_InOutPort* anInPort = dynamic_cast( aPort ); + if ( anInPort ) + { + if ( !anInPort->isGate() && anInPort->isInput() ) + { // input data (i.e. not Gate) ports + anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); + iy += PORT_HEIGHT+PORT_SPACE; + } + } + else + { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort => we not need to dynamic cast + aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); + oy += PORT_HEIGHT+PORT_SPACE; } - } - else - { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort => we not need to dynamic cast - aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); - oy += PORT_HEIGHT+PORT_SPACE; } } } // can update gates only after body height will be defined - updateGates(withCreate); + bool createGates = withCreate; + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ) ) + { + if ( anIOPort->isGate() ) + { // gate ports are already created - we should only update them + createGates = false; + break; + } + } + } + updateGates(createGates); + + if (theForce && myPointMaster) + { + QPoint aPnt = getConnectionMasterPoint(); + myPointMaster->setCoords(aPnt.x(), aPnt.y()); + } if (aDisp) show(); } int YACSPrs_LoopNode::maxWidth() const { + if ( isControlDMode() ) + return YACSPrs_ElementaryNode::maxWidth(); + + // Full view mode as a default return YACSPrs_ElementaryNode::maxWidth() - 4*HOOKPOINT_SIZE + ( ( 4*HOOKPOINT_SIZE > 3*TITLE_HEIGHT ) ? 4*HOOKPOINT_SIZE-3*TITLE_HEIGHT : 0 ); } +int YACSPrs_LoopNode::minX() const +{ + return YACSPrs_ElementaryNode::minX() + 2*HOOKPOINT_SIZE - ( ( 2*HOOKPOINT_SIZE > 3*TITLE_HEIGHT/2 ) ? + 2*HOOKPOINT_SIZE : + 3*TITLE_HEIGHT/2 ); +} + +int YACSPrs_LoopNode::maxX() const +{ + return YACSPrs_ElementaryNode::maxX() - 2*HOOKPOINT_SIZE + ( ( 2*HOOKPOINT_SIZE > 3*TITLE_HEIGHT/2 ) ? + 2*HOOKPOINT_SIZE : + 3*TITLE_HEIGHT/2 ); +} + void YACSPrs_LoopNode::drawPort(QPainter& thePainter) { QRect r = getBodyRect(); @@ -302,36 +412,39 @@ void YACSPrs_LoopNode::drawFrame(QPainter& thePainter) thePainter.drawRect(aRect); - QBrush savedB = thePainter.brush(); - thePainter.setBrush(bracketColor()); - - int aCorner = 3*TITLE_HEIGHT/2; - QPoint aP1(aRect.x(), aRect.y()); - QPoint aP2(aRect.x()+aCorner, aRect.y()-aCorner); - QPoint aP3(aRect.right()+aCorner,aRect.y()-aCorner); - QPoint aP4(aRect.right(), aRect.y()); - QPoint aP5(aRect.x(), aRect.bottom()); - QPoint aP6(aRect.x()-aCorner, aRect.bottom()+aCorner); - QPoint aP7(aRect.right()-aCorner,aRect.bottom()+aCorner); - QPoint aP8(aRect.right(), aRect.bottom()); - QPointArray aPAUp(4); - aPAUp.putPoints(0, 4, aP1.x(),aP1.y(), aP2.x(),aP2.y(), aP3.x(),aP3.y(), aP4.x(),aP4.y()); - thePainter.drawPolygon( aPAUp ); - QPointArray aPADown(4); - aPADown.putPoints(0, 4, aP5.x(),aP5.y(), aP6.x(),aP6.y(), aP7.x(),aP7.y(), aP8.x(),aP8.y()); - thePainter.drawPolygon( aPADown ); - - thePainter.setBrush(savedB); - - // draw top pixmap - QRect aTPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.y()-aCorner/2-aCorner/3, - 2*aCorner/3, 2*aCorner/3); - thePainter.drawPixmap(aTPRect,myTopPixmap); - - // draw bottom pixmap - QRect aBPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.bottom()+aCorner/2-aCorner/3, - 2*aCorner/3, 2*aCorner/3); - thePainter.drawPixmap(aBPRect,myBottomPixmap); + if ( isFullDMode() ) + { + QBrush savedB = thePainter.brush(); + thePainter.setBrush(bracketColor()); + + int aCorner = 3*TITLE_HEIGHT/2; + QPoint aP1(aRect.x(), aRect.y()); + QPoint aP2(aRect.x()+aCorner, aRect.y()-aCorner); + QPoint aP3(aRect.right()+aCorner,aRect.y()-aCorner); + QPoint aP4(aRect.right(), aRect.y()); + QPoint aP5(aRect.x(), aRect.bottom()); + QPoint aP6(aRect.x()-aCorner, aRect.bottom()+aCorner); + QPoint aP7(aRect.right()-aCorner,aRect.bottom()+aCorner); + QPoint aP8(aRect.right(), aRect.bottom()); + QPointArray aPAUp(4); + aPAUp.putPoints(0, 4, aP1.x(),aP1.y(), aP2.x(),aP2.y(), aP3.x(),aP3.y(), aP4.x(),aP4.y()); + thePainter.drawPolygon( aPAUp ); + QPointArray aPADown(4); + aPADown.putPoints(0, 4, aP5.x(),aP5.y(), aP6.x(),aP6.y(), aP7.x(),aP7.y(), aP8.x(),aP8.y()); + thePainter.drawPolygon( aPADown ); + + thePainter.setBrush(savedB); + + // draw top pixmap + QRect aTPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.y()-aCorner/2-aCorner/3, + 2*aCorner/3, 2*aCorner/3); + thePainter.drawPixmap(aTPRect,myTopPixmap); + + // draw bottom pixmap + QRect aBPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.bottom()+aCorner/2-aCorner/3, + 2*aCorner/3, 2*aCorner/3); + thePainter.drawPixmap(aBPRect,myBottomPixmap); + } // draw bounding nodes' polygon if node is currently selected if ( isSelected() ) drawBoundary(thePainter,5); @@ -357,3 +470,9 @@ bool YACSPrs_LoopNode::checkArea(double dx, double dy) return false; // <-- } + +bool YACSPrs_LoopNode::synchronize( YACSPrs_Port* port, const bool toSelect ) +{ + return YACSPrs_InOutPort::synchronize( port, toSelect ); +} + diff --git a/src/prs/YACSPrs_LoopNode.h b/src/prs/YACSPrs_LoopNode.h index 7a260c7e5..76a9af966 100644 --- a/src/prs/YACSPrs_LoopNode.h +++ b/src/prs/YACSPrs_LoopNode.h @@ -23,7 +23,7 @@ class YACSPrs_LoopNode : public YACSPrs_InlineNode { public: - YACSPrs_LoopNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node*, const bool& thePortUpdate=true ); + YACSPrs_LoopNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode*, const bool& thePortUpdate=true ); virtual ~YACSPrs_LoopNode(); /* reimplement functions from QxGraph_ActiveItem */ @@ -37,17 +37,22 @@ class YACSPrs_LoopNode : public YACSPrs_InlineNode { virtual void setBracketColor(const QColor& theColor, bool theUpdate=false); virtual QColor bracketColor() const { return myBracketColor; } - virtual void updatePorts(); + virtual void updatePorts(bool theForce=false); virtual int getCorner() const { return 0; } virtual int maxWidth() const; + virtual int minX() const; + virtual int maxX() const; + virtual QPoint getConnectionMasterPoint(); // for constraint nodes' moving inside the Bloc--> virtual bool checkArea(double dx, double dy); // <-- + bool synchronize( YACSPrs_Port* port, const bool toSelect ); + protected: virtual void drawPort(QPainter& thePainter); virtual void drawFrame(QPainter& thePainter); diff --git a/src/prs/YACSPrs_ServiceNode.cxx b/src/prs/YACSPrs_ServiceNode.cxx index 9f90904e1..158dc7280 100644 --- a/src/prs/YACSPrs_ServiceNode.cxx +++ b/src/prs/YACSPrs_ServiceNode.cxx @@ -27,6 +27,9 @@ #include #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace YACS::ENGINE; void drawText1(QPainter& thePainter, const QString& theText, @@ -65,9 +68,10 @@ void drawText1(QPainter& thePainter, const QString& theText, /*! Constructor */ -YACSPrs_ServiceNode::YACSPrs_ServiceNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode): - YACSPrs_ElementaryNode(theMgr, theCanvas, theNode) +YACSPrs_ServiceNode::YACSPrs_ServiceNode(SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::HMI::SubjectNode* theSNode): + YACSPrs_ElementaryNode(theMgr, theCanvas, theSNode) { + DEBTRACE("YACSPrs_ServiceNode::YACSPrs_ServiceNode"); myServiceHeight = TITLE_HEIGHT; myComponentHeight = TITLE_HEIGHT; myMachineHeight = TITLE_HEIGHT; @@ -79,7 +83,7 @@ YACSPrs_ServiceNode::YACSPrs_ServiceNode(SUIT_ResourceMgr* theMgr, QCanvas* theC setStoreSubColor(nodeSubColor()); //updatePorts(); // will be called in moveBy(...) function - moveBy(2*HOOKPOINT_SIZE,0); + moveBy(2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN,2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN); update(); } @@ -98,7 +102,11 @@ int YACSPrs_ServiceNode::rtti() const int YACSPrs_ServiceNode::getInfoHeight() const { - return getTitleHeight() + NODE_SPACE + + if ( isControlDMode() ) + return getTitleHeight() + NODE_SPACE; + + // Full view by default + return getTitleHeight() + NODE_SPACE + getServiceHeight() + NODE_SPACE + getComponentHeight() + NODE_SPACE + getMachineHeight() + NODE_SPACE + @@ -178,70 +186,87 @@ void YACSPrs_ServiceNode::drawTitleShape(QPainter& thePainter) int aXRnd = getTitleRect().width()*myXRnd/getServiceRect().width(); int aYRnd = getTitleRect().height()*myYRnd/TITLE_HEIGHT; + QBrush savedB = thePainter.brush(); + QPen savedP = thePainter.pen(); thePainter.setPen(thePainter.brush().color().dark(140)); // title thePainter.drawRoundRect(getTitleRect(),myXRnd,myYRnd); - // service - thePainter.drawRoundRect(getServiceRect(),aXRnd,aYRnd); - // component - thePainter.drawRoundRect(getComponentRect(),aXRnd,aYRnd); - // machine - thePainter.drawRoundRect(getMachineRect(),aXRnd,aYRnd); - //state and time - thePainter.drawRoundRect(getStatusRect(),aXRnd,aYRnd); - - // draw progress bar - thePainter.setPen(NoPen); - - QBrush savedB = thePainter.brush(); - - thePainter.setBrush(savedB.color().light(130)); - thePainter.drawRect(getWholeRect()); - if ( getPercentRect().width() > 1 ) { - thePainter.setBrush(savedB.color().dark(160)); - thePainter.drawRect(getPercentRect()); + if ( isFullDMode() ) + { + // service + thePainter.drawRoundRect(getServiceRect(),aXRnd,aYRnd); + // component + thePainter.drawRoundRect(getComponentRect(),aXRnd,aYRnd); + // machine + thePainter.drawRoundRect(getMachineRect(),aXRnd,aYRnd); + //state and time + thePainter.drawRoundRect(getStatusRect(),aXRnd,aYRnd); + + // draw progress bar + thePainter.setPen(NoPen); + + //savedB = thePainter.brush(); + + thePainter.setBrush(savedB.color().light(130)); + thePainter.drawRect(getWholeRect()); + + if ( getPercentRect().width() > 1 ) { + thePainter.setBrush(savedB.color().dark(160)); + thePainter.drawRect(getPercentRect()); + } + + thePainter.setBrush(savedB); } - thePainter.setBrush(savedB); - // draw texts thePainter.setPen(Qt::white); - - ServiceNode* aSEngine = dynamic_cast( myEngine ); - drawText1(thePainter, QString(myEngine->getName()), getTitleRect(), Qt::AlignLeft); - drawText1(thePainter, QString( "Service: ") + QString( aSEngine ? aSEngine->getMethod() : "..." ), getServiceRect(), Qt::AlignLeft); - drawText1(thePainter, QString( "Component: " ) + QString( aSEngine ? aSEngine->getComponent()->getName() : "..." ), getComponentRect(), Qt::AlignLeft); - drawText1(thePainter, QString("Machine: ..."), getMachineRect(), Qt::AlignLeft); - - int aMidX = getTitleRect().right()-getTitleRect().width()/2; - thePainter.drawLine(aMidX, getStatusRect().top()+2, aMidX, getStatusRect().bottom()-2); - QRect aStateRect(getStatusRect().x(), getStatusRect().y(), aMidX-getStatusRect().left(), TITLE_HEIGHT); - QRect aTimeRect(aMidX, getStatusRect().y(), 2*getStatusRect().width()/3, TITLE_HEIGHT); - - drawText1(thePainter, myStatus, aStateRect, Qt::AlignLeft); - drawText1(thePainter, myTime, aTimeRect, Qt::AlignLeft); - drawText1(thePainter, QString::number(( (getStoredPercentage() < 0) ? getPercentage() : getStoredPercentage() ))+QString("%"), aTimeRect, Qt::AlignRight); // percentage + if ( isControlDMode() ) + drawText1(thePainter, QString(getEngine()->getName()), getTitleRect(), Qt::AlignHCenter); + else if ( isFullDMode() ) + { + drawText1(thePainter, QString(getEngine()->getName()), getTitleRect(), Qt::AlignLeft); + ServiceNode* aSEngine = dynamic_cast( getEngine() ); + drawText1(thePainter, QString( "Service: ") + QString( aSEngine ? aSEngine->getMethod() : "..." ), getServiceRect(), Qt::AlignLeft); + drawText1(thePainter, QString( "Component: " ) + + QString( (aSEngine && aSEngine->getComponent()) ? aSEngine->getComponent()->getInstanceName() : "..." ), + getComponentRect(), Qt::AlignLeft); + drawText1(thePainter, QString("Machine: ..."), getMachineRect(), Qt::AlignLeft); + + int aMidX = getTitleRect().right()-getTitleRect().width()/2; + thePainter.drawLine(aMidX, getStatusRect().top()+2, aMidX, getStatusRect().bottom()-2); + + QRect aStateRect(getStatusRect().x(), getStatusRect().y(), aMidX-getStatusRect().left(), TITLE_HEIGHT); + QRect aTimeRect(aMidX, getStatusRect().y(), 2*getStatusRect().width()/3, TITLE_HEIGHT); + + drawText1(thePainter, myStatus, aStateRect, Qt::AlignLeft); + drawText1(thePainter, myTime, aTimeRect, Qt::AlignLeft); + drawText1(thePainter, QString::number(( (getStoredPercentage() < 0) ? getPercentage() : getStoredPercentage() ), 'g', 4)+QString("%"), + aTimeRect, Qt::AlignRight); // percentage + } thePainter.setPen(savedP); - // draw pixmap - thePainter.setBrush(NoBrush); - - aXRnd = getTitleRect().width()*myXRnd/getPixmapRect(true,true).width(); - aYRnd = getTitleRect().height()*myYRnd/getPixmapRect(true,true).height(); - thePainter.drawRoundRect(getPixmapRect(true,true),aXRnd,aYRnd); - QRect aPRect = getPixmapRect(true,true); - aPRect.setX(aPRect.x()+PIXMAP_MARGIN+2); - aPRect.setY(aPRect.y()+PIXMAP_MARGIN); - aPRect.setWidth(aPRect.width()-2*PIXMAP_MARGIN); - aPRect.setHeight(aPRect.height()-2*PIXMAP_MARGIN); - thePainter.drawPixmap(aPRect,myStatePixmap); - - thePainter.setBrush(savedB); + if ( isFullDMode() ) + { + // draw pixmap + thePainter.setBrush(NoBrush); + + aXRnd = getTitleRect().width()*myXRnd/getPixmapRect(true,true).width(); + aYRnd = getTitleRect().height()*myYRnd/getPixmapRect(true,true).height(); + thePainter.drawRoundRect(getPixmapRect(true,true),aXRnd,aYRnd); + QRect aPRect = getPixmapRect(true,true); + aPRect.setX(aPRect.x()+PIXMAP_MARGIN+2); + aPRect.setY(aPRect.y()+PIXMAP_MARGIN); + aPRect.setWidth(aPRect.width()-2*PIXMAP_MARGIN); + aPRect.setHeight(aPRect.height()-2*PIXMAP_MARGIN); + thePainter.drawPixmap(aPRect,myStatePixmap); + + thePainter.setBrush(savedB); + } } QString YACSPrs_ServiceNode::getToolTipText(const QPoint& theMousePos, QRect& theRect) const diff --git a/src/prs/YACSPrs_ServiceNode.h b/src/prs/YACSPrs_ServiceNode.h index fe1556588..81d4e1161 100644 --- a/src/prs/YACSPrs_ServiceNode.h +++ b/src/prs/YACSPrs_ServiceNode.h @@ -23,7 +23,7 @@ class YACSPrs_ServiceNode : public YACSPrs_ElementaryNode { public: - YACSPrs_ServiceNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node* ); + YACSPrs_ServiceNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode* ); virtual ~YACSPrs_ServiceNode(); /* reimplement functions from QxGraph_ActiveItem */ diff --git a/src/prs/YACSPrs_SwitchNode.cxx b/src/prs/YACSPrs_SwitchNode.cxx index 815edce9e..4f8a2146c 100644 --- a/src/prs/YACSPrs_SwitchNode.cxx +++ b/src/prs/YACSPrs_SwitchNode.cxx @@ -34,8 +34,8 @@ using namespace YACS::ENGINE; /*! Constructor */ -YACSPrs_SwitchNode::YACSPrs_SwitchNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::ENGINE::Node* theNode ): - YACSPrs_InlineNode(theMgr, theCanvas, theNode, false) +YACSPrs_SwitchNode::YACSPrs_SwitchNode( SUIT_ResourceMgr* theMgr, QCanvas* theCanvas, YACS::HMI::SubjectNode* theSNode ): + YACSPrs_InlineNode(theMgr, theCanvas, theSNode, false) { setNodeColor(SWITCHNODE_COLOR); setNodeSubColor(SWITCHNODE_SUBCOLOR); @@ -46,7 +46,7 @@ YACSPrs_SwitchNode::YACSPrs_SwitchNode( SUIT_ResourceMgr* theMgr, QCanvas* theCa myTitlePixmap = myMgr->loadPixmap( "YACSPrs", QObject::tr( "ICON_TITLE_RARROW" )); //updatePorts(); // will be called in moveBy(...) function - moveBy(2*HOOKPOINT_SIZE,2*TITLE_HEIGHT); + moveBy(2*HOOKPOINT_SIZE+NODEBOUNDARY_MARGIN,2*HOOKPOINT_SIZE+2*TITLE_HEIGHT+NODEBOUNDARY_MARGIN); } /*! @@ -63,23 +63,63 @@ int YACSPrs_SwitchNode::rtti() const QPointArray YACSPrs_SwitchNode::constructAreaPoints(int theW, int theH) const { - int aCorner = 2*TITLE_HEIGHT; - - QPointArray aPnts(5); - QPoint p((int)x(), (int)y()); - aPnts[0] = p + QPoint(-NODEBOUNDARY_MARGIN,0); - aPnts[1] = p + QPoint(theW/2, -aCorner) + QPoint(0,-NODEBOUNDARY_MARGIN); - aPnts[2] = p + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); - aPnts[3] = aPnts[2] + QPoint(0, theH) + QPoint(0,NODEBOUNDARY_MARGIN/2); - aPnts[4] = p + QPoint(0, theH) + QPoint(-NODEBOUNDARY_MARGIN,NODEBOUNDARY_MARGIN/2); + QPointArray aPnts; + + if ( isControlDMode() ) + { + aPnts = QPointArray(4); + aPnts[0] = QPoint((int)x(), (int)y()) + QPoint(-NODEBOUNDARY_MARGIN,-NODEBOUNDARY_MARGIN); + aPnts[1] = aPnts[0] + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); + aPnts[2] = aPnts[1] + QPoint(0, theH) + QPoint(0,NODEBOUNDARY_MARGIN); + aPnts[3] = aPnts[0] + QPoint(0, theH) + QPoint(0,NODEBOUNDARY_MARGIN); + } + else if ( isFullDMode() ) + { + int aCorner = 2*TITLE_HEIGHT; + + aPnts = QPointArray(5); + QPoint p((int)x(), (int)y()); + aPnts[0] = p + QPoint(-NODEBOUNDARY_MARGIN,0); + aPnts[1] = p + QPoint(theW/2, -aCorner) + QPoint(0,-NODEBOUNDARY_MARGIN); + aPnts[2] = p + QPoint(theW, 0) + QPoint(NODEBOUNDARY_MARGIN,0); + aPnts[3] = aPnts[2] + QPoint(0, theH) + QPoint(0,NODEBOUNDARY_MARGIN/2); + aPnts[4] = p + QPoint(0, theH) + QPoint(-NODEBOUNDARY_MARGIN,NODEBOUNDARY_MARGIN/2); + } + return aPnts; } -void YACSPrs_SwitchNode::updatePorts() +void YACSPrs_SwitchNode::updatePorts(bool theForce) { bool aDisp = isVisible(); if (aDisp) hide(); - + + bool withCreate = theForce; + + if (theForce) + { + if ( isFullDMode() ) + myPortHeight = 2*PORT_MARGIN; + else + myPortHeight = 0; + + myPortList.setAutoDelete(true); + //myPortList.clear(); + + QPtrList aDeletePortList; + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( YACSPrs_LabelPort* aLabelPort = dynamic_cast( aPort ) ) + { + aDeletePortList.append( aLabelPort ); + withCreate = true; + } + } + + for (YACSPrs_Port* aPort = aDeletePortList.first(); aPort; aPort = aDeletePortList.next()) + myPortList.remove( aPort ); + } + // Switch node has only 1 input port: its name is 'select', // its type is 'int', // its value is a number of active case (i.e. the case to execute) @@ -88,116 +128,155 @@ void YACSPrs_SwitchNode::updatePorts() // as a 'label' ports. Each 'label' port connects with help of 'case' link to 'Master' hook // of the node, which is set to this case ID. - bool withCreate = false; if ( myPortList.isEmpty() ) withCreate = true; - QRect r = getBodyRect(); - int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; - if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; - - int ix = r.x() + PORT_MARGIN + 1; - int iy = r.y() + PORT_MARGIN;// + 1; - int ox = ix + aPRectWidth + 2*PORT_MARGIN; - int oy = r.y() + PORT_MARGIN;// + 1; - - if ( withCreate ) - { // create (and update) - // 'select' input port (name, type (and value) of the port will set in YACSPrs_InOutPort from port engine) - Switch* aSEngine = dynamic_cast( myEngine ); - if ( aSEngine ) - { - YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aSEngine->edGetConditionPort(),this); - anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); - anInPort->setColor(nodeSubColor()); - anInPort->setStoreColor(nodeSubColor()); - myPortList.append(anInPort); + if ( isFullDMode() ) + { + QRect r = getBodyRect(); + int aPRectWidth = (int)(r.width()/2) - 2*PORT_MARGIN; + if ( aPRectWidth < PORT_WIDTH ) aPRectWidth = PORT_WIDTH; - // get a set of internal case nodes - std::set aNodes = aSEngine->edGetDirectDescendants(); - std::set::iterator aNodesIter = aNodes.begin(); - - // get default node - Node* aDefaultNode = aSEngine->getChildByShortName(Switch::DEFAULT_NODE_NAME); - - int aMinCaseId, aMaxCaseId; - aMinCaseId = aMaxCaseId = aSEngine->getRankOfNode(*aNodesIter); - // a list of case nodes ordered from minimum to maximum case id - std::list aCaseNodes; - for (; aNodesIter != aNodes.end(); aNodesIter++) + int ix = r.x() + PORT_MARGIN + 1; + int iy = r.y() + PORT_MARGIN;// + 1; + int ox = ix + aPRectWidth + 2*PORT_MARGIN; + int oy = r.y() + PORT_MARGIN;// + 1; + + if ( withCreate ) + { // create (and update) + // 'select' input port (name, type (and value) of the port will set in YACSPrs_InOutPort from port engine) + Switch* aSEngine = dynamic_cast( getEngine() ); + if ( aSEngine ) { - if ( *aNodesIter == aDefaultNode) continue; - - // less than min => push front - if ( aMinCaseId >= aSEngine->getRankOfNode(*aNodesIter) ) { - aCaseNodes.push_front(*aNodesIter); - aMinCaseId = aSEngine->getRankOfNode(*aNodesIter); + bool isConditionPortCreated = false; + InputPort* aConditionPort = aSEngine->edGetConditionPort(); + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( !aPort->getName().compare( QString( aConditionPort->getName() ) ) ) + { + isConditionPortCreated = true; + break; + } } - // in the middle - else if ( aMinCaseId < aSEngine->getRankOfNode(*aNodesIter) - && - aMaxCaseId > aSEngine->getRankOfNode(*aNodesIter) ) { - std::list::iterator aCaseNodesIter = aCaseNodes.begin(); - for (std::list::iterator anIt = aCaseNodesIter; - anIt++ != aCaseNodes.end(); - aCaseNodesIter++, anIt = aCaseNodesIter) { - if ( aSEngine->getRankOfNode(*aNodesIter) >= aSEngine->getRankOfNode(*aCaseNodesIter) - && - aSEngine->getRankOfNode(*aNodesIter) <= aSEngine->getRankOfNode(*anIt) ) { - aCaseNodes.insert(anIt,*aNodesIter); - break; + if( !isConditionPortCreated ) + { + YACSPrs_InOutPort* anInPort = new YACSPrs_InOutPort(myMgr,canvas(),aConditionPort,this); + anInPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT)); + anInPort->setColor(nodeSubColor()); + anInPort->setStoreColor(nodeSubColor()); + myPortList.append(anInPort); + } + + // get a set of internal case nodes + std::list aNodes = aSEngine->edGetDirectDescendants(); + if ( aNodes.empty() ) + myPortHeight += PORT_HEIGHT; + else + { + std::list::iterator aNodesIter = aNodes.begin(); + + // get default node + Node* aDefaultNode = aSEngine->getChildByShortName(Switch::DEFAULT_NODE_NAME); + + int aMinCaseId, aMaxCaseId; + aMinCaseId = aMaxCaseId = aSEngine->getRankOfNode(*aNodesIter); + // a list of case nodes ordered from minimum to maximum case id + std::list aCaseNodes; + for (; aNodesIter != aNodes.end(); aNodesIter++) + { + if ( *aNodesIter == aDefaultNode) continue; + + // less than min => push front + if ( aMinCaseId >= aSEngine->getRankOfNode(*aNodesIter) ) { + aCaseNodes.push_front(*aNodesIter); + aMinCaseId = aSEngine->getRankOfNode(*aNodesIter); + } + // in the middle + else if ( aMinCaseId < aSEngine->getRankOfNode(*aNodesIter) + && + aMaxCaseId > aSEngine->getRankOfNode(*aNodesIter) ) { + std::list::iterator aCaseNodesIter = aCaseNodes.begin(); + for (std::list::iterator anIt = aCaseNodesIter; + anIt++ != aCaseNodes.end(); + aCaseNodesIter++, anIt = aCaseNodesIter) { + if ( aSEngine->getRankOfNode(*aNodesIter) >= aSEngine->getRankOfNode(*aCaseNodesIter) + && + aSEngine->getRankOfNode(*aNodesIter) <= aSEngine->getRankOfNode(*anIt) ) { + aCaseNodes.insert(anIt,*aNodesIter); + break; + } + } + } + // more than max => push back + else if ( aMaxCaseId <= aSEngine->getRankOfNode(*aNodesIter) ) { + aCaseNodes.push_back(*aNodesIter); + aMaxCaseId = aSEngine->getRankOfNode(*aNodesIter); } } + if ( aDefaultNode ) + aCaseNodes.push_back(aDefaultNode); + + int heightIncr = 0; + std::list::iterator aCaseNodesIter = aCaseNodes.begin(); + for (; aCaseNodesIter != aCaseNodes.end(); aCaseNodesIter++) + { // (in fact we have to get from user number of switch cases) + // output label ports + YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aCaseNodesIter,this, + true,aSEngine->getRankOfNode(*aCaseNodesIter)); + anOutPort->setPortRect(QRect(ox, oy+heightIncr, aPRectWidth, PORT_HEIGHT)); + anOutPort->setColor(nodeSubColor().dark(140)); + anOutPort->setStoreColor(nodeSubColor().dark(140)); + if ( *aCaseNodesIter == aDefaultNode) anOutPort->setName(Switch::DEFAULT_NODE_NAME); + myPortList.append(anOutPort); + heightIncr += PORT_HEIGHT+PORT_SPACE; + } + + myPortHeight += aNodes.size()*PORT_HEIGHT + (aNodes.size()-1)*PORT_SPACE; } - // more than max => push back - else if ( aMaxCaseId <= aSEngine->getRankOfNode(*aNodesIter) ) { - aCaseNodes.push_back(*aNodesIter); - aMaxCaseId = aSEngine->getRankOfNode(*aNodesIter); - } - } - aCaseNodes.push_back(aDefaultNode); - - int heightIncr = 0; - std::list::iterator aCaseNodesIter = aCaseNodes.begin(); - for (; aCaseNodesIter != aCaseNodes.end(); aCaseNodesIter++) - { // (in fact we have to get from user number of switch cases) - // output label ports - YACSPrs_LabelPort* anOutPort = new YACSPrs_LabelPort(myMgr,canvas(),*aCaseNodesIter,this, - true,aSEngine->getRankOfNode(*aCaseNodesIter)); - anOutPort->setPortRect(QRect(ox, oy+heightIncr, aPRectWidth, PORT_HEIGHT)); - anOutPort->setColor(nodeSubColor().dark(140)); - anOutPort->setStoreColor(nodeSubColor().dark(140)); - if ( *aCaseNodesIter == aDefaultNode) anOutPort->setName(Switch::DEFAULT_NODE_NAME); - myPortList.append(anOutPort); - heightIncr += PORT_HEIGHT+PORT_SPACE; } - - myPortHeight += aNodes.size()*PORT_HEIGHT + (aNodes.size()-1)*PORT_SPACE; } - } - else - { // only update - YACSPrs_Port* aPort; - for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) - { - YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); - if ( anIOPort ) + else + { // only update + YACSPrs_Port* aPort; + for (aPort = myPortList.first(); aPort; aPort = myPortList.next()) { - if ( !anIOPort->isGate() && anIOPort->isInput() ) - { // input data (i.e. not Gate) ports - anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); - iy += PORT_HEIGHT+PORT_SPACE; + YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ); + if ( anIOPort ) + { + if ( !anIOPort->isGate() && anIOPort->isInput() ) + { // input data (i.e. not Gate) ports + anIOPort->setPortRect(QRect(ix, iy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); + iy += PORT_HEIGHT+PORT_SPACE; + } + } + else + { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort (output!) => we not need to dynamic cast + aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); + oy += PORT_HEIGHT+PORT_SPACE; } - } - else - { // not YACSPrs_InOutPort => it is YACSPrs_LabelPort (output!) => we not need to dynamic cast - aPort->setPortRect(QRect(ox, oy, aPRectWidth, PORT_HEIGHT), !isSelfMoving(), myArea); - oy += PORT_HEIGHT+PORT_SPACE; } } } - + // can update gates only after body height will be defined - updateGates(withCreate); + bool createGates = withCreate; + for (YACSPrs_Port* aPort = myPortList.first(); aPort; aPort = myPortList.next()) + { + if( YACSPrs_InOutPort* anIOPort = dynamic_cast( aPort ) ) + { + if ( anIOPort->isGate() ) + { // gate ports are already created - we should only update them + createGates = false; + break; + } + } + } + updateGates(createGates); + + if (theForce && myPointMaster) + { + QPoint aPnt = getConnectionMasterPoint(); + myPointMaster->setCoords(aPnt.x(), aPnt.y()); + } if (aDisp) show(); } @@ -237,55 +316,60 @@ void YACSPrs_SwitchNode::drawFrame(QPainter& thePainter) int aXRnd = aTRect.width()*myXRnd/aRect.width(); int aYRnd = aTRect.height()*myYRnd/aRect.height(); - QPen savedP = thePainter.pen(); - thePainter.setPen(NoPen); - - // calculate width and height for acrs - int w = 4*(aXRnd*aRect.width()/100)/3; - int h = 4*(aYRnd*aRect.height()/100)/3; - - // draw chords without pen - thePainter.drawChord( aRect.x(),aRect.y(), w,h, 90*16, 90*16 ); - thePainter.drawChord( aRect.right()-w+1,aRect.y(), w,h, 0*16, 90*16 ); - thePainter.drawChord( aRect.right()-w+1,aRect.bottom()-h+1, w,h, 270*16, 90*16 ); - thePainter.drawChord( aRect.x(),aRect.bottom()-h+1, w,h, 180*16, 90*16 ); - - //thePainter.drawRoundRect(aRect,aXRnd,aYRnd); - int aCorner = 2*TITLE_HEIGHT; - QPoint aP1(aRect.x()+(w-1)/2,aRect.y()); - QPoint aP2(aRect.x()+aRect.width()/2,aRect.y()-aCorner); - QPoint aP3(aRect.right()-(w-1)/2,aRect.y()); - QPoint aP4(aRect.right(),aRect.y()+h/2-1); - QPoint aP5(aRect.right(),aRect.bottom()-h/2+1); - QPoint aP6(aRect.right()-(w-1)/2,aRect.bottom()); - QPoint aP7(aRect.x()+(w-1)/2,aRect.bottom()); - QPoint aP8(aRect.x(),aRect.bottom()-h/2+1); - QPoint aP9(aRect.x(),aRect.y()+h/2-1); - QPointArray aPA(9); - aPA.putPoints(0, 9, - aP1.x(),aP1.y(), aP2.x(),aP2.y(), aP3.x(),aP3.y(), aP4.x(),aP4.y(), - aP5.x(),aP5.y(), aP6.x(),aP6.y(), aP7.x(),aP7.y(), aP8.x(),aP8.y(), aP9.x(),aP9.y()); - thePainter.drawPolygon( aPA ); - thePainter.setPen(savedP); - - // draw arcs - thePainter.drawArc( aRect.x(),aRect.y(), w,h, 90*16, 90*16 ); - thePainter.drawArc( aRect.right()-w+1,aRect.y(), w,h, 0*16, 90*16 ); - thePainter.drawArc( aRect.right()-w+1,aRect.bottom()-h+1, w,h, 270*16, 90*16 ); - thePainter.drawArc( aRect.x(),aRect.bottom()-h+1, w,h, 180*16, 90*16 ); - - // draw line segments - thePainter.drawLine(aP1,aP2); - thePainter.drawLine(aP2,aP3); - thePainter.drawLine(aP4,aP5); - thePainter.drawLine(aP6,aP7); - thePainter.drawLine(aP8,aP9); - - // draw title pixmap - QRect aTPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.y()-(aCorner-NODE_MARGIN)/2-aCorner/3, - 2*aCorner/3, 2*aCorner/3); - thePainter.drawPixmap(aTPRect,myTitlePixmap); + if ( isControlDMode() ) + thePainter.drawRoundRect(aRect,aXRnd,aYRnd); + else if ( isFullDMode() ) + { + QPen savedP = thePainter.pen(); + thePainter.setPen(NoPen); + + // calculate width and height for acrs + int w = 4*(aXRnd*aRect.width()/100)/3; + int h = 4*(aYRnd*aRect.height()/100)/3; + + // draw chords without pen + thePainter.drawChord( aRect.x(),aRect.y(), w,h, 90*16, 90*16 ); + thePainter.drawChord( aRect.right()-w+1,aRect.y(), w,h, 0*16, 90*16 ); + thePainter.drawChord( aRect.right()-w+1,aRect.bottom()-h+1, w,h, 270*16, 90*16 ); + thePainter.drawChord( aRect.x(),aRect.bottom()-h+1, w,h, 180*16, 90*16 ); + + //thePainter.drawRoundRect(aRect,aXRnd,aYRnd); + int aCorner = 2*TITLE_HEIGHT; + QPoint aP1(aRect.x()+(w-1)/2,aRect.y()); + QPoint aP2(aRect.x()+aRect.width()/2,aRect.y()-aCorner); + QPoint aP3(aRect.right()-(w-1)/2,aRect.y()); + QPoint aP4(aRect.right(),aRect.y()+h/2-1); + QPoint aP5(aRect.right(),aRect.bottom()-h/2+1); + QPoint aP6(aRect.right()-(w-1)/2,aRect.bottom()); + QPoint aP7(aRect.x()+(w-1)/2,aRect.bottom()); + QPoint aP8(aRect.x(),aRect.bottom()-h/2+1); + QPoint aP9(aRect.x(),aRect.y()+h/2-1); + QPointArray aPA(9); + aPA.putPoints(0, 9, + aP1.x(),aP1.y(), aP2.x(),aP2.y(), aP3.x(),aP3.y(), aP4.x(),aP4.y(), + aP5.x(),aP5.y(), aP6.x(),aP6.y(), aP7.x(),aP7.y(), aP8.x(),aP8.y(), aP9.x(),aP9.y()); + thePainter.drawPolygon( aPA ); + thePainter.setPen(savedP); + + // draw arcs + thePainter.drawArc( aRect.x(),aRect.y(), w,h, 90*16, 90*16 ); + thePainter.drawArc( aRect.right()-w+1,aRect.y(), w,h, 0*16, 90*16 ); + thePainter.drawArc( aRect.right()-w+1,aRect.bottom()-h+1, w,h, 270*16, 90*16 ); + thePainter.drawArc( aRect.x(),aRect.bottom()-h+1, w,h, 180*16, 90*16 ); + + // draw line segments + thePainter.drawLine(aP1,aP2); + thePainter.drawLine(aP2,aP3); + thePainter.drawLine(aP4,aP5); + thePainter.drawLine(aP6,aP7); + thePainter.drawLine(aP8,aP9); + + // draw title pixmap + QRect aTPRect(aRect.x()+aRect.width()/2-aCorner/3, aRect.y()-(aCorner-NODE_MARGIN)/2-aCorner/3, + 2*aCorner/3, 2*aCorner/3); + thePainter.drawPixmap(aTPRect,myTitlePixmap); + } // draw bounding nodes' polygon if node is currently selected - if ( isSelected() ) drawBoundary(thePainter,3); + if ( isSelected() ) drawBoundary(thePainter,(isFullDMode() ? 3 : 2)); } diff --git a/src/prs/YACSPrs_SwitchNode.h b/src/prs/YACSPrs_SwitchNode.h index 654842b0a..f0060a2b0 100644 --- a/src/prs/YACSPrs_SwitchNode.h +++ b/src/prs/YACSPrs_SwitchNode.h @@ -23,7 +23,7 @@ class YACSPrs_SwitchNode : public YACSPrs_InlineNode { public: - YACSPrs_SwitchNode( SUIT_ResourceMgr*, QCanvas*, YACS::ENGINE::Node*); + YACSPrs_SwitchNode( SUIT_ResourceMgr*, QCanvas*, YACS::HMI::SubjectNode*); virtual ~YACSPrs_SwitchNode(); /* reimplement functions from QxGraph_ActiveItem */ @@ -33,7 +33,8 @@ class YACSPrs_SwitchNode : public YACSPrs_InlineNode { virtual QPointArray constructAreaPoints(int theW, int theH) const; - virtual void updatePorts(); + virtual void updatePorts(bool theForce=false); + virtual int getCorner() const { return 0; } protected: diff --git a/src/prs/YACSPrs_toString.cxx b/src/prs/YACSPrs_toString.cxx new file mode 100644 index 000000000..6bafcf708 --- /dev/null +++ b/src/prs/YACSPrs_toString.cxx @@ -0,0 +1,291 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include +#include +#include +#include +#include +#include +#include + +using namespace YACS::ENGINE; + +char * toString(CORBA::Any* theAny, QString& theRetStr) +{ + if ( !theAny ) theRetStr += QString("< ? >"); + else + { + CORBA::Any anAny = *theAny; + if ( !anAny.value() ) theRetStr += QString("< ? >"); + else + { + std::ostringstream astr; + const char * retstr; + int startstr = 0; + switch ( anAny.type()->kind() ) + { + case CORBA::tk_string: { + anAny >>= retstr; + theRetStr += QString(retstr); + break; + } + case CORBA::tk_long: { + CORBA::Long l; + anAny >>= l; + astr << l << std::ends; + theRetStr += QString(astr.str()); + break; + } + case CORBA::tk_double: { + double d; + anAny >>= d; + astr << d << std::ends; + //astr << setw(25) << setprecision(18) << d << std::ends; + QString aRetStr = QString(astr.str()); + int i = 0; + while ( i < (int ) theRetStr.length() && theRetStr.at(i++) == ' ' ) { + startstr = i; + } + theRetStr += aRetStr.mid(startstr,aRetStr.length()); + break; + } + case CORBA::tk_sequence: { + theRetStr += QString("["); + + CORBA::Long aSeqLength = 0; + *(anAny.type()->parameter(1)) >>= aSeqLength; + + if ( aSeqLength == 0 ) + { + theRetStr += QString(" ]"); + break; + } + + // TO DO : implement recursion for the sequence type + /*CORBA::TypeCode* aType; + *(anAny.type()->parameter(0)) >>= aType; + switch ( aType->kind() ) + { + case CORBA::tk_string: { + printf("StringElem\n"); + CORBA::StringSeq* aStringSeq; + anAny >>= aStringSeq; + for (int i=0; i < aSeqLength; i++) + { + CORBA::Any anArg; + anArg <<= aStringSeq[i]; + toString( &anArg, theRetStr ); + if ( i < aSeqLength-1 ) theRetStr += QString(","); + } + break; + } + case CORBA::tk_double: { + printf("DoubleElem\n"); + CORBA::DoubleSeq* aDoubleSeq; + anAny >>= aDoubleSeq; + for (int i=0; i < aSeqLength; i++) + { + CORBA::Any anArg; + anArg <<= aDoubleSeq[i]; + toString( &anArg, theRetStr ); + if ( i < aSeqLength-1 ) theRetStr += QString(","); + } + break; + } + case CORBA::tk_sequence: { + printf("SequenceElem\n"); + CORBA::Any* aSequenceSeq; + anAny >>= aSequenceSeq; + for (int i=0; i < aSeqLength; i++) + { + CORBA::Any anArg; + anArg <<= aSequenceSeq[i]; + toString( &anArg, theRetStr ); + if ( i < aSeqLength-1 ) theRetStr += QString(","); + } + break; + } + default: { + printf("DefaultElem\n"); + theRetStr += QString("< ? >"); + break; + } + }*/ + theRetStr += QString("]"); + break; + } + case CORBA::tk_objref: { + /*CORBA::Object_ptr obj; + try { + anAny >>= (CORBA::Any::to_object ) obj; + theRetStr += QString( _Orb->object_to_string( obj ) ); + } + catch ( ... ) { + theRetStr += QString("object_to_string catched "); + }*/ + theRetStr += QString("Objref"); + break; + } + default: { + theRetStr += QString("< ? >"); + break; + } + } + } + } +} + +void toString(PyObject* theObject, QString& theRetStr) +{ + if ( !theObject ) theRetStr += QString("< ? >"); + + std::ostringstream aStr; + if ( PyString_CheckExact(theObject) ) + theRetStr += QString( PyString_AsString(theObject) ); + else if ( PyLong_CheckExact(theObject) ) + { + long aVal = PyLong_AsLong(theObject); + aStr << aVal << std::ends; + theRetStr += QString( aStr.str() ); + } + else if ( PyInt_CheckExact(theObject) ) + { + long aVal = PyInt_AsLong(theObject); + aStr << aVal << std::ends; + theRetStr += QString( aStr.str() ); + } + else if ( PyBool_Check(theObject) ) + theRetStr += QString( (theObject == Py_True) ? "true" : "false" ); + else if ( PyFloat_CheckExact(theObject) ) + { + double aVal = PyFloat_AsDouble(theObject); + aStr << aVal << std::ends; + theRetStr += QString( aStr.str() ); + } + else if ( PyList_CheckExact(theObject) ) + { + theRetStr += QString("["); + for (int i=0; i < PyList_Size(theObject); i++) + { + toString( PyList_GetItem(theObject, i), theRetStr ); + if ( i < PyList_Size(theObject)-1 ) theRetStr += QString(","); + } + theRetStr += QString("]"); + } + //else if ( ... ) // objref case + else + theRetStr += QString("< ? >"); +} + +void toString(YACS::ENGINE::Any* theAny, QString& theValue) +{ + if ( !theAny ) theValue += QString("< ? >"); + else if ( theAny->getType() ) + { + DynType aKind = theAny->getType()->kind(); + switch (aKind) + { + case Double: + theValue += QString::number(theAny->getDoubleValue()); + break; + case Int: + theValue += QString::number(theAny->getIntValue()); + break; + case String: + theValue += QString(theAny->getStringValue()); + break; + case Bool: + theValue += QString(theAny->getBoolValue()?"true":"false"); + break; + case Objref: + theValue += QString("Objref"); /// ? + break; + case Sequence: { + SequenceAny* aSeqAny = dynamic_cast( theAny ); + if ( aSeqAny ) + { + theValue += QString("["); + for (int i=0; i < aSeqAny->size(); i++) + { + toString( (*aSeqAny)[i], theValue ); + if ( i < aSeqAny->size()-1 ) theValue += QString(","); + } + theValue += QString("]"); + } + break; + } + case NONE: + default: + theValue += QString(""); + break; + } + } +} + +void toString(const std::string& value, const TypeCode * t,QString& theRetStr) +{ + if(value == "") + { + theRetStr=""; + return; + } + xmlDocPtr doc; + xmlNodePtr cur; + YACS::ENGINE::Any *ob=NULL; + doc = xmlParseMemory(value.c_str(), value.size()); + if (doc == NULL ) + { + theRetStr="< ? >"; + return; + } + cur = xmlDocGetRootElement(doc); + if (cur == NULL) + { + xmlFreeDoc(doc); + theRetStr="< ? >"; + return; + } + while (cur != NULL) + { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"value"))) + { + try + { + ob=convertXmlNeutral(t,doc,cur); + } + catch(...) + { + } + break; + } + cur = cur->next; + } + xmlFreeDoc(doc); + if(ob==NULL) + { + theRetStr="< ? >"; + } + else + { + toString(ob,theRetStr); + ob->decrRef(); + } +} + diff --git a/src/prs/YACSPrs_toString.h b/src/prs/YACSPrs_toString.h new file mode 100644 index 000000000..67ae714e2 --- /dev/null +++ b/src/prs/YACSPrs_toString.h @@ -0,0 +1,41 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef YACSPRS_SERVICENODE_H +#define YACSPRS_SERVICENODE_H + +#include +#include +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class Any; + class TypeCode; + } +} + +char * toString(CORBA::Any* theAny, QString& theRetStr); +void toString(PyObject* theObject, QString& theRetStr); +void toString(YACS::ENGINE::Any* theAny, QString& theValue); +void toString(const std::string& value, const YACS::ENGINE::TypeCode * t,QString& theRetStr); +#endif diff --git a/src/prs/resources/YACSPrs_images.po b/src/prs/resources/YACSPrs_images.po index 6136825f0..33b298b16 100755 --- a/src/prs/resources/YACSPrs_images.po +++ b/src/prs/resources/YACSPrs_images.po @@ -1,3 +1,18 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2007-12-24 13:07+0300\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + #### Icons for YACS module presentations #### @@ -5,6 +20,12 @@ msgid "ICON_STATUS_NO" msgstr "no_status.png" +msgid "ICON_STATUS_INVALID" +msgstr "ledred.png" + +msgid "ICON_STATUS_READY" +msgstr "ledgreen.png" + msgid "ICON_DISABLED" msgstr "disabled.png" diff --git a/src/prs/resources/ledgreen.png b/src/prs/resources/ledgreen.png new file mode 100644 index 0000000000000000000000000000000000000000..4d1e1912c0db7b8554adfee45fa2c1ecfeca6586 GIT binary patch literal 1265 zcmVfB{I=cOxh-(bP+d|WKp^j*EQh2h!v!DYZu*DO1o8X zQE*Y}q7<`pQOu^UEH2cd1tDM}LMcNdNi&&w@8#Yu&b{y5_nZl}6})hn`}cg`J?Ff0 z&cJJK>Lt%F11Esvz&tSJ);EDQ;4ZKVth`DBZQvqs9_X}=P0~6#j-GANn@hofeiAWQ z@6mtUBYUt5&;_mn-vV3zhrk)&8>Lle>f}MpDb4eDcd93H3kJw#Jh|Q?Tiv05Ya0f( z3w!}w`!5781E05-4$wF^!RGwm5WC|M0y=~MDUezwHpb}x^ql-oAK(gbVHikb1o#iY z*+Zuf^VgRd{kJk`DoB7BNR-@+5mJ#Orj(FVigY~3e9$0CH0EKt2pj=!{2Kz7fwOOa z@*aPDwgcJ$HH=Jq<}oriGm1zzu#d7uU<0^EdAewAV6DA$ptJQgFs7tyQL{?i%Ogr3aJILZ zE$!d8(ko*Nec-zu+{wDgC%lCd<=aK2Ri|-oqExf9v1%$93rJNuvL6R`D)+s4KrOeR zNeB6?sS`Lqb@HI|b}z)eT)X)&0$TQ!H;t}oDpJMRz6qSrATgyvU>WF`Q`&j8+X=KF zKmw|oQ2<_heQ{S+W%>S*2Ix4+RpXXYYB;c0dtHWa@5dndq*$KUvn?4Jz}WJzDZ917I&L29mv?M! zUfZ9EK)wWGw=~t8ODn=Ff`d;kjWd)|0-ldJSC><7od{eejVlLpFI1KBy+QenBWpGa zUY^?WUPvgnWu6#Cj?x61`bkuIsTXXsGQkvqCG4r}m%*s6nIUHC8ju>I(7@VYz1JyT zky>%29EdCyP)0#)_m70(eLv0v65fZN8ju2}AaJ+;xVJ>!bfBsfgaTu+2H2zO&0!jT z0XQ&$pZoTE4pKc8;#RWVS+IJd!I;$Xaiu|!f!c9=~fU}0lL}h zP6=EW?8iNqSb8J&!}}gQwV<2^Zl@q6+e%0P;A;QYHWM3TP8d}!c;G(een_Ms?e;@c zc-wDVSWQ9dMPNuej+e$d`GsbX(Sqa>S0f?tqMbvvrxvon_TTqkNXKD8G61^fS^ja7 zXv~}vetQVOo^#AS0&fR01jO5XV9T`-{Fe-VPC;tJJAS!d5#0l(&BJstX=}`k0_(u{ z9C+q_Jz(a#cf8Dz*bBga&ER@boL&k6ht-5Pfg|RAx)A9G_MJuv?qBbTgak55pP}}0 z0lyA>S_d0d72g1+?W1gwKMiU&7C-O=Ja}CLE^Gkea6b;b+OG@)-;aRT#0JmIhuj{# zL1y7#Bt*i{YHPQ=r(fHJb<;&`eu)w7rT?0-5KBIviF{U**#6W=gp(li%Knz*Tw{HLd1Vl+h zK~#90#h1Tp8%Y$$KhjE;w2EZ}>wqC5g~2!nRwa}oaE+UE!PUWCrSlyaoHnW48DEjW zRSG!GxpImt;wHE=Y45-X{s-KoT|prF5$zA{UNQ5uqt(iHxg7YxL;GWPzMpyXX66ZQ z*>Ydleh1hFTEIF`*Uvu!*T5xk0i6Ax05#wlum?Ch^*Y-tE3~Rr){8}mBCdx+E(ZfH z`hCtuBY+-o47>zBeGNbdcu}(~=UJn{UZa6iE<-K{aSTxelL-U?_&#_Zz2T5!*X3ou z&!;%<0ndSx{{qkj_B(59ym;^cr&@(V0W2#4m`orH6M*qp`DjFMFyOiCa^iUauYjjn zBGv-&Q((8dxyezpiM_lGwhfhv@^TqUC0JU5Vle^B=M`Kohn>suWNC@jFyuT4+Q0_z z_TK<>f!)()liiICs8$oNR1}B+6pPAJ;!}%b+W9;iVaVGs+yYjC^P2!Vz)^Q|b5`88 zlV39eGWvWz0f^%yKXi_40js{xc@(vQ55QFxKn-};SzEJ@n$6jfn;r0i3-?Lv<=%EGnT=Nr_gg zP^%>_iJ4vz;+Bt0jTFduJPRXk0-*{AR1Gl&xV{_=oQJ+YFD{7}Me3aZ zMUm=Mq96b!L>36DY7q_rxV-51AMU4xW#lq7@=kU>nI_{Ho&zyqv|W&J2*AbJXtduO z4sp`rGSVPO*0~7~hDu~SP9m`g0#z!V85{y|2K0_y*EuK_lQnBrJd%i61&K_XK#WH7 z(a_8Am|2dQ)9^3f|Mur{8QTOfSBK1HT2Nd>&EL^TwbiQM0UrE{K8(zgtOi_nN+svF zyLYoIAG7dSP!rBT34pdAffL2CjxJWs2zWs6YBG7U8ius<`T0#rgiNutVES6yE8rJ( z`4sq5o~J9KD`53J2-+KA$QI0pUy@1^EDa&zI_v;%fS=|#lr5@?Pl4~dg#!DP%Hq;X zawHucW8XK*;Wxk!3-mIr3&b6WUCWB&QYnsYJC5(%N!+&8^Fm?n=yCP8DDQrWuxTB@ ztwDUKJN<|AE_QX>ni6((A75oP;81rK??Bvz_zx}S>g%q4MNew
""" """

An empty editor window will be created.

""") - self.newAct.connect(self.newAct,SIGNAL('activated()'), self.handleFile) + self.newAct.connect(self.newAct,SIGNAL('activated()'), self.newProc) self.actions.append(self.newAct) self.prefAct=QAction('Preferences',QIconSet(Icons.get_image("configure.png")),'&Preferences...', @@ -169,6 +203,10 @@ class Appli(QMainWindow): self.stopAct.setStatusTip('Stop the selected schema') self.actions.append(self.stopAct) + self.cataToolAct=QAction('Catalog Tool',0,self,"catatool") + self.cataToolAct.connect(self.cataToolAct,SIGNAL('activated()'), self.cata_tool) + self.actions.append(self.cataToolAct) + def initMenus(self): menubar = self.menuBar() @@ -177,6 +215,16 @@ class Appli(QMainWindow): self.newAct.addTo(self.fileMenu) self.fileMenu.insertItem("&Open", self.openFile) self.fileMenu.insertItem("&Open Salome", self.openSalomeFile) + self.loadersMenu = QPopupMenu(self) + self.fileMenu.insertItem("Loaders", self.loadersMenu) + self.loaders=[] + for file in glob.glob("/local/chris/SALOME2/SUPERV/YACS/BR_CC/YACS_SRC/src/pyqt/*loader.py"): + d,f=os.path.split(file) + name=f[:-9] + def call_loader(event,obj=self,file=file): + obj.openFileWithLoader(file) + self.loaders.append(call_loader) + self.loadersMenu.insertItem(name, call_loader) menubar.insertItem('&File',self.fileMenu) #menu settings @@ -194,15 +242,22 @@ class Appli(QMainWindow): #sous menu layout self.layoutMenu = QPopupMenu(self) self.layoutMenu.insertItem("&Left Right", self.LR) + self.layoutMenu.insertItem("Right Left", self.RL) + self.layoutMenu.insertItem("Top Bottom", self.TB) + self.layoutMenu.insertItem("Bottom Top", self.BT) self.canvasMenu = QPopupMenu(self) self.canvasMenu.insertItem("&Zoom in", self.zoomIn) self.canvasMenu.insertItem("Zoom &out", self.zoomOut) self.canvasMenu.insertItem("Layout", self.layoutMenu) + self.canvasMenu.insertItem("Ortholinks", self.orthoLinks) + self.canvasMenu.insertItem("Clearlinks", self.clearLinks) self.canvasMenu.insertItem("&Update", self.updateCanvas) menubar.insertItem('&Canvas', self.canvasMenu) #menu window self.windowMenu = QPopupMenu(self) + self.cataToolAct.addTo(self.windowMenu) + self.windowMenu.insertItem("&Log", self.view_log) menubar.insertItem('&Window', self.windowMenu) self.connect(self.windowMenu, SIGNAL('aboutToShow()'), self.handleWindowMenu) @@ -220,6 +275,7 @@ class Appli(QMainWindow): self.loader = loader.YACSLoader() self.executor = pilot.ExecutorSwig() self.salomeloader=salomeloader.SalomeLoader() + self.loader.registerProcCataLoader() def openSalomeFile(self): fn = QFileDialog.getOpenFileName(QString.null,QString.null,self) @@ -228,6 +284,11 @@ class Appli(QMainWindow): return fileName = str(fn) proc=self.salomeloader.load(fileName) + logger=proc.getLogger("parser") + if logger.hasErrors(): + self.logFile=logview.LogView() + self.logFile.text.setText(logger.getStr()) + self.logFile.show() panel=Browser(self.tabWidget,proc) self.currentPanel=panel @@ -241,42 +302,102 @@ class Appli(QMainWindow): return fileName = str(fn) proc=self.loader.load(fileName) + logger=proc.getLogger("parser") + if logger.hasErrors(): + self.logFile=logview.LogView() + self.logFile.text.setText(logger.getStr()) + self.logFile.show() + + panel=Browser(self.tabWidget,proc) + self.currentPanel=panel + self.tabWidget.addTab( panel,os.path.basename(fileName)) + self.tabWidget.showPage(panel) + + def newProc(self): + r=pilot.getRuntime() + proc=r.createProc("pr") + panel=Browser(self.tabWidget,proc) + self.currentPanel=panel + self.tabWidget.addTab( panel,proc.getName()) + self.tabWidget.showPage(panel) + + def openFileWithLoader(self,file): + d,f=os.path.split(file) + sys.path.insert(0,d) + module=__import__(os.path.splitext(f)[0]) + del sys.path[0] + loader=module.Loader() + + fn = QFileDialog.getOpenFileName(QString.null,QString.null,self) + if fn.isEmpty(): + self.statusBar().message('Loading aborted',2000) + return + fileName = str(fn) + proc=loader.load(fileName) + logger=proc.getLogger("parser") + if logger.hasErrors(): + self.logFile=logview.LogView() + self.logFile.text.setText(logger.getStr()) + self.logFile.show() panel=Browser(self.tabWidget,proc) self.currentPanel=panel self.tabWidget.addTab( panel,os.path.basename(fileName)) self.tabWidget.showPage(panel) - def LR(self): - if self.currentPanel.selected and isinstance(self.currentPanel.selected,Items.ItemComposedNode): - self.currentPanel.selected.layout("LR") + def cata_tool(self): + self.catalogTool=catalog.CatalogTool(self) + self.catalogTool.show() + return + + def view_log(self): + if self.currentPanel: + self.currentPanel.view_log() + + def LR(self,*args ):self.rankdir("LR") + def RL(self,*args ):self.rankdir("RL") + def TB(self,*args ):self.rankdir("TB") + def BT(self,*args ):self.rankdir("BT") + + def rankdir(self,orient): + if self.currentPanel and self.currentPanel.panelManager.visible: + self.currentPanel.panelManager.visible.layout(orient) def updateCanvas(self): if self.currentPanel.selected:#item selected if isinstance(self.currentPanel.selected,Items.ItemComposedNode): - #on peut updater - self.currentPanel.selected.editor.updateCanvas() + #can update + self.currentPanel.selected.graph.editor.updateCanvas() - def addNode(self): - if self.currentPanel.selected:#item selected + def addNode(self,node): + if self.currentPanel and self.currentPanel.selected:#item selected if isinstance(self.currentPanel.selected,Items.ItemComposedNode): - #on peut ajouter un noeud - self.currentPanel.selected.addNode() + #can add node + self.currentPanel.selected.addNode(node) def zoomIn(self): - if self.currentPanel.selected:#item selected - if isinstance(self.currentPanel.selected,Items.ItemComposedNode): - #on peut zoomer - self.currentPanel.selected.editor.zoomIn() + if self.currentPanel and self.currentPanel.panelManager.visible: + if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode): + #we can zoom + self.currentPanel.panelManager.visible.graph.editor.zoomIn() def zoomOut(self): - if self.currentPanel.selected:#item selected - if isinstance(self.currentPanel.selected,Items.ItemComposedNode): - #on peut dezoomer - self.currentPanel.selected.editor.zoomOut() - - def handleFile(self): - pass + if self.currentPanel and self.currentPanel.panelManager.visible: + if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode): + #we can unzoom + self.currentPanel.panelManager.visible.graph.editor.zoomOut() + + def orthoLinks(self): + if self.currentPanel and self.currentPanel.panelManager.visible: + if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode): + #it is a composed node with a graph + self.currentPanel.panelManager.visible.graph.orthoLinks() + + def clearLinks(self): + if self.currentPanel and self.currentPanel.panelManager.visible: + if isinstance(self.currentPanel.panelManager.visible,Items.ItemComposedNode): + #it is a composed node with a graph + self.currentPanel.panelManager.visible.graph.clearLinks() def handlePreferences(self): pass diff --git a/src/pyqt/gui/BoxManager.py b/src/pyqt/gui/BoxManager.py new file mode 100644 index 000000000..f3428eed2 --- /dev/null +++ b/src/pyqt/gui/BoxManager.py @@ -0,0 +1,34 @@ + +from qt import * +import CONNECTOR + +class BoxManager(QWidgetStack): + """ A BoxManager manages a collection of widget + Each widget is associated to an item + A widget is displayed when the associated item is selected + To get the associated widget : item.box(self) + """ + def __init__(self,parent): + QWidgetStack.__init__(self,parent) + self.panels={} + + def setRootItem(self,rootItem): + self.rootItem=rootItem + CONNECTOR.Connect(self.rootItem,"selected",self.setview,()) + + def setview(self,item): + if not self.panels.has_key(item): + CONNECTOR.Connect(item,"changed",self.changePanel,(item,)) + panel=item.box(self) + self.panels[item]=panel + idd=self.addWidget(panel) + self.raiseWidget(self.panels[item]) + + def changePanel(self,item): + print "changePanel",item + if self.panels.has_key(item): + self.removeWidget(self.panels[item]) + panel=item.box(self) + self.panels[item]=panel + idd=self.addWidget(panel) + self.raiseWidget(self.panels[item]) diff --git a/src/pyqt/gui/CItems.py b/src/pyqt/gui/CItems.py index 4e9f79be3..9e7cc87e1 100644 --- a/src/pyqt/gui/CItems.py +++ b/src/pyqt/gui/CItems.py @@ -3,13 +3,43 @@ import sys,traceback from qt import * from qtcanvas import * import pilot +import pypilot +import Item +import math + dispatcher=pilot.Dispatcher.getDispatcher() +class TextItem(QCanvasText): + """A text in a composite object""" + def __init__(self,obj,canvas): + QCanvasText.__init__(self,canvas) + self.obj=obj + self.item=None + def getObj(self): + """The composite object which contains the text""" + return self.obj + def moveBy(self,dx,dy): + """Request the text move by x,y""" + if self.obj: + #the text is a part of a composite object + self.obj.moveBy(dx,dy) + else: + #the text is independant + self.myMove(dx,dy) + def myMove(self,dx,dy): + """The real move""" + QCanvasText.moveBy(self,dx,dy) + def selected(self): + """The canvas item has been selected""" + if self.obj: + self.obj.selected() + class PointItem(QCanvasEllipse): def __init__(self,obj,x,y,canvas): """Create a point contained in a composite line (obj)""" QCanvasEllipse.__init__(self,6,6,canvas) self.obj=obj + self.item=None self.inline=None self.outline=None self.setPen(QPen(Qt.black)) @@ -45,8 +75,10 @@ class PointItem(QCanvasEllipse): def handleDoubleClick(self,pos): self.obj.deletePoint(self,pos) + #def __del__(self): # print "PointItem.__del__" + def clear(self): """To remove from canvas""" self.setCanvas(None) @@ -54,11 +86,15 @@ class PointItem(QCanvasEllipse): self.inline=None self.outline=None + def selected(self): + """The canvas item has been selected""" + class LineItem(QCanvasLine): """A line between 2 points""" def __init__(self,obj,fromPoint, toPoint,canvas): QCanvasLine.__init__(self,canvas) self.obj=obj + self.item=None self.fromPoint=fromPoint self.toPoint=toPoint self.setPen(QPen(Qt.black)) @@ -66,35 +102,64 @@ class LineItem(QCanvasLine): self.setPoints(int(fromPoint.x()),int(fromPoint.y()), int(toPoint.x()), int(toPoint.y())) self.setZ(min(fromPoint.z(),toPoint.z())-1) self.setVisible(True) + self.arrow = QCanvasPolygon(self.canvas()) + self.arrow.setBrush(QBrush(Qt.black)) + self.setArrow() + self.arrow.show() def setFromPoint(self,x,y): self.setPoints(x,y,self.endPoint().x(),self.endPoint().y()) + self.setArrow() def setToPoint(self,x,y): self.setPoints(self.startPoint().x(), self.startPoint().y(),x,y) + self.setArrow() def moveBy(self,dx,dy): """Disable line move""" pass + def setArrow(self): + x1,y1=self.startPoint().x(),self.startPoint().y() + x2,y2=self.endPoint().x(),self.endPoint().y() + d=math.hypot(x2-x1,y2-y1) + sina=(y2-y1)/d + cosa=(x2-x1)/d + x=(x1+x2)/2. + y=(y1+y2)/2. + l,e=6,3 + pa=QPointArray(3) + pa.setPoint(0, QPoint(x+l*cosa,y+l*sina)) + pa.setPoint(1, QPoint(x-e*sina,y+e*cosa)) + pa.setPoint(2, QPoint(x+e*sina,y-e*cosa)) + self.arrow.setPoints(pa) + def getObj(self): """The object which contains the line""" return self.obj def handleDoubleClick(self,pos): #split the line self.obj.splitline(self,pos) + #def __del__(self): # print "LineItem.__del__" + def clear(self): """To remove from canvas""" self.setCanvas(None) self.fromPoint=None self.toPoint=None self.obj=None + self.arrow.setCanvas(None) + self.arrow=None + + def selected(self): + """The canvas item has been selected""" class LinkItem: def __init__(self,fromPort, toPort,canvas): self.fromPort=fromPort self.toPort=toPort self.canvas=canvas + self.item=None fromPort.addOutLink(self) toPort.addInLink(self) self.lines=[] @@ -117,10 +182,18 @@ class LinkItem: point.clear() outline.clear() + def clearPoints(self): + #make a copy as deletePoint modify self.points + for point in self.points[:]: + self.deletePoint(point,0) + def splitline(self,line,pos): - """Split line at position pos""" + self.splitLine(line,pos.x(),pos.y()) + + def splitLine(self,line,x,y): + """Split line at position x,y""" #The new point - point=PointItem(self,pos.x(),pos.y(),self.canvas) + point=PointItem(self,x,y,self.canvas) self.points.append(point) i=self.lines.index(line) @@ -130,7 +203,7 @@ class LinkItem: line.toPoint.setInline(newline) self.lines.insert(i+1,newline) - line.setToPoint(pos.x(),pos.y()) + line.setToPoint(x,y) line.toPoint=point point.setInline(line) point.setOutline(newline) @@ -161,7 +234,9 @@ class LinkItem: r = QRect(pos.x(), pos.y(), pos.x()+10, pos.y()+10) s = QString( "link: "+self.fromPort.port.getNode().getName() +":"+self.fromPort.port.getName()+"->"+self.toPort.port.getNode().getName()+":"+self.toPort.port.getName() ) view.tip( r, s ) - #QToolTip(view).tip( r, s ) + + def selected(self): + """The canvas item has been selected""" class ControlLinkItem(LinkItem): def tooltip(self,view,pos): @@ -179,12 +254,17 @@ class ControlItem(QCanvasRectangle): self.setBrush(QBrush(Qt.red)) self.setZ(node.z()+1) self.node=node + self.item=Item.adapt(self.port) + def moveBy(self,dx,dy): self.node.moveBy(dx,dy) + def myMove(self,dx,dy): QCanvasRectangle.moveBy(self,dx,dy) + def getObj(self): return self + def popup(self,canvasView): self.context=canvasView menu=QPopupMenu() @@ -193,16 +273,32 @@ class ControlItem(QCanvasRectangle): menu.insertItem( caption ) menu.insertItem("Connect", self.connect) return menu + def connect(self): - print "connect",self.context - self.context.connecting(self) + print "ControlItem.connect",self.context + print self.port + item=Item.adapt(self.port) + print item + item.connect() + self.context.connecting(item) + #self.context.connecting(self) + def link(self,obj): + #Protocol to link 2 objects (ports, at first) + #First, notify the canvas View (or any view that can select) we are connecting (see method connect above) + #Second (and last) make the link in the link method of object that was declared connecting print "link:",obj + def tooltip(self,view,pos): r = QRect(pos.x(), pos.y(), self.width(), self.height()) s = QString( "gate:") view.tip( r, s ) - #QToolTip(view).tip( r, s ) + + def selected(self): + """The canvas item has been selected""" + #print "control port selected" + item=Item.adapt(self.port) + item.selected() class InControlItem(ControlItem): def __init__(self,node,port,canvas): @@ -215,6 +311,8 @@ class InControlItem(ControlItem): link.setToPoint( int(self.x()), int(self.y()) ) def link(self,obj): + #Here we create the link between self and obj. + #self has been declared connecting in connect method print "link:",obj if isinstance(obj,OutControlItem): #Connection possible @@ -240,6 +338,8 @@ class OutControlItem(ControlItem): link.setFromPoint( int(self.x()), int(self.y()) ) def link(self,obj): + #Here we create the link between self and obj. + #self has been declared connecting in connect method print "link:",obj if isinstance(obj,InControlItem): #Connection possible @@ -254,10 +354,15 @@ class OutControlItem(ControlItem): view.tip( r, s ) #QToolTip(view).tip( r, s ) + def links(self): + return self.__outList + class PortItem(QCanvasEllipse): def __init__(self,node,port,canvas): QCanvasEllipse.__init__(self,6,6,canvas) self.port=port + self.item=None + self.item=Item.adapt(self.port) self.setPen(QPen(Qt.black)) self.setBrush(QBrush(Qt.red)) self.setZ(node.z()+1) @@ -282,18 +387,27 @@ class PortItem(QCanvasEllipse): return menu def connect(self): - print "connect",self.context - self.context.connecting(self) + print "PortItem.connect",self.context + print self.port + item=Item.adapt(self.port) + print item + self.context.connecting(item) + #self.context.connecting(self) def link(self,obj): - print "link:",obj + print "PortItem.link:",obj def tooltip(self,view,pos): r = QRect(pos.x(),pos.y(),self.width(), self.height()) t=self.port.edGetType() s = QString( "port: " + self.port.getName() + ":" + t.name()) view.tip( r, s ) - #QToolTip(view).tip( r, s ) + + def selected(self): + """The canvas item has been selected""" + #print "port selected" + item=Item.adapt(self.port) + item.selected() class InPortItem(PortItem): def __init__(self,node,port,canvas): @@ -306,6 +420,8 @@ class InPortItem(PortItem): link.setToPoint( int(self.x()), int(self.y()) ) def link(self,obj): + #Here we create the link between self and obj. + #self has been declared connecting in connect method print "link:",obj if isinstance(obj,OutPortItem): #Connection possible @@ -314,8 +430,6 @@ class InPortItem(PortItem): def addInLink(self,link): self.__inList.append(link) - - class OutPortItem(PortItem): def __init__(self,node,port,canvas): PortItem.__init__(self,node,port,canvas) @@ -327,6 +441,8 @@ class OutPortItem(PortItem): link.setFromPoint( int(self.x()), int(self.y()) ) def link(self,obj): + #Here we create the link between self and obj. + #self has been declared connecting in connect method print "link:",obj if isinstance(obj,InPortItem): #Connection possible @@ -335,6 +451,9 @@ class OutPortItem(PortItem): def addOutLink(self,link): self.__outList.append(link) + def links(self): + return self.__outList + class InStreamItem(InPortItem): def __init__(self,node,port,canvas): InPortItem.__init__(self,node,port,canvas) @@ -345,7 +464,7 @@ class OutStreamItem(OutPortItem): OutPortItem.__init__(self,node,port,canvas) self.setBrush(QBrush(Qt.green)) -class Cell(QCanvasRectangle,pilot.PyObserver): +class Cell(QCanvasRectangle,pypilot.PyObserver): colors={ "pink":Qt.cyan, "green":Qt.green, @@ -360,25 +479,23 @@ class Cell(QCanvasRectangle,pilot.PyObserver): def __init__(self,node,canvas): QCanvasRectangle.__init__(self,canvas) - pilot.PyObserver.__init__(self) + pypilot.PyObserver.__init__(self) + self.inports=[] + self.outports=[] self.setSize(50,50) #node is an instance of YACS::ENGINE::Node self.node=node + self.item=Item.adapt(self.node) dispatcher.addObserver(self,node,"status") - self.label=QCanvasText(canvas) + self.label=TextItem(self,canvas) self.label.setText(self.node.getName()) self.label.setFont(QFont("Helvetica",8)) rect=self.label.boundingRect() - self.label.setX(self.x()+self.width()/2-rect.width()/2) - self.label.setY(self.y()+self.height()/2-rect.height()/2) self.label.setZ(self.z()+1) + self.label.myMove(self.x()+self.width()/2-rect.width()/2,self.y()+self.height()/2-rect.height()/2) color= self.colors.get(node.getColorState(node.getEffectiveState()),Qt.white) self.setBrush(QBrush(color)) - self.inports=[] - self.outports=[] - - liste= self.node.getSetOfInputPort() dy=6 y=0 for inport in self.node.getSetOfInputPort(): @@ -395,7 +512,6 @@ class Cell(QCanvasRectangle,pilot.PyObserver): ymax=y - liste= self.node.getSetOfOutputPort() dy=6 y=0 for outport in self.node.getSetOfOutputPort(): @@ -458,7 +574,7 @@ class Cell(QCanvasRectangle,pilot.PyObserver): def moveBy(self,dx,dy): QCanvasRectangle.moveBy(self,dx,dy) - self.label.moveBy(dx,dy) + self.label.myMove(dx,dy) for p in self.inports: p.myMove(dx,dy) for p in self.outports: @@ -491,3 +607,9 @@ class Cell(QCanvasRectangle,pilot.PyObserver): def browse(self): print "browse" + + def selected(self): + """The canvas item has been selected""" + #print "node selected" + item=Item.adapt(self.node) + item.selected() diff --git a/src/pyqt/gui/CONNECTOR.py b/src/pyqt/gui/CONNECTOR.py new file mode 100644 index 000000000..692f64ba3 --- /dev/null +++ b/src/pyqt/gui/CONNECTOR.py @@ -0,0 +1,155 @@ +# -*- coding: iso-8859-15 -*- +""" + La classe CONNECTOR sert à enregistrer les observateurs d'objets et à délivrer + les messages émis à ces objets. + + Le principe général est le suivant : un objet (subscriber) s'enregistre aupres du + connecteur global (theconnector) pour observer un objet emetteur de messages (publisher) + sur un canal donné (channel). Il demande à etre notifie par appel d'une fonction (listener). + La séquence est donc : + + - enregistrement du subscriber pour le publisher : theconnector.Connect(publisher,channel,listener,args) + - émission du message par le publisher : theconnector.Emit(publisher,channel,cargs) + + args et cargs sont des tuples contenant les arguments de la fonction listener qui sera appelée + comme suit:: + + listener(cargs+args) +""" +import traceback +from copy import copy +import weakref + +class ConnectorError(Exception): + pass + +class CONNECTOR: + + def __init__(self): + self.connections={} + + def Connect(self, object, channel, function, args): + ###print "Connect",object, channel, function, args + idx = id(object) + if self.connections.has_key(idx): + channels = self.connections[idx] + else: + channels = self.connections[idx] = {} + + if channels.has_key(channel): + receivers = channels[channel] + else: + receivers = channels[channel] = [] + + for funct,fargs in receivers[:]: + if funct() is None: + receivers.remove((funct,fargs)) + elif (function,args) == (funct(),fargs): + receivers.remove((funct,fargs)) + + receivers.append((ref(function),args)) + ###print "Connect",receivers + + + def Disconnect(self, object, channel, function, args): + try: + receivers = self.connections[id(object)][channel] + except KeyError: + raise ConnectorError, \ + 'no receivers for channel %s of %s' % (channel, object) + + for funct,fargs in receivers[:]: + if funct() is None: + receivers.remove((funct,fargs)) + + for funct,fargs in receivers: + if (function,args) == (funct(),fargs): + receivers.remove((funct,fargs)) + if not receivers: + # the list of receivers is empty now, remove the channel + channels = self.connections[id(object)] + del channels[channel] + if not channels: + # the object has no more channels + del self.connections[id(object)] + return + + raise ConnectorError,\ + 'receiver %s%s is not connected to channel %s of %s' \ + % (function, args, channel, object) + + + def Emit(self, object, channel, *args): + ###print "Emit",object, channel, args + try: + receivers = self.connections[id(object)][channel] + except KeyError: + return + ###print "Emit",object, channel, receivers + # Attention : copie pour eviter les pbs lies aux deconnexion reconnexion + # pendant l'execution des emit + for rfunc, fargs in copy(receivers): + try: + func=rfunc() + if func: + apply(func, args + fargs) + else: + # Le receveur a disparu + if (rfunc,fargs) in receivers:receivers.remove((rfunc,fargs)) + except: + traceback.print_exc() + +def ref(target,callback=None): + if hasattr(target,"im_self"): + return BoundMethodWeakref(target) + else: + return weakref.ref(target,callback) + +class BoundMethodWeakref(object): + def __init__(self,callable): + self.Self=weakref.ref(callable.im_self) + self.Func=weakref.ref(callable.im_func) + + def __call__(self): + target=self.Self() + if not target:return None + func=self.Func() + if func: + return func.__get__(self.Self()) + +_the_connector =CONNECTOR() +Connect = _the_connector.Connect +Emit = _the_connector.Emit +Disconnect = _the_connector.Disconnect + +if __name__ == "__main__": + class A:pass + class B: + def add(self,a): + print "add",self,a + def __del__(self): + print "__del__",self + + def f(a): + print f,a + print "a=A()" + a=A() + print "b=B()" + b=B() + print "c=B()" + c=B() + Connect(a,"add",b.add,()) + Connect(a,"add",b.add,()) + Connect(a,"add",c.add,()) + Connect(a,"add",f,()) + Emit(a,"add",1) + print "del b" + del b + Emit(a,"add",1) + print "del f" + del f + Emit(a,"add",1) + Disconnect(a,"add",c.add,()) + Emit(a,"add",1) + + diff --git a/src/pyqt/gui/GraphViewer.py b/src/pyqt/gui/GraphViewer.py index 4d78cc9ec..bd1260b9b 100644 --- a/src/pyqt/gui/GraphViewer.py +++ b/src/pyqt/gui/GraphViewer.py @@ -2,6 +2,7 @@ import sys from qt import * from qtcanvas import * +import math class DynamicTip( QToolTip ): def __init__( self, parent ): @@ -20,12 +21,16 @@ class DynamicTip( QToolTip ): return class GraphViewer(QCanvasView): - def __init__(self,item,c,parent,name,f): + def __init__(self,c,parent,name,f): QCanvasView.__init__(self,c,parent,name,f) - self.item=item self.__moving=0 self.__connecting=0 self.__moving_start= 0 + # for highlighting selections + self.selectPen=QPen(QColor(255,255,0),2,Qt.DashLine) + self.selectBrush=QBrush(Qt.red) + self.selectStyle = Qt.Dense5Pattern + self.selected=None self.tooltip = DynamicTip( self ) def contentsMouseDoubleClickEvent(self,e): # QMouseEvent e @@ -51,6 +56,7 @@ class GraphViewer(QCanvasView): if not each_item.hit(point): continue if e.button()== Qt.RightButton: + #Right button click self.__moving=0 self.__connecting=0 if hasattr(each_item,"popup"): @@ -63,16 +69,23 @@ class GraphViewer(QCanvasView): if menu: menu.exec_loop( QCursor.pos() ) self.canvas().update() + elif e.button()== Qt.LeftButton: + #Left button click if self.__connecting: + #We are linking objects if hasattr(each_item,"getObj"): #a connection is ending - self.__connecting.link(each_item.getObj()) + self.__connecting.link(each_item.getObj().item) + #self.__connecting.link(each_item.getObj()) self.canvas().update() self.__connecting=0 else: + #We are moving or selecting a composite object + each_item.selected() self.__moving=each_item self.__moving_start=point + self.canvas().update() return if e.button()== Qt.RightButton: menu=self.popup() @@ -83,6 +96,35 @@ class GraphViewer(QCanvasView): self.__connecting=0 QCanvasView.contentsMousePressEvent(self,e) + def selectItem(self,item): + #print "selectItem",item + if self.selected: + try: + self.deselectObj(self.selected) + except: + pass + self.selected=None + #need to find equivalent canvas item + for citem in self.canvas().allItems(): + if hasattr(citem,"item") and citem.item is item: + self.selected=citem + self.selectObj(self.selected) + break + self.canvas().update() + + def selectObj(self,obj): + if obj: + obj._origPen = obj.pen() + obj._origBrush = obj.brush() + obj._origStyle = obj.brush().style() + obj.setPen(self.selectPen) + #obj.setBrush(self.selectBrush) + + def deselectObj(self,obj): + if obj: + obj.setPen(obj._origPen) + #obj.setBrush(obj._origBrush) + def popup(self): menu=QPopupMenu() caption = QLabel( "View Menu", self ) @@ -91,8 +133,8 @@ class GraphViewer(QCanvasView): menu.insertItem("add Node", self.addNode) return menu - def layout(self,rankdir): - print rankdir + #def layout(self,rankdir): + # print rankdir def updateCanvas(self): #Par defaut, Qt n'efface pas le background. Seul repaintContents @@ -102,7 +144,7 @@ class GraphViewer(QCanvasView): #self.canvas().update() def addNode(self): - self.item.addNode() + print "addNode" def zoomIn(self): m = self.worldMatrix() @@ -161,53 +203,6 @@ class ImageItem(QCanvasRectangle): def drawShape(self,p): p.drawPixmap( self.x(), self.y(), self.pixmap ) - -class NodeItem(QCanvasEllipse): - def __init__(self,canvas): - QCanvasEllipse.__init__(self,6,6,canvas) - self.__inList=[] - self.__outList=[] - self.setPen(QPen(Qt.black)) - self.setBrush(QBrush(Qt.red)) - self.setZ(128) - - def addInEdge(self,edge): - self.__inList.append(edge) - - def addOutEdge(self,edge): - self.__outList.append(edge) - - def moveBy(self,dx,dy): - QCanvasEllipse.moveBy(self,dx,dy) - for each_edge in self.__inList: - each_edge.setToPoint( int(self.x()), int(self.y()) ) - for each_edge in self.__outList: - each_edge.setFromPoint( int(self.x()), int(self.y()) ) - -class EdgeItem(QCanvasLine): - __c=0 - def __init__(self,fromNode, toNode,canvas): - QCanvasLine.__init__(self,canvas) - self.__c=self.__c+1 - self.setPen(QPen(Qt.black)) - self.setBrush(QBrush(Qt.red)) - fromNode.addOutEdge(self) - toNode.addInEdge(self) - self.setPoints(int(fromNode.x()),int(fromNode.y()), int(toNode.x()), int(toNode.y())) - self.setZ(127) - - def setFromPoint(self,x,y): - self.setPoints(x,y,self.endPoint().x(),self.endPoint().y()) - - def setToPoint(self,x,y): - self.setPoints(self.startPoint().x(), self.startPoint().y(),x,y) - - def count(self): - return self.__c - - def moveBy(self,dx,dy): - pass - class LinkItem(QCanvasLine): def __init__(self,fromPort, toPort,canvas): QCanvasLine.__init__(self,canvas) @@ -218,16 +213,36 @@ class LinkItem(QCanvasLine): self.setPoints(int(fromPort.x()),int(fromPort.y()), int(toPort.x()), int(toPort.y())) self.setZ(min(fromPort.z(),toPort.z())-1) self.setVisible(True) + self.arrow = QCanvasPolygon(self.canvas()) + self.arrow.setBrush(QBrush(Qt.black)) + self.setArrow() + self.arrow.show() def setFromPoint(self,x,y): self.setPoints(x,y,self.endPoint().x(),self.endPoint().y()) + self.setArrow() def setToPoint(self,x,y): self.setPoints(self.startPoint().x(), self.startPoint().y(),x,y) + self.setArrow() def moveBy(self,dx,dy): pass + def setArrow(self): + x1,y1=self.startPoint().x(),self.startPoint().y() + x2,y2=self.endPoint().x(),self.endPoint().y() + d=math.hypot(x2-x1,y2-y1) + sina=(y2-y1)/d + cosa=(x2-x1)/d + x=(x1+x2)/2. + y=(y1+y2)/2. + pa=QPointArray(3) + pa.setPoint(0, QPoint(x+10*cosa,y+10*sina)) + pa.setPoint(1, QPoint(x-5*sina,y+5*cosa)) + pa.setPoint(2, QPoint(x+5*sina,y-5*cosa)) + self.arrow.setPoints(pa) + def popup(self,canvasView): menu=QPopupMenu() caption = QLabel( "Node Menu",menu ) @@ -242,7 +257,7 @@ class LinkItem(QCanvasLine): def tooltip(self,view,pos): r = QRect(pos.x(), pos.y(), pos.x()+10, pos.y()+10) s = QString( "link: %d,%d" % (r.center().x(), r.center().y()) ) - QToolTip(view).tip( r, s ) + view.tip( r, s ) class PortItem(QCanvasEllipse): def __init__(self,node,canvas): @@ -280,7 +295,7 @@ class PortItem(QCanvasEllipse): def tooltip(self,view,pos): r = QRect(self.x(), self.y(), self.width(), self.height()) s = QString( "port: %d,%d" % (r.center().x(), r.center().y()) ) - QToolTip(view).tip( r, s ) + view.tip( r, s ) class InPortItem(PortItem): def __init__(self,node,canvas): @@ -363,25 +378,32 @@ class Cell(QCanvasRectangle): def tooltip(self,view,pos): r = QRect(self.x(), self.y(), self.width(), self.height()) s = QString( "node: %d,%d" % (r.center().x(), r.center().y()) ) - QToolTip(view).tip( r, s ) + view.tip( r, s ) def browse(self): print "browse" + def selected(self): + print "selected" + if __name__=='__main__': app=QApplication(sys.argv) - qvbox=QVBox() - QToolBar(qvbox,"toolbar") + box=QMainWindow() + QToolBar(box,"toolbar") canvas=QCanvas(800,600) canvas.setAdvancePeriod(30) - m=GraphViewer(canvas,qvbox,"example",0) - for x,y in ((150,150),(150,250)): - c=Cell(canvas) - c.moveBy(x,y) - c.show() - - qApp.setMainWidget(qvbox) - qvbox.show() + m=GraphViewer(canvas,box,"example",0) + box.setCentralWidget(m) + c1=Cell(canvas) + c1.moveBy(150,150) + c1.show() + c2=Cell(canvas) + c2.moveBy(250,150) + c2.show() + c1.outports[0].link(c2.inports[0]) + + qApp.setMainWidget(box) + box.show() app.exec_loop() diff --git a/src/pyqt/gui/Item.py b/src/pyqt/gui/Item.py index 7ac53357e..e36cfce89 100644 --- a/src/pyqt/gui/Item.py +++ b/src/pyqt/gui/Item.py @@ -1,15 +1,20 @@ import sys from qt import * +import CONNECTOR +import adapt class Item: - def __init__(self,label): + def __init__(self,label=""): self.label=label + self.emitting=0 def isExpandable(self): return False def getChildren(self): return [] + def father(self): + return None def getIconName(self): return "python" @@ -21,6 +26,29 @@ class Item: label.setAlignment( Qt.AlignHCenter | Qt.AlignVCenter ) return qvbox + def box(self,parent): + """Retourne un widget pour browser/editer l'item""" + qvbox=QVBox(parent) + label=QLabel("Default Panel",qvbox) + label.setAlignment( Qt.AlignHCenter | Qt.AlignVCenter ) + return qvbox + + def selected(self): + """Method called on selection""" + #print "Item selected" + def dblselected(self): + """Method called on double selection""" + #print "Item dblselected" + +ADAPT=adapt.adapt +items={} +def adapt(obj): + if items.has_key(obj.ptr()): + return items[obj.ptr()] + else: + item= ADAPT(obj,Item) + items[obj.ptr()]=item + return item if __name__ == "__main__": app = QApplication(sys.argv) diff --git a/src/pyqt/gui/Items.py b/src/pyqt/gui/Items.py index bad879226..8bd705885 100644 --- a/src/pyqt/gui/Items.py +++ b/src/pyqt/gui/Items.py @@ -1,18 +1,21 @@ import sys import pilot +import SALOMERuntime import Item import adapt from qt import * from qtcanvas import * -from GraphViewer import GraphViewer import Editor import CItems import pygraphviz import traceback - +import CONNECTOR +import graph +import panels class DataLinkItem(Item.Item): def __init__(self,pin,pout): + Item.Item.__init__(self) self.pin=pin self.pout=pout self.label= pout.getNode().getName()+":"+pout.getName()+"->"+pin.getNode().getName()+":"+pin.getName() @@ -22,6 +25,7 @@ class DataLinkItem(Item.Item): class StreamLinkItem(Item.Item): def __init__(self,pin,pout): + Item.Item.__init__(self) self.pin=pin self.pout=pout self.label= pout.getNode().getName()+":"+pout.getName()+"->"+pin.getNode().getName()+":"+pin.getName() @@ -31,6 +35,7 @@ class StreamLinkItem(Item.Item): class ControlLinkItem(Item.Item): def __init__(self,nodeup,nodedown): + Item.Item.__init__(self) self.nodedown=nodedown self.nodeup=nodeup self.label= nodeup.getName()+"->"+nodedown.getName() @@ -39,14 +44,17 @@ class ControlLinkItem(Item.Item): return "controllink.png" class ControlLinksItem(Item.Item): - """Item pour les liens controle d'un noeud compose""" + """Item for all control links of a composed node""" def __init__(self,item): + Item.Item.__init__(self) self.item=item self.label="Control Links" + def getIconName(self): return "folder" def isExpandable(self): return True + def getChildren(self): sublist=[] for n in self.item.node.edGetDirectDescendants(): @@ -54,15 +62,18 @@ class ControlLinksItem(Item.Item): sublist.append(ControlLinkItem(n,p)) return sublist + def addLink(self,link): + CONNECTOR.Emit(self,"add",link) + class DataLinksItem(Item.Item): - """Item pour les liens data d'un noeud compose""" + """Item for all data links of a composed node""" def __init__(self,item): + Item.Item.__init__(self) self.item=item self.label="Data Links" def getIconName(self): return "folder" - def isExpandable(self): return True @@ -81,19 +92,20 @@ class DataLinksItem(Item.Item): # sublist.append(DataLinkItem(pin,pout)) return sublist -class MyCanvas(QCanvas): - def customEvent(self,event): - object=event.data() - object.customEvent(event) - self.update() + def addLink(self,link): + CONNECTOR.Emit(self,"add",link) class ItemComposedNode(Item.Item): """Item pour les noeuds composes""" n=0 def __init__(self,node): #node is an instance of YACS::ENGINE::ComposedNode + Item.Item.__init__(self) self.node=node + self.graph=None self.label=node.getName() + self.datalinks=DataLinksItem(self) + self.controllinks=ControlLinksItem(self) def isExpandable(self): return True @@ -105,15 +117,33 @@ class ItemComposedNode(Item.Item): sublist=[] for n in liste: try: - sublist.append(adapt.adapt(n,Item.Item)) + sublist.append(Item.adapt(n)) except: - print n + #print n #traceback.print_exc() raise - sublist.append(DataLinksItem(self)) - sublist.append(ControlLinksItem(self)) + sublist.append(self.datalinks) + sublist.append(self.controllinks) return sublist + def dblselected(self): + #print "ItemComposedNode dblselected" + root=self.node.getRootNode() + rootItem=Item.adapt(root) + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(rootItem,"dblselected",self) + self.emitting=0 + + def selected(self): + #print "ItemComposedNode selected" + root=self.node.getRootNode() + rootItem=Item.adapt(root) + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(rootItem,"selected",self) + self.emitting=0 + def getIconName(self): return "green-los" @@ -124,130 +154,96 @@ class ItemComposedNode(Item.Item): tabWidget.addTab( method(self,tabWidget), name ) return tabWidget - def addNode(self): - r=pilot.getRuntime() + def addNode(self,service): + print "Composed.addNode",service + #add node service in the parent self which is a ComposedNode + new_node=service.clone(None) ItemComposedNode.n=ItemComposedNode.n+1 - n1=r.createScriptNode("","unknown_%d" % ItemComposedNode.n) - node=CItems.Cell(n1,self.canvas) - node.show() - self.citems[n1.ptr()]=node - self.canvas.update() + name=service.getName()+"_%d" % ItemComposedNode.n + new_node.setName(name) + self.node.edAddChild(new_node) + item=Item.adapt(new_node) + CONNECTOR.Emit(self,"add",item) def panel1(self,parent): qvbox=QVBox(parent) - #Canvas size : 10000x10000 - self.canvas=MyCanvas(10000,10000) - self.editor=GraphViewer(self,self.canvas,qvbox,"example",0) - - #permet de retrouver un item node dans le canvas a partir - #d'un proxy swig quelconque (astuce) - #Pour retrouver un item node faire : citems[node.ptr()] - citems={} - self.citems=citems - #permet de retrouver un item port dans le canvas a partir - #d'un proxy swig quelconque (astuce) - #Pour retrouver un item port faire : pitems[port.ptr()] - pitems={} - #self.pitems=pitems - - y=0 - lnode=self.node.edGetDirectDescendants() - for n in lnode: - c=CItems.Cell(n,self.canvas) - citems[n.ptr()]=c - c.show() - - for k,n in citems.items(): - for p in n.inports: - pitems[p.port.ptr()]=p - for p in n.outports: - pitems[p.port.ptr()]=p - - for pout,pin in self.node.getSetOfInternalLinks(): - if pout.getNode().getFather() != self.node and pin.getNode().getFather() != self.node: - continue - po=pitems.get(pout.ptr()) - pi=pitems.get(pin.ptr()) - if pi and po: - CItems.LinkItem(po,pi,self.canvas) + self.graph=graph.Graph(self,qvbox) + return qvbox - for n in lnode: - itemup=citems[n.ptr()] - for ndown in n.getOutNodes(): - itemdown=citems[ndown.ptr()] - CItems.ControlLinkItem(itemup.outgate,itemdown.ingate,self.canvas) + def layout(self,rankdir): + if self.graph: + self.graph.layout(rankdir) - self.layout("LR") + panels=[("Panel1",panel1)] - return qvbox + def addLink(self,link): + print "Composed.addLink",link + if isinstance(link,DataLinkItem): + self.datalinks.addLink(link) + elif isinstance(link,StreamLinkItem): + self.datalinks.addLink(link) + else: + self.controllinks.addLink(link) - panels=[("Panel1",panel1)] - def layout(self,rankdir): - """Compute graph layout with graphviz package""" - G=pygraphviz.AGraph(strict=False,directed=True) - G.graph_attr["rankdir"]=rankdir - for k,n in self.citems.items(): - #k est l'adresse du node (YACS) - #n est l'item dans le canvas - G.add_node(k) - - for pout,pin in self.node.getSetOfInternalLinks(): - if pout.getNode().ptr() not in self.citems : - continue - if pin.getNode().ptr() not in self.citems: - continue - G.add_edge(pout.getNode().ptr(),pin.getNode().ptr()) - - for k,n in self.citems.items(): - for ndown in n.node.getOutNodes(): - G.add_edge(n.node.ptr(),ndown.ptr()) - - #By default graphviz uses 96.0 pixel per inch (dpi=96.0) - for n in G.nodes(): - item=self.citems[int(n)] - h=item.height()/96. #height in inch - w=item.width()/96. #width in inch - n.attr['height']=str(h) - n.attr['width']=str(w) - n.attr['fixedsize']="true" - n.attr['shape']="box" - #n.attr['label']=item.node.getName() - - G.layout(prog='dot') # use dot - #G.write("layout.dot") - #G.draw("layout.png") - - #from pygraphviz import graphviz as gv - #bbox= gv.agget(G.handle,"bb")#bounding box to resize - #x1,y1,x2,y2=eval(bbox) - #self.canvas.resize(w,h) - - for n in G: - pos=n.attr['pos'] #position is given in points (72 points par inch, so 1 point = 96./72=1.34) - x,y=eval(pos) - x=96./72*x+10 - y=96./72*y+10 - item=self.citems[int(n)] - # x0=item.x()+item.width()/2. - # y0=item.y()+item.height()/2. - x0=item.x() - y0=item.y() - x=x-x0 - y=y-y0 - item.moveBy(x,y) - - self.canvas.update() +class ItemForLoop(ItemComposedNode): + def box(self,parent): + return panels.PanelForLoop(parent,self) + + def addNode(self,service): + new_node=service.clone(None) + ItemComposedNode.n=ItemComposedNode.n+1 + name=service.getName()+"_%d" % ItemComposedNode.n + new_node.setName(name) + #replace the old node (if it exists) with the new one + nodes=self.node.edGetDirectDescendants() + if nodes: + old_item=Item.adapt(nodes[0]) + CONNECTOR.Emit(old_item,"remove") + self.node.edSetNode(new_node) + item=Item.adapt(new_node) + CONNECTOR.Emit(self,"add",item) + CONNECTOR.Emit(self,"changed") + +class ItemWhile(ItemForLoop): + pass + +class ItemForEach(ItemForLoop): + pass + +class ItemSwitch(ItemComposedNode): + def addNode(self,service): + return class ItemProc(ItemComposedNode): """Item pour la procedure""" + def connecting(self,item): + print "ItemProc.connecting",item + self._connecting=item class ItemPort(Item.Item): """Item pour les ports """ panels=[] - def __init__(self,port): + def __init__(self,port,root=None): + Item.Item.__init__(self) self.port=port self.label=port.getName() + if root: + self.root=root + elif self.port.getNode().getFather(): + root=self.port.getNode().getRootNode() + self.root=Item.adapt(root) + else: + self.root=None + + def selected(self): + #print "ItemPort selected" + if not self.root: + return + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 def getIconName(self): return "port.png" @@ -258,37 +254,21 @@ class ItemPort(Item.Item): for name,method in self.panels: tabWidget.addTab( method(self,tabWidget), name ) return tabWidget + box=panel + + def link(self,other): + print "ItemPort.link:",self,other + + def connect(self): + print "ItemPort.connect:" + self.root.connecting(self) class ItemInPort(ItemPort): def getIconName(self): return "inport.png" def panel1(self,parent): - qvbox=QVBox(parent) - qvbox.layout().setAlignment(Qt.AlignTop|Qt.AlignLeft) - qvbox.setSpacing( 5 ) - row0=QHBox(qvbox) - label=QLabel("Name: ",row0) - lined0 = QLineEdit(self.port.getName(),row0) - label=QLabel("Type: ",row0) - QLineEdit(self.port.edGetType().name(),row0) - - label=QLabel("Value: ",qvbox) - #self.value=QLabel("Empty",qvbox) - self.value=QTextEdit(qvbox) - self.value.setText("Empty") - if not self.port.isEmpty(): - self.value.setText(self.port.dump()) - - row3=QHBox(qvbox) - but2=QPushButton( "Refresh", row3 ) - qvbox.connect( but2, SIGNAL("clicked()"), self.handleRefresh ) - - return qvbox - - def handleRefresh(self): - if not self.port.isEmpty(): - self.value.setText(self.port.dump()) + return panels.PanelInPort(parent,self) panels=[("Panel1",panel1)] @@ -297,46 +277,66 @@ class ItemOutPort(ItemPort): return "outport.png" def panel1(self,parent): - qvbox=QVBox(parent) - qvbox.layout().setAlignment(Qt.AlignTop|Qt.AlignLeft) - qvbox.setSpacing( 5 ) + return panels.PanelOutPort(parent,self) - row0=QHBox(qvbox) - QLabel("Name: ",row0) - QLineEdit(self.port.getName(),row0) - QLabel("Type: ",row0) - QLineEdit(self.port.edGetType().name(),row0) - - QLabel("Value: ",qvbox) - self.value=QTextEdit(qvbox) - self.value.setText("Empty") - try: - self.value.setText(self.port.dump()) - except: - traceback.print_exc() - - row3=QHBox(qvbox) - but2=QPushButton( "Refresh", row3 ) - qvbox.connect( but2, SIGNAL("clicked()"), self.handleRefresh ) - - return qvbox + panels=[("Panel1",panel1)] - def handleRefresh(self): + def link(self,other): + nodeS=self.port.getNode() + nodeE=other.port.getNode() + father=nodeS.getFather() + if father != nodeE.getFather(): + #not same father : do nothing for the moment + return try: - self.value.setText(self.port.dump()) - except: + #cflink=nodeS.getOutGate().isAlreadyInSet(nodeE.getInGate()) + cflink= nodeE.getInGate() in nodeS.getOutGate().edSetInGate() + father.edAddDFLink(self.port,other.port) + l=DataLinkItem(other.port,self.port) + fitem=Item.adapt(father) + fitem.addLink(l) + if not cflink: + #add also a control flow link + fitem.addLink(ControlLinkItem(nodeS,nodeE)) + except ValueError,ex: traceback.print_exc() - - panels=[("Panel1",panel1)] - + QMessageBox.warning(None,"YACS error",str(ex)) + return class ItemInStream(ItemPort): def getIconName(self): return "instream.png" + class ItemOutStream(ItemPort): def getIconName(self): return "outstream.png" + def link(self,other): + father=self.port.getNode().getFather() + if father != other.port.getNode().getFather(): + #not same father : not for the moment + return + try: + father.edAddLink(self.port,other.port) + l=StreamLinkItem(other.port,self.port) + fitem=Item.adapt(father) + fitem.addLink(l) + except ValueError,ex: + traceback.print_exc() + QMessageBox.warning(None,"YACS error",str(ex)) + return + +class ItemInGate(ItemPort): + """Item for InGate""" + def __init__(self,port): + Item.Item.__init__(self) + self.port=port +class ItemOutGate(ItemPort): + """Item for OutGate""" + def __init__(self,port): + Item.Item.__init__(self) + self.port=port + class ItemNode(Item.Item): """Item pour les noeuds elementaires Il n a pas de fils @@ -344,8 +344,22 @@ class ItemNode(Item.Item): #attr donnant la liste des panels du noeud (nom,method) panels=[] def __init__(self,node): + Item.Item.__init__(self) self.node=node self.label=node.getName() + self.father=Item.adapt(node.getFather()) + + def selected(self): + #print "ItemNode selected" + root=self.node.getRootNode() + rootItem=Item.adapt(root) + if not self.emitting: + self.emitting=1 + #for those that have subscribed to item level + CONNECTOR.Emit(self,"selected",self) + #for those that have subscribed to rootItem level + CONNECTOR.Emit(rootItem,"selected",self) + self.emitting=0 def isExpandable(self): return True @@ -353,13 +367,13 @@ class ItemNode(Item.Item): def getChildren(self): sublist=[] for n in self.node.getSetOfInputPort(): - sublist.append(adapt.adapt(n,Item.Item)) + sublist.append(Item.adapt(n)) for n in self.node.getSetOfOutputPort(): - sublist.append(adapt.adapt(n,Item.Item)) + sublist.append(Item.adapt(n)) for n in self.node.getSetOfInputDataStreamPort(): - sublist.append(adapt.adapt(n,Item.Item)) + sublist.append(Item.adapt(n)) for n in self.node.getSetOfOutputDataStreamPort(): - sublist.append(adapt.adapt(n,Item.Item)) + sublist.append(Item.adapt(n)) return sublist def panel(self,parent): @@ -368,81 +382,30 @@ class ItemNode(Item.Item): for name,method in self.panels: tabWidget.addTab( method(self,tabWidget), name ) return tabWidget + box=panel class ItemScriptNode(ItemNode): def panel1(self,parent): - qvbox=QVBox(parent) - qvbox.setSpacing( 5 ) - - row0=QHBox(qvbox) - label=QLabel("Name: ",row0) - lined0 = QLineEdit(self.node.getName(),row0) - - label=QLabel("Script: ",qvbox) - mle=Editor.Editor(qvbox,"multiLineEdit" ) - mle.setText(self.node.getScript()) - - row2=QHBox(qvbox) - but1=QPushButton( "Save", row2 ) - but2=QPushButton( "Cancel", row2 ) - qvbox.connect( but1, SIGNAL("clicked()"), self.handleSave ) - qvbox.connect( but2, SIGNAL("clicked()"), self.handleCancel ) - - return qvbox + return panels.PanelScript(parent,self) panels=[("Panel1",panel1)] def getIconName(self): return "green-ball" - def handleSave(self): - self.node.setScript(str(self.mle.text())) - def handleCancel(self): - self.lined0.setText(self.node.getName()) - self.mle.setText(self.node.getScript()) - class ItemFuncNode(ItemNode): def panel1(self,parent): - """Retourne un widget pour browser/editer l'item""" - qvbox=QVBox(parent) - qvbox.setSpacing( 5 ) - - row0=QHBox(qvbox) - label=QLabel("Name: ",row0) - self.lined0 = QLineEdit(self.node.getName(),row0) - - row1=QHBox(qvbox) - label=QLabel("Fname: ",row1) - self.lined1 = QLineEdit(self.node.getFname(),row1) - - label=QLabel("Function: ",qvbox) - self.mle=Editor.Editor(qvbox,"multiLineEdit" ) - self.mle.setText(self.node.getScript()) - - row2=QHBox(qvbox) - but1=QPushButton( "Save", row2 ) - but2=QPushButton( "Cancel", row2 ) - qvbox.connect( but1, SIGNAL("clicked()"), self.handleSave ) - qvbox.connect( but2, SIGNAL("clicked()"), self.handleCancel ) - - return qvbox + return panels.PanelFunc(parent,self) panels=[("Panel1",panel1)] def getIconName(self): return "green-ball" + def FuncChanged(self, newText ): self.myFunc=str(newText) - def handleSave(self): - self.node.setFname(str(self.lined1.text())) - self.node.setScript(str(self.mle.text())) - def handleCancel(self): - self.lined0.setText(self.node.getName()) - self.lined1.setText(self.node.getFname()) - self.mle.setText(self.node.getScript()) - class ItemService(ItemNode): def panel1(self,parent): """Retourne un widget pour browser/editer l'item""" @@ -508,6 +471,18 @@ def adapt_Node_to_Item(obj, protocol, alternate): def adapt_ComposedNode_to_Item(obj, protocol, alternate): return ItemComposedNode(obj) +def adapt_ForLoop_to_Item(obj, protocol, alternate): + return ItemForLoop(obj) + +def adapt_Switch_to_Item(obj, protocol, alternate): + return ItemSwitch(obj) + +def adapt_While_to_Item(obj, protocol, alternate): + return ItemWhile(obj) + +def adapt_ForEach_to_Item(obj, protocol, alternate): + return ItemForEach(obj) + def adapt_InlineFuncNode_to_Item(obj, protocol, alternate): return ItemFuncNode(obj) @@ -532,7 +507,14 @@ def adapt_InStream_to_Item(obj, protocol, alternate): def adapt_OutStream_to_Item(obj, protocol, alternate): return ItemOutStream(obj) +def adapt_InGate_to_Item(obj, protocol, alternate): + return ItemInGate(obj) + +def adapt_OutGate_to_Item(obj, protocol, alternate): + return ItemOutGate(obj) + if hasattr(pilot,"ProcPtr"): + #SWIG 1.3.24 adapt.registerAdapterFactory(pilot.ProcPtr, Item.Item, adapt_Proc_to_Item) adapt.registerAdapterFactory(pilot.BlocPtr, Item.Item, adapt_ComposedNode_to_Item) adapt.registerAdapterFactory(pilot.ForLoopPtr, Item.Item, adapt_ComposedNode_to_Item) @@ -555,23 +537,36 @@ if hasattr(pilot,"ProcPtr"): pilot_InputDataStreamPort=pilot.InputDataStreamPortPtr else: + #SWIG 1.3.29 adapt.registerAdapterFactory(pilot.Proc, Item.Item, adapt_Proc_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.SalomeProc, Item.Item, adapt_Proc_to_Item) adapt.registerAdapterFactory(pilot.Bloc, Item.Item, adapt_ComposedNode_to_Item) - adapt.registerAdapterFactory(pilot.ForLoop, Item.Item, adapt_ComposedNode_to_Item) - adapt.registerAdapterFactory(pilot.WhileLoop, Item.Item, adapt_ComposedNode_to_Item) - adapt.registerAdapterFactory(pilot.ForEachLoop, Item.Item, adapt_ComposedNode_to_Item) - adapt.registerAdapterFactory(pilot.Switch, Item.Item, adapt_ComposedNode_to_Item) + adapt.registerAdapterFactory(pilot.ForLoop, Item.Item, adapt_ForLoop_to_Item) + + adapt.registerAdapterFactory(pilot.WhileLoop, Item.Item, adapt_While_to_Item) + adapt.registerAdapterFactory(pilot.ForEachLoop, Item.Item, adapt_ForEach_to_Item) + adapt.registerAdapterFactory(pilot.Switch, Item.Item, adapt_Switch_to_Item) adapt.registerAdapterFactory(pilot.ComposedNode, Item.Item, adapt_ComposedNode_to_Item) adapt.registerAdapterFactory(pilot.ServiceNode, Item.Item, adapt_ServiceNode_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.CORBANode, Item.Item, adapt_ServiceNode_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.SalomeNode, Item.Item, adapt_ServiceNode_to_Item) #adapt.registerAdapterFactory(pilot.ServiceNodeNode, Item.Item, adapt_Node_to_Item) adapt.registerAdapterFactory(pilot.InlineNode, Item.Item, adapt_InlineScriptNode_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.PythonNode, Item.Item, adapt_InlineScriptNode_to_Item) adapt.registerAdapterFactory(pilot.InlineFuncNode, Item.Item, adapt_InlineFuncNode_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.PyFuncNode, Item.Item, adapt_InlineFuncNode_to_Item) adapt.registerAdapterFactory(pilot.Node, Item.Item, adapt_Node_to_Item) adapt.registerAdapterFactory(pilot.OutputPort, Item.Item, adapt_OutPort_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.OutputPyPort, Item.Item, adapt_OutPort_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.OutputCorbaPort, Item.Item, adapt_OutPort_to_Item) adapt.registerAdapterFactory(pilot.InputPort, Item.Item, adapt_InPort_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.InputPyPort, Item.Item, adapt_InPort_to_Item) + adapt.registerAdapterFactory(SALOMERuntime.InputCorbaPort, Item.Item, adapt_InPort_to_Item) adapt.registerAdapterFactory(pilot.OutputDataStreamPort, Item.Item, adapt_OutStream_to_Item) adapt.registerAdapterFactory(pilot.InputDataStreamPort, Item.Item, adapt_InStream_to_Item) + adapt.registerAdapterFactory(pilot.OutGate, Item.Item, adapt_OutGate_to_Item) + adapt.registerAdapterFactory(pilot.InGate, Item.Item, adapt_InGate_to_Item) pilot_InputDataStreamPort=pilot.InputDataStreamPort diff --git a/src/pyqt/gui/PanelManager.py b/src/pyqt/gui/PanelManager.py index 17f87f508..d276b464d 100644 --- a/src/pyqt/gui/PanelManager.py +++ b/src/pyqt/gui/PanelManager.py @@ -1,15 +1,26 @@ from qt import * +import CONNECTOR class PanelManager(QWidgetStack): + """ A PanelManager manages a collection of widget + Each widget is associated to an item + A widget is displayed when the associated item is double selected + To get the associated widget : item.panel(self) + """ def __init__(self,parent): QWidgetStack.__init__(self,parent) + self.visible=None self.panels={} + def setRootItem(self,rootItem): + self.rootItem=rootItem + CONNECTOR.Connect(self.rootItem,"dblselected",self.setview,()) + def setview(self,item): if not self.panels.has_key(item): panel=item.panel(self) self.panels[item]=panel idd=self.addWidget(panel) - self.raiseWidget(panel) + self.visible=item self.raiseWidget(self.panels[item]) diff --git a/src/pyqt/gui/Tree.py b/src/pyqt/gui/Tree.py index cbd1bf20e..3e2b2a9ec 100644 --- a/src/pyqt/gui/Tree.py +++ b/src/pyqt/gui/Tree.py @@ -7,12 +7,13 @@ import sys from qt import * import Icons +import CONNECTOR class Tree(QListView): """Tree(parent=None) Classe pour faire une vue d'un arbre """ - def __init__(self,parent=None,onSelect=None): + def __init__(self,parent=None,onSelect=None,onDblSelect=None): QListView.__init__(self,parent) self.setCaption("Tree") self.setRootIsDecorated(1) @@ -21,18 +22,54 @@ class Tree(QListView): self.children=[] self.last=None self.onSelect=onSelect + self.onDblSelect=onDblSelect self.connect(self,SIGNAL('selectionChanged(QListViewItem *)'), self.handleSelected) + self.connect(self,SIGNAL('doubleClicked(QListViewItem *, const QPoint &, int)'), + self.handleDblSelected) def handleSelected(self,node): - if self.onSelect:self.onSelect(node.item) + node.item.selected() + if self.onSelect: + self.onSelect(node.item) + + def handleDblSelected(self,node,point,col): + node.item.dblselected() + if self.onDblSelect: + self.onDblSelect(node.item) def additem(self,item): node=Node(self,item.label,item,self.last) self.last=node self.children.append(node) + CONNECTOR.Connect(item,"selected",self.selectItem,()) + CONNECTOR.Connect(item,"add",node.addNode,()) return node + def selectNodeItem(self,item,node): + #print "selectNodeItem",node,item + self.setSelected(node,True) + + def selectItem(self,item): + #print "selectItem",item + node=self.selectedItem() + if node.item is item: + #print "item has been selected at item level" + return + + #print "item has not been selected at item level" + #try another way + #find its father ??? + it = QListViewItemIterator(self) + node = it.current() + while node: + if node.item is item: + break + it += 1 + node = it.current() + + if node: + self.setSelected(node,True) class Node(QListViewItem): """Node(parent,text,item,after) @@ -48,15 +85,40 @@ class Node(QListViewItem): self.setExpandable(self.item.isExpandable()) self.children = [] + def selectNode(self,item): + self.listView().setSelected(self,True) + + def addNode(self,item): + #print "Tree.addNode",item + self.additem(item) + + def delNode(self,node): + #print "Tree.delNode",node,node.item + CONNECTOR.Disconnect(node.item,"selected",node.selectNode,()) + CONNECTOR.Disconnect(node.item,"add",node.addNode,()) + CONNECTOR.Disconnect(node.item,"remove",self.delNode,(node,)) + self.takeItem(node) + self.children.remove(node) + def additem(self,item): if self.children: node=Node(self,item.label,item,self.children[-1]) else: node=Node(self,item.label,item) self.children.append(node) + #CONNECTOR.Connect(item,"selected",self.listView().selectNodeItem,(node,)) + CONNECTOR.Connect(item,"selected",node.selectNode,()) + CONNECTOR.Connect(item,"add",node.addNode,()) + CONNECTOR.Connect(item,"remove",self.delNode,(node,)) return node def setOpen(self,o): + if o and not self.childCount(): + for child in self.item.getChildren(): + self.additem(child) + QListViewItem.setOpen(self,o) + + def setOpen_old(self,o): if o: #open for child in self.item.getChildren(): @@ -64,6 +126,9 @@ class Node(QListViewItem): else: #close for node in self.children: + #CONNECTOR.Disconnect(node.item,"selected",self.listView().selectNodeItem,(node,)) + CONNECTOR.Disconnect(node.item,"selected",node.selectNode,()) + CONNECTOR.Disconnect(node.item,"add",node.addNode,()) self.takeItem(node) del node self.children=[] diff --git a/src/pyqt/gui/adapt.py b/src/pyqt/gui/adapt.py index b5d50941f..85b2366f9 100644 --- a/src/pyqt/gui/adapt.py +++ b/src/pyqt/gui/adapt.py @@ -18,7 +18,7 @@ def _adapt_by_registry(obj, protocol, alternate): else: adapter = factory(obj, protocol, alternate) if adapter is AdaptationError: - raise AdaptationError + raise AdaptationError,obj else: return adapter diff --git a/src/pyqt/gui/browser.py b/src/pyqt/gui/browser.py new file mode 100644 index 000000000..574d23061 --- /dev/null +++ b/src/pyqt/gui/browser.py @@ -0,0 +1,26 @@ + +from qt import * +import Tree +from BoxManager import BoxManager + +class Browser(QVBox): + def __init__(self,parent,appli): + QVBox.__init__(self,parent) + self.appli=appli + self.hSplitter = QSplitter(self,"hSplitter") + self.objectBrowser=Tree.Tree(self.hSplitter,self.onSelect,self.onDblSelect) + self.boxManager=BoxManager(self.hSplitter) + self.selected=None + self.init() + + def init(self): + pass + + def onDblSelect(self,item): + #item is instance of Item.Item + pass + + def onSelect(self,item): + #item is instance of Item.Item + self.selected=item + diff --git a/src/pyqt/gui/browser_catalog.py b/src/pyqt/gui/browser_catalog.py new file mode 100644 index 000000000..49c7a70c0 --- /dev/null +++ b/src/pyqt/gui/browser_catalog.py @@ -0,0 +1,24 @@ + +from qt import * +import browser +import cataitems + +class Browser(browser.Browser): + def init(self): + self.setStretchFactor(self.hSplitter,10) + row2=QHBox(self) + but1=QPushButton( "Add node", row2 ) + but1.setFixedSize( but1.sizeHint()) + self.connect( but1, SIGNAL("clicked()"), self.handleBut1 ) + + def handleBut1(self): + print "handleBut1",self.selected + if hasattr(self.selected,"addNode"): + self.selected.addNode(self.appli) + return + + def setCata(self,cata): + self.rootItem=cataitems.Cata(cata) + self.objectBrowser.additem(self.rootItem) + self.boxManager.setRootItem(self.rootItem) + diff --git a/src/pyqt/gui/browser_session.py b/src/pyqt/gui/browser_session.py new file mode 100644 index 000000000..a0a5dd510 --- /dev/null +++ b/src/pyqt/gui/browser_session.py @@ -0,0 +1,48 @@ + +import sys +from qt import * +import browser +import sessions +import pilot + +class Browser(browser.Browser): + def init(self): + self.rootItem=sessions.Sessions(port=2809) + self.objectBrowser.additem(self.rootItem) + self.boxManager.setRootItem(self.rootItem) + self.setStretchFactor(self.hSplitter,10) + +class MainBrowser(QMainWindow): + def __init__(self,parent,appli): + QMainWindow.__init__(self,parent) + self.appli=appli + self.catalogTool=parent + self.createWidgets() + + def createWidgets(self): + box=QVBox(self) + + hb=QHBox(box) + self.browser=Browser(hb,self.appli) + + row2=QHBox(box) + but1=QPushButton( "Import catalog", row2 ) + but1.setFixedSize( but1.sizeHint()) + #but2=QPushButton( "Cancel", row2 ) + self.connect( but1, SIGNAL("clicked()"), self.handleBut1 ) + #box.connect( but2, SIGNAL("clicked()"), self.handleCancel ) + self.setCentralWidget(box) + #self.resize(800,600) + + def handleBut1(self): + addr=self.browser.selected.addr+"#Kernel.dir/ModulCatalog.object" + cata=pilot.getRuntime().loadCatalog("session",addr) + self.catalogTool.register(cata,self.browser.selected.addr) + +if __name__ == "__main__": + app = QApplication(sys.argv) + t=MainBrowser(None,None) + app.setMainWidget(t) + t.show() + app.exec_loop() + diff --git a/src/pyqt/gui/cataitems.py b/src/pyqt/gui/cataitems.py new file mode 100644 index 000000000..68c151b9f --- /dev/null +++ b/src/pyqt/gui/cataitems.py @@ -0,0 +1,271 @@ +from qt import * + +import Item +import CONNECTOR +import Items + +class Obj(Item.Item): + def __init__(self,root=None): + Item.Item.__init__(self) + if root: + self.root=root + else: + self.root=self + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 + + def panel(self,parent): + """Retourne un tab widget pour browser/editer la proc""" + tabWidget = QTabWidget( parent ) + for name,method in self.panels: + tabWidget.addTab( method(self,tabWidget), name ) + return tabWidget + + box=panel + + def panel1(self,parent): + qvbox=QVBox(parent) + self.text=QTextEdit(qvbox,"log") + self.text.setFrameShape(QTextEdit.NoFrame) + self.text.setTextFormat(QTextEdit.PlainText) + self.text.setWordWrap(QTextEdit.FixedColumnWidth) + #self.text.setWrapColumnOrWidth(120) + self.text.setReadOnly(1) + return qvbox + + panels=[("Panel1",panel1)] + +class ItemService(Item.Item): + def __init__(self,service,root): + Item.Item.__init__(self) + self.root=root + self.service=service + self.label=service.getName() + + def isExpandable(self): + return True + + def addNode(self,appli): + appli.addNode(self.service) + + def getChildren(self): + sublist=[] + for port in self.service.getSetOfInputPort(): + sublist.append(Items.ItemInPort(port,self.root)) + for port in self.service.getSetOfOutputPort(): + sublist.append(Items.ItemOutPort(port,self.root)) + for port in self.service.getSetOfInputDataStreamPort(): + sublist.append(Items.ItemInStream(port,self.root)) + for port in self.service.getSetOfOutputDataStreamPort(): + sublist.append(Items.ItemOutStream(port,self.root)) + return sublist + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 + +class ItemType(Item.Item): + def __init__(self,typ,root,name=""): + Item.Item.__init__(self) + self.typ=typ + self.root=root + if name: + self.label=name + else: + self.label=typ.name() + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + return sublist + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 + +class ItemCompo(Item.Item): + def __init__(self,compo,root): + Item.Item.__init__(self) + self.compo=compo + self.root=root + self.label=compo.getName() + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + for service in self.compo._serviceMap.values(): + itemservice=ItemService(service,self.root) + sublist.append(itemservice) + return sublist + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 + +class ItemNode(Item.Item): + def __init__(self,node,root): + Item.Item.__init__(self) + self.node=node + self.root=root + self.label=node.getName() + + def isExpandable(self): + return True + + def addNode(self,appli): + appli.addNode(self.node) + + def getChildren(self): + sublist=[] + return sublist + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 + +class ItemComposedNode(Item.Item): + def __init__(self,node,root): + Item.Item.__init__(self) + self.node=node + self.root=root + self.label=node.getName() + + def addNode(self,appli): + appli.addNode(self.node) + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + return sublist + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 + +class TypesItem(Item.Item): + """Item for types folder""" + def __init__(self,typeMap,root): + Item.Item.__init__(self) + self.typeMap=typeMap + self.label="Types" + self.root=root + + def getIconName(self): + return "folder" + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + for name,typ in self.typeMap.items(): + itemtype=ItemType(typ,self.root,name) + sublist.append(itemtype) + return sublist + +class ComponentsItem(Item.Item): + """Item for components folder""" + def __init__(self,compoMap,root): + Item.Item.__init__(self) + self.compoMap=compoMap + self.label="Components" + self.root=root + + def getIconName(self): + return "folder" + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + for compo in self.compoMap.values(): + itemcompo=ItemCompo(compo,self.root) + sublist.append(itemcompo) + return sublist + +class NodesItem(Item.Item): + """Item for nodes folder""" + def __init__(self,nodesMap,root): + Item.Item.__init__(self) + self.nodesMap=nodesMap + self.label="Nodes" + self.root=root + + def getIconName(self): + return "folder" + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + for node in self.nodesMap.values(): + itemnode=ItemNode(node,self.root) + sublist.append(itemnode) + return sublist + +class ComposedNodesItem(Item.Item): + """Item for composed nodes folder""" + def __init__(self,composedMap,root): + Item.Item.__init__(self) + self.composedMap=composedMap + self.label="ComposedNodes" + self.root=root + + def getIconName(self): + return "folder" + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + for node in self.composedMap.values(): + itemnode=ItemComposedNode(node,self.root) + sublist.append(itemnode) + return sublist + +class Cata(Obj): + def __init__(self,cata): + Obj.__init__(self) + self.cata=cata + self.label=cata.getName() + + def isExpandable(self): + return True + + def getChildren(self): + sublist=[] + sublist.append(TypesItem(self.cata._typeMap,self)) + sublist.append(NodesItem(self.cata._nodeMap,self)) + sublist.append(ComposedNodesItem(self.cata._composednodeMap,self)) + sublist.append(ComponentsItem(self.cata._componentMap,self)) + return sublist + + def dblselected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self,"dblselected",self) + self.emitting=0 + diff --git a/src/pyqt/gui/catalog.py b/src/pyqt/gui/catalog.py new file mode 100644 index 000000000..ca9c808bd --- /dev/null +++ b/src/pyqt/gui/catalog.py @@ -0,0 +1,84 @@ + +from qt import * +import browser_session +import browser_catalog +import pilot + +class CatalogTool(QMainWindow): + """ + CatalogTool() + Main window of Catalog Tool + """ + def __init__(self,parent=None): + QMainWindow.__init__(self,parent) + self.appli=parent + self.createWidgets() + self.initActions() + self.initMenus() + self.initToolbar() + self.initStatusbar() + cata=pilot.getRuntime().getBuiltinCatalog() + self.register(cata,"Builtin Catalog") + + def createWidgets(self): + self.tabWidget = QTabWidget(self) + #self.currentPanel=None + #self.connect(self.tabWidget, SIGNAL('currentChanged(QWidget *)'),self.handlePanelChanged) + self.setCentralWidget(self.tabWidget) + self.resize(800,600) + + def initActions(self): + self.actions = [] + self.impSessionAct=QAction('Import from session...',0,self) + self.impSessionAct.connect(self.impSessionAct,SIGNAL('activated()'), self.importFromSession) + self.actions.append(self.impSessionAct) + self.impProcAct=QAction('Import from proc...',0,self) + self.impProcAct.connect(self.impProcAct,SIGNAL('activated()'), self.importFromProc) + self.actions.append(self.impProcAct) + + def initMenus(self): + menubar = self.menuBar() + + #menu import + self.importMenu=QPopupMenu(self) + self.impSessionAct.addTo(self.importMenu) + self.impProcAct.addTo(self.importMenu) + menubar.insertItem('&Import',self.importMenu) + + def importFromSession(self): + browser_session.MainBrowser(self,self.appli).show() + return + + def importFromProc(self): + fn = QFileDialog.getOpenFileName(QString.null,QString.null,self) + if fn.isEmpty(): + self.statusBar().message('Loading aborted',2000) + return + filename = str(fn) + cata=pilot.getRuntime().loadCatalog("proc",filename) + print cata + print cata._nodeMap + for name,node in cata._nodeMap.items(): + print name,node + self.register(cata,filename) + + def register(self,cata,name): + """Add a catalog in the catalog tool list""" + panel=browser_catalog.Browser(self,appli=self.appli) + panel.setCata(cata) + self.tabWidget.addTab( panel,name) + self.tabWidget.showPage(panel) + + def initToolbar(self): + #tb = QToolBar(self) + #self.importAct.addTo(tb) + self.toolbars={} + #self.toolbars['Import']=tb + + def initStatusbar(self): + sb = self.statusBar() + self.SBfile=QLabel(sb) + sb.addWidget(self.SBfile) + QWhatsThis.add(self.SBfile, """

Message""") + self.SBfile.setText("") + diff --git a/src/pyqt/gui/graph.py b/src/pyqt/gui/graph.py new file mode 100644 index 000000000..035cda0ac --- /dev/null +++ b/src/pyqt/gui/graph.py @@ -0,0 +1,430 @@ +import sys +import pilot +import Item +from qt import * +from qtcanvas import * +from GraphViewer import GraphViewer +import Editor +import CItems +import pygraphviz +from pygraphviz import graphviz as gv +import traceback +import CONNECTOR +import bisect + +class MyCanvas(QCanvas): + def customEvent(self,event): + object=event.data() + object.customEvent(event) + self.update() + +class Graph: + def __init__(self,item,parent): + self.parent=parent + self.item=item + self.node=item.node + #initial canvas size : 1000x1000 + self.canvas=MyCanvas(1000,1000) + self.editor=GraphViewer(self.canvas,parent,"example",0) + self.createGraph() + root=self.node.getRootNode() + rootItem=Item.adapt(root) + CONNECTOR.Connect(rootItem,"selected",self.selectItem,()) + CONNECTOR.Connect(self.item,"add",self.addItem,()) + CONNECTOR.Connect(self.item.datalinks,"add",self.addLink,()) + + def createGraph(self): + #citems dict helps finding items in canvas from swig proxy + #To find an item node make : citems[node.ptr()] + citems={} + self.citems=citems + #pitems dict helps finding items in canvas from swig proxy + #To find an item port make : pitems[port.ptr()] + pitems={} + + y=0 + lnode=self.node.edGetDirectDescendants() + for n in lnode: + c=CItems.Cell(n,self.canvas) + citems[n.ptr()]=c + c.show() + + for k,n in citems.items(): + for p in n.inports: + pitems[p.port.ptr()]=p + for p in n.outports: + pitems[p.port.ptr()]=p + + for pout,pin in self.node.getSetOfInternalLinks(): + if pout.getNode().getFather() != self.node and pin.getNode().getFather() != self.node: + continue + po=pitems.get(pout.ptr()) + pi=pitems.get(pin.ptr()) + if pi and po: + CItems.LinkItem(po,pi,self.canvas) + + for n in lnode: + itemup=citems[n.ptr()] + for ndown in n.getOutNodes(): + itemdown=citems[ndown.ptr()] + CItems.ControlLinkItem(itemup.outgate,itemdown.ingate,self.canvas) + + self.layout("LR") + + def addLink(self,link): + print "graph.addLink",link + #CItem for outport + nodeS=self.citems[link.pout.getNode().ptr()] + nodeE=self.citems[link.pin.getNode().ptr()] + po=pi=None + for p in nodeS.outports: + if p.port == link.pout: + po=p + break + for p in nodeE.inports: + if p.port == link.pin: + pi=p + break + + if pi and po: + l=CItems.LinkItem(po,pi,self.canvas) + self.canvas.update() + + def addItem(self,item): + #print "graph.addItem",item + node=CItems.Cell(item.node,self.canvas) + self.citems[item.node.ptr()]=node + node.show() + self.canvas.update() + + def selectItem(self,item): + #print "graph.selectItem",item + self.editor.selectItem(item) + + def layout(self,rankdir): + """Compute graph layout with graphviz package""" + G=pygraphviz.AGraph(strict=False,directed=True) + G.graph_attr["rankdir"]=rankdir + G.graph_attr["dpi"]="72" + dpi=72. + aspect=dpi/72 + for k,n in self.citems.items(): + #k is node address (YACS) + #n is item in canvas + G.add_node(k) + + for pout,pin in self.node.getSetOfInternalLinks(): + if pout.getNode().ptr() not in self.citems : + continue + if pin.getNode().ptr() not in self.citems: + continue + G.add_edge(pout.getNode().ptr(),pin.getNode().ptr()) + + for k,n in self.citems.items(): + for ndown in n.node.getOutNodes(): + G.add_edge(n.node.ptr(),ndown.ptr()) + + #By default graphviz uses 96.0 pixel per inch (dpi=96.0) + for n in G.nodes(): + item=self.citems[int(n)] + h=item.height()/dpi #height in inch + w=item.width()/dpi #width in inch + n.attr['height']=str(h) + n.attr['width']=str(w) + n.attr['fixedsize']="true" + n.attr['shape']="box" + #n.attr['label']=item.node.getName() + + G.layout(prog='dot') # use dot + #G.write("layout.dot") + #G.draw("layout.png") + + graph_attr=dict(attrs(G)) + bbox=graph_attr["bb"] + x1,y1,x2,y2=eval(bbox) + h=self.canvas.height() + w=self.canvas.width() + h2=max(h,y2-y1+100) + w2=max(w,x2-x1+100) + if h2 > h or w2 > w: + self.canvas.resize(w2,h2) + + for n in G: + pos=n.attr['pos'] #position is given in points (72 points par inch, so 1 point = dpi/72=1.34) + x,y=eval(pos) + x=aspect*x + y=aspect*y + item=self.citems[int(n)] + x0=item.x() + y0=item.y() + x=x-x0 + y=y-y0 + item.moveBy(x,y) + + self.canvas.update() + + def clearLinks(self): + items=self.citems.values() + for node in items: + for port in node.outports: + if not hasattr(port,"links"): + continue + for link in port.links(): + link.clearPoints() + self.canvas.update() + + def orthoLinks(self): + items=self.citems.values() + g=grid(items) + for node in items: + for port in node.outports: + if not hasattr(port,"links"): + continue + for link in port.links(): + #clear all intermediate points of the link + link.clearPoints() + #if isinstance(link,CItems.ControlLinkItem): + # print port.port.getNode().getName() +"->"+link.toPort.port.getNode().getName() + #else: + # print port.port.getNode().getName() +":"+port.port.getName()+"->"+link.toPort.port.getNode().getName()+":"+link.toPort.port.getName() + #print (port.x(),port.y()),(link.toPort.x(),link.toPort.y()) + x0,y0=port.x()+5,port.y() + while g.get((x0,y0)).blocked: + x0=x0+1 + x1,y1=link.toPort.x()-5,link.toPort.y() + while g.get((x1,y1)).blocked: + x1=x1-1 + path=g.findPath((x0,y0),(x1,y1)) + #print path + if len(path)==1: + if port.y() == link.toPort.y(): + #near ports face to face + continue + else: + x,y=path[0] + path=[(x,port.y()),(x,link.toPort.y())] + elif len(path)==2: + x1,y1=path[0] + x2,y2=path[1] + if x1 == x2: + #vertical line + path=[(x1,port.y()),(x1,link.toPort.y())] + else: + #horizontal line + if port.y() == link.toPort.y(): + #near ports face to face + continue + else: + #transform it into a vertical line + x=(x1+x2)/2 + path=[(x,port.y()),(x,link.toPort.y())] + + #adjust the first point to the same y as port + x0,y0=path[0] + x1,y1=path[1] + if y0==y1: + #remove first point and adjust second one + del path[0] + x0=x1 + path[0]=x0,port.y() + #adjust the last point to the same y as link.toPort + x0,y0=path[-1] + x1,y1=path[-2] + if y0==y1: + #remove last point and adjust new last one + del path[-1] + x0=x1 + path[-1]=x0,link.toPort.y() + #print path + + #add intermediate points + for x,y in path: + line=link.lines[-1] + link.splitLine(line,x,y) + self.canvas.update() + +def attrs(g,t=gv.AGRAPH): + ah=None + while 1: + ah=gv.agnxtattr(g.handle,t,ah) + value=gv.agxget(g.handle,ah) + yield gv.agattrname(ah),value + +def h(x,y,destx,desty): + return abs(destx-x)+abs(desty-y) + +def distance(node,new_node): + x,y=node.coord + x1,y1=new_node.coord + d= abs(x1-x)+abs(y1-y) + if node.parent != None: + x0,y0=node.parent.coord + if (x1-x)*(y0-y)-(y1-y)*(x0-x) != 0: + #corner add some cost to penalize + d=d+1 + return d + +class node: + def __init__(self,coord,index): + self.coord=coord + self.index=index + self.blocked=0 + self.total=0 + self.path_cost=0 + self.parent=None + self.open=0 + self.close=0 + +class grid: + def __init__(self,graph): + self.graph=graph + xs=set() + ys=set() + xmargin=5 + ymargin=5 + for n in graph: + h=n.height() + w=n.width() + x=n.x() + y=n.y() + xs.add(x-xmargin) + xs.add(x+w+xmargin) + ys.add(y-ymargin) + ys.add(y+h+ymargin) + + xs=list(xs) + xs.sort() + x0=xs[0]-36 + xs.insert(0,x0) + x0=xs[-1]+36 + xs.append(x0) + + ys=list(ys) + ys.sort() + y0=ys[0]-36 + ys.insert(0,y0) + y0=ys[-1]+36 + ys.append(y0) + + self.xs=xs + self.ys=ys + self.cols=[] + for w in xrange(len(xs)-1): + col=[] + x=(xs[w]+xs[w+1])/2 + for h in xrange(len(ys)-1): + y=(ys[h]+ys[h+1])/2 + col.append(node((x,y),(w,h))) + self.cols.append(col) + + for n in graph: + h=n.height() + w=n.width() + x=n.x() + y=n.y() + l1,l2=bisect.bisect_left(ys,y-ymargin),bisect.bisect_left(ys,y+h+ymargin) + i1,i2=bisect.bisect_left(xs,x-xmargin),bisect.bisect_left(xs,x+w+xmargin) + for c in self.cols[i1:i2]: + for e in c[l1:l2]: + e.blocked=1 + + #for col in self.cols: + # print [e.coord +(e.blocked,) for e in col] + + def reset(self): + for c in self.cols: + for n in c: + n.open=n.close=0 + n.total= n.path_cost=0 + n.parent=None + + def get(self,coord): + x,y=coord + col= bisect.bisect_left(self.xs,x)-1 + if col < 0 or col >= len(self.cols): + return None + col=self.cols[col] + row=bisect.bisect_left(self.ys,y)-1 + if row < 0 or row >= len(col): + return None + return col[row] + + def getPath(self,node): + path=[node.coord] + parent=node.parent + while parent: + prev=node + node=parent + parent=node.parent + if parent: + #if points are aligned don't keep the middle point + x,y=node.coord + x0,y0=prev.coord + x1,y1=parent.coord + if (x1-x)*(y0-y)-(y1-y)*(x0-x) == 0: + continue + path.append(node.coord) + path.reverse() + return path + + def neighbours(self,node): + col,row=node.index + l=[] + steps=((0, +1), (+1, 0), (0, -1), (-1, 0 )) + for step in steps: + c=col+step[0] + r=row+step[1] + if c < 0 or c >=len(self.cols): + continue + co=self.cols[c] + if r <0 or r >= len(co): + continue + n=co[r] + if n.blocked: + continue + l.append(n) + return l + + def findPath(self,fromLoc,toLoc): + """Find shortest path from fromLoc to toLoc""" + self.reset() + self.open=[] + fromNode=self.get(fromLoc) + self.open.append((fromNode.total,fromNode)) + toNode=self.get(toLoc) + if toNode.blocked: + print "toNode is blocked" + return [] + destx,desty=toNode.coord + while self.open: + #if open is not void, take the best node (the first one) + t,node=self.open.pop(0) + node.close=1 + if node == toNode: + #got toLoc + return self.getPath(node) + + for new_node in self.neighbours(node): + if new_node.close : + continue + x,y =new_node.coord + path_cost=node.path_cost+distance(node,new_node) + total=path_cost+h(x,y,destx,desty) + if new_node.open : + #the node is already in open + if total < new_node.total: + self.open.remove((new_node.total,new_node)) + new_node.path_cost=path_cost + new_node.parent=node + new_node.total=total + bisect.insort(self.open,(new_node.total,new_node)) + else: + #the node is not yet in open + new_node.path_cost=path_cost + new_node.parent=node + new_node.total=total + bisect.insort(self.open,(new_node.total,new_node)) + new_node.open=1 + + return [] + diff --git a/src/pyqt/gui/logview.py b/src/pyqt/gui/logview.py new file mode 100644 index 000000000..615fce465 --- /dev/null +++ b/src/pyqt/gui/logview.py @@ -0,0 +1,46 @@ +import sys +from qt import * + +log=""" +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +Ligne 1 +""" +class LogView(QDialog): + def __init__(self,parent = None,name = None,modal = 0,fl = 0): + QDialog.__init__(self,parent,name,modal,fl) + layout = QVBoxLayout(self,6,6,"AboutFormLayout") + self.text=QTextBrowser(self,"log") + self.text.setFrameShape(QTextEdit.NoFrame) + self.text.setTextFormat(QTextEdit.PlainText) + #self.text.setWordWrap(QTextEdit.FixedColumnWidth) + #self.text.setWrapColumnOrWidth(120) + self.text.setReadOnly(1) + #self.text.setText(log) + layout.addWidget(self.text) + self.button = QPushButton(self,"pushButton1") + self.button.setText("&Close") + layout.addWidget(self.button) + self.resize(QSize(532,437).expandedTo(self.minimumSizeHint())) + self.connect(self.button,SIGNAL("clicked()"),self.accept) + + + +if __name__ == "__main__": + a = QApplication(sys.argv) + QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()")) + w = LogView() + w.text.setText("un texte extremement loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong") + a.setMainWidget(w) + w.show() + a.exec_loop() diff --git a/src/pyqt/gui/panels.py b/src/pyqt/gui/panels.py new file mode 100644 index 000000000..033f920ba --- /dev/null +++ b/src/pyqt/gui/panels.py @@ -0,0 +1,146 @@ + +from qt import * +import traceback +import Editor +import Item + +class PanelScript(QVBox): + def __init__(self,parent,item): + QVBox.__init__(self,parent) + self.item=item + self.setSpacing( 5 ) + + row0=QHBox(self) + label=QLabel("Name: ",row0) + self.lined0 = QLineEdit(item.node.getName(),row0) + + label=QLabel("Script: ",self) + self.mle=Editor.Editor(self,"multiLineEdit" ) + self.mle.setText(item.node.getScript()) + + row2=QHBox(self) + but1=QPushButton( "Save", row2 ) + but1.setFixedSize( but1.sizeHint()) + but2=QPushButton( "Cancel", row2 ) + but2.setFixedSize( but2.sizeHint()) + self.connect( but1, SIGNAL("clicked()"), self.handleSave ) + self.connect( but2, SIGNAL("clicked()"), self.handleCancel ) + + def handleSave(self): + self.item.node.setScript(str(self.mle.text())) + + def handleCancel(self): + self.lined0.setText(self.item.node.getName()) + self.mle.setText(self.item.node.getScript()) + +class PanelFunc(QVBox): + def __init__(self,parent,item): + QVBox.__init__(self,parent) + self.item=item + self.setSpacing( 5 ) + + row0=QHBox(self) + label=QLabel("Name: ",row0) + self.lined0 = QLineEdit(self.item.node.getName(),row0) + + row1=QHBox(self) + label=QLabel("Fname: ",row1) + self.lined1 = QLineEdit(self.item.node.getFname(),row1) + + label=QLabel("Function: ",self) + self.mle=Editor.Editor(self,"multiLineEdit" ) + self.mle.setText(self.item.node.getScript()) + + row2=QHBox(self) + but1=QPushButton( "Save", row2 ) + but1.setFixedSize( but1.sizeHint()) + but2=QPushButton( "Cancel", row2 ) + but2.setFixedSize( but2.sizeHint()) + self.connect( but1, SIGNAL("clicked()"), self.handleSave ) + self.connect( but2, SIGNAL("clicked()"), self.handleCancel ) + + def handleSave(self): + self.item.node.setFname(str(self.lined1.text())) + self.item.node.setScript(str(self.mle.text())) + + def handleCancel(self): + self.lined0.setText(self.item.node.getName()) + self.lined1.setText(self.item.node.getFname()) + self.mle.setText(self.item.node.getScript()) + +class PanelForLoop(QVBox): + def __init__(self,parent,item): + QVBox.__init__(self,parent) + self.item=item + vsplit=QSplitter(Qt.Vertical,self,"VSplitter") + vbox=QVBox(vsplit) + vbox.layout().setAlignment(Qt.AlignTop|Qt.AlignLeft) + + row0=QHBox(vbox) + label=QLabel("Name: ",row0) + self.lined0 = QLineEdit(item.node.getName(),row0) + + #row1=QVBox(self) + #self.setStretchFactor(row1,10) + + row2=QHBox(vbox) + but1=QPushButton( "Save", row2 ) + but1.setFixedSize( but1.sizeHint()) + but2=QPushButton( "Cancel", row2 ) + but2.setFixedSize( but2.sizeHint()) + self.connect( but1, SIGNAL("clicked()"), self.handleSave ) + self.connect( but2, SIGNAL("clicked()"), self.handleCancel ) + + nodes= item.node.edGetDirectDescendants() + if nodes: + node=nodes[0] + subitem=Item.adapt(node) + panel=subitem.box(vsplit) + + def handleSave(self): + return + def handleCancel(self): + return + +class PanelInPort(QVBox): + def __init__(self,parent,item): + QVBox.__init__(self,parent) + self.item=item + self.layout().setAlignment(Qt.AlignTop|Qt.AlignLeft) + self.setSpacing( 5 ) + row0=QHBox(self) + label=QLabel("Name: ",row0) + lined0 = QLineEdit(self.item.port.getName(),row0) + label=QLabel("Type: ",row0) + QLineEdit(self.item.port.edGetType().name(),row0) + + label=QLabel("Value: ",self) + self.value=QTextEdit(self) + self.value.setText("Empty") + self.handleRestore() + + row3=QHBox(self) + but1=QPushButton( "Save", row3 ) + but1.setFixedSize( but1.sizeHint()) + self.connect( but1, SIGNAL("clicked()"), self.handleSave ) + but2=QPushButton( "Restore", row3 ) + but2.setFixedSize( but2.sizeHint()) + self.connect( but2, SIGNAL("clicked()"), self.handleRestore ) + + def handleSave(self): + try: + self.item.port.edInitXML(str(self.value.text())) + except: + traceback.print_exc() + self.value.setText(self.item.port.dump()) + + def handleRestore(self): + if not self.item.port.isEmpty(): + self.value.setText(self.item.port.dump()) + +class PanelOutPort(PanelInPort): + def handleRestore(self): + try: + self.value.setText(self.item.port.dump()) + except: + traceback.print_exc() diff --git a/src/pyqt/gui/sessions.py b/src/pyqt/gui/sessions.py new file mode 100644 index 000000000..a8b8e3b24 --- /dev/null +++ b/src/pyqt/gui/sessions.py @@ -0,0 +1,57 @@ + +import sys +import omniORB +from omniORB import CORBA +import CosNaming + +import Item +import CONNECTOR + +class Sessions(Item.Item): + def __init__(self,port): + Item.Item.__init__(self) + self.label="Sessions" + self.orb=CORBA.ORB_init(sys.argv, CORBA.ORB_ID) + self.port=port + + def getChildren(self): + sublist=[] + port=self.port + while 1: + port=port+1 + try: + session=Session(self,self.orb,port) + sublist.append(session) + except: + #traceback.print_exc() + break + return sublist + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self,"selected",self) + self.emitting=0 + + def getIconName(self): + return "folder" + + def isExpandable(self): + return True + +class Session(Item.Item): + def __init__(self,root,orb,port): + Item.Item.__init__(self) + self.root=root + self.port=port + self.addr="corbaname::localhost:%d/NameService" % port + obj=orb.string_to_object(self.addr) + context=obj._narrow(CosNaming.NamingContext) + self.label="Session on port: %d" % port + + def selected(self): + if not self.emitting: + self.emitting=1 + CONNECTOR.Emit(self.root,"selected",self) + self.emitting=0 + diff --git a/src/pyqt/yacsedit.py b/src/pyqt/yacsedit.py index cd86bfebf..9d1ef44d3 100644 --- a/src/pyqt/yacsedit.py +++ b/src/pyqt/yacsedit.py @@ -1,4 +1,5 @@ # -*- coding: iso-8859-1 -*- +import sys import glob import SALOMERuntime import pilot diff --git a/src/runtime/CORBAComponent.cxx b/src/runtime/CORBAComponent.cxx index 3084ee7ec..4ea192644 100644 --- a/src/runtime/CORBAComponent.cxx +++ b/src/runtime/CORBAComponent.cxx @@ -81,7 +81,7 @@ void CORBAComponent::load() { DEBTRACE( "+++++++++++++++++" << getName() << " +++++++++++++++++" ); orb = getSALOMERuntime()->getOrb(); - _objComponent= orb->string_to_object(getName().c_str()); + _objComponent= orb->string_to_object(getCompoName().c_str()); #ifdef REFCNT std::cerr << "CORBAComponent::load:refCount: " <<_objComponent->_PR_getobj()->pd_refCount << std::endl; #endif @@ -165,6 +165,6 @@ ComponentInstance* CORBAComponent::clone() const std::string CORBAComponent::getFileRepr() const { ostringstream stream; - stream << "" << getName() << ""; + stream << "" << getCompoName() << ""; return stream.str(); } diff --git a/src/runtime/CORBAComponent.hxx b/src/runtime/CORBAComponent.hxx index f04863516..2f41012bd 100644 --- a/src/runtime/CORBAComponent.hxx +++ b/src/runtime/CORBAComponent.hxx @@ -12,7 +12,6 @@ namespace YACS /*! \brief Class for CORBA component instance * - * \ingroup Nodes * */ class CORBAComponent : public ComponentInstance diff --git a/src/runtime/CORBANode.cxx b/src/runtime/CORBANode.cxx index 2014c46c5..1e27fb62f 100644 --- a/src/runtime/CORBANode.cxx +++ b/src/runtime/CORBANode.cxx @@ -15,10 +15,12 @@ #include "OutputDataStreamPort.hxx" #include "CalStreamPort.hxx" #include "InPort.hxx" +#include "TypeCode.hxx" #ifdef SALOME_KERNEL #include "SALOME_NamingService.hxx" #include "SALOME_LifeCycleCORBA.hxx" +#include "SALOME_Exception.hh" #endif #include @@ -132,12 +134,11 @@ void CORBANode::execute() #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)ob->pd_tc.in())->pd_ref_count); #endif + delete ob; } //return value req->set_return_type(CORBA::_tc_void); - //user exceptions - //req->exceptions()->add(eo::_tc_SALOME_Exception); DEBTRACE( "+++++++++++++++++CorbaNode::calculation+++++++++++++++++" << _method ) req->invoke(); @@ -146,6 +147,20 @@ void CORBANode::execute() { DEBTRACE( "An exception was thrown!" ) DEBTRACE( "The raised exception is of Type:" << exc->_name() ) + + std::cerr << "The raised exception is of Type:" << exc->_name() << std::endl; + /* + if(strcmp(exc->_name(),"MARSHAL") == 0) + { + const char* ms = ((CORBA::MARSHAL*)exc)->NP_minorString(); + if (ms) + std::cerr << "(CORBA::MARSHAL: minor = " << ms << ")" << std::endl; + else + std::cerr << "(CORBA::MARSHAL: minor = " << ((CORBA::MARSHAL*)exc)->minor() << ")" << std::endl; + } + */ + _errorDetails="Execution problem: the raised exception is of Type:"; + _errorDetails += exc->_name(); throw Exception("Execution problem"); } @@ -267,15 +282,30 @@ void SalomeNode::initService() Engines::Superv_Component_var compo=Engines::Superv_Component::_narrow(objComponent); if( CORBA::is_nil(compo) ) { - throw Exception("Can't get reference to DSC object (or it was nil)."); + std::string msg="Can't get reference to DSC object (or it was nil)."; + _errorDetails=msg; + throw Exception(msg); + } + try + { + CORBA::Boolean ret=compo->init_service(_method.c_str()); + if(!ret) + { + _errorDetails="Problem with component '"+_ref+"' in init_service of service '"+ _method + "'"; + throw Exception(_errorDetails); + } + } + catch(...) + { + _errorDetails="Problem with component '"+_ref+"' in init_service of service '"+ _method + "'"; + throw; } - compo->init_service(_method.c_str()); } //! Connect the datastream ports of the component associated to the node void SalomeNode::connectService() { - DEBTRACE( "SalomeNode::connectService: "<getCompoPtr(); @@ -284,6 +314,12 @@ void SalomeNode::connectService() CORBA::Object_var obj = NS.Resolve("/ConnectionManager"); Engines::ConnectionManager_var manager=Engines::ConnectionManager::_narrow(obj); Engines::Superv_Component_var me=Engines::Superv_Component::_narrow(objComponent); + if( CORBA::is_nil(me) ) + { + std::string msg="Can't get reference to Engines::Superv_Component: "+getName(); + _errorDetails=msg; + throw Exception(msg); + } std::list::iterator iter; Engines::ConnectionManager::connectionId id; for(iter = _setOfOutputDataStreamPort.begin(); iter != _setOfOutputDataStreamPort.end(); iter++) @@ -296,11 +332,73 @@ void SalomeNode::connectService() //It's only possible to connect 2 SalomeNode : try to get a SalomeNode SalomeNode* snode= dynamic_cast((*iterout)->getNode()); if(snode == 0) //don't connect, it's not a SalomeNode - throw Exception("Can't connect : not a SalomeNode"); + { + std::string msg="Can't connect : not a SalomeNode"; + _errorDetails=msg; + throw Exception(msg); + } CORBA::Object_var comp=((SalomeComponent*)snode->getComponent())->getCompoPtr(); + if( CORBA::is_nil(comp)) + { + std::string msg="Problem in connectService: " + snode->getName(); + msg=msg+" Component is probably not launched. Modify your YACS file"; + _errorDetails=msg; + throw Exception(msg); + } + Engines::Superv_Component_var other=Engines::Superv_Component::_narrow(comp); - id=manager->connect(me,port->getName().c_str(),other,(*iterout)->getName().c_str()); + if( CORBA::is_nil(other)) + { + std::string msg="Can't connect to nil Engines::Superv_Component: " + snode->getName(); + _errorDetails=msg; + throw Exception(msg); + } + try + { + id=manager->connect(me,port->getName().c_str(),other,(*iterout)->getName().c_str()); + } + catch(Engines::DSC::PortNotDefined& ex) + { + std::string msg="Problem in connectService. Unknown port: "+port->getName()+" or "+(*iterout)->getName(); + _errorDetails=msg; + throw Exception(msg); + } + catch(Engines::DSC::BadPortType& ex) + { + std::string msg="Problem in connectService. Type of provides port is bad. Expected: "; + msg=msg + ex.expected.in(); + msg=msg + "Received: "+ex.received.in(); + _errorDetails=msg; + throw Exception(msg); + } + catch(Engines::DSC::NilPort& ex) + { + std::string msg="Problem in connectService. Port is nil: "+port->getName()+" or "+(*iterout)->getName(); + _errorDetails=msg; + throw Exception(msg); + } + catch( const SALOME::SALOME_Exception& ex ) + { + std::string msg="Problem in connectService. "; + msg += ex.details.text.in(); + msg=msg+getName()+" " + port->getName() + " " + snode->getName() + " " + (*iterout)->getName(); + _errorDetails=msg; + throw Exception(msg); + } + catch(CORBA::SystemException& ex) + { + std::string msg="Problem in connectService. CORBA System exception"; + msg=msg+getName()+" " + port->getName() + " " + snode->getName() + " " + (*iterout)->getName(); + throw Exception(msg); + } + catch(...) + { + std::string msg="Problem in connectService. Unknown exception"; + msg=msg+getName()+" " + port->getName() + " " + snode->getName() + " " + (*iterout)->getName(); + throw Exception(msg); + } + DEBTRACE("Connected: " <getName()<<" "<getName()<<" "<<(*iterout)->getName()); ids.push_back(id); } } @@ -320,7 +418,7 @@ void SalomeNode::connectService() //! Disconnect the datastream ports of the component associated to the node void SalomeNode::disconnectService() { - DEBTRACE( "SalomeNode::disconnectService: "<getOrb()) ; @@ -330,7 +428,35 @@ void SalomeNode::disconnectService() std::list::iterator iter; for(iter = ids.begin(); iter != ids.end(); iter++) { - manager->disconnect(*iter,Engines::DSC::RemovingConnection); + DEBTRACE("Trying to disconnect: " << *iter ); + try + { + manager->disconnect(*iter,Engines::DSC::RemovingConnection); + } + catch(Engines::ConnectionManager::BadId& ex) + { + DEBTRACE( "Problem in disconnect: " << *iter ); + } + catch(Engines::DSC::PortNotDefined& ex) + { + DEBTRACE( "Problem in disconnect: " << *iter ); + } + catch(Engines::DSC::PortNotConnected& ex) + { + DEBTRACE( "Problem in disconnect: " << *iter ); + } + catch(Engines::DSC::BadPortReference& ex) + { + DEBTRACE( "Problem in disconnect (Engines::DSC::BadPortReference): " << *iter ); + } + catch(CORBA::SystemException& ex) + { + DEBTRACE( "Problem in disconnect (CORBA::SystemException): " << *iter ); + } + catch(...) + { + DEBTRACE( "Problem in disconnect: " << *iter ); + } } ids.clear(); } @@ -339,31 +465,60 @@ void SalomeNode::disconnectService() //! Execute the service on the component associated to the node void SalomeNode::execute() { - DEBTRACE( "+++++++++++++++++ SalomeNode::execute: " << getName() << " +++++++++++++++++" ) + DEBTRACE( "+++++++++++++++++ SalomeNode::execute: " << getName() << " " << _method << " +++++++++++++++++" ) { CORBA::Object_var objComponent=((SalomeComponent*)_component)->getCompoPtr(); + Engines::Component_var compo=Engines::Component::_narrow(objComponent); + + // Set component properties + if(_propertyMap.size() > 0) + { + Engines::FieldsDict_var dico = new Engines::FieldsDict; + dico->length(_propertyMap.size()); + std::map::const_iterator it; + int i=0; + for(it = _propertyMap.begin(); it != _propertyMap.end(); ++it) + { + dico[i].key=CORBA::string_dup(it->first.c_str()); + dico[i].value <<=it->second.c_str(); + i++; + } + compo->setProperties(dico); + } + //DII request building : // a service gets all its in parameters first // then all its out parameters // no inout parameters // the return value (if any) is the first out parameter - // not yet user exception (only CORBA exception) // - CORBA::Request_var req = objComponent->_request(_method.c_str()); + CORBA::Request_var req ; + try + { + req = objComponent->_request(_method.c_str()); + } + catch(CORBA::SystemException& ex) + { + std::string msg="component '" +_ref+ "' has no service '" + _method+ "'"; + _errorDetails=msg; + throw Exception(msg); + } CORBA::NVList_ptr arguments = req->arguments() ; - DEBTRACE( "+++++++++++++++++SalomeNode::inputs+++++++++++++++++" ) + DEBTRACE( "+++++++++++++++++SalomeNode::inputs+++++++++++++++++" ); int in_param=0; //in parameters list::iterator iter2; for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++) { InputCorbaPort *p=(InputCorbaPort *)*iter2; - DEBTRACE( "port name: " << p->getName() ) - DEBTRACE( "port kind: " << p->edGetType()->kind() ) + if(p->edGetType()->isA(Runtime::_tc_file)) + continue; + DEBTRACE( "port name: " << p->getName() ); + DEBTRACE( "port kind: " << p->edGetType()->kind() ); CORBA::Any* ob=p->getAny(); #ifdef _DEVDEBUG_ - CORBA::TypeCode_var tc; + CORBA::TypeCode_var tc=ob->type(); switch(p->edGetType()->kind()) { case Double: @@ -392,6 +547,49 @@ void SalomeNode::execute() arguments->add_value( p->getName().c_str() , *ob , CORBA::ARG_IN ) ; in_param=in_param+1; } + //in files + int nfiles=0; + DEBTRACE("checkInputFilesToService: " << _method); + try + { + for(iter2 = _setOfInputPort.begin(); iter2 != _setOfInputPort.end(); iter2++) + { + InputCorbaPort *p=(InputCorbaPort *)*iter2; + if(!p->edGetType()->isA(Runtime::_tc_file)) + continue; + std::string filename=p->getName(); + // replace ':' by '.'. Needed because port name can not contain '.' + string::size_type debut =filename.find_first_of(':',0); + while(debut != std::string::npos) + { + filename[debut]='.'; + debut=filename.find_first_of(':',debut); + } + DEBTRACE( "inport with file: " << filename ); + Engines::Salome_file_var isf=compo->setInputFileToService(_method.c_str(),p->getName().c_str()); + isf->setDistributedFile(filename.c_str()); + Engines::Salome_file_ptr osf; + CORBA::Any* any=p->getAny(); + *any >>= osf; + isf->connect(osf); + nfiles++; + } + if(nfiles) + compo->checkInputFilesToService(_method.c_str()); + } + catch( const SALOME::SALOME_Exception& ex ) + { + std::string text="Execution problem in checkInputFilesToService: "; + text += (const char*)ex.details.text; + _errorDetails=text; + throw Exception(text); + } + catch(CORBA::SystemException& ex) + { + std::string msg="Execution problem: component probably does not support files ??"; + _errorDetails=msg; + throw Exception(msg); + } //out parameters DEBTRACE( "+++++++++++++++++SalomeNode::outputs+++++++++++++++++" ) @@ -401,9 +599,12 @@ void SalomeNode::execute() OutputCorbaPort *p=(OutputCorbaPort *)*iter; DEBTRACE( "port name: " << p->getName() ) DEBTRACE( "port kind: " << p->edGetType()->kind() ) + if(p->edGetType()->isA(Runtime::_tc_file)) + continue; CORBA::Any* ob=p->getAnyOut(); //add_value makes a copy of any. Copy will be deleted with request arguments->add_value( p->getName().c_str() , *ob , CORBA::ARG_OUT ); + delete ob; } //return value @@ -412,7 +613,7 @@ void SalomeNode::execute() //as the first out argument (don't forget to add it as the first output argument) req->set_return_type(CORBA::_tc_void); //user exceptions - //req->exceptions()->add(eo::_tc_SALOME_Exception); + req->exceptions()->add(SALOME::_tc_SALOME_Exception); DEBTRACE( "+++++++++++++++++SalomeNode::calculation+++++++++++++++++" << _method ) req->invoke(); @@ -421,7 +622,50 @@ void SalomeNode::execute() { DEBTRACE( "An exception was thrown!" ) DEBTRACE( "The raised exception is of Type:" << exc->_name() ) - throw Exception("Execution problem"); + + CORBA::SystemException* sysexc; + sysexc=CORBA::SystemException::_downcast(exc); + if(sysexc != NULL) + { + // It's a SystemException + DEBTRACE( "minor code: " << sysexc->minor() ); + DEBTRACE( "completion code: " << sysexc->completed() ); + std::string text="Execution problem: "; + std::string excname=sysexc->_name(); + if(excname == "BAD_OPERATION") + { + text=text+"component '" +_ref+ "' has no service '" + _method+ "'"; + } + else + { + text=text+"System Exception "+ excname; + } + _errorDetails=text; + throw Exception(text); + } + + // Not a System Exception + CORBA::UnknownUserException* userexc; + userexc=CORBA::UnknownUserException::_downcast(exc); + if(userexc != NULL) + { + CORBA::Any anyExcept = userexc->exception(); + + const SALOME::SALOME_Exception* salexc; + if(anyExcept >>= salexc) + { + DEBTRACE("SALOME_Exception: "<< salexc->details.sourceFile); + DEBTRACE("SALOME_Exception: "<details.lineNumber); + _errorDetails=salexc->details.text; + throw Exception("Execution problem: Salome Exception occurred" + getErrorDetails() ); + } + std::string msg="Execution problem: User Exception occurred"; + _errorDetails=msg; + throw Exception(msg); + } + std::string msg="Execution problem"; + _errorDetails=msg; + throw Exception(msg); } DEBTRACE( "++++++++++++SalomeNode::outputs++++++++++++" ) @@ -429,9 +673,11 @@ void SalomeNode::execute() for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++) { OutputCorbaPort *p=(OutputCorbaPort *)*iter; - DEBTRACE( "port name: " << p->getName() ) - DEBTRACE( "port kind: " << p->edGetType()->kind() ) - DEBTRACE( "port number: " << out_param ) + DEBTRACE( "port name: " << p->getName() ); + DEBTRACE( "port kind: " << p->edGetType()->kind() ); + DEBTRACE( "port number: " << out_param ); + if(p->edGetType()->isA(Runtime::_tc_file)) + continue; CORBA::Any *ob=arguments->item(out_param)->value(); #ifdef _DEVDEBUG_ switch(p->edGetType()->kind()) @@ -461,6 +707,48 @@ void SalomeNode::execute() p->put(ob); out_param=out_param+1; } + + //Out files + nfiles=0; + DEBTRACE("checkOutputFilesToService: " << _method); + try + { + for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++) + { + OutputCorbaPort *p=(OutputCorbaPort *)*iter; + if(!p->edGetType()->isA(Runtime::_tc_file)) + continue; + // The output port has a file object : special treatment + std::string filename=p->getName(); + // replace ':' by '.'. Needed because port name can not contain '.' + string::size_type debut =filename.find_first_of(':',0); + while(debut != std::string::npos) + { + filename[debut]='.'; + debut=filename.find_first_of(':',debut); + } + DEBTRACE( "outport with file: " << filename ); + Engines::Salome_file_var osf=compo->setOutputFileToService(_method.c_str(),p->getName().c_str()); + osf->setLocalFile(filename.c_str()); + CORBA::Any any; + any <<= osf; + p->put(&any); + } + if(nfiles) + compo->checkOutputFilesToService(_method.c_str()); + } + catch( const SALOME::SALOME_Exception& ex ) + { + std::string text=(const char*)ex.details.text; + _errorDetails=text; + throw Exception("Execution problem in checkOutputFilesToService: " + text); + } + catch(CORBA::SystemException& ex) + { + std::string msg="Execution problem: component probably does not support files ?"; + _errorDetails=msg; + throw Exception(msg); + } } //Request has been deleted (_var ) //All anys given to the request are deleted : don't forget to copy them @@ -484,3 +772,20 @@ ServiceNode* SalomeNode::createNode(const std::string& name) node->setComponent(_component); return node; } + +std::string SalomeNode::getContainerLog() +{ + std::string msg="Component is not loaded"; + CORBA::Object_var objComponent=((SalomeComponent*)_component)->getCompoPtr(); + Engines::Component_var compo=Engines::Component::_narrow(objComponent); + if( !CORBA::is_nil(compo) ) + { + Engines::Container_var cont= compo->GetContainerRef(); + CORBA::String_var logname = cont->logfilename(); + DEBTRACE(logname); + msg=logname; + std::string::size_type pos = msg.find(":"); + msg=msg.substr(pos+1); + } + return msg; +} diff --git a/src/runtime/CORBANode.hxx b/src/runtime/CORBANode.hxx index b7bd66202..f65ebb16c 100644 --- a/src/runtime/CORBANode.hxx +++ b/src/runtime/CORBANode.hxx @@ -31,6 +31,7 @@ namespace YACS virtual ServiceNode* createNode(const std::string& name); virtual std::string getKind() const; static const char KIND[]; + virtual std::string typeName() {return "YACS__ENGINE__CORBANode";} public: static const char IMPL_NAME[]; }; @@ -54,12 +55,14 @@ namespace YACS virtual ServiceNode* createNode(const std::string& name); virtual std::string getKind() const; static const char KIND[]; + virtual std::string typeName() {return "YACS__ENGINE__SalomeNode";} #ifdef DSC_PORTS virtual void initService(); virtual void connectService(); virtual void disconnectService(); std::list ids; #endif + virtual std::string getContainerLog(); }; } } diff --git a/src/runtime/CORBAPorts.cxx b/src/runtime/CORBAPorts.cxx index e4ad8ae76..fa478721f 100644 --- a/src/runtime/CORBAPorts.cxx +++ b/src/runtime/CORBAPorts.cxx @@ -9,9 +9,11 @@ #include "RuntimeSALOME.hxx" #include "TypeConversions.hxx" +#include "TypeCode.hxx" #include "CORBAPorts.hxx" #include "ServiceNode.hxx" #include "ComponentInstance.hxx" +#include "SALOME_GenericObj.hh" #include #include @@ -22,6 +24,41 @@ using namespace YACS::ENGINE; using namespace std; +void releaseObj(CORBA::Any& data) +{ + CORBA::Object_var obj; + if(data >>= CORBA::Any::to_object(obj)) + { + SALOME::GenericObj_var gobj=SALOME::GenericObj::_narrow(obj); + if(!CORBA::is_nil(gobj)) + { + DEBTRACE("It's a SALOME::GenericObj"); + gobj->Destroy(); + } + else + DEBTRACE("It's a CORBA::Object but not a SALOME::GenericObj"); + } + else + DEBTRACE("It's not a CORBA::Object"); +} + +void registerObj(CORBA::Any& data) +{ + CORBA::Object_var obj; + if(data >>= CORBA::Any::to_object(obj)) + { + SALOME::GenericObj_var gobj=SALOME::GenericObj::_narrow(obj); + if(!CORBA::is_nil(gobj)) + { + DEBTRACE("It's a SALOME::GenericObj"); + gobj->Register(); + } + else + DEBTRACE("It's a CORBA::Object but not a SALOME::GenericObj"); + } + else + DEBTRACE("It's not a CORBA::Object"); +} InputCorbaPort::InputCorbaPort(const std::string& name, Node *node, @@ -46,6 +83,8 @@ InputCorbaPort::InputCorbaPort(const InputCorbaPort& other, Node *newHelder):Inp InputCorbaPort::~InputCorbaPort() { delete _initData; + // Release or not release : all GenericObj are deleted when the input port is deleted + releaseObj(_data); } bool InputCorbaPort::edIsManuallyInitialized() const @@ -93,8 +132,14 @@ void InputCorbaPort::put(CORBA::Any *data) throw (ConversionException) #ifdef _DEVDEBUG_ display(data); #endif + + releaseObj(_data); + // make a copy of the any (protect against deletion of any source) _data=*data; + + registerObj(_data); + #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count); #endif @@ -179,6 +224,8 @@ OutputCorbaPort::OutputCorbaPort(const OutputCorbaPort& other, Node *newHelder): OutputCorbaPort::~OutputCorbaPort() { DEBTRACE(getName()); + // Release or not release : all GenericObj are deleted when the output port is deleted + releaseObj(_data); #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count); DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); @@ -199,7 +246,13 @@ void OutputCorbaPort::put(CORBA::Any *data) throw (ConversionException) #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count); #endif + + releaseObj(_data); + _data=*data; + + //no registerObj : we steal the output reference of the node + #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)_data.pd_tc.in())->pd_ref_count); #endif @@ -225,66 +278,62 @@ CORBA::Any * OutputCorbaPort::getAny() CORBA::Any * OutputCorbaPort::getAnyOut() { - CORBA::Any* a=&_data; + CORBA::Any* a=new CORBA::Any; DynType kind=edGetType()->kind(); + CORBA::TypeCode_var t; if(kind == Int) { a->replace(CORBA::_tc_long, (void*) 0); } - else if(kind == String) - { - a->replace(CORBA::_tc_string, (void*) 0); - } - else if(kind == Double) - { - a->replace(CORBA::_tc_double, (void*) 0); - } - else if(kind == Objref) - { - //a->replace(CORBA::_tc_Object, (void*) 0); - CORBA::TypeCode_var t; - t = getCorbaTC(edGetType()); - a->replace(t, (void*) 0); - } - else if(kind == Sequence) - { - CORBA::TypeCode_var t; - t = getCorbaTC(edGetType()); - a->replace(t, (void*) 0); - } - else if(kind == Struct) - { - CORBA::TypeCode_var t; - t = getCorbaTC(edGetType()); + else if(kind == String) + { + a->replace(CORBA::_tc_string, (void*) 0); + } + else if(kind == Double) + { + a->replace(CORBA::_tc_double, (void*) 0); + } + else if(kind == Objref) + { + t = getCorbaTC(edGetType()); + a->replace(t, (void*) 0); + } + else if(kind == Sequence) + { + t = getCorbaTC(edGetType()); + a->replace(t, (void*) 0); + } + else if(kind == Struct) + { + t = getCorbaTC(edGetType()); #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)t.in())->pd_ref_count); #endif - a->replace(t, (void*) 0); + a->replace(t, (void*) 0); #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)t.in())->pd_ref_count); #endif - } - else if(kind == Bool) - { - a->replace(CORBA::_tc_boolean, (void*) 0); - } - else if(kind == None) - { - stringstream msg; - msg << "Cannot set Any Out for None" << __FILE__ << ":" << __LINE__; - throw Exception(msg.str()); - } - else - { - stringstream msg; - msg << "Cannot set Any Out for unknown type" << __FILE__ - << ":" << __LINE__; - throw Exception(msg.str()); - } + } + else if(kind == Bool) + { + a->replace(CORBA::_tc_boolean, (void*) 0); + } + else if(kind == NONE) + { + stringstream msg; + msg << "Cannot set Any Out for None" << __FILE__ << ":" << __LINE__; + throw Exception(msg.str()); + } + else + { + stringstream msg; + msg << "Cannot set Any Out for unknown type" << __FILE__ + << ":" << __LINE__; + throw Exception(msg.str()); + } - // return a pointer to internal any reinitialized - DEBTRACE( "getAnyOut::_data: " << a ); + DEBTRACE( "getAnyOut:a: " << a ); #ifdef REFCNT DEBTRACE("refcount CORBA : " << ((omni::TypeCode_base*)a->pd_tc.in())->pd_ref_count); #endif @@ -299,12 +348,15 @@ std::string OutputCorbaPort::dump() string xmldump = convertCorbaXml(edGetType(), &_data); return xmldump; } - -ostream& YACS::ENGINE::operator<<(ostream& os, const OutputCorbaPort& p) -{ - CORBA::Double l; - p._data>>=l; - os << p._name << " : " << l ; - return os; -} +namespace YACS { + namespace ENGINE { + ostream& operator<<(ostream& os, const OutputCorbaPort& p) + { + CORBA::Double l; + p._data>>=l; + os << p._name << " : " << l ; + return os; + } + }; +}; diff --git a/src/runtime/CORBAPorts.hxx b/src/runtime/CORBAPorts.hxx index 7d13244f7..ec8a39bc1 100644 --- a/src/runtime/CORBAPorts.hxx +++ b/src/runtime/CORBAPorts.hxx @@ -34,14 +34,22 @@ namespace YACS virtual void exSaveInit(); virtual void exRestoreInit(); virtual std::string dump(); + virtual std::string typeName() {return "YACS__ENGINE__InputCorbaPort";} protected: CORBA::Any _data; CORBA::Any * _initData; CORBA::ORB_ptr _orb; }; + class OutputCorbaPort; + + std::ostream & operator<<( std::ostream &os, + const YACS::ENGINE::OutputCorbaPort& p); + class OutputCorbaPort : public OutputPort { + friend std::ostream &operator<< ( std::ostream &os, + const OutputCorbaPort& p); public: OutputCorbaPort(const std::string& name, Node *node, TypeCode * type); OutputCorbaPort(const OutputCorbaPort& other, Node *newHelder); @@ -52,8 +60,7 @@ namespace YACS virtual CORBA::Any * getAny(); virtual CORBA::Any * getAnyOut(); virtual std::string dump(); - friend std::ostream & operator<< ( std::ostream &os, - const OutputCorbaPort& p); + virtual std::string typeName() {return "YACS__ENGINE__OutputCorbaPort";} protected: CORBA::Any _data; CORBA::ORB_ptr _orb; diff --git a/src/runtime/CORBAPythonConv.cxx b/src/runtime/CORBAPythonConv.cxx index 200fe4454..21b32228b 100644 --- a/src/runtime/CORBAPythonConv.cxx +++ b/src/runtime/CORBAPythonConv.cxx @@ -27,14 +27,9 @@ void CorbaPyDouble::put(const void *data) throw(ConversionException) */ void CorbaPyDouble::put(CORBA::Any *data) throw(ConversionException) { - CORBA::Double d; - *data >>=d; - PyObject *ob; - { InterpreterUnlocker loc; - ob=PyFloat_FromDouble(d); + PyObject* ob=convertCorbaPyObject(edGetType(),data); DEBTRACE("ob refcnt: " << ob->ob_refcnt ); - } _port->put(ob); Py_DECREF(ob); } @@ -55,14 +50,9 @@ void CorbaPyInt::put(const void *data) throw(ConversionException) */ void CorbaPyInt::put(CORBA::Any *data) throw(ConversionException) { - CORBA::Long l; - *data >>=l; - PyObject *ob; - { InterpreterUnlocker loc; - ob=PyLong_FromLong(l); + PyObject* ob=convertCorbaPyObject(edGetType(),data); DEBTRACE("ob refcnt: " << ob->ob_refcnt ); - } _port->put(ob); Py_DECREF(ob); } @@ -81,14 +71,9 @@ void CorbaPyString::put(const void *data) throw(ConversionException) */ void CorbaPyString::put(CORBA::Any *data) throw(ConversionException) { - const char *s; - *data >>=s; - PyObject *ob; - { InterpreterUnlocker loc; - ob=PyString_FromString(s); + PyObject* ob=convertCorbaPyObject(edGetType(),data); DEBTRACE("ob refcnt: " << ob->ob_refcnt ); - } _port->put(ob); Py_DECREF(ob); } @@ -111,7 +96,9 @@ void CorbaPyBool::put(const void *data) throw(ConversionException) */ void CorbaPyBool::put(CORBA::Any *data) throw(ConversionException) { + InterpreterUnlocker loc; PyObject* ob=convertCorbaPyObject(edGetType(),data); + DEBTRACE("ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); } @@ -131,16 +118,9 @@ void CorbaPyObjref::put(const void *data) throw(ConversionException) */ void CorbaPyObjref::put(CORBA::Any *data) throw(ConversionException) { - CORBA::Object_var ObjRef ; - *data >>= (CORBA::Any::to_object ) ObjRef ; - PyObject *ob; - { InterpreterUnlocker loc; - //hold_lock is true: caller is supposed to hold the GIL. - //omniorb will not take the GIL - ob = getSALOMERuntime()->getApi()->cxxObjRefToPyObjRef(ObjRef, 1); + PyObject* ob=convertCorbaPyObject(edGetType(),data); DEBTRACE("ob refcnt: " << ob->ob_refcnt ); - } _port->put(ob); Py_DECREF(ob); } @@ -166,15 +146,11 @@ void CorbaPySequence::put(const void *data) throw(ConversionException) */ void CorbaPySequence::put(CORBA::Any *data) throw(ConversionException) { - PyObject *ob; - { InterpreterUnlocker loc; - ob=convertCorbaPyObject(edGetType(),data); + PyObject* ob=convertCorbaPyObject(edGetType(),data); DEBTRACE("ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); - DEBTRACE("ob refcnt: " << ob->ob_refcnt ); - } } //!Class to convert a CORBA::Any struct into a PyObject struct @@ -197,13 +173,9 @@ void CorbaPyStruct::put(const void *data) throw(ConversionException) */ void CorbaPyStruct::put(CORBA::Any *data) throw(ConversionException) { - PyObject *ob; - { - InterpreterUnlocker loc; - ob=convertCorbaPyObject(edGetType(),data); - DEBTRACE("ob refcnt: " << ob->ob_refcnt ); - _port->put(ob); - Py_DECREF(ob); - DEBTRACE("ob refcnt: " << ob->ob_refcnt ); - } + InterpreterUnlocker loc; + PyObject* ob=convertCorbaPyObject(edGetType(),data); + DEBTRACE("ob refcnt: " << ob->ob_refcnt ); + _port->put(ob); + Py_DECREF(ob); } diff --git a/src/runtime/CalStreamPort.cxx b/src/runtime/CalStreamPort.cxx index bd7d0eb87..e5da67a03 100644 --- a/src/runtime/CalStreamPort.cxx +++ b/src/runtime/CalStreamPort.cxx @@ -63,8 +63,7 @@ void InputCalStreamPort::setProperty(const std::string& name, const std::string& setSchema(value); else if(name == "level") setLevel(value); - else - InputDataStreamPort::setProperty(name,value); + InputDataStreamPort::setProperty(name,value); } #ifdef DSC_PORTS @@ -157,8 +156,7 @@ void OutputCalStreamPort::setProperty(const std::string& name, const std::string setSchema(value); else if(name == "level") setLevel(value); - else - OutputDataStreamPort::setProperty(name,value); + OutputDataStreamPort::setProperty(name,value); } std::string OutputCalStreamPort::getNameOfTypeOfCurrentInstance() const @@ -173,7 +171,7 @@ OutputCalStreamPort *OutputCalStreamPort::clone(Node *newHelder) const bool OutputCalStreamPort::addInPort(InPort *inPort) throw(Exception) { - DEBTRACE("OutputCalStreamPort::addInPort" << InputCalStreamPort::NAME ); + DEBTRACE("OutputCalStreamPort::addInPort " << InputCalStreamPort::NAME ); if(inPort->getNameOfTypeOfCurrentInstance()!=InputCalStreamPort::NAME) { string what="not compatible type of port requested during building of link FROM "; @@ -193,3 +191,15 @@ bool OutputCalStreamPort::addInPort(InPort *inPort) throw(Exception) } +int OutputCalStreamPort::removeInPort(InPort *inPort, bool forward) throw(Exception) +{ + DEBTRACE("OutputCalStreamPort::removeInPort"); + if(inPort->getNameOfTypeOfCurrentInstance()!=InputCalStreamPort::NAME && !forward) + { + string what="not compatible type of port requested during destruction of for link FROM "; + what+=NAME; what+=" TO "; what+=inPort->getNameOfTypeOfCurrentInstance(); + throw Exception(what); + } + return edRemoveInputDataStreamPort(static_cast(inPort),forward); +} + diff --git a/src/runtime/CalStreamPort.hxx b/src/runtime/CalStreamPort.hxx index 8319bdb9f..b78513814 100644 --- a/src/runtime/CalStreamPort.hxx +++ b/src/runtime/CalStreamPort.hxx @@ -66,6 +66,7 @@ namespace YACS virtual bool addInPort(InPort *inPort) throw(Exception); std::string getNameOfTypeOfCurrentInstance() const; OutputCalStreamPort * clone(Node *newHelder) const; + virtual int removeInPort(InPort *inPort, bool forward) throw(Exception); protected: std::string _depend; std::string _schema; diff --git a/src/runtime/CppComponent.cxx b/src/runtime/CppComponent.cxx index 331bf0e1c..26b94773f 100644 --- a/src/runtime/CppComponent.cxx +++ b/src/runtime/CppComponent.cxx @@ -23,7 +23,7 @@ static std::ostream & operator<<(std::ostream & f, const Any & A) f << "(type NULL)"; else switch (t->kind()) { - case None : + case NONE : f << "(type None)"; break; case Double : @@ -71,7 +71,7 @@ CppComponent::CppComponent(const std::string &name) : ComponentInstance(name) } //! CppComponent copy constructor -CppComponent::CppComponent(const CppComponent& other) : ComponentInstance(other._name), __run(other.__run), +CppComponent::CppComponent(const CppComponent& other) : ComponentInstance(other._compoName), __run(other.__run), __terminate(other.__terminate), __obj(0) { _container = getRuntime()->createContainer(CppNode::KIND); @@ -79,7 +79,7 @@ CppComponent::CppComponent(const CppComponent& other) : ComponentInstance(other. _container->start(); CppContainer * _containerC = dynamic_cast (_container); - _containerC->createInternalInstance(_name, __obj, __run, __terminate); + _containerC->createInternalInstance(_compoName, __obj, __run, __terminate); } CppComponent::~CppComponent() @@ -166,11 +166,11 @@ void CppComponent::load() containerC->unLock(); containerC->lock();//To be sure - YACS::BASES::DynLibLoader D(_name + "Local"); + YACS::BASES::DynLibLoader D(_compoName + "Local"); - bool isLoadable = containerC->loadComponentLibrary(_name); + bool isLoadable = containerC->loadComponentLibrary(_compoName); if (isLoadable) - containerC->createInternalInstance(_name, __obj, __run, __terminate); + containerC->createInternalInstance(_compoName, __obj, __run, __terminate); if(NULL == __obj) { diff --git a/src/runtime/CppComponent.hxx b/src/runtime/CppComponent.hxx index 080abbc29..9acc78dec 100644 --- a/src/runtime/CppComponent.hxx +++ b/src/runtime/CppComponent.hxx @@ -2,7 +2,6 @@ #define __YACS_CppCOMPONENT__ #include -#include "Any.hxx" #include "ComponentInstance.hxx" namespace YACS @@ -10,6 +9,8 @@ namespace YACS namespace ENGINE { + class Any; + struct returnInfo { int code; std::string message; diff --git a/src/runtime/CppContainer.cxx b/src/runtime/CppContainer.cxx index e43f6265a..5fa19e249 100644 --- a/src/runtime/CppContainer.cxx +++ b/src/runtime/CppContainer.cxx @@ -235,19 +235,10 @@ void LocalContainer::createInternalInstance(const char *name, void *&obj, void LocalContainer::unregisterComponentInstance(CppComponent * C) { _instance_mapMutex.lock(); // lock to be alone - _instance_map.erase(C->getName()); + _instance_map.erase(C->getCompoName()); _instance_mapMutex.unlock(); // unlock } -//============================================================================= -/*! - * load a new component class (C++ implementation) - * \param componentName like COMPONENT - * try to load libCOMPONENTLocal.so - * \return true if dlopen successfull or already done, false otherwise - */ -//============================================================================= - inline void toupper (std::string & s) { transform (s.begin (), s.end (), s.begin (), (int(*)(int)) toupper); diff --git a/src/runtime/CppContainer.hxx b/src/runtime/CppContainer.hxx index a2dc91520..f35f89824 100644 --- a/src/runtime/CppContainer.hxx +++ b/src/runtime/CppContainer.hxx @@ -3,10 +3,9 @@ #include #include -#include "Any.hxx" #include "Mutex.hxx" -#include "CppComponent.hxx" #include "Container.hxx" +#include "CppComponent.hxx" namespace YACS { diff --git a/src/runtime/CppNode.cxx b/src/runtime/CppNode.cxx index 720b48f4e..1bd37c23f 100644 --- a/src/runtime/CppNode.cxx +++ b/src/runtime/CppNode.cxx @@ -32,7 +32,7 @@ CppNode::CppNode(const std::string & name) : ServiceNode(name), _run(NULL) _implementation=IMPL_NAME; } -void CppNode::setCode(const::string & componentName, const string & method) +void CppNode::setCode(const std::string & componentName, const std::string & method) { _method = method; _componentName = componentName; diff --git a/src/runtime/CppNode.hxx b/src/runtime/CppNode.hxx index af202608b..aebcfffbd 100644 --- a/src/runtime/CppNode.hxx +++ b/src/runtime/CppNode.hxx @@ -8,6 +8,8 @@ namespace YACS { namespace ENGINE { + class Any; + // local C++ implementation - single process class CppComponent; diff --git a/src/runtime/CppPorts.cxx b/src/runtime/CppPorts.cxx index e60169027..87554a101 100644 --- a/src/runtime/CppPorts.cxx +++ b/src/runtime/CppPorts.cxx @@ -2,6 +2,7 @@ #include "TypeConversions.hxx" #include "CppPorts.hxx" #include "Node.hxx" +#include "TypeCode.hxx" #include #include diff --git a/src/runtime/CppPorts.hxx b/src/runtime/CppPorts.hxx index 9745e6f91..47c060e06 100644 --- a/src/runtime/CppPorts.hxx +++ b/src/runtime/CppPorts.hxx @@ -2,7 +2,6 @@ #ifndef _CPPPORTS_HXX_ #define _CPPPORTS_HXX_ -#include "Any.hxx" #include "InputPort.hxx" #include "OutputPort.hxx" @@ -11,6 +10,7 @@ namespace YACS { namespace ENGINE { + class Any; /*! \brief Class for C++ Ports * diff --git a/src/runtime/CppPythonConv.cxx b/src/runtime/CppPythonConv.cxx index aad26be01..a05dfe428 100644 --- a/src/runtime/CppPythonConv.cxx +++ b/src/runtime/CppPythonConv.cxx @@ -37,12 +37,13 @@ namespace YACS { DEBTRACE(" CppPython::put(Any *data)"); PyObject *ob; - { - InterpreterUnlocker l; - ob=convertCppPyObject(edGetType(), data); - PyObject_Print(ob,stderr,Py_PRINT_RAW); - DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); - } + InterpreterUnlocker l; + ob=convertCppPyObject(edGetType(), data); +#ifdef _DEVDEBUG_ + PyObject_Print(ob,stderr,Py_PRINT_RAW); + std::cerr << std::endl; +#endif + DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); diff --git a/src/runtime/Makefile.am b/src/runtime/Makefile.am index f9b9f0ddb..404aa1420 100644 --- a/src/runtime/Makefile.am +++ b/src/runtime/Makefile.am @@ -41,50 +41,58 @@ libYACSRuntimeSALOME_la_SOURCES = \ SalomeComponent.cxx \ CppComponent.cxx \ CppContainer.cxx \ - CppCORBAConv.cxx \ - CppNeutralConv.cxx \ - CppXMLConv.cxx \ - CppCppConv.cxx \ - CppPythonConv.cxx \ + CppCORBAConv.cxx \ + CppNeutralConv.cxx \ + CppXMLConv.cxx \ + CppCppConv.cxx \ + CppPythonConv.cxx \ CORBACppConv.cxx \ - NeutralCppConv.cxx \ + NeutralCppConv.cxx \ XMLCppConv.cxx \ - PythonCppConv.cxx \ + PythonCppConv.cxx \ + SessionCataLoader.cxx \ + PresetPorts.cxx \ + PresetNode.cxx \ + OutNode.cxx \ + StudyNodes.cxx \ + StudyPorts.cxx \ + VisitorSaveSalomeSchema.cxx \ + PyStdout.cxx \ $(__dummy__) +salomeinclude_HEADERS = \ +CalStreamPort.hxx CORBAComponent.hxx CORBACORBAConv.hxx CORBACppConv.hxx \ +CORBANeutralConv.hxx CORBANode.hxx CORBAPorts.hxx CORBAPythonConv.hxx \ +CORBAXMLConv.hxx CppComponent.hxx CppContainer.hxx CppCORBAConv.hxx \ +CppCppConv.hxx CppNeutralConv.hxx CppNode.hxx CppPorts.hxx \ +CppPythonConv.hxx CppXMLConv.hxx NeutralCORBAConv.hxx NeutralCppConv.hxx \ +NeutralPythonConv.hxx NeutralXMLConv.hxx OutNode.hxx PresetNode.hxx \ +PresetPorts.hxx PyStdout.hxx PythonCORBAConv.hxx PythonCppConv.hxx \ +PythonNeutralConv.hxx PythonNode.hxx PythonPorts.hxx PythonXMLConv.hxx \ +RuntimeSALOME.hxx SalomeComponent.hxx SALOMEconfig.h SalomeContainer.hxx \ +SALOMEDispatcher.hxx SalomeProc.hxx SalomePythonComponent.hxx SalomePythonNode.hxx \ +SessionCataLoader.hxx StudyNodes.hxx StudyPorts.hxx TypeConversions.hxx \ +VisitorSaveSalomeSchema.hxx XMLCORBAConv.hxx XMLCppConv.hxx XMLNeutralConv.hxx \ +XMLNode.hxx XMLPorts.hxx XMLPythonConv.hxx EXTRA_libYACSRuntimeSALOME_la_SOURCES = \ $(__dummy__) if SALOME_KERNEL libYACSRuntimeSALOME_la_SOURCES += ../../idl/yacsguiSK.cc - -SALOME_IDL = \ - $(KERNEL_ROOT_DIR)/idl/salome/SALOME_ContainerManager.idl \ - $(KERNEL_ROOT_DIR)/idl/salome/SALOME_Component.idl \ - $(KERNEL_ROOT_DIR)/idl/salome/SALOME_Exception.idl - -SALOME_INCLUDES =SALOME_ContainerManager.hh SALOME_Exception.hh SALOME_Component.hh -SALOME_LIBS=-L$(KERNEL_ROOT_DIR)/lib@LIB_LOCATION_SUFFIX@/salome -lSalomeLifeCycleCORBA -SALOME_INCL_PATH=-I$(KERNEL_ROOT_DIR)/include/salome $(QT_INCLUDES) -SALOME_OMNIPY= +SALOME_LIBS=-L$(KERNEL_ROOT_DIR)/lib$(LIB_LOCATION_SUFFIX)/salome -lSalomeLifeCycleCORBA +SALOME_INCL_PATH=-I$(KERNEL_ROOT_DIR)/include/salome endif if DSC_PORTS -DSC_IDL = $(KERNEL_ROOT_DIR)/idl/salome/DSC_Engines.idl \ - $(KERNEL_ROOT_DIR)/idl/salome/SALOME_Ports.idl -DSC_INCLUDES = DSC_Engines.hh SALOME_Ports.hh -DSC_LIBS=-L$(KERNEL_ROOT_DIR)/lib@LIB_LOCATION_SUFFIX@/salome -lSalomeDSCContainer -DSC_INCL_PATH=-I$(KERNEL_ROOT_DIR)/include -DSC_OMNIPY=DSC_Engines_idl.py +DSC_LIBS=-L$(KERNEL_ROOT_DIR)/lib$(LIB_LOCATION_SUFFIX)/salome -lSalomeDSCContainer endif -IDL_FILES=$(DSC_IDL) $(SALOME_IDL) -BUILT_SOURCES=$(DSC_INCLUDES) $(SALOME_INCLUDES) SALOMERuntimeWRAP.cxx +BUILT_SOURCES=SALOMERuntimeWRAP.cxx libYACSRuntimeSALOME_la_LIBADD = \ $(DSC_LIBS) $(SALOME_LIBS) $(OMNIORB_LIBS) \ - ../engine/libYACSEngine.la + ../engine/libYACSlibEngine.la AM_CXXFLAGS = \ $(THREAD_DEF) \ @@ -93,48 +101,28 @@ AM_CXXFLAGS = \ -I$(OMNIORB_ROOT)/include/omniORB4/internal \ $(OMNIORB_CXXFLAGS) \ $(SALOME_INCL_PATH) \ - $(DSC_INCL_PATH) \ -I$(srcdir)/../bases \ -I$(srcdir)/../engine \ -I../../idl \ - -I/usr/include/libxml2 - - + $(LIBXML_INCLUDES) ############################################################ -if SALOME_KERNEL -SALOME_Component.hh:$(KERNEL_ROOT_DIR)/idl/salome/SALOME_Component.idl - $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx -I$(KERNEL_ROOT_DIR)/idl/salome $< -SALOME_Exception.hh:$(KERNEL_ROOT_DIR)/idl/salome/SALOME_Exception.idl - $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx -I$(KERNEL_ROOT_DIR)/idl/salome $< -SALOME_ContainerManager.hh:$(KERNEL_ROOT_DIR)/idl/salome/SALOME_ContainerManager.idl - $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx -I$(KERNEL_ROOT_DIR)/idl/salome $< - -SALOME_Component_idl.py:$(KERNEL_ROOT_DIR)/idl/salome/SALOME_Component.idl - $(OMNIORB_IDL) -bpython -I. -I$(KERNEL_ROOT_DIR)/idl/salome $< -endif - -if DSC_PORTS -DSC_Engines.hh:$(KERNEL_ROOT_DIR)/idl/salome/DSC_Engines.idl - $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx -I$(KERNEL_ROOT_DIR)/idl $< -SALOME_Ports.hh:$(KERNEL_ROOT_DIR)/idl/salome/SALOME_Ports.idl - $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx -I$(KERNEL_ROOT_DIR)/idl $< - -SALOME_Ports_idl.py :$(KERNEL_ROOT_DIR)/idl/salome/SALOME_Ports.idl - $(OMNIORB_IDL) -bpython -I. -I$(KERNEL_ROOT_DIR)/idl $< -endif - -################################################################# - -pkgpython_PYTHON = SALOMERuntime.py -pkgpyexec_LTLIBRARIES = _SALOMERuntime.la +salomepython_PYTHON = SALOMERuntime.py +salomepyexec_LTLIBRARIES = _SALOMERuntime.la _SALOMERuntime_la_SOURCES = \ SALOMERuntimeWRAP.cxx MYSWIG_FLAGS = -noexcept -I$(srcdir)/../bases -I$(srcdir)/../engine +SWIGINCLUDES= RuntimeSALOME.hxx SALOMEDispatcher.hxx SalomeProc.hxx PythonNode.hxx PythonPorts.hxx \ + CORBANode.hxx CORBAPorts.hxx TypeConversions.hxx \ + ../engine/pilot.i ../engine/engtypemaps.i + +SALOMERuntimeWRAP.cxx: SALOMERuntime.i $(SWIGINCLUDES) + $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) $(MYSWIG_FLAGS) -o $@ $(srcdir)/SALOMERuntime.i + _SALOMERuntime_la_CXXFLAGS = \ $(THREAD_DEF) \ $(PYTHON_CPPFLAGS) \ @@ -144,14 +132,12 @@ _SALOMERuntime_la_CXXFLAGS = \ -I$(srcdir)/../bases \ -I$(srcdir)/../engine \ -I../../idl \ - -I/usr/include/libxml2 + $(LIBXML_INCLUDES) _SALOMERuntime_la_LDFLAGS = -module -_SALOMERuntime_la_LIBADD = libYACSRuntimeSALOME.la \ - ../engine/libYACSEngine.la \ - $(DSC_LIBS) $(SALOME_LIBS) \ - -lxml2 +_SALOMERuntime_la_LIBADD = libYACSRuntimeSALOME.la +EXTRA_DIST = SALOMERuntime.i include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/runtime/NeutralCORBAConv.cxx b/src/runtime/NeutralCORBAConv.cxx index b8e9b119f..84870544c 100644 --- a/src/runtime/NeutralCORBAConv.cxx +++ b/src/runtime/NeutralCORBAConv.cxx @@ -21,10 +21,10 @@ void NeutralCorbaInt::put(const void *data) throw(ConversionException) void NeutralCorbaInt::put(YACS::ENGINE::Any *data) throw(ConversionException) { - CORBA::Long l= data->getIntValue(); - CORBA::Any a; - a <<= l; - _port->put(&a); + CORBA::Any *a =convertNeutralCorba(edGetType(),data); + _port->put(a); + //delete Any that has been allocated by convertNeutralCorba + delete a; } void NeutralCorbaBool::put(const void *data) throw(ConversionException) @@ -58,10 +58,10 @@ void NeutralCorbaDouble::put(const void *data) throw(ConversionException) void NeutralCorbaDouble::put(YACS::ENGINE::Any *data) throw(ConversionException) { - CORBA::Double d = data->getDoubleValue(); - CORBA::Any a; - a <<= d; - _port->put(&a); + CORBA::Any *a =convertNeutralCorba(edGetType(),data); + _port->put(a); + //delete Any that has been allocated by convertNeutralCorba + delete a; } void NeutralCorbaSequence::put(const void *data) throw(ConversionException) @@ -96,10 +96,10 @@ void NeutralCorbaString::put(const void *data) throw(ConversionException) */ void NeutralCorbaString::put(YACS::ENGINE::Any *data) throw(ConversionException) { - string val=data->getStringValue(); - CORBA::Any a; - a <<= val.c_str(); - _port->put(&a); + CORBA::Any *a =convertNeutralCorba(edGetType(),data); + _port->put(a); + //delete Any that has been allocated by convertNeutralCorba + delete a; } NeutralCorbaObjref::NeutralCorbaObjref(InputCorbaPort* p):ProxyPort(p), DataPort(p->getName(), p->getNode(), p->edGetType()), Port(p->getNode()) diff --git a/src/runtime/NeutralCORBAConv.hxx b/src/runtime/NeutralCORBAConv.hxx index 692260a35..8c17d1846 100644 --- a/src/runtime/NeutralCORBAConv.hxx +++ b/src/runtime/NeutralCORBAConv.hxx @@ -3,12 +3,12 @@ #include "ConversionException.hxx" #include "CORBAPorts.hxx" -#include "Any.hxx" namespace YACS { namespace ENGINE { + class Any; // --- adaptator ports Neutral->Corba for several types diff --git a/src/runtime/NeutralPythonConv.cxx b/src/runtime/NeutralPythonConv.cxx index ed6c156ea..41db7921a 100644 --- a/src/runtime/NeutralPythonConv.cxx +++ b/src/runtime/NeutralPythonConv.cxx @@ -1,6 +1,6 @@ -#include "NeutralPythonConv.hxx" #include "TypeConversions.hxx" +#include "NeutralPythonConv.hxx" #include "RuntimeSALOME.hxx" #include @@ -23,12 +23,11 @@ void NeutralPyDouble::put(const void *data) throw(ConversionException) */ void NeutralPyDouble::put(YACS::ENGINE::Any *data) throw(ConversionException) { - double d = data->getDoubleValue(); - PyObject *ob=PyFloat_FromDouble(d); + InterpreterUnlocker loc; + PyObject* ob=convertNeutralPyObject(edGetType(),data); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); - DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); } @@ -43,12 +42,11 @@ void NeutralPyInt::put(const void *data) throw(ConversionException) */ void NeutralPyInt::put(YACS::ENGINE::Any *data) throw(ConversionException) { - int l = data->getIntValue(); - PyObject *ob=PyLong_FromLong(l); + InterpreterUnlocker loc; + PyObject* ob=convertNeutralPyObject(edGetType(),data); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); - DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); } void NeutralPyString::put(const void *data) throw(ConversionException) @@ -62,12 +60,11 @@ void NeutralPyString::put(const void *data) throw(ConversionException) */ void NeutralPyString::put(YACS::ENGINE::Any *data) throw(ConversionException) { - string val=data->getStringValue(); - PyObject *ob=PyString_FromString(val.c_str()); + InterpreterUnlocker loc; + PyObject* ob=convertNeutralPyObject(edGetType(),data); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); - DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); } void NeutralPyBool::put(const void *data) throw(ConversionException) @@ -81,12 +78,11 @@ void NeutralPyBool::put(const void *data) throw(ConversionException) */ void NeutralPyBool::put(YACS::ENGINE::Any *data) throw(ConversionException) { - int l = data->getBoolValue(); - PyObject *ob=PyLong_FromLong(l); + InterpreterUnlocker loc; + PyObject* ob=convertNeutralPyObject(edGetType(),data); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); - DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); } void NeutralPyObjref::put(const void *data) throw(ConversionException) @@ -100,11 +96,8 @@ void NeutralPyObjref::put(const void *data) throw(ConversionException) */ void NeutralPyObjref::put(YACS::ENGINE::Any *data) throw(ConversionException) { - PyObject *ob; - { - InterpreterUnlocker loc; - ob=convertNeutralPyObject(edGetType(),data); - } + InterpreterUnlocker loc; + PyObject* ob=convertNeutralPyObject(edGetType(),data); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); _port->put(ob); Py_DECREF(ob); @@ -123,17 +116,14 @@ void NeutralPySequence::put(const void *data) throw(ConversionException) void NeutralPySequence::put(YACS::ENGINE::Any *data) throw(ConversionException) { DEBTRACE( "--------NeutralPySequence::put" ); - PyObject *ob; - { InterpreterUnlocker loc; - ob=convertNeutralPyObject(edGetType(),data); + PyObject* ob=convertNeutralPyObject(edGetType(),data); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); #ifdef _DEVDEBUG_ cerr << "Sequence= "; PyObject_Print(ob,stderr,Py_PRINT_RAW); cerr << endl; #endif - } _port->put(ob); Py_DECREF(ob); DEBTRACE( "ob refcnt: " << ob->ob_refcnt ); diff --git a/src/runtime/NeutralPythonConv.hxx b/src/runtime/NeutralPythonConv.hxx index b1fc4e053..8bc3a489e 100644 --- a/src/runtime/NeutralPythonConv.hxx +++ b/src/runtime/NeutralPythonConv.hxx @@ -2,13 +2,11 @@ #define __NEUTRALPYTHONCONV_HXX__ #include "PythonPorts.hxx" -#include "Any.hxx" namespace YACS { namespace ENGINE { - // --- adaptator ports Neutral->Python for several types class NeutralPyDouble : public ProxyPort diff --git a/src/runtime/OutNode.cxx b/src/runtime/OutNode.cxx new file mode 100644 index 000000000..d8cb937d9 --- /dev/null +++ b/src/runtime/OutNode.cxx @@ -0,0 +1,121 @@ + +#include "OutNode.hxx" +#include "PresetPorts.hxx" +#include "Visitor.hxx" + +#include +#include +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace std; + +namespace YACS +{ + namespace ENGINE + { + +const char OutNode::IMPL_NAME[]="XML"; + +OutNode::OutNode(const std::string& name) + : DataNode(name) +{ + _implementation=IMPL_NAME; +} + +OutNode::OutNode(const OutNode& other, ComposedNode *father) + : DataNode(other, father) +{ +} + +InputPort* OutNode::createInputPort(const std::string& inputPortName, TypeCode* type) +{ + return new InputPresetPort(inputPortName, this, type); +} + +void OutNode::dump(std::ostream &out) +{ + std::list::const_iterator iter; + for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++) + { + InputPresetPort *inp = dynamic_cast(*iter); + if(inp->getData() != "") + { + //save the file in the given reference + std::string xmlValue=inp->dump(); + std::string::size_type i=xmlValue.find_first_of('/',0); + xmlValue=xmlValue.substr(i); + i=xmlValue.find_first_of('<',0); + std::ifstream fin(xmlValue.substr(0,i).c_str()); + std::ofstream fout(inp->getData().c_str()); + fout << fin.rdbuf(); // Dumps file contents to file + out << "" << inp->getData() << "" << std::endl; + } + else + out << inp->dump() << std::endl; + } +} + +void OutNode::execute() +{ + DEBTRACE("+++++++ OutNode::execute +++++++++++"); + if(_ref != "") + { + std::ofstream out(_ref.c_str()); + dump(out); + } + else + dump(std::cout); + DEBTRACE("+++++++ end OutNode::execute +++++++++++" ); +} + +void OutNode::accept(Visitor *visitor) +{ + visitor->visitOutNode(this); +} + +void OutNode::setData(InputPort* port, std::string& data) +{ + InputPresetPort *inp = dynamic_cast(port); + inp->setData(data); +} + +void OutNode::checkBasicConsistency() const throw(Exception) +{ + DEBTRACE("OutNode::checkBasicConsistency"); + if (! _setOfOutputPort.empty()) + { + string what = "OutNode "; + what += getName(); + what += " only accepts InputPorts, no OutputPorts"; + throw Exception(what); + } + list::const_iterator iter; + for(iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++) + { + InputPresetPort *preset = dynamic_cast(*iter); + if (!preset) + { + string what("Input port: "); + what += (*iter)->getName(); + what += " is not an InputPresetPort. PresetNode "; + what += getName(); + what += " only accepts InputPresetPorts"; + throw Exception(what); + } + preset->checkBasicConsistency(); + } + +} + +Node *OutNode::simpleClone(ComposedNode *father, bool editionOnly) const +{ + return new OutNode(*this,father); +} + + } +} + diff --git a/src/runtime/OutNode.hxx b/src/runtime/OutNode.hxx new file mode 100644 index 000000000..62a70970e --- /dev/null +++ b/src/runtime/OutNode.hxx @@ -0,0 +1,30 @@ + +#ifndef _OUTNODE_HXX_ +#define _OUTNODE_HXX_ + +#include "DataNode.hxx" + +namespace YACS +{ + namespace ENGINE + { + class OutNode: public DataNode + { + protected: + Node *simpleClone(ComposedNode *father, bool editionOnly) const; + public: + OutNode(const std::string& name); + OutNode(const OutNode& other, ComposedNode *father); + virtual void execute(); + virtual void accept(Visitor *visitor); + virtual void checkBasicConsistency() const throw(Exception); + virtual void setData(InputPort* port, std::string& data); + virtual void dump(std::ostream &os); + virtual InputPort *createInputPort(const std::string& inputPortName, TypeCode* type); + public: + static const char IMPL_NAME[]; + }; + } +} + +#endif diff --git a/src/runtime/PresetNode.cxx b/src/runtime/PresetNode.cxx new file mode 100644 index 000000000..c2b88f1bd --- /dev/null +++ b/src/runtime/PresetNode.cxx @@ -0,0 +1,91 @@ + +#include "PresetNode.hxx" +#include "PresetPorts.hxx" +#include "Visitor.hxx" + +#include +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; +using namespace std; + +const char PresetNode::IMPL_NAME[]="XML"; + +PresetNode::PresetNode(const std::string& name) + : DataNode(name) +{ + _implementation=IMPL_NAME; +} + +PresetNode::PresetNode(const PresetNode& other, ComposedNode *father) + : DataNode(other, father) +{ +} + +OutputPort* PresetNode::createOutputPort(const std::string& outputPortName, TypeCode* type) +{ + return new OutputPresetPort(outputPortName, this, type); +} + +void PresetNode::execute() +{ + DEBTRACE("+++++++ PresetNode::execute +++++++++++"); + list::const_iterator iter; + for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++) + { + OutputPresetPort *outp = dynamic_cast(*iter); + assert(outp); + string data = outp->getData(); + DEBTRACE("data: " << data ); + outp->put(data.c_str()); + } + DEBTRACE("+++++++ end PresetNode::execute +++++++++++" ); +} + +void PresetNode::accept(Visitor *visitor) +{ + visitor->visitPresetNode(this); +} + +void PresetNode::setData(OutputPort* port, std::string& data) +{ + OutputPresetPort *outp = dynamic_cast(port); + outp->setData(data); +} + +void PresetNode::checkBasicConsistency() const throw(Exception) +{ + DEBTRACE("PresetNode::checkBasicConsistency"); + if (! _setOfInputPort.empty()) + { + string what = "PresetNode "; + what += getName(); + what += " only accepts OutputPresetPorts, no InputPorts"; + throw Exception(what); + } + + list::const_iterator iter; + for(iter=_setOfOutputPort.begin();iter!=_setOfOutputPort.end();iter++) + { + OutputPresetPort *preset = dynamic_cast(*iter); + if (!preset) + { + string what("Output port: "); + what += (*iter)->getName(); + what += " is not an OutputPresetPort. PresetNode "; + what += getName(); + what += "only accepts OutputPresetPorts"; + throw Exception(what); + } + preset->checkBasicConsistency(); + } +} + +Node *PresetNode::simpleClone(ComposedNode *father, bool editionOnly) const +{ + return new PresetNode(*this,father); +} diff --git a/src/runtime/PresetNode.hxx b/src/runtime/PresetNode.hxx new file mode 100644 index 000000000..65235381c --- /dev/null +++ b/src/runtime/PresetNode.hxx @@ -0,0 +1,29 @@ + +#ifndef _PRESETNODE_HXX_ +#define _PRESETNODE_HXX_ + +#include "DataNode.hxx" + +namespace YACS +{ + namespace ENGINE + { + class PresetNode: public DataNode + { + protected: + Node *simpleClone(ComposedNode *father, bool editionOnly) const; + public: + PresetNode(const std::string& name); + PresetNode(const PresetNode& other, ComposedNode *father); + virtual void execute(); + virtual void accept(Visitor *visitor); + virtual void checkBasicConsistency() const throw(Exception); + virtual void setData(OutputPort* port, std::string& data); + virtual OutputPort *createOutputPort(const std::string& outputPortName, TypeCode* type); + public: + static const char IMPL_NAME[]; + }; + } +} + +#endif diff --git a/src/runtime/PresetPorts.cxx b/src/runtime/PresetPorts.cxx new file mode 100644 index 000000000..2cb21bf61 --- /dev/null +++ b/src/runtime/PresetPorts.cxx @@ -0,0 +1,118 @@ + +#include "PresetPorts.hxx" +#include "TypeCode.hxx" +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; +using namespace std; + +OutputPresetPort::OutputPresetPort(const std::string& name, Node* node, TypeCode* type) + : OutputXmlPort(name, node, type), + DataPort(name, node, type), + Port(node) +{ +} + +OutputPresetPort::OutputPresetPort(const OutputPresetPort& other, Node *newHelder) + : OutputXmlPort(other,newHelder), + DataPort(other,newHelder), + Port(other,newHelder) +{ +} + +void OutputPresetPort::setData(std::string data) +{ + _storeData = data; + DEBTRACE( "OutputPresetPort::setData " << _storeData ); + modified(); +} + +void OutputPresetPort::checkBasicConsistency() const throw(Exception) +{ + DEBTRACE("OutputPresetPort::checkBasicConsistency " << _storeData); + if (_storeData.empty()) + { + std::string what("OutputPresetPort: "); + what += getName(); + what += " is not initialised"; + throw Exception(what); + } +} + +std::string OutputPresetPort::getData() +{ + DEBTRACE("OutputPresetPort::getData " << _storeData); + if(_storeData.substr(0,7) == "") + { + return _storeData; + } + else + { + std::string value; + switch(edGetType()->kind()) + { + case Double: + value=""+_storeData+""; + break; + case Int: + value=""+_storeData+""; + break; + case String: + value=""+_storeData+""; + break; + case Bool: + value=""+_storeData+""; + break; + case Objref: + value=""+_storeData+""; + break; + case Sequence: + case Array: + case Struct: + default: + break; + } + return value; + } +} + +std::string OutputPresetPort::dump() +{ + return getData(); +} + +InputPresetPort::InputPresetPort(const std::string& name, Node* node, TypeCode* type) + : InputXmlPort(name, node, type), + DataPort(name, node, type), + Port(node) +{ +} + +InputPresetPort::InputPresetPort(const InputPresetPort& other, Node *newHelder) + : InputXmlPort(other,newHelder), + DataPort(other,newHelder), + Port(other,newHelder) +{ +} + +void InputPresetPort::setData(std::string data) +{ + _storeData = data; + DEBTRACE( "InputPresetPort::setData " << _storeData ); + modified(); +} + +std::string InputPresetPort::getData() +{ + DEBTRACE("InputPresetPort::getData " << _storeData); + return _storeData; +} + +std::string InputPresetPort::dump() +{ + return _data; +} + diff --git a/src/runtime/PresetPorts.hxx b/src/runtime/PresetPorts.hxx new file mode 100644 index 000000000..f4230f231 --- /dev/null +++ b/src/runtime/PresetPorts.hxx @@ -0,0 +1,53 @@ + +#ifndef _PRESETPORTS_HXX_ +#define _PRESETPORTS_HXX_ + +#include "XMLPorts.hxx" + +namespace YACS +{ + namespace ENGINE + { + +/*! \brief Class for PRESET output Ports + * + * \ingroup Ports + * + * \see PresetNode + */ + class OutputPresetPort: public OutputXmlPort + { + public: + OutputPresetPort(const std::string& name, Node* node, TypeCode* type); + OutputPresetPort(const OutputPresetPort& other, Node *newHelder); + void setData(std::string data); + std::string getData(); + virtual void checkBasicConsistency() const throw(Exception); + virtual std::string dump(); + protected: + std::string _storeData; + }; + +/*! \brief Class for PRESET input Ports + * + * \ingroup Ports + * + * \see OutNode + */ + class InputPresetPort: public InputXmlPort + { + public: + InputPresetPort(const std::string& name, Node* node, TypeCode* type); + InputPresetPort(const InputPresetPort& other, Node *newHelder); + void setData(std::string data); + std::string getData(); + virtual std::string dump(); + protected: + std::string _storeData; + }; + + } +} + + +#endif diff --git a/src/runtime/PyStdout.cxx b/src/runtime/PyStdout.cxx new file mode 100644 index 000000000..ca5aeaebf --- /dev/null +++ b/src/runtime/PyStdout.cxx @@ -0,0 +1,113 @@ + +#include "PyStdout.hxx" +#include + +namespace YACS +{ + namespace ENGINE + { + + typedef struct { + PyObject_HEAD + int softspace; + std::string *out; + } PyStdOut; + +static void +PyStdOut_dealloc(PyStdOut *self) +{ + PyObject_Del(self); +} + +static PyObject * +PyStdOut_write(PyStdOut *self, PyObject *args) +{ + char *c; + int l; + if (!PyArg_ParseTuple(args, "t#:write",&c, &l)) + return NULL; + + std::cerr << c ; + *(self->out)=*(self->out)+c; + + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef PyStdOut_methods[] = { + {"write", (PyCFunction)PyStdOut_write, METH_VARARGS, + PyDoc_STR("write(string) -> None")}, + {NULL, NULL} /* sentinel */ +}; + +static PyMemberDef PyStdOut_memberlist[] = { + {"softspace", T_INT, offsetof(PyStdOut, softspace), 0, + "flag indicating that a space needs to be printed; used by print"}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject PyStdOut_Type = { + /* The ob_type field must be initialized in the module init function + * to be portable to Windows without using C++. */ + PyObject_HEAD_INIT(NULL) + 0, /*ob_size*/ + "PyOut", /*tp_name*/ + sizeof(PyStdOut), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)PyStdOut_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + PyObject_GenericGetAttr, /*tp_getattro*/ + /* softspace is writable: we must supply tp_setattro */ + PyObject_GenericSetAttr, /* tp_setattro */ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + PyStdOut_methods, /*tp_methods*/ + PyStdOut_memberlist, /*tp_members*/ + 0, /*tp_getset*/ + 0, /*tp_base*/ + 0, /*tp_dict*/ + 0, /*tp_descr_get*/ + 0, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + 0, /*tp_init*/ + 0, /*tp_alloc*/ + 0, /*tp_new*/ + 0, /*tp_free*/ + 0, /*tp_is_gc*/ +}; + + +#define PyStdOut_Check(v) ((v)->ob_type == &PyStdOut_Type) + +PyObject * newPyStdOut( std::string& out ) +{ + PyStdOut *self; + self = PyObject_New(PyStdOut, &PyStdOut_Type); + if (self == NULL) + return NULL; + self->softspace = 0; + self->out=&out; + return (PyObject*)self; +} + +} +} + diff --git a/src/runtime/PyStdout.hxx b/src/runtime/PyStdout.hxx new file mode 100644 index 000000000..60bd5876e --- /dev/null +++ b/src/runtime/PyStdout.hxx @@ -0,0 +1,16 @@ +#ifndef _PYSTDOUT_HXX_ +#define _PYSTDOUT_HXX_ + +#include +#include + +namespace YACS +{ + namespace ENGINE + { + PyObject * newPyStdOut( std::string& out ); + } +} + +#endif + diff --git a/src/runtime/PythonCORBAConv.cxx b/src/runtime/PythonCORBAConv.cxx index c5657e71c..740c5b87f 100644 --- a/src/runtime/PythonCORBAConv.cxx +++ b/src/runtime/PythonCORBAConv.cxx @@ -33,14 +33,9 @@ void PyCorbaInt::put(const void *data) throw(ConversionException) */ void PyCorbaInt::put(PyObject *data) throw(ConversionException) { - CORBA::Long l= 0; - if (PyInt_Check(data))l=PyInt_AS_LONG(data); - else if(PyLong_Check(data))l=PyLong_AsLong(data); - else throw ConversionException("Not an int"); - - CORBA::Any a; - a <<= l; - _port->put(&a); + CORBA::Any *a= convertPyObjectCorba(_port->edGetType(),data); + _port->put(a); + delete a; } //!Convert a PyObject (boolean) to CORBA::Any (boolean) @@ -80,13 +75,9 @@ void PyCorbaString::put(const void *data) throw(ConversionException) void PyCorbaString::put(PyObject *data) throw(ConversionException) { - char * s; - if(PyString_Check(data))s=PyString_AsString(data); - else throw ConversionException("Not a string"); - - CORBA::Any a; - a <<= s; - _port->put(&a); + CORBA::Any *a= convertPyObjectCorba(_port->edGetType(),data); + _port->put(a); + delete a; } @@ -102,15 +93,9 @@ void PyCorbaDouble::put(const void *data) throw(ConversionException) void PyCorbaDouble::put(PyObject *data) throw(ConversionException) { - CORBA::Double d = 0; - if (PyFloat_Check(data)) d = (CORBA::Double)PyFloat_AS_DOUBLE(data); - else if (PyInt_Check(data)) d = (CORBA::Double)PyInt_AS_LONG(data); - else if (PyLong_Check(data)) d = (CORBA::Double)PyLong_AsDouble(data); - else throw ConversionException("Not a double"); - - CORBA::Any a; - a <<= d; - _port->put(&a); + CORBA::Any *a= convertPyObjectCorba(_port->edGetType(),data); + _port->put(a); + delete a; } //!Class PyCorbaSequence is a proxy port that converts a PyObject object (of type sequence) to a CORBA::Any object (of type sequence) @@ -180,24 +165,9 @@ void PyCorbaObjref::put(PyObject *data) throw(ConversionException) PyObject_Print(data,stderr,Py_PRINT_RAW); std::cerr << std::endl; #endif - - //does not work : replace by a call to object_to_string - string_to_object - //hold_lock is true: caller is supposed to hold the GIL. - //omniorb will not take the GIL - //CORBA::Object_ptr ob=api->pyObjRefToCxxObjRef(data,(CORBA::Boolean)1); - - PyObject *pystring = PyObject_CallMethod(_pyorb, "object_to_string", "O", data); - if(pystring == NULL) - { - PyErr_Print(); - throw ConversionException("can't get objref"); - } - CORBA::Object_var ob= _orb->string_to_object(PyString_AsString(pystring)); - Py_DECREF(pystring); - - CORBA::Any a; - a <<= ob; - _port->put(&a); + CORBA::Any *a= convertPyObjectCorba(_port->edGetType(),data); + _port->put(a); + delete a; } //!Class PyCorbaStruct is a proxy port that converts a PyObject object (of type struct) to a CORBA::Any object (of type struct) diff --git a/src/runtime/PythonNode.cxx b/src/runtime/PythonNode.cxx index 2f5667873..dcccba49a 100644 --- a/src/runtime/PythonNode.cxx +++ b/src/runtime/PythonNode.cxx @@ -3,6 +3,7 @@ #include "PythonNode.hxx" #include "PythonPorts.hxx" +#include "PyStdout.hxx" #include #include @@ -52,6 +53,7 @@ void PythonNode::execute() stringstream msg; msg << "Impossible to set builtins" << __FILE__ << ":" << __LINE__; PyGILState_Release(gstate); + _errorDetails=msg.str(); throw Exception(msg.str()); } @@ -80,9 +82,17 @@ void PythonNode::execute() DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); PyObject *res=PyRun_String(_script.c_str(),Py_file_input,_context,_context); DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); + fflush(stdout); + fflush(stderr); if(res == NULL) { + _errorDetails=""; + PyObject* new_stderr = newPyStdOut(_errorDetails); + PySys_SetObject("stderr", new_stderr); PyErr_Print(); + PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + Py_DECREF(new_stderr); + PyGILState_Release(gstate); throw Exception("Error during execution"); } @@ -102,6 +112,7 @@ void PythonNode::execute() PyGILState_Release(gstate); std::string msg="Error during execution: there is no variable "; msg=msg+p->getName()+" in node context"; + _errorDetails=msg; throw Exception(msg); } DEBTRACE( "PyNode::outputs::ob refcnt: " << ob->ob_refcnt ); @@ -112,9 +123,10 @@ void PythonNode::execute() p->put(ob); } } - catch(ConversionException) + catch(ConversionException& ex) { PyGILState_Release(gstate); + _errorDetails=ex.what(); throw; } @@ -162,6 +174,7 @@ PyFuncNode::PyFuncNode(const PyFuncNode& other, ComposedNode *father):InlineFunc { stringstream msg; msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__; + _errorDetails=msg.str(); PyGILState_Release(gstate); throw Exception(msg.str()); } @@ -180,6 +193,7 @@ PyFuncNode::PyFuncNode(const std::string& name): InlineFuncNode(name),_pyfunc(0) { stringstream msg; msg << "Not possible to set builtins" << __FILE__ << ":" << __LINE__; + _errorDetails=msg.str(); PyGILState_Release(gstate); throw Exception(msg.str()); } @@ -215,7 +229,13 @@ void PyFuncNode::load() DEBTRACE( "_context refcnt: " << _context->ob_refcnt ); if(res == NULL) { + _errorDetails=""; + PyObject* new_stderr = newPyStdOut(_errorDetails); + PySys_SetObject("stderr", new_stderr); PyErr_Print(); + PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + Py_DECREF(new_stderr); + PyGILState_Release(gstate); throw Exception("Error during execution"); return; @@ -225,7 +245,13 @@ void PyFuncNode::load() DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt ); if(_pyfunc == NULL) { + _errorDetails=""; + PyObject* new_stderr = newPyStdOut(_errorDetails); + PySys_SetObject("stderr", new_stderr); PyErr_Print(); + PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + Py_DECREF(new_stderr); + PyGILState_Release(gstate); throw Exception("Error during execution"); } @@ -273,9 +299,17 @@ void PyFuncNode::execute() PyObject* result = PyObject_CallObject( _pyfunc , args ) ; DEBTRACE( "_pyfunc refcnt: " << _pyfunc->ob_refcnt ); Py_DECREF(args); + fflush(stdout); + fflush(stderr); if(result == NULL) { + _errorDetails=""; + PyObject* new_stderr = newPyStdOut(_errorDetails); + PySys_SetObject("stderr", new_stderr); PyErr_Print(); + PySys_SetObject("stderr", PySys_GetObject("__stderr__")); + Py_DECREF(new_stderr); + PyGILState_Release(gstate); throw Exception("Error during execution"); } @@ -290,9 +324,11 @@ void PyFuncNode::execute() if(getNumberOfOutputPorts() != nres) { + std::string msg="Number of output arguments : Mismatch between definition and execution"; Py_DECREF(result); PyGILState_Release(gstate); - throw Exception("Number of output arguments : Mismatch between definition and execution"); + _errorDetails=msg; + throw Exception(msg); } pos=0; @@ -320,10 +356,11 @@ void PyFuncNode::execute() pos++; } } - catch(ConversionException) + catch(ConversionException& ex) { Py_DECREF(result); PyGILState_Release(gstate); + _errorDetails=ex.what(); throw; } DEBTRACE( "-----------------End PyFuncNode::outputs-----------------" ); diff --git a/src/runtime/PythonNode.hxx b/src/runtime/PythonNode.hxx index db28bed06..6365cb31d 100644 --- a/src/runtime/PythonNode.hxx +++ b/src/runtime/PythonNode.hxx @@ -22,6 +22,7 @@ namespace YACS PythonNode* cloneNode(const std::string& name); static const char KIND[]; static const char IMPL_NAME[]; + virtual std::string typeName() {return "YACS__ENGINE__PythonNode";} protected: PyObject* _context; }; @@ -37,6 +38,7 @@ namespace YACS virtual void execute(); virtual void load(); PyFuncNode* cloneNode(const std::string& name); + virtual std::string typeName() {return "YACS__ENGINE__PyFuncNode";} protected: PyObject* _context; PyObject* _pyfunc; diff --git a/src/runtime/PythonPorts.cxx b/src/runtime/PythonPorts.cxx index e1c97bbc5..bef60e918 100644 --- a/src/runtime/PythonPorts.cxx +++ b/src/runtime/PythonPorts.cxx @@ -1,7 +1,9 @@ #include "PythonPorts.hxx" #include "TypeConversions.hxx" +#include "TypeCode.hxx" #include "Node.hxx" +#include "ConversionException.hxx" #include #include @@ -12,6 +14,79 @@ using namespace YACS::ENGINE; using namespace std; +void releasePyObj(PyObject* data) +{ + DEBTRACE( "data refcnt: " << data->ob_refcnt ); + if (PyObject_HasAttrString(data, (char*)"_is_a")) + { + PyObject *result = PyObject_CallMethod(data, (char*)"_is_a", (char*)"s",(char*)"IDL:SALOME/GenericObj:1.0"); + if(result && PyInt_Check(result)) + { + if(PyInt_AS_LONG(result)) + { + PyObject* o=PyObject_CallMethod(data, (char*)"Destroy", (char*)""); + if(o) + Py_XDECREF( o); + else + { +#ifdef _DEVDEBUG_ + PyErr_Print(); +#else + PyErr_Clear(); +#endif + throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj"); + } + } + Py_XDECREF(result); + } + if(!result) + { +#ifdef _DEVDEBUG_ + PyErr_Print(); +#else + PyErr_Clear(); +#endif + throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj"); + } + } +} + +void registerPyObj(PyObject* data) +{ + if (PyObject_HasAttrString(data, (char*)"_is_a")) + { + PyObject *result = PyObject_CallMethod(data, (char*)"_is_a", (char*)"s",(char*)"IDL:SALOME/GenericObj:1.0"); + if(result && PyInt_Check(result)) + { + if(PyInt_AS_LONG(result)) + { + PyObject* o= PyObject_CallMethod(data, (char*)"Register", (char*)"") ; + if(o) + Py_XDECREF( o); + else + { +#ifdef _DEVDEBUG_ + PyErr_Print(); +#else + PyErr_Clear(); +#endif + throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj"); + } + } + Py_XDECREF(result); + } + if(!result) + { +#ifdef _DEVDEBUG_ + PyErr_Print(); +#else + PyErr_Clear(); +#endif + throw ConversionException("Corba object does not exist: you have perhaps forgotten to call Register on a GenericObj"); + } + } +} + InputPyPort::InputPyPort(const std::string& name, Node *node, TypeCode * type) : InputPort(name, node, type), DataPort(name, node, type), Port(node), _data(Py_None),_initData(Py_None) { @@ -23,6 +98,8 @@ InputPyPort::~InputPyPort() PyGILState_STATE gstate = PyGILState_Ensure(); DEBTRACE( "_data refcnt: " << _data->ob_refcnt ); DEBTRACE( "_initData refcnt: " << _initData->ob_refcnt ); + // Release or not release : all GenericObj are deleted when the input port is deleted + releasePyObj(_data); Py_XDECREF(_data); Py_XDECREF(_initData); PyGILState_Release(gstate); @@ -56,9 +133,12 @@ void InputPyPort::put(const void *data) throw(ConversionException) void InputPyPort::put(PyObject *data) throw(ConversionException) { + InterpreterUnlocker l; + releasePyObj(_data); Py_XDECREF(_data); _data = data; Py_INCREF(_data); + registerPyObj(_data); DEBTRACE( "_data refcnt: " << _data->ob_refcnt ); } @@ -140,6 +220,8 @@ OutputPyPort::~OutputPyPort() { PyGILState_STATE gstate = PyGILState_Ensure(); DEBTRACE( "_data refcnt: " << _data->ob_refcnt ); + // Release or not release : all GenericObj are deleted when the output port is deleted + releasePyObj(_data); Py_XDECREF(_data); PyGILState_Release(gstate); } @@ -162,9 +244,11 @@ void OutputPyPort::put(PyObject *data) throw(ConversionException) PyObject_Print(data,stderr,Py_PRINT_RAW); cerr << endl; #endif + releasePyObj(_data); Py_XDECREF(_data); _data = data; Py_INCREF(_data); + //no registerPyObj : we steal the output reference of the node DEBTRACE( "OutputPyPort::put.ob refcnt: " << data->ob_refcnt ); OutputPort::put(data); } @@ -179,6 +263,11 @@ PyObject * OutputPyPort::get() const return _data; } +PyObject * OutputPyPort::getPyObj() const +{ + return _data; +} + std::string OutputPyPort::dump() { if( _data == Py_None) diff --git a/src/runtime/PythonPorts.hxx b/src/runtime/PythonPorts.hxx index 71982a497..a4844650b 100644 --- a/src/runtime/PythonPorts.hxx +++ b/src/runtime/PythonPorts.hxx @@ -24,6 +24,8 @@ namespace YACS PyGILState_STATE gstate_; }; + typedef PyObject PyObj; + /*! \brief Class for Python Ports * * \ingroup Ports @@ -41,12 +43,13 @@ namespace YACS virtual void put(const void *data) throw(ConversionException); void put(PyObject *data) throw(ConversionException); InputPort *clone(Node *newHelder) const; - virtual PyObject * getPyObj() const; + virtual PyObj * getPyObj() const; void *get() const throw(Exception); virtual bool isEmpty(); virtual void exSaveInit(); virtual void exRestoreInit(); virtual std::string dump(); + virtual std::string typeName() {return "YACS__ENGINE__InputPyPort";} protected: PyObject* _data; PyObject* _initData; @@ -62,7 +65,9 @@ namespace YACS void put(PyObject *data) throw(ConversionException); OutputPort *clone(Node *newHelder) const; virtual PyObject * get() const; + virtual PyObj * getPyObj() const; virtual std::string dump(); + virtual std::string typeName() {return "YACS__ENGINE__OutputPyPort";} protected: PyObject* _data; }; diff --git a/src/runtime/RuntimeSALOME.cxx b/src/runtime/RuntimeSALOME.cxx index b3755924d..797a2abbe 100644 --- a/src/runtime/RuntimeSALOME.cxx +++ b/src/runtime/RuntimeSALOME.cxx @@ -11,14 +11,19 @@ #include "RuntimeSALOME.hxx" #include "SALOMEDispatcher.hxx" #include "Proc.hxx" +#include "TypeCode.hxx" #include "WhileLoop.hxx" #include "ForLoop.hxx" #include "Bloc.hxx" #include "InputPort.hxx" #include "OutputPort.hxx" +#include "PresetPorts.hxx" #include "InputDataStreamPort.hxx" #include "OutputDataStreamPort.hxx" #include "SalomeProc.hxx" +//Catalog Loaders +#include "SessionCataLoader.hxx" + //Components #include "CORBAComponent.hxx" #include "SalomeComponent.hxx" @@ -33,8 +38,11 @@ #include "CORBANode.hxx" #include "XMLNode.hxx" #include "CppNode.hxx" -#include "TypeConversions.hxx" +#include "PresetNode.hxx" +#include "OutNode.hxx" +#include "StudyNodes.hxx" #include "SalomePythonNode.hxx" + //CORBA proxy ports #include "CORBACORBAConv.hxx" #include "CORBAPythonConv.hxx" @@ -42,6 +50,7 @@ #include "CORBACppConv.hxx" #include "CORBANeutralConv.hxx" +#include "TypeConversions.hxx" //Python proxy ports #include "PythonCORBAConv.hxx" #include "PythonXMLConv.hxx" @@ -91,7 +100,9 @@ void RuntimeSALOME::setRuntime(long flags) // singleton creation (not thread saf { if (! Runtime::_singleton) { - Runtime::_singleton = new RuntimeSALOME(flags); + RuntimeSALOME* r=new RuntimeSALOME(flags); + Runtime::_singleton = r; + r->initBuiltins(); } DEBTRACE("RuntimeSALOME::setRuntime() done !"); } @@ -111,6 +122,26 @@ RuntimeSALOME::RuntimeSALOME() assert(0); } +void RuntimeSALOME::initBuiltins() +{ + //Fill the builtin catalog with nodes specific to the runtime + std::map& typeMap=_builtinCatalog->_typeMap; + std::map& nodeMap=_builtinCatalog->_nodeMap; + std::map& composednodeMap=_builtinCatalog->_composednodeMap; + std::map& componentMap=_builtinCatalog->_componentMap; + nodeMap["PyFunction"]=new PyFuncNode("PyFunction"); + nodeMap["PyScript"]=new PythonNode("PyScript"); + nodeMap["CORBANode"]=new CORBANode("CORBANode"); + nodeMap["XmlNode"]=new XmlNode("XmlNode"); + nodeMap["SalomeNode"]=new SalomeNode("SalomeNode"); + nodeMap["CppNode"]=new CppNode("CppNode"); + nodeMap["SalomePythonNode"]=new SalomePythonNode("SalomePythonNode"); + nodeMap["PresetNode"]=new PresetNode("PresetNode"); + nodeMap["OutNode"]=new OutNode("OutNode"); + nodeMap["StudyInNode"]=new StudyInNode("StudyInNode"); + nodeMap["StudyOutNode"]=new StudyOutNode("StudyOutNode"); +} + RuntimeSALOME::RuntimeSALOME(long flags) { // If all flags (apart the IsPyExt flags) are unset, force them to true @@ -131,6 +162,9 @@ RuntimeSALOME::RuntimeSALOME(long flags) _useCpp = flags & RuntimeSALOME::UseCpp; _useXml = flags & RuntimeSALOME::UseXml; + /* Init libxml */ + xmlInitParser(); + if (_useCpp) _setOfImplementation.insert(CppNode::IMPL_NAME); if (_usePython) _setOfImplementation.insert(PythonNode::IMPL_NAME); if (_useCorba) _setOfImplementation.insert(CORBANode::IMPL_NAME); @@ -140,6 +174,13 @@ RuntimeSALOME::RuntimeSALOME(long flags) RuntimeSALOME::~RuntimeSALOME() { + DEBTRACE("RuntimeSALOME::~RuntimeSALOME"); + // destroy catalog loader prototypes + std::map::const_iterator pt; + for(pt=_catalogLoaderFactoryMap.begin();pt!=_catalogLoaderFactoryMap.end();pt++) + { + delete (*pt).second; + } } //! CORBA and Python initialization @@ -160,12 +201,20 @@ void RuntimeSALOME::init(long flags) bool ispyext = flags & RuntimeSALOME::IsPyExt; if (_useCorba) { + PortableServer::POA_var root_poa; + PortableServer::POAManager_var pman; + CORBA::Object_var obj; int nbargs = 0; char **args = 0; _orb = CORBA::ORB_init (nbargs, args); + obj = _orb->resolve_initial_references("RootPOA"); + root_poa = PortableServer::POA::_narrow(obj); + pman = root_poa->the_POAManager(); + pman->activate(); + #ifdef REFCNT DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount); #endif - CORBA::Object_var obj = _orb->resolve_initial_references("DynAnyFactory"); + obj = _orb->resolve_initial_references("DynAnyFactory"); _dynFactory = DynamicAny::DynAnyFactory::_narrow(obj); } @@ -200,19 +249,19 @@ void RuntimeSALOME::init(long flags) } _bltins = PyEval_GetBuiltins(); /* borrowed ref */ - + if (_useCorba) { //init section - PyObject* omnipy = PyImport_ImportModule((char*)"_omnipy"); - if (!omnipy) + _omnipy = PyImport_ImportModule((char*)"_omnipy"); + if (!_omnipy) { PyErr_Print(); PyErr_SetString(PyExc_ImportError, (char*)"Cannot import _omnipy"); goto out; } - pyapi = PyObject_GetAttrString(omnipy, (char*)"API"); + pyapi = PyObject_GetAttrString(_omnipy, (char*)"API"); if (!pyapi) { goto out; @@ -227,6 +276,10 @@ void RuntimeSALOME::init(long flags) "from omniORB import any\n" "orb = CORBA.ORB_init([], CORBA.ORB_ID)\n" "#print sys.getrefcount(orb)\n" + "try:\n" + " import SALOME\n" + "except:\n" + " pass\n" "\n", Py_file_input,globals,globals ); if(res == NULL) @@ -250,6 +303,11 @@ void RuntimeSALOME::init(long flags) out: PyGILState_Release(gstate); // Release the Global Interpreter Lock } + if (_useCorba) + { + // initialize the catalogLoaderFactory map with the session one + _catalogLoaderFactoryMap["session"]=new SessionCataLoader; + } } void RuntimeSALOME::fini() @@ -274,6 +332,14 @@ void RuntimeSALOME::fini() else Py_DECREF(res); } + std::map& nodeMap=_builtinCatalog->_nodeMap; + delete nodeMap["PyFunction"]; + delete nodeMap["PyScript"]; + delete nodeMap["SalomePythonNode"]; + nodeMap.erase("PyFunction"); + nodeMap.erase("PyScript"); + nodeMap.erase("SalomePythonNode"); + Py_Finalize(); #ifdef REFCNT DEBTRACE("_orb refCount: " << ((omniOrbORB*)_orb.in())->pd_refCount); @@ -311,6 +377,37 @@ ForLoop* RuntimeSALOME::createForLoop(const std::string& name) return new ForLoop(name); } +DataNode* RuntimeSALOME::createInDataNode(const std::string& kind,const std::string& name) +{ + DataNode* node; + if(kind == "" ) + { + node = new PresetNode(name); + return node; + } + else if(kind == "study" ) + { + return new StudyInNode(name); + } + std::string msg="DataNode kind ("+kind+") unknown"; + throw Exception(msg); +} + +DataNode* RuntimeSALOME::createOutDataNode(const std::string& kind,const std::string& name) +{ + if(kind == "" ) + { + return new OutNode(name); + } + else if(kind == "study" ) + { + return new StudyOutNode(name); + } + + std::string msg="OutDataNode kind ("+kind+") unknown"; + throw Exception(msg); +} + InlineFuncNode* RuntimeSALOME::createFuncNode(const std::string& kind,const std::string& name) { InlineFuncNode* node; @@ -645,7 +742,7 @@ InputPort* RuntimeSALOME::adaptNeutral(InputPort* source, { return adaptNeutralToCorba(source,type); } - else if(impl == XmlNode::IMPL_NAME) + else if(impl == XmlNode::IMPL_NAME ) { return adaptNeutralToXml(source,type); } @@ -771,7 +868,7 @@ InputPort* RuntimeSALOME::adapt(InputXmlPort* source, { return adaptXmlToCpp(source,type); } - else if(impl == XmlNode::IMPL_NAME) + else if(impl == XmlNode::IMPL_NAME ) { return new ProxyPort(source); } @@ -852,8 +949,9 @@ InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport, else { stringstream msg; - msg << "Cannot connect InputPyPort : incompatible objref types " << type->id() << " " << inport->edGetType()->id(); - msg << " " << __FILE__ << ":" <<__LINE__; + msg << "Cannot connect Python output port with type: " << type->id() ; + msg << " to CORBA input port " << inport->getName() << " with incompatible objref type: " << inport->edGetType()->id(); + msg << " (" << __FILE__ << ":" <<__LINE__ << ")"; throw ConversionException(msg.str()); } } @@ -887,8 +985,9 @@ InputPort* RuntimeSALOME::adaptCorbaToPython(InputCorbaPort* inport, } // Adaptation not possible stringstream msg; - msg << "Cannot connect InputCorbaPort to Python output " ; - msg << __FILE__ << ":" <<__LINE__; + msg << "Cannot connect Python output port with type: " << type->id() ; + msg << " to CORBA input port " << inport->getName() << " with type: " << inport->edGetType()->id(); + msg << " (" << __FILE__ << ":" <<__LINE__ << ")"; throw ConversionException(msg.str()); } @@ -1012,7 +1111,7 @@ InputPort* RuntimeSALOME::adapt(InputCorbaPort* source, { return adaptCorbaToCorba(source,type); } - else if(impl == XmlNode::IMPL_NAME) + else if(impl == XmlNode::IMPL_NAME ) { return adaptCorbaToXml(source,type); } @@ -1050,8 +1149,8 @@ InputPort* RuntimeSALOME::adaptPythonToPython(InputPyPort* inport, } //output data is not convertible to input type stringstream msg; - msg << "Cannot connect 2 Python Port with non convertible types: " ; - msg << type->id() << " != " << inport->edGetType()->id(); + msg << "Cannot connect Python output port with type: " << type->id() ; + msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id(); msg << " ("<<__FILE__ << ":" << __LINE__<<")"; throw ConversionException(msg.str()); } @@ -1200,8 +1299,9 @@ InputPort* RuntimeSALOME::adaptPythonToCorba(InputPyPort* inport, } // Adaptation not possible stringstream msg; - msg << "Cannot connect InputPyPort to Corba output " ; - msg << __FILE__ << ":" << __LINE__; + msg << "Cannot connect Corba output port with type: " << type->id() ; + msg << " to Python input port " << inport->getName() << " with type: " << inport->edGetType()->id(); + msg << " ("__FILE__ << ":" << __LINE__ << ")"; throw ConversionException(msg.str()); } @@ -1447,6 +1547,11 @@ DynamicAny::DynAnyFactory_ptr RuntimeSALOME::getDynFactory() return _dynFactory; } +PyObject * RuntimeSALOME::get_omnipy() +{ + return _omnipy; +} + omniORBpyAPI* RuntimeSALOME::getApi() { return _api; diff --git a/src/runtime/RuntimeSALOME.hxx b/src/runtime/RuntimeSALOME.hxx index b64312d35..2f62bb9bc 100644 --- a/src/runtime/RuntimeSALOME.hxx +++ b/src/runtime/RuntimeSALOME.hxx @@ -9,31 +9,31 @@ #include #include -namespace YACS +//--- from omniORBpy.h (not present on Debian Sarge packages) +struct omniORBpyAPI { - namespace ENGINE - { - - //--- from omniORBpy.h (not present on Debian Sarge packages) - - struct omniORBpyAPI - { - PyObject* (*cxxObjRefToPyObjRef)(const CORBA::Object_ptr cxx_obj, CORBA::Boolean hold_lock); // Convert a C++ object reference to a Python object reference. // If is true, caller holds the Python interpreter lock. - + CORBA::Object_ptr (*pyObjRefToCxxObjRef)(PyObject* py_obj, CORBA::Boolean hold_lock); // Convert a Python object reference to a C++ object reference. // Raises BAD_PARAM if the Python object is not an object reference. // If is true, caller holds the Python interpreter lock. + + PyObject* (*handleCxxSystemException)(const CORBA::SystemException& ex); + // Sets the Python exception state to reflect the given C++ system + // exception. Always returns NULL. The caller must hold the Python + // interpreter lock. +}; +//--- end of from omniORBpy.h (not present on Debian Sarge packages) - - omniORBpyAPI(); - // Constructor for the singleton. Sets up the function pointers. - }; +namespace YACS +{ + namespace ENGINE + { class RuntimeSALOME; RuntimeSALOME* getSALOMERuntime(); @@ -43,12 +43,11 @@ namespace YACS class InputXmlPort; class InputCppPort; - class RuntimeSALOME: public Runtime { public: - static enum + enum { IsPyExt = 1, UsePython = 2, @@ -80,6 +79,8 @@ namespace YACS virtual OutputDataStreamPort* createOutputDataStreamPort(const std::string& name, Node *node,TypeCode *type); + virtual DataNode* createInDataNode(const std::string& kind,const std::string& name); + virtual DataNode* createOutDataNode(const std::string& kind,const std::string& name); virtual InlineFuncNode* createFuncNode(const std::string& kind,const std::string& name); virtual InlineNode* createScriptNode(const std::string& kind,const std::string& name); @@ -193,15 +194,18 @@ namespace YACS PyObject * getBuiltins(); DynamicAny::DynAnyFactory_ptr getDynFactory(); omniORBpyAPI* getApi(); + PyObject * get_omnipy(); protected: RuntimeSALOME(); // singleton RuntimeSALOME(long flags); // singleton + void initBuiltins(); CORBA::ORB_var _orb; PyObject * _pyorb; PyObject * _bltins; DynamicAny::DynAnyFactory_var _dynFactory; omniORBpyAPI* _api; + PyObject* _omnipy; long _flags; bool _usePython, _useCorba, _useCpp, _useXml; diff --git a/src/runtime/SALOMEDispatcher.cxx b/src/runtime/SALOMEDispatcher.cxx index b900a766c..04b87666c 100644 --- a/src/runtime/SALOMEDispatcher.cxx +++ b/src/runtime/SALOMEDispatcher.cxx @@ -4,11 +4,14 @@ #include +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + using namespace std; using namespace YACS::BASES; using namespace YACS::ENGINE; -map< pair , set > SALOMEDispatcher::_observers; +map< pair , set > SALOMEDispatcher::_observers; SALOMEDispatcher* SALOMEDispatcher::_disp = 0; SALOMEDispatcher::SALOMEDispatcher() @@ -21,7 +24,7 @@ SALOMEDispatcher::~SALOMEDispatcher() void SALOMEDispatcher::setSALOMEDispatcher() { - cerr << "SALOMEDispatcher::setSALOMEDispatcher" << endl; + DEBTRACE("SALOMEDispatcher::setSALOMEDispatcher"); _disp=new SALOMEDispatcher(); YACS::ENGINE::Dispatcher::setDispatcher(_disp); } @@ -33,25 +36,25 @@ SALOMEDispatcher* SALOMEDispatcher::getSALOMEDispatcher() void SALOMEDispatcher::dispatch(Node* object, const std::string& event) { - cerr << "SALOMEDispatcher::dispatch " << event << " " << object->getNumId() << endl; + DEBTRACE("SALOMEDispatcher::dispatch " << event << " " << object->getNumId()); CORBA::Long numId = object->getNumId(); - typedef set::iterator jt; + typedef set::iterator jt; std::pair key(numId, event); for(jt iter = _observers[key].begin(); iter!=_observers[key].end(); iter++) { if (! CORBA::is_nil(*iter)) { - cerr << "numId, event " << numId << " " << event << endl; + DEBTRACE("numId, event " << numId << " " << event ); (*iter)->notifyObserver(numId, event.c_str()); } else - cerr << "************************** dispatch on a CORBA::nil *******************************" <(numid,event)].insert(YACSGui_ORB::Observer::_duplicate(observer)); + _observers[std::pair(numid,event)].insert(YACS_ORB::Observer::_duplicate(observer)); } diff --git a/src/runtime/SALOMEDispatcher.hxx b/src/runtime/SALOMEDispatcher.hxx index 76fb20860..be2a6c8ad 100644 --- a/src/runtime/SALOMEDispatcher.hxx +++ b/src/runtime/SALOMEDispatcher.hxx @@ -21,12 +21,12 @@ namespace YACS public: SALOMEDispatcher(); void dispatch(Node* object, const std::string& event); - void addObserver(YACSGui_ORB::Observer_ptr observer,int numid, std::string event); + void addObserver(YACS_ORB::Observer_ptr observer,int numid, std::string event); static void setSALOMEDispatcher(); static SALOMEDispatcher* getSALOMEDispatcher(); virtual ~SALOMEDispatcher(); protected: - static std::map< std::pair , std::set > _observers; + static std::map< std::pair , std::set > _observers; static SALOMEDispatcher* _disp; static void *ThDisp( void *a); static YACS::BASES::Semaphore _s1; diff --git a/src/runtime/SALOMERuntime.i b/src/runtime/SALOMERuntime.i index 75b2ced9f..c0e1d4851 100644 --- a/src/runtime/SALOMERuntime.i +++ b/src/runtime/SALOMERuntime.i @@ -1,59 +1,33 @@ // ---------------------------------------------------------------------------- %define SALOMEDOCSTRING -"SALOMERuntime docstring -Implementation of nodes for SALOME platform." +"Implementation of nodes for SALOME platform." %enddef %module(docstring=SALOMEDOCSTRING) SALOMERuntime -%feature("autodoc", "0"); -%include std_string.i +//work around SWIG bug #1863647 +#define PySwigIterator SALOMERuntime_PySwigIterator + +%feature("autodoc", "1"); + +%include engtypemaps.i // ---------------------------------------------------------------------------- %{ #include "RuntimeSALOME.hxx" #include "SALOMEDispatcher.hxx" - -#include -#include -#include -#include -#include -#include "utilities.h" - -using namespace std; -using namespace YACS::ENGINE; - -//--- from omniORBpy.h (not present on Debian Sarge packages) -// (rename omniORBpyAPI in omniORBpy_API) -struct omniORBpy_API -{ - - PyObject* (*cxxObjRefToPyObjRef)(const CORBA::Object_ptr cxx_obj, - CORBA::Boolean hold_lock); - // Convert a C++ object reference to a Python object reference. - // If is true, caller holds the Python interpreter lock. - - CORBA::Object_ptr (*pyObjRefToCxxObjRef)(PyObject* py_obj, - CORBA::Boolean hold_lock); - // Convert a Python object reference to a C++ object reference. - // Raises BAD_PARAM if the Python object is not an object reference. - // If is true, caller holds the Python interpreter lock. - - - omniORBpy_API(); - // Constructor for the singleton. Sets up the function pointers. -}; - - omniORBpy_API* api; - +#include "SalomeProc.hxx" +#include "PythonNode.hxx" +#include "PythonPorts.hxx" +#include "CORBANode.hxx" +#include "CORBAPorts.hxx" +#include "TypeConversions.hxx" +#include "TypeCode.hxx" %} - // ---------------------------------------------------------------------------- - %init %{ // init section @@ -61,63 +35,81 @@ struct omniORBpy_API PyObject* omnipy = PyImport_ImportModule((char*)"_omnipy"); if (!omnipy) { - PyErr_SetString(PyExc_ImportError, - (char*)"Cannot import _omnipy"); + PyErr_SetString(PyExc_ImportError,(char*)"Cannot import _omnipy"); return; } PyObject* pyapi = PyObject_GetAttrString(omnipy, (char*)"API"); - api = (omniORBpy_API*)PyCObject_AsVoidPtr(pyapi); + api = (omniORBPYAPI*)PyCObject_AsVoidPtr(pyapi); Py_DECREF(pyapi); %} // ---------------------------------------------------------------------------- -%typemap(python,out) YACSGui_ORB::Observer_ptr +#ifdef SWIGPYTHON +%typemap(out) YACS_ORB::Observer_ptr { - MESSAGE("typemap out on CORBA object ptr"); - SCRUTE($1); $result = api->cxxObjRefToPyObjRef($1, 1); - SCRUTE($result); } -%typemap(python,in) YACSGui_ORB::Observer_ptr +%typemap(in) YACS_ORB::Observer_ptr { - MESSAGE("typemap in on CORBA object ptr"); try { CORBA::Object_ptr obj = api->pyObjRefToCxxObjRef($input,1); - $1 = YACSGui_ORB::Observer::_narrow(obj); - SCRUTE($1); + $1 = YACS_ORB::Observer::_narrow(obj); } catch (...) { PyErr_SetString(PyExc_RuntimeError, "not a valid CORBA object ptr"); + return NULL; } } +%typemap(out) YACS::ENGINE::PyObj * "Py_INCREF($1); $result = $1;"; + +#endif + // ---------------------------------------------------------------------------- -namespace YACS +%import "pilot.i" + +%rename(getSALOMERuntime) YACS::ENGINE::getSALOMERuntime; // to suppress a 503 warning +%ignore omniORBpyAPI; + +%include "RuntimeSALOME.hxx" +%include "SALOMEDispatcher.hxx" +%include "SalomeProc.hxx" +%include "PythonNode.hxx" +%include "PythonPorts.hxx" +%include "CORBANode.hxx" +%include "CORBAPorts.hxx" + +%extend YACS::ENGINE::InputCorbaPort { - namespace ENGINE + PyObject * getPyObj() { - class RuntimeSALOME: public Runtime - { - public: - static void setRuntime(bool ispyext=false); // singleton creation - virtual ~RuntimeSALOME(); - protected: - RuntimeSALOME(); // singleton - RuntimeSALOME(bool ispyext); // singleton - }; - - class SALOMEDispatcher: public Dispatcher - { - public: - void addObserver(YACSGui_ORB::Observer_ptr observer,int numid, std::string event); - static void setSALOMEDispatcher(); - static SALOMEDispatcher* getSALOMEDispatcher(); - }; - + CORBA::TypeCode_var tc=self->getAny()->type(); + if (!tc->equivalent(CORBA::_tc_null)) + return convertCorbaPyObject(self->edGetType(),self->getAny()); + else + { + Py_INCREF(Py_None); + return Py_None; + } } } +%extend YACS::ENGINE::OutputCorbaPort +{ + PyObject * getPyObj() + { + CORBA::TypeCode_var tc=self->getAny()->type(); + if (!tc->equivalent(CORBA::_tc_null)) + return convertCorbaPyObject(self->edGetType(),self->getAny()); + else + { + Py_INCREF(Py_None); + return Py_None; + } + } +} + diff --git a/src/runtime/SalomeComponent.cxx b/src/runtime/SalomeComponent.cxx index 552996def..b1ddd5801 100644 --- a/src/runtime/SalomeComponent.cxx +++ b/src/runtime/SalomeComponent.cxx @@ -76,19 +76,28 @@ void SalomeComponent::load() } containerC->unLock(); containerC->lock();//To be sure - const char* componentName=_name.c_str(); + const char* componentName=_compoName.c_str(); //char *val2=CORBA::string_dup(""); // does not work with python components // does not make a strict load but a find or load component // _objComponent=containerC->_trueCont->load_impl(componentName,val2); bool isLoadable = containerC->_trueCont->load_component_Library(componentName); if (isLoadable) - _objComponent=containerC->_trueCont->create_component_instance(componentName, 0); + if (containerC->isAPaCOContainer()) { + std::string compo_paco_name(componentName); + compo_paco_name = compo_paco_name + "@PARALLEL@"; + char * c_paco_name = CORBA::string_dup(compo_paco_name.c_str()); + _objComponent=containerC->_trueCont->create_component_instance(c_paco_name, 0); + } + else + _objComponent=containerC->_trueCont->create_component_instance(componentName, 0); if(CORBA::is_nil(_objComponent)) { containerC->unLock(); - throw Exception("SalomeComponent::load : Error while trying to create a new component."); + std::string text="Error while trying to create a new component: component '"+ _compoName; + text=text+"' is not installed or it's a wrong name"; + throw Exception(text); } containerC->unLock(); return; @@ -101,7 +110,7 @@ void SalomeComponent::load() LCC.preSet(params); params.hostname="localhost"; params.container_name ="FactoryServer"; - _objComponent=LCC.LoadComponent(params,_name.c_str()); + _objComponent=LCC.LoadComponent(params,_compoName.c_str()); } #else void SalomeComponent::load() @@ -137,6 +146,24 @@ ComponentInstance* SalomeComponent::clone() const std::string SalomeComponent::getFileRepr() const { ostringstream stream; - stream << "" << getName() << ""; + stream << "" << getCompoName() << ""; return stream.str(); } + +void SalomeComponent::setContainer(Container *cont) +{ + if (cont == _container) return; + + if(cont) + cont->checkCapabilityToDealWith(this); + + if(_container) + _container->decrRef(); + _container=cont; + if(_container) + { + _container->incrRef(); + ((SalomeContainer*)_container)->addComponentName(_compoName); + } +} + diff --git a/src/runtime/SalomeComponent.hxx b/src/runtime/SalomeComponent.hxx index a276e2124..18bc250f6 100644 --- a/src/runtime/SalomeComponent.hxx +++ b/src/runtime/SalomeComponent.hxx @@ -12,7 +12,6 @@ namespace YACS /*! \brief Class for Salome component instance * - * \ingroup Nodes * */ class SalomeComponent : public ComponentInstance @@ -24,6 +23,7 @@ namespace YACS virtual void load(); virtual void unload(); virtual bool isLoaded(); + virtual void setContainer(Container *cont); virtual ServiceNode* createNode(const std::string& name); virtual ComponentInstance* clone() const; virtual std::string getFileRepr() const; diff --git a/src/runtime/SalomeContainer.cxx b/src/runtime/SalomeContainer.cxx index f7963d341..0887dda78 100644 --- a/src/runtime/SalomeContainer.cxx +++ b/src/runtime/SalomeContainer.cxx @@ -13,6 +13,7 @@ #include "SALOME_NamingService.hxx" #include "SALOME_LifeCycleCORBA.hxx" #include "SALOME_ContainerManager.hxx" +#include "OpUtil.hxx" #include #include @@ -25,10 +26,32 @@ using namespace std; SalomeContainer::SalomeContainer():_trueCont(Engines::Container::_nil()) { + /* Init MachinesParameters */ + _params.container_name = ""; + _params.hostname = ""; + _params.OS = ""; + _params.mem_mb = 0; + _params.cpu_clock = 0; + _params.nb_proc_per_node = 0; + _params.nb_node = 0; + _params.isMPI = false; + _params.parallelLib = ""; + _params.nb_component_nodes = 0; } SalomeContainer::SalomeContainer(const SalomeContainer& other):Container(other),_trueCont(Engines::Container::_nil()) { + _params.container_name = CORBA::string_dup(other._params.container_name); + _params.hostname = CORBA::string_dup(other._params.hostname); + _params.OS = CORBA::string_dup(other._params.OS); + _params.mem_mb = other._params.mem_mb; + _params.cpu_clock = other._params.cpu_clock; + _params.nb_proc_per_node = other._params.nb_proc_per_node; + _params.nb_node = other._params.nb_node; + _params.isMPI = other._params.isMPI; + _params.parallelLib = CORBA::string_dup(other._params.parallelLib); + _params.nb_component_nodes = other._params.nb_component_nodes; + _params.workingdir= CORBA::string_dup(other._params.workingdir); } SalomeContainer::~SalomeContainer() @@ -56,25 +79,61 @@ bool SalomeContainer::isAlreadyStarted() const void SalomeContainer::start() throw (Exception) { CORBA::ORB_ptr orb=getSALOMERuntime()->getOrb(); - SALOME_NamingService ns(orb); + SALOME_NamingService ns; + try + { + ns.init_orb(orb); + } + catch(SALOME_Exception& e) + { + throw Exception("SalomeContainer::start : Unable to contact the SALOME Naming Service"); + } CORBA::Object_var obj=ns.Resolve(SALOME_ContainerManager::_ContainerManagerNameInNS); Engines::ContainerManager_var contManager=Engines::ContainerManager::_narrow(obj); - SALOME_LifeCycleCORBA LCC(&ns); - Engines::MachineParameters params; - LCC.preSet(params); - params.hostname=CORBA::string_dup(""); - std::ostringstream stream; - stream << (void *)(this); - params.container_name=CORBA::string_dup(stream.str().c_str()); + + std::string str(_params.container_name); + //If a container_name is given try to find an already existing container in naming service + //If not found start a new container with the given parameters + if (str != "") + { + std::string machine(_params.hostname); + if(machine == "" || machine == "localhost") + machine=GetHostname(); + std::string ContainerNameInNS=ns.BuildContainerNameForNS(_params,machine.c_str()); + obj=ns.Resolve(ContainerNameInNS.c_str()); + if(!CORBA::is_nil(obj)) + { + std::cerr << "Container already exists: " << ContainerNameInNS << std::endl; + _trueCont=Engines::Container::_narrow(obj); + return; + } + } + + if (str == "") + { + std::ostringstream stream; + stream << (void *)(this); + _params.container_name=CORBA::string_dup(stream.str().c_str()); + } + Engines::CompoList compolist; + compolist.length(_componentNames.size()); + std::vector::iterator iter; + for(CORBA::ULong i=0; i < _componentNames.size();i++) + { + compolist[i]=CORBA::string_dup(_componentNames[i].c_str()); + } + try { + // --- GiveContainer is used in batch mode to retreive launched containers, + // and is equivalent to StartContainer when not in batch. std::string policy=getProperty("policy"); if(policy=="best") - _trueCont=contManager->StartContainer(params,Engines::P_BEST); + _trueCont=contManager->GiveContainer(_params,Engines::P_BEST,compolist); else if(policy=="first") - _trueCont=contManager->StartContainer(params,Engines::P_FIRST); + _trueCont=contManager->GiveContainer(_params,Engines::P_FIRST,compolist); else - _trueCont=contManager->StartContainer(params,Engines::P_CYCL); + _trueCont=contManager->GiveContainer(_params,Engines::P_CYCL,compolist); } catch(CORBA::COMM_FAILURE&) { @@ -85,7 +144,12 @@ void SalomeContainer::start() throw (Exception) throw Exception("SalomeContainer::start : Unable to launch container in Salome : Unexpected CORBA failure detected"); } if(CORBA::is_nil(_trueCont)) - throw Exception("SalomeContainer::start : Unable to launch container in Salome"); + throw Exception("SalomeContainer::start : Unable to launch container in Salome. Check your CatalogResources.xml file"); + + CORBA::String_var containerName=_trueCont->name(); + CORBA::String_var hostName=_trueCont->getHostName(); + std::cerr << "SalomeContainer launched : " << containerName << " " << hostName << " " << _trueCont->getPID() << std::endl; + #ifdef REFCNT DEBTRACE(_trueCont->_PR_getobj()->pd_refCount ); #endif @@ -127,3 +191,72 @@ void SalomeContainer::checkCapabilityToDealWith(const ComponentInstance *inst) c throw Exception("SalomeContainer::checkCapabilityToDealWith : SalomeContainer is not able to deal with this type of ComponentInstance."); } +void SalomeContainer::setProperty(const std::string& name, const std::string& value) +{ + DEBTRACE("SalomeContainer::setProperty : " << name << " ; " << value); + + if (name == "container_name") + _params.container_name = CORBA::string_dup(value.c_str()); + else if (name == "hostname") + _params.hostname = CORBA::string_dup(value.c_str()); + else if (name == "OS") + _params.OS = CORBA::string_dup(value.c_str()); + else if (name == "parallelLib") + _params.parallelLib = CORBA::string_dup(value.c_str()); + else if (name == "workingdir") + _params.workingdir = CORBA::string_dup(value.c_str()); + else if (name == "isMPI") + { + if (value == "true") + _params.isMPI = true; + else if (value == "false") + _params.isMPI = false; + else + throw Exception("SalomeContainer::SetProperty : params.isMPI value not correct : " + value); + } + else if (name == "mem_mb") + { + std::istringstream iss(value); + if (!(iss >> _params.mem_mb)) + throw Exception("salomecontainer::setproperty : params.mem_mb value not correct : " + value); + } + else if (name == "cpu_clock") + { + std::istringstream iss(value); + if (!(iss >> _params.cpu_clock)) + throw Exception("salomecontainer::setproperty : params.cpu_clock value not correct : " + value); + } + else if (name == "nb_proc_per_node") + { + std::istringstream iss(value); + if (!(iss >> _params.nb_proc_per_node)) + throw Exception("salomecontainer::setproperty : params.nb_proc_per_node value not correct : " + value); + } + else if (name == "nb_node") + { + std::istringstream iss(value); + if (!(iss >> _params.nb_node)) + throw Exception("salomecontainer::setproperty : params.nb_node value not correct : " + value); + } + else if (name == "nb_component_nodes") + { + std::istringstream iss(value); + if (!(iss >> _params.nb_component_nodes)) + throw Exception("salomecontainer::setproperty : params.nb_component_nodes value not correct : " + value); + } + Container::setProperty(name, value); +} + +bool SalomeContainer::isAPaCOContainer() const +{ + bool result = false; + string parallelLib(_params.parallelLib); + if (parallelLib != "") + result = true; + return result; +} + +void SalomeContainer::addComponentName(std::string name) +{ + _componentNames.push_back(name); +} diff --git a/src/runtime/SalomeContainer.hxx b/src/runtime/SalomeContainer.hxx index 275243016..901c5b061 100644 --- a/src/runtime/SalomeContainer.hxx +++ b/src/runtime/SalomeContainer.hxx @@ -3,8 +3,11 @@ #include "Container.hxx" #include "Mutex.hxx" +#include +#include #include #include CORBA_CLIENT_HEADER(SALOME_Component) +#include CORBA_CLIENT_HEADER(SALOME_ContainerManager) namespace YACS { @@ -27,12 +30,18 @@ namespace YACS Container *clone() const; std::string getPlacementId() const; void checkCapabilityToDealWith(const ComponentInstance *inst) const throw (Exception); + virtual void setProperty(const std::string& name, const std::string& value); + bool isAPaCOContainer() const; + virtual void addComponentName(std::string name); protected: virtual ~SalomeContainer(); protected: //! thread safety in Salome ??? YACS::BASES::Mutex _mutex; Engines::Container_var _trueCont; + std::vector _componentNames; + public: + Engines::MachineParameters _params; }; } } diff --git a/src/runtime/SalomeProc.cxx b/src/runtime/SalomeProc.cxx index 8427cfbde..9d0968095 100644 --- a/src/runtime/SalomeProc.cxx +++ b/src/runtime/SalomeProc.cxx @@ -1,5 +1,6 @@ #include "SalomeProc.hxx" #include "Runtime.hxx" +#include "TypeCode.hxx" #include using namespace YACS::ENGINE; diff --git a/src/runtime/SalomeProc.hxx b/src/runtime/SalomeProc.hxx index f37853e14..4fee619dc 100644 --- a/src/runtime/SalomeProc.hxx +++ b/src/runtime/SalomeProc.hxx @@ -20,6 +20,7 @@ namespace YACS virtual TypeCode * createInterfaceTc(const std::string& id, const std::string& name, std::list ltc); virtual TypeCode * createStructTc(const std::string& id, const std::string& name); + virtual std::string typeName() {return "YACS__ENGINE__SalomeProc";} }; } } diff --git a/src/runtime/SalomePythonComponent.cxx b/src/runtime/SalomePythonComponent.cxx index 7e9922bdb..3ebec9fed 100644 --- a/src/runtime/SalomePythonComponent.cxx +++ b/src/runtime/SalomePythonComponent.cxx @@ -1,3 +1,4 @@ +#include #include "SalomePythonComponent.hxx" #include "SalomeComponent.hxx" #include "SalomePythonNode.hxx" diff --git a/src/runtime/SalomePythonNode.cxx b/src/runtime/SalomePythonNode.cxx index 4466fc71f..5dbc3f9a4 100644 --- a/src/runtime/SalomePythonNode.cxx +++ b/src/runtime/SalomePythonNode.cxx @@ -4,6 +4,7 @@ #include "PythonNode.hxx" #include "PythonPorts.hxx" #include "CORBANode.hxx" +#include "TypeCode.hxx" #include #include @@ -34,7 +35,6 @@ SalomePythonNode::SalomePythonNode(const std::string& name): ServiceInlineNode(n //Not a bug : just because port point of view this is like PythonNode. _implementation = PythonNode::IMPL_NAME; - cerr << "SalomePythonNode::SalomePythonNode " << name << endl; PyGILState_STATE gstate = PyGILState_Ensure(); _context=PyDict_New(); if( PyDict_SetItemString( _context, "__builtins__", getSALOMERuntime()->getBuiltins() )) diff --git a/src/runtime/SessionCataLoader.cxx b/src/runtime/SessionCataLoader.cxx new file mode 100644 index 000000000..0f7fe3f95 --- /dev/null +++ b/src/runtime/SessionCataLoader.cxx @@ -0,0 +1,405 @@ +#include "RuntimeSALOME.hxx" +#include "SessionCataLoader.hxx" +#include "ComponentDefinition.hxx" +#include "ServiceNode.hxx" +#include "TypeCode.hxx" + +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +#define NEW_KERNEL + +using namespace YACS::ENGINE; + +SessionCataLoader::SessionCataLoader(const std::string& path):CatalogLoader(path) +{ + //path should be a CORBA URI like that : corbaname::machine:port/NameService#Kernel.dir/ModulCatalog.object + //or equivalent corbaname +} + +/* + In salome catalog, the type names for CALCIUM are : INTEGER, FLOAT,DOUBLE,STRING,BOOLEAN + enum DataStreamType { + DATASTREAM_UNKNOWN, + DATASTREAM_INTEGER, + DATASTREAM_FLOAT, + DATASTREAM_DOUBLE, + DATASTREAM_STRING, + DATASTREAM_BOOLEAN + } ; +*/ +#ifndef NEW_KERNEL +std::map datastreamMap; +#endif + +//! import a SALOME component definition in a YACS catalog +/*! + * SALOME components can have several interfaces. + * YACS for the moment allows only one interface by component, so if there is only one interface we import it. + * If we have more than one interface, we import the one with the same name as the component or the first one. + * + * \param cata : a YACS catalog + * \param compo : a CORBA reference on a component in a SALOME_ModuleCatalog + */ +void SessionCataLoader::importComponent(Catalog* cata,SALOME_ModuleCatalog::Acomponent_ptr compo) +{ + CORBA::String_var componame = compo->componentname(); + + DEBTRACE("Implementation type : " << compo->implementation_type()); +#ifdef NEW_KERNEL + SALOME_ModuleCatalog::ImplType imptyp=compo->implementation_type(); + if(imptyp == SALOME_ModuleCatalog::SO)DEBTRACE("Dyn lib"); + if(imptyp == SALOME_ModuleCatalog::PY)DEBTRACE("Python module"); + if(imptyp == SALOME_ModuleCatalog::EXE)DEBTRACE("Executable"); + DEBTRACE("Implementation name : " << compo->implementation_name()); +#endif + + SALOME_ModuleCatalog::ListOfInterfaces_var interfacename_list = compo->GetInterfaceList(); + if(interfacename_list->length() == 0) + return; + int found=0; + for (int j = 0; j < interfacename_list->length();j++) + { + DEBTRACE ("Interface : " << interfacename_list[j]); + if(strcmp(componame,interfacename_list[j]) == 0) + { + found=j; + break; + } + } + DEBTRACE ("Interface found : " << interfacename_list[found]); + ComponentDefinition* compodef=new ComponentDefinition((const char*)componame); + + SALOME_ModuleCatalog::DefinitionInterface_var interface; + interface= compo->GetInterface(interfacename_list[found]); + SALOME_ModuleCatalog::ListOfInterfaceService services = interface->interfaceservicelist; + for (int k = 0; k < services.length(); k++) + { + DEBTRACE("Service : " << services[k].ServiceName); + const char* s=services[k].ServiceName; + //create a new service node (prototype) + ServiceNode* node=getRuntime()->createCompoNode("Salome",s); + node->setRef((const char*)componame); + node->setMethod(s); + for (int kk=0;kk< services[k].ServiceinParameter.length();kk++) + { + DEBTRACE("Parameter : " << services[k].ServiceinParameter[kk].Parametername); + DEBTRACE("Type : " << services[k].ServiceinParameter[kk].Parametertype); + const char* ty=services[k].ServiceinParameter[kk].Parametertype; + if(cata->_typeMap.count(ty)==0) + { + std::stringstream msg; + msg << "Type " <_serviceMap[s+std::string("_IS_INVALID")]=0; + delete node; + node=0; + break; + } + const char* name=services[k].ServiceinParameter[kk].Parametername; + node->edAddInputPort(name,cata->_typeMap[ty]); + } + if(node == 0)continue; + + for (int kk=0;kk< services[k].ServiceoutParameter.length();kk++) + { + DEBTRACE("Parameter : " << services[k].ServiceoutParameter[kk].Parametername); + DEBTRACE("Type : " << services[k].ServiceoutParameter[kk].Parametertype); + const char* ty=services[k].ServiceoutParameter[kk].Parametertype; + if(cata->_typeMap.count(ty)==0) + { + std::stringstream msg; + msg << "Type " <_serviceMap[s+std::string("_IS_INVALID")]=0; + delete node; + node=0; + break; + } + const char* name=services[k].ServiceoutParameter[kk].Parametername; + node->edAddOutputPort(name,cata->_typeMap[ty]); + } + if(node == 0)continue; + + for (int kk=0;kk< services[k].ServiceinDataStreamParameter.length();kk++) + { + DEBTRACE("Parameter : " << services[k].ServiceinDataStreamParameter[kk].Parametername); + DEBTRACE("Type : " << services[k].ServiceinDataStreamParameter[kk].Parametertype); + DEBTRACE("Dependency : " << services[k].ServiceinDataStreamParameter[kk].Parameterdependency); +#ifdef NEW_KERNEL + const char* ty=services[k].ServiceinDataStreamParameter[kk].Parametertype; +#else + std::string ty=datastreamMap[services[k].ServiceinDataStreamParameter[kk].Parametertype]; +#endif + if(cata->_typeMap.count(ty)==0) + { + std::stringstream msg; + msg << "Type " <_serviceMap[s+std::string("_IS_INVALID")]=0; + delete node; + node=0; + break; + } + const char* name=services[k].ServiceinDataStreamParameter[kk].Parametername; + InputDataStreamPort* port; + port=node->edAddInputDataStreamPort(name,cata->_typeMap[ty]); + } + if(node == 0)continue; + + for (int kk=0;kk< services[k].ServiceoutDataStreamParameter.length();kk++) + { + DEBTRACE("Parameter : " << services[k].ServiceoutDataStreamParameter[kk].Parametername); + DEBTRACE("Type : " << services[k].ServiceoutDataStreamParameter[kk].Parametertype); + DEBTRACE("Dependency : " << services[k].ServiceoutDataStreamParameter[kk].Parameterdependency); +#ifdef NEW_KERNEL + const char* ty=services[k].ServiceoutDataStreamParameter[kk].Parametertype; +#else + std::string ty=datastreamMap[services[k].ServiceoutDataStreamParameter[kk].Parametertype]; +#endif + if(cata->_typeMap.count(ty)==0) + { + std::stringstream msg; + msg << "Type " <_serviceMap[s+std::string("_IS_INVALID")]=0; + delete node; + node=0; + break; + } + const char* name=services[k].ServiceoutDataStreamParameter[kk].Parametername; + OutputDataStreamPort* port; + port=node->edAddOutputDataStreamPort(name,cata->_typeMap[ty]); + // Set all properties for this port + /* + std::map::const_iterator pt; + for(pt=p._props.begin();pt!=p._props.end();pt++) + port->setProperty((*pt).first,(*pt).second); + */ + } + if(node == 0)continue; + compodef->_serviceMap[s]=node; + } + + /* Even if a component has no service, put it in the catalog + if(compodef->_serviceMap.size() > 0) + { + cata->_componentMap[(const char*)componame]=compodef; + } + else + { + delete compodef; + } + */ + cata->_componentMap[(const char*)componame]=compodef; +} + +SessionCataLoader::~SessionCataLoader() +{ + DEBTRACE ("SessionCataLoader::~SessionCataLoader"); +} + +TypeCode * createInterfaceTc(const std::string& id, const std::string& name, + std::list ltc) +{ + std::string myName; + if(id == "") myName = "IDL:" + name + ":1.0"; + else myName = id; + return TypeCode::interfaceTc(myName.c_str(),name.c_str(),ltc); +} + +void SessionCataLoader::loadTypes(Catalog* cata,SALOME_ModuleCatalog::ModuleCatalog_ptr catalog) +{ + Runtime* r=getRuntime(); + std::map& typeMap=cata->_typeMap; + // Get types list + SALOME_ModuleCatalog::ListOfTypeDefinition_var types_list=catalog->GetTypes(); + for (int i=0; i< types_list->length(); i++) + { + const char* name=types_list[i].name; + DEBTRACE ("type : " << types_list[i].name << " " << types_list[i].kind); + if(types_list[i].kind == SALOME_ModuleCatalog::Dble) + { + r->_tc_double->incrRef(); + typeMap[name]=r->_tc_double; + } + else if(types_list[i].kind == SALOME_ModuleCatalog::Int) + { + r->_tc_int->incrRef(); + typeMap[name]=r->_tc_int; + } + else if(types_list[i].kind == SALOME_ModuleCatalog::Bool) + { + r->_tc_bool->incrRef(); + typeMap[name]=r->_tc_bool; + } + else if(types_list[i].kind == SALOME_ModuleCatalog::Str) + { + r->_tc_string->incrRef(); + typeMap[name]=r->_tc_string; + } + else if(types_list[i].kind == SALOME_ModuleCatalog::Seq) + { + const char* content=types_list[i].content; + if ( typeMap.find(content) != typeMap.end() ) + typeMap[name]=TypeCode::sequenceTc(name,name,typeMap[content]); + //else ignored !! + } + else if(types_list[i].kind == SALOME_ModuleCatalog::Array) + { + //ignored, for the moment !! + } + else if(types_list[i].kind == SALOME_ModuleCatalog::Objref) + { + std::list ltc; + const char* id=types_list[i].id; + for (int m=0; m< types_list[i].bases.length(); m++) + { + const char* b_name=types_list[i].bases[m]; + if(typeMap.find(b_name) != typeMap.end()) + ltc.push_back((TypeCodeObjref *)typeMap[b_name]); + //else ignored !!! + } + typeMap[name]=TypeCode::interfaceTc(id,name,ltc); + } + else if(types_list[i].kind == SALOME_ModuleCatalog::Struc) + { + TypeCodeStruct* t=(TypeCodeStruct*)TypeCode::structTc("",name); + for (int m=0; m< types_list[i].members.length(); m++) + { + const char* m_name=types_list[i].members[m].name; + const char* m_type=types_list[i].members[m].type; + if(typeMap.find(m_type) != typeMap.end()) + t->addMember(m_name,typeMap[m_type]); + //else ignored !!! + } + typeMap[name]=t; + } + else + { + std::cerr << "Unknown kind: " << types_list[i].kind << std::endl; + } + } +} + +void SessionCataLoader::loadTypesOld(Catalog* cata) +{ + // Fill the types map with built in types + Runtime* r=getRuntime(); + std::map& typeMap=cata->_typeMap; + +#ifdef NEW_KERNEL + //Add old Calcium data types for KERNEL + if(typeMap.count("CALCIUM_double")!=0) + { + typeMap["DOUBLE"]=typeMap["CALCIUM_double"]; + typeMap["DOUBLE"]->incrRef(); + } + if(typeMap.count("CALCIUM_real")!=0) + { + typeMap["FLOAT"]=typeMap["CALCIUM_real"]; + typeMap["FLOAT"]->incrRef(); + } + if(typeMap.count("CALCIUM_integer")!=0) + { + typeMap["INTEGER"]=typeMap["CALCIUM_integer"]; + typeMap["INTEGER"]->incrRef(); + } + if(typeMap.count("CALCIUM_boolean")!=0) + { + typeMap["BOOLEAN"]=typeMap["CALCIUM_boolean"]; + typeMap["BOOLEAN"]->incrRef(); + } + if(typeMap.count("CALCIUM_string")!=0) + { + typeMap["STRING"]=typeMap["CALCIUM_string"]; + typeMap["STRING"]->incrRef(); + } +#endif + + //GEOM + /* + typeMap["GEOM_Object"]=TypeCode::interfaceTc("IDL:GEOM/GEOM_Object:1.0","GEOM_Object"); + typeMap["ListOfLong"]=TypeCode::sequenceTc("ListOfLong","ListOfLong",r->_tc_int); + typeMap["GEOM_List"]=TypeCode::interfaceTc("IDL:GEOM/GEOM_List:1.0","GEOM_List"); + typeMap["GEOM_Superv"]=TypeCode::interfaceTc("IDL:GEOM/GEOM_Superv:1.0","GEOM_Superv"); + typeMap["ListOfGO"]=TypeCode::sequenceTc("ListOfGO","ListOfGO",cata->_typeMap["GEOM_Object"]); + typeMap["string_array"]=TypeCode::sequenceTc("string_array","string_array",r->_tc_string); + r->_tc_int->incrRef(); + typeMap["BCErrorType"]=r->_tc_int; + typeMap["BCError"]=TypeCode::structTc("","BCError"); + ((TypeCodeStruct*)typeMap["BCError"])->addMember("incriminated",typeMap["ListOfLong"]); + typeMap["BCErrors"]=TypeCode::sequenceTc("BCErrors","BCErrors",typeMap["BCError"]); + typeMap["GEOM_Gen"]=TypeCode::interfaceTc("IDL:GEOM/GEOM_Gen:1.0","GEOM_Gen"); + typeMap["GEOM_Object"]->incrRef(); + typeMap["GEOM_Shape"]=typeMap["GEOM_Object"]; + */ + + //SMESH + /* + typeMap["SMESH_Mesh"]=TypeCode::interfaceTc("IDL:Mesh/SMESH_Mesh:1.0","SMESH_Mesh"); + typeMap["SMESH_Hypothesis"]=TypeCode::interfaceTc("IDL:SMESH/SMESH_Hypothesis:1.0","SMESH_Hypothesis"); + */ + + //MED + /* + typeMap["MED"]=TypeCode::interfaceTc("IDL:SALOME_MED/MED:1.0","MED"); + typeMap["FIELD"]=TypeCode::interfaceTc("IDL:SALOME_MED/FIELD:1.0","FIELD"); + // TODO : FIELDDOUBLE inherits FIELD + typeMap["FIELDDOUBLE"]=TypeCode::interfaceTc("IDL:SALOME_MED/FIELDDOUBLE:1.0","FIELDDOUBLE"); + */ + + //COMPONENT + /* + typeMap["AddComponent"]=TypeCode::interfaceTc("IDL:SuperVisionTest/AddComponent:1.0","AddComponent"); + typeMap["AddComponent"]->incrRef(); + typeMap["AddInterface"]=typeMap["AddComponent"]; + typeMap["SuperVisionTest/Adder"]=TypeCode::interfaceTc("IDL:SuperVisionTest/Adder:1.0","SuperVisionTest/Adder"); + typeMap["AdditionComponent/Adder"]=TypeCode::interfaceTc("IDL:AdditionComponent/Adder:1.0","AdditionComponent/Adder"); + typeMap["Syr"]=TypeCode::interfaceTc("IDL:SuperVisionTest/Syr:1.0","Syr"); + typeMap["ListOfSyr"]=TypeCode::interfaceTc("IDL:SuperVisionTest/ListOfSyr:1.0","ListOfSyr"); + */ +} + +void SessionCataLoader::loadCata(Catalog* cata) +{ + DEBTRACE("SessionCataLoader::load") +#ifndef NEW_KERNEL + datastreamMap[SALOME_ModuleCatalog::DATASTREAM_UNKNOWN]="CALCIUM_unknown"; + datastreamMap[SALOME_ModuleCatalog::DATASTREAM_INTEGER]="CALCIUM_integer"; + datastreamMap[SALOME_ModuleCatalog::DATASTREAM_FLOAT]="CALCIUM_real"; + datastreamMap[SALOME_ModuleCatalog::DATASTREAM_DOUBLE]="CALCIUM_double"; + datastreamMap[SALOME_ModuleCatalog::DATASTREAM_BOOLEAN]="CALCIUM_boolean"; + datastreamMap[SALOME_ModuleCatalog::DATASTREAM_STRING]="CALCIUM_string"; +#endif + + CORBA::ORB_ptr orb = getSALOMERuntime()->getOrb(); + CORBA::Object_var obj; + SALOME_ModuleCatalog::ModuleCatalog_var catalog; + obj=orb->string_to_object(_path.c_str()); + catalog= SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj); + _errors=""; + + // Get types in catalog + loadTypes(cata,catalog); + // Get old types + loadTypesOld(cata); + + // Get component list + SALOME_ModuleCatalog::ListOfComponents_var componentname_list; + componentname_list = catalog->GetComponentList(); + for (int i=0; ilength(); i++) + { + DEBTRACE ("Component : " << componentname_list[i]); + SALOME_ModuleCatalog::Acomponent_var component = catalog->GetComponent(componentname_list[i]); + importComponent(cata,component); + } + cata->setErrors(_errors); +} diff --git a/src/runtime/SessionCataLoader.hxx b/src/runtime/SessionCataLoader.hxx new file mode 100644 index 000000000..82cecbe6d --- /dev/null +++ b/src/runtime/SessionCataLoader.hxx @@ -0,0 +1,32 @@ +#ifndef _SESSIONCATALOADER_HXX_ +#define _SESSIONCATALOADER_HXX_ + +#include "Catalog.hxx" +#include "SALOME_ModuleCatalog.hh" + +#include +#include +#include + +namespace YACS +{ + namespace ENGINE + { + class SessionCataLoader: public CatalogLoader + { + public: + SessionCataLoader():CatalogLoader(){}; + SessionCataLoader(const std::string& path); + virtual ~SessionCataLoader(); + virtual void loadCata(Catalog* cata); + virtual void loadTypesOld(Catalog* cata); + virtual void loadTypes(Catalog* cata,SALOME_ModuleCatalog::ModuleCatalog_ptr catalog); + virtual CatalogLoader* newLoader(const std::string& path) {return new SessionCataLoader(path);} + virtual void importComponent(Catalog* cata,SALOME_ModuleCatalog::Acomponent_ptr compo); + protected: + std::string _errors; + }; + } +} + +#endif diff --git a/src/runtime/StudyNodes.cxx b/src/runtime/StudyNodes.cxx new file mode 100644 index 000000000..9a9a23f12 --- /dev/null +++ b/src/runtime/StudyNodes.cxx @@ -0,0 +1,415 @@ +#include "RuntimeSALOME.hxx" +#include "StudyNodes.hxx" +#include "StudyPorts.hxx" +#include "Visitor.hxx" + +#include "SALOME_NamingService.hxx" +#include "SALOMEDS.hh" +#include "SALOMEDS_Attributes.hh" + +#include +#include +#include +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +namespace YACS +{ +namespace ENGINE +{ + +const char StudyInNode::IMPL_NAME[]="XML"; + +StudyInNode::StudyInNode(const std::string& name) + : DataNode(name) +{ + _implementation=IMPL_NAME; +} + +StudyInNode::StudyInNode(const StudyInNode& other, ComposedNode *father) + : DataNode(other, father) +{ +} + +Node *StudyInNode::simpleClone(ComposedNode *father, bool editionOnly) const +{ + return new StudyInNode(*this,father); +} + +OutputPort* StudyInNode::createOutputPort(const std::string& outputPortName, TypeCode* type) +{ + return new OutputStudyPort(outputPortName, this, type); +} + +void StudyInNode::setData(OutputPort* port, std::string& data) +{ + OutputStudyPort *outp = dynamic_cast(port); + outp->setData(data); +} + +void StudyInNode::execute() +{ + DEBTRACE("+++++++ StudyInNode::execute +++++++++++"); + SALOME_NamingService NS(getSALOMERuntime()->getOrb()); + CORBA::Object_var obj=NS.Resolve("/myStudyManager"); + if(CORBA::is_nil(obj)) + { + _errorDetails="Execution problem: no naming service"; + throw Exception(_errorDetails); + } + + SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow(obj); + if(CORBA::is_nil(aStudyManager)) + { + _errorDetails="Execution problem: no naming service"; + throw Exception(_errorDetails); + } + + int studyid=1; + if (_propertyMap.find("StudyID") != _propertyMap.end()) + { + // StudyId is specified + studyid=atoi(_propertyMap["StudyID"].c_str()); + } + + SALOMEDS::Study_var myStudy =aStudyManager->GetStudyByID(studyid); + if(CORBA::is_nil(myStudy)) + { + std::stringstream msg; + msg << "Execution problem: no study with id " << studyid; + _errorDetails=msg.str(); + throw Exception(_errorDetails); + } + + std::list::const_iterator iter; + for(iter = _setOfOutputPort.begin(); iter != _setOfOutputPort.end(); iter++) + { + OutputStudyPort *outp = dynamic_cast(*iter); + std::string data = outp->getData(); + DEBTRACE("data: " << data ); + //try an id + SALOMEDS::SObject_var aSO = myStudy->FindObjectID(data.c_str()); + if(CORBA::is_nil(aSO)) + { + //try a path + aSO=myStudy->FindObjectByPath(data.c_str()); + if(CORBA::is_nil(aSO)) + { + _errorDetails="Execution problem: no id or path: "; + _errorDetails=_errorDetails+data+" in study"; + throw Exception(_errorDetails); + } + } + + CORBA::String_var path=myStudy->GetObjectPath(aSO); + DEBTRACE(path); + CORBA::String_var id=aSO->GetID(); + DEBTRACE(id); + //CORBA::Object_var sobj=aSO->GetObject(); + SALOMEDS::GenericAttribute_var aGAttr; + + CORBA::String_var value; + if ( aSO->FindAttribute( aGAttr, "AttributeIOR" ) ) + { + SALOMEDS::AttributeIOR_var anAttr = SALOMEDS::AttributeIOR::_narrow( aGAttr ); + value=anAttr->Value(); + } + else + { + //Problem !!! + _errorDetails="Execution problem: no AttributeIOR in study object: "; + _errorDetails=_errorDetails+data; + throw Exception(_errorDetails); + } + outp->putIOR((const char*)value); + } + DEBTRACE("+++++++ end StudyInNode::execute +++++++++++" ); +} + +void StudyInNode::checkBasicConsistency() const throw(Exception) +{ + DEBTRACE("StudyInNode::checkBasicConsistency"); + if (! _setOfInputPort.empty()) + { + std::string what = "StudyNode "; + what += getName(); + what += " only accepts OutputStudyPort, no InputPort"; + throw Exception(what); + } + + std::list::const_iterator iter; + for(iter=_setOfOutputPort.begin();iter!=_setOfOutputPort.end();iter++) + { + OutputStudyPort *inp = dynamic_cast(*iter); + if (!inp) + { + std::string what("Output port: "); + what += (*iter)->getName(); + what += " is not an OutputStudyPort. StudyNode "; + what += getName(); + what += " only accepts OutputStudyPorts"; + throw Exception(what); + } + + std::string data = inp->getData(); + DEBTRACE(data); + if (data.empty()) + { + std::string what("OutputStudyPort: "); + what += (*iter)->getName(); + what += " is not initialised"; + throw Exception(what); + } + } +} + +void StudyInNode::accept(Visitor *visitor) +{ + visitor->visitStudyInNode(this); +} + +const char StudyOutNode::IMPL_NAME[]="XML"; + +StudyOutNode::StudyOutNode(const std::string& name) + : DataNode(name) +{ + _implementation=IMPL_NAME; +} + +StudyOutNode::StudyOutNode(const StudyOutNode& other, ComposedNode *father) + : DataNode(other, father) +{ +} + +Node *StudyOutNode::simpleClone(ComposedNode *father, bool editionOnly) const +{ + return new StudyOutNode(*this,father); +} + +InputPort* StudyOutNode::createInputPort(const std::string& inputPortName, TypeCode* type) +{ + return new InputStudyPort(inputPortName, this, type); +} + +void StudyOutNode::setData(InputPort* port, std::string& data) +{ + InputStudyPort *inp = dynamic_cast(port); + inp->setData(data); +} + +SALOMEDS::SObject_ptr findOrCreateSoWithName(SALOMEDS::Study_ptr study, SALOMEDS::StudyBuilder_ptr builder, + SALOMEDS::SObject_ptr sobj, const std::string& name) +{ + SALOMEDS::ChildIterator_var anIterator= study->NewChildIterator(sobj); + SALOMEDS::GenericAttribute_var anAttr; + SALOMEDS::AttributeName_var namAttr ; + SALOMEDS::SObject_var result=SALOMEDS::SObject::_nil(); + + for (; anIterator->More(); anIterator->Next()) + { + SALOMEDS::SObject_var anObj=anIterator->Value(); + if(anObj->FindAttribute(anAttr, "AttributeName")) + { + namAttr = SALOMEDS::AttributeName::_narrow( anAttr ); + CORBA::String_var value=namAttr->Value(); + if(name == (const char*)value) + { + result=anObj; + break; + } + } + } + if(CORBA::is_nil(result)) + { + //create it + result = builder->NewObject( sobj ); + anAttr=builder->FindOrCreateAttribute(result,"AttributeName"); + namAttr = SALOMEDS::AttributeName::_narrow( anAttr ); + namAttr->SetValue(name.c_str()); + } + return result._retn(); +} + +void StudyOutNode::execute() +{ + DEBTRACE("+++++++ StudyOutNode::execute +++++++++++"); + SALOME_NamingService NS(getSALOMERuntime()->getOrb()); + CORBA::Object_var obj=NS.Resolve("/myStudyManager"); + if(CORBA::is_nil(obj)) + { + _errorDetails="Execution problem: no naming service"; + throw Exception(_errorDetails); + } + + SALOMEDS::StudyManager_var aStudyManager = SALOMEDS::StudyManager::_narrow(obj); + if(CORBA::is_nil(aStudyManager)) + { + _errorDetails="Execution problem: no naming service"; + throw Exception(_errorDetails); + } + + int studyid=1; + if (_propertyMap.find("StudyID") != _propertyMap.end()) + { + // StudyId is specified + studyid=atoi(_propertyMap["StudyID"].c_str()); + } + + SALOMEDS::Study_var myStudy =aStudyManager->GetStudyByID(studyid); + if(CORBA::is_nil(myStudy)) + { + //open a new one + std::stringstream msg; + msg << "Study" << studyid; + myStudy=aStudyManager->NewStudy(msg.str().c_str()); + if(CORBA::is_nil(myStudy)) + { + _errorDetails="Execution problem: can not create new study " + msg.str(); + throw Exception(_errorDetails); + } + } + DEBTRACE(myStudy->StudyId()); + + SALOMEDS::StudyBuilder_var aBuilder =myStudy->NewBuilder() ; + if(CORBA::is_nil(aBuilder)) + { + _errorDetails="Execution problem: can not create StudyBuilder"; + throw Exception(_errorDetails); + } + + SALOMEDS::GenericAttribute_var aGAttr; + SALOMEDS::SObject_var aSO ; + SALOMEDS::AttributeName_var anAttr ; + SALOMEDS::AttributeIOR_var iorAttr ; + + std::list::const_iterator iter; + for(iter = _setOfInputPort.begin(); iter != _setOfInputPort.end(); iter++) + { + InputStudyPort *inp = dynamic_cast(*iter); + std::string data = inp->getData(); + DEBTRACE("data: " << data ); + //try to find an id + aSO = myStudy->FindObjectID(data.c_str()); + if(CORBA::is_nil(aSO)) + { + // the id does not exist. Try to create it by id + aSO=myStudy->CreateObjectID(data.c_str()); + if(!CORBA::is_nil(aSO)) + { + aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeName"); + anAttr = SALOMEDS::AttributeName::_narrow( aGAttr ); + anAttr->SetValue(inp->getName().c_str()); + } + } + if(CORBA::is_nil(aSO)) + { + // try a path + aSO=myStudy->FindObjectByPath(data.c_str()); + } + if(CORBA::is_nil(aSO)) + { + //try to create it by path + std::string name; + std::string::size_type begin = data.find_first_not_of("/"); + std::string::size_type pos=data.find_first_of("/", begin); + if (pos != std::string::npos) + name=data.substr(begin,pos-begin); + else + name=data.substr(begin); + name="/"+name; + DEBTRACE(name); + aSO=myStudy->FindObjectByPath(name.c_str()); + if(CORBA::is_nil(aSO)) + { + DEBTRACE("Create an entry " << name); + //create a container component + aSO=aBuilder->NewComponent(name.c_str()); + if(CORBA::is_nil(aSO)) + { + std::cerr << "Execution problem: can not create component: " + data << std::endl; + continue; + } + aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeIOR"); + iorAttr = SALOMEDS::AttributeIOR::_narrow( aGAttr ); + iorAttr->SetValue(name.c_str()); + } + begin=data.find_first_not_of("/",pos); + while (begin != std::string::npos) + { + pos = data.find_first_of("/", begin); + if (pos != std::string::npos) + name=data.substr(begin,pos-begin); + else + name=data.substr(begin); + aSO=findOrCreateSoWithName(myStudy,aBuilder,aSO,name); + begin=data.find_first_not_of("/",pos); + } + } + if(CORBA::is_nil(aSO)) + { + std::cerr << "Execution problem: can not create id or path: " + data + " in study" << std::endl; + continue; + } + std::string value=inp->getIOR(); + DEBTRACE(value); + aGAttr=aBuilder->FindOrCreateAttribute(aSO,"AttributeIOR"); + iorAttr = SALOMEDS::AttributeIOR::_narrow( aGAttr ); + iorAttr->SetValue(value.c_str()); + } + + // save in file if ref is given + if(_ref != "") + { + aStudyManager->SaveAs(_ref.c_str(),myStudy, false); + } + DEBTRACE("+++++++ end StudyOutNode::execute +++++++++++" ); +} + +void StudyOutNode::checkBasicConsistency() const throw(Exception) +{ + DEBTRACE("StudyOutNode::checkBasicConsistency"); + if (! _setOfOutputPort.empty()) + { + std::string what = "StudyNode "; + what += getName(); + what += " only accepts InputStudyPort, no OutputPort"; + throw Exception(what); + } + + std::list::const_iterator iter; + for(iter=_setOfInputPort.begin();iter!=_setOfInputPort.end();iter++) + { + InputStudyPort *inp = dynamic_cast(*iter); + if (!inp) + { + std::string what("Input port: "); + what += (*iter)->getName(); + what += " is not an InputStudyPort. StudyNode "; + what += getName(); + what += " only accepts InputStudyPorts"; + throw Exception(what); + } + inp->checkBasicConsistency(); + + std::string data = inp->getData(); + DEBTRACE(data); + if (data.empty()) + { + std::string what("InputStudyPort: "); + what += (*iter)->getName(); + what += " is not initialised"; + throw Exception(what); + } + } + +} + +void StudyOutNode::accept(Visitor *visitor) +{ + visitor->visitStudyOutNode(this); +} + +} //end namespace ENGINE +} //end namespace YACS diff --git a/src/runtime/StudyNodes.hxx b/src/runtime/StudyNodes.hxx new file mode 100644 index 000000000..53e818a58 --- /dev/null +++ b/src/runtime/StudyNodes.hxx @@ -0,0 +1,43 @@ +#ifndef _STUDYNODES_HXX_ +#define _STUDYNODES_HXX_ + +#include "DataNode.hxx" + +namespace YACS +{ + namespace ENGINE + { + class StudyInNode: public DataNode + { + protected: + Node *simpleClone(ComposedNode *father, bool editionOnly) const; + public: + StudyInNode(const std::string& name); + StudyInNode(const StudyInNode& other, ComposedNode *father); + virtual void execute(); + virtual void accept(Visitor *visitor); + virtual void checkBasicConsistency() const throw(Exception); + virtual void setData(OutputPort* port, std::string& data); + virtual OutputPort *createOutputPort(const std::string& outputPortName, TypeCode* type); + public: + static const char IMPL_NAME[]; + }; + class StudyOutNode: public DataNode + { + protected: + Node *simpleClone(ComposedNode *father, bool editionOnly) const; + public: + StudyOutNode(const std::string& name); + StudyOutNode(const StudyOutNode& other, ComposedNode *father); + virtual void execute(); + virtual void accept(Visitor *visitor); + virtual void checkBasicConsistency() const throw(Exception); + virtual void setData(InputPort* port, std::string& data); + virtual InputPort *createInputPort(const std::string& inputPortName, TypeCode* type); + public: + static const char IMPL_NAME[]; + }; + } +} + +#endif diff --git a/src/runtime/StudyPorts.cxx b/src/runtime/StudyPorts.cxx new file mode 100644 index 000000000..1fec730ac --- /dev/null +++ b/src/runtime/StudyPorts.cxx @@ -0,0 +1,147 @@ +#include "StudyPorts.hxx" +#include "TypeCode.hxx" + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + + +namespace YACS +{ +namespace ENGINE +{ + +OutputStudyPort::OutputStudyPort(const std::string& name, Node* node, TypeCode* type) + : OutputXmlPort(name, node, type), + DataPort(name, node, type), + Port(node) +{ +} + +OutputStudyPort::OutputStudyPort(const OutputStudyPort& other, Node *newHelder) + : OutputXmlPort(other,newHelder), + DataPort(other,newHelder), + Port(other,newHelder) +{ +} + +void OutputStudyPort::setData(const std::string& data) +{ + _storeData = data; + DEBTRACE( "OutputStudyPort::setData " << _storeData ); + modified(); +} + +std::string OutputStudyPort::getData() +{ + DEBTRACE("OutputStudyPort::getData " << _storeData); + return _storeData; +} + +void OutputStudyPort::putIOR(const std::string& ior) +{ + DEBTRACE("OutputStudyPort::putIOR " << ior); + if(ior.substr(0,7) == "") + { + put(ior.c_str()); + } + else + { + int tk=edGetType()->kind(); + std::string value; + switch(tk) + { + case Double: + value=""+ior+""; + break; + case Int: + value=""+ior+""; + break; + case String: + value=""+ior+""; + break; + case Bool: + value=""+ior+""; + break; + case Objref: + value=""+ior+""; + break; + case Sequence: + case Array: + case Struct: + default: + break; + } + put(value.c_str()); + } +} + +std::string OutputStudyPort::dump() +{ + DEBTRACE( "OutputStudyPort::dump " << _storeData ); + DEBTRACE( "OutputStudyPort::dump " << _data ); + //return ""+_storeData+""; + return _data; +} + +InputStudyPort::InputStudyPort(const std::string& name, Node* node, TypeCode* type) + : InputXmlPort(name, node, type), + DataPort(name, node, type), + Port(node) +{ +} + +InputStudyPort::InputStudyPort(const InputStudyPort& other, Node *newHelder) + : InputXmlPort(other,newHelder), + DataPort(other,newHelder), + Port(other,newHelder) +{ +} + +void InputStudyPort::setData(const std::string& data) +{ + _storeData = data; + DEBTRACE( "InputStudyPort::setData " << _storeData ); + modified(); +} + +std::string InputStudyPort::getData() +{ + DEBTRACE("InputStudyPort::getData " << _storeData); + return _storeData; +} + +std::string InputStudyPort::getIOR() +{ + switch(edGetType()->kind()) + { + case Objref: + return splitXML(_data); + default: + return _data; + } +} + +std::string InputStudyPort::splitXML(const std::string& s) +{ + // content + std::string::size_type begin = s.find_first_of("<"); // + begin = s.find_first_of(">",begin); // end of + begin = s.find_first_of("<",begin); // beginning of + begin = s.find_first_of(">",begin); // end of + begin = s.find_first_not_of("> ",begin); // beginning of content + std::string::size_type last = s.find_first_of("<",begin); // beginning of + return s.substr(begin,last-begin); +} + +std::string InputStudyPort::dump() +{ + DEBTRACE( "InputStudyPort::dump " << _storeData ); + DEBTRACE( "InputStudyPort::dump " << _data ); + //return ""+_storeData+""; + return _data; +} + +} +} diff --git a/src/runtime/StudyPorts.hxx b/src/runtime/StudyPorts.hxx new file mode 100644 index 000000000..d6a641ee9 --- /dev/null +++ b/src/runtime/StudyPorts.hxx @@ -0,0 +1,54 @@ +#ifndef _STUDYPORTS_HXX_ +#define _STUDYPORTS_HXX_ + +#include "XMLPorts.hxx" + +namespace YACS +{ + namespace ENGINE + { + +/*! \brief Class for Study output Ports + * + * \ingroup Ports + * + * \see StudyInNode + */ + class OutputStudyPort: public OutputXmlPort + { + public: + OutputStudyPort(const std::string& name, Node* node, TypeCode* type); + OutputStudyPort(const OutputStudyPort& other, Node *newHelder); + void setData(const std::string& data); + std::string getData(); + virtual void putIOR(const std::string& ior); + virtual std::string dump(); + protected: + std::string _storeData; + }; + +/*! \brief Class for Study input Ports + * + * \ingroup Ports + * + * \see StudyOutNode + */ + class InputStudyPort: public InputXmlPort + { + public: + InputStudyPort(const std::string& name, Node* node, TypeCode* type); + InputStudyPort(const InputStudyPort& other, Node *newHelder); + void setData(const std::string& data); + std::string getData(); + virtual std::string getIOR(); + virtual std::string splitXML(const std::string& s); + virtual std::string dump(); + protected: + std::string _storeData; + }; + + } +} + + +#endif diff --git a/src/runtime/Test/Makefile.am b/src/runtime/Test/Makefile.am index 51e84e94c..ad3159c35 100644 --- a/src/runtime/Test/Makefile.am +++ b/src/runtime/Test/Makefile.am @@ -6,8 +6,10 @@ check_PROGRAMS = TestRuntime echoSrv echo_clt lib_LTLIBRARIES = libTestComponentLocal.la IDL_FILES = echo.idl -IDL_SOURCES = echoSK.cc -BUILT_SOURCES = $(IDL_SOURCES) echo_idl.py xmlrun.sh +IDL_SOURCES = echoSK.cc echoDynSK.cc +BUILT_SOURCES = $(IDL_SOURCES) echo_idl.py xmlrun.sh echo.hh + +EXTRA_DIST = $(IDL_FILES) standaloneTest.sh runtimeTest.hxx runtimeTest.sh TestComponent.hxx xmlrun_orig.sh TESTS = runtimeTest.sh TESTS_ENVIRONMENT=$(SHELL) -x @@ -21,12 +23,12 @@ TestRuntime_LDADD = \ $(PYTHON_LDFLAGS) \ $(PYTHON_EXTRA_LIBS) \ ../libYACSRuntimeSALOME.la \ - ../../engine/libYACSEngine.la \ + ../../engine/libYACSlibEngine.la \ ../../bases/libYACSBases.la TestRuntime_LDFLAGS = \ - @CPPUNIT_LIBS@ -pthread -ldl -lxml2 + @CPPUNIT_LIBS@ -pthread -ldl $(LIBXML_LIBS) TestRuntime_CXXFLAGS = \ -DUSE_CPPUNIT \ @@ -40,13 +42,17 @@ TestRuntime_CXXFLAGS = \ -I$(srcdir)/../../bases/Test \ -I$(srcdir)/../../engine \ -I$(srcdir)/../../engine/Test \ - -I/usr/include/libxml2 \ + $(LIBXML_INCLUDES) \ -DLOCATION="\"@prefix@\"" -DYACS_PTHREAD xmlrun.sh:${srcdir}/xmlrun_orig.sh cp $(srcdir)/xmlrun_orig.sh xmlrun.sh -echoSrv_SOURCES = echoSrv.cxx $(IDL_SOURCES) +echoDynSK.cc echoSK.cc echo.hh:echo.idl + $(OMNIORB_IDL) $(OMNIORB_IDLCXXFLAGS) -bcxx -Wba $< + +echoSrv_SOURCES = echoSrv.cxx +nodist_echoSrv_SOURCES = $(IDL_SOURCES) echoSrv_CXXFLAGS = \ -I$(srcdir)/../../bases \ @@ -56,10 +62,13 @@ echoSrv_CXXFLAGS = \ echoSrv_LDFLAGS = \ $(OMNIORB_LIBS) -echo_clt_SOURCES = echo_clt.cxx $(IDL_SOURCES) +echo_clt_SOURCES = echo_clt.cxx +nodist_echo_clt_SOURCES = $(IDL_SOURCES) echo_clt_CXXFLAGS = \ + -I$(srcdir)/../../bases \ $(OMNIORB_INCLUDES) \ + -I$(OMNIORB_ROOT)/include/omniORB4/internal \ $(OMNIORB_CXXFLAGS) echo_clt_LDFLAGS = \ @@ -77,4 +86,7 @@ libTestComponentLocal_la_CXXFLAGS = \ libTestComponentLocal_la_LDFLAGS = -module +clean-local: + rm -rf echo_idl.py* echoSK.cc echoDynSK.cc echo.hh eo eo__POA yacs* omnilog lib omniorb.cfg traceExec_* xmlrun.sh + include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/runtime/Test/echo.idl b/src/runtime/Test/echo.idl index ca9276c10..e8faa6b5a 100644 --- a/src/runtime/Test/echo.idl +++ b/src/runtime/Test/echo.idl @@ -58,6 +58,7 @@ module eo{ void echoObj2(in Obj i,out Obj j) ; void echoD(in D i,out D j) ; void echoC(in C i,out C j) ; + void echoObjVec(in ObjVec i,out ObjVec j) ; void echoObjectVec(in ObjectVec i,out ObjectVec j) ; void echoObjectVecVec(in ObjectVecVec i,out ObjectVecVec j) ; Obj echoObj(in long i,in Obj o,in long k,out Obj p); diff --git a/src/runtime/Test/echoSrv.cxx b/src/runtime/Test/echoSrv.cxx index c343ebb54..261c68bec 100644 --- a/src/runtime/Test/echoSrv.cxx +++ b/src/runtime/Test/echoSrv.cxx @@ -5,7 +5,7 @@ #include using namespace std; -//#define _DEVDEBUG_ +#define _DEVDEBUG_ #include "YacsTrace.hxx" static CORBA::Boolean bindObjectToName(CORBA::ORB_ptr, CORBA::Object_ptr,const char*); @@ -73,6 +73,7 @@ public: void echoIntVec(const eo::IntVec&, eo::IntVec_out); void echoStrVec(const eo::StrVec&, eo::StrVec_out); void echoObjectVec(const eo::ObjectVec&, eo::ObjectVec_out); + void echoObjVec(const eo::ObjVec&, eo::ObjVec_out); void echoObj2(eo::Obj_ptr , eo::Obj_out); void echoD(eo::D_ptr , eo::D_out); void echoC(eo::C_ptr , eo::C_out); @@ -136,6 +137,32 @@ void Echo_i::echoObjectVec(const eo::ObjectVec& in, eo::ObjectVec_out out) out=new eo::ObjectVec(in); } +void Echo_i::echoObjVec(const eo::ObjVec& in, eo::ObjVec_out out) + { + DEBTRACE("Echo_i::echoObjVec " << in.length()); + for(int i=0;i_mostDerivedRepoId()); + }; + + out=new eo::ObjVec; + out->length(2); + + Obj_i* obj0 = new Obj_i(); + CORBA::Object_var ref0 = obj0->_this(); + eo::Obj_var o0 = eo::Obj::_narrow(ref0); + (*out)[0]=o0; + obj0->_remove_ref(); + + C_i* obj1 = new C_i(); + CORBA::Object_var ref1 = obj1->_this(); + eo::Obj_var o1 = eo::Obj::_narrow(ref1); + (*out)[1]=o1; + obj1->_remove_ref(); + + DEBTRACE("ENDOF Echo_i::echoObjVec " ); +} + void Echo_i::echoObjectVecVec(const eo::ObjectVecVec& in, eo::ObjectVecVec_out out) { DEBTRACE("Echo_i::echoObjectVecVec " << in.length()); diff --git a/src/runtime/Test/echo_clt.cxx b/src/runtime/Test/echo_clt.cxx index cdc5cfb1c..113f7a103 100644 --- a/src/runtime/Test/echo_clt.cxx +++ b/src/runtime/Test/echo_clt.cxx @@ -1,75 +1,401 @@ +//#define REFCNT +#ifdef REFCNT +#define private public +#define protected public +#include +#include +#endif + #include #include +#include +#include + +#define _DEVDEBUG_ +#include "YacsTrace.hxx" int main(int argc, char** argv) { - try { - CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); - CORBA::Object_var obj = orb->string_to_object("corbaname:rir:#test.my_context/Echo.Object"); - eo::Echo_var echoref = eo::Echo::_narrow(obj); - if( CORBA::is_nil(echoref) ) { - std::cerr << "Can't narrow reference to type Echo (or it was nil)." << std::endl; - return 1; - } + try + { + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); + CORBA::Object_var obj = orb->string_to_object("corbaname:rir:#test.my_context/Echo.Object"); + eo::Echo_var echoref = eo::Echo::_narrow(obj); + if( CORBA::is_nil(echoref) ) + { + std::cerr << "Can't narrow reference to type Echo (or it was nil)." << std::endl; + return 1; + } - CORBA::String_var src = (const char*) "Hello!"; - CORBA::String_var dest = echoref->echoString(src); - std::cerr << "I said, \"" << (char*)src << "\"." << std::endl + CORBA::String_var src = (const char*) "Hello!"; + CORBA::String_var dest = echoref->echoString(src); + std::cerr << "I said, \"" << (char*)src << "\"." << std::endl << "The Echo object replied, \"" << (char*)dest <<"\"." << std::endl; - CORBA::Object_var ob = orb->string_to_object("corbaname:rir:#test.my_context/D.Object"); - eo::D_var Dref = eo::D::_narrow(ob); - if( CORBA::is_nil(Dref) ) { + CORBA::Object_var ob = orb->string_to_object("corbaname:rir:#test.my_context/D.Object"); + eo::D_var Dref = eo::D::_narrow(ob); + if( CORBA::is_nil(Dref) ) { std::cerr << "Can't narrow reference to type D (or it was nil)." << std::endl; return 1; + } + Dref->echoLong2(10); + + eo::D_var dout; + echoref->echoD(Dref,dout); + std::cerr << dout->echoLong2(10) << std::endl; + + eo::D_var ddout; + echoref->echoD(dout,ddout); + std::cerr << dout->echoLong2(10) << std::endl; + + CORBA::Object_var oob = orb->string_to_object("corbaname:rir:#test.my_context/Obj.Object"); + eo::Obj_var Objref = eo::Obj::_narrow(oob); + Objref->echoLong(10); + eo::Obj_var Objout; + echoref->echoObj2(Objref,Objout); + std::cerr << Objout->echoLong(10) << std::endl; + + CORBA::Object_var cob = orb->string_to_object("corbaname:rir:#test.my_context/C.Object"); + eo::C_var Cref = eo::C::_narrow(cob); + eo::C_var Cout; + echoref->echoC(Cref,Cout); + + echoref->echoObj2(Cref,Objout); + //echoref->echoC(Cref,Objout); compilation impossible + //echoref->echoObj2(Cref,Cout); compilation impossible + //echoref->echoC(Objref,Cout); compilation impossible + + CORBA::Object_var dobj = orb->resolve_initial_references("DynAnyFactory"); + DynamicAny::DynAnyFactory_var dynFactory = DynamicAny::DynAnyFactory::_narrow(dobj); + + CORBA::TypeCode_var content_type=orb->create_interface_tc("IDL:eo/Obj:1.0","Obj"); + + std::vector v; + std::vector::const_iterator iter; + + CORBA::Any *any = new CORBA::Any(); + *any <<= cob; + v.push_back(any); + /* + */ + CORBA::Any *any2 = new CORBA::Any(); + *any2 <<= oob; + v.push_back(any2); +#ifdef REFCNT + std::cerr << "refcount: " << oob->_PR_getobj()->pd_refCount << std::endl; +#endif + + CORBA::Any *any3 = new CORBA::Any(); + *any3 <<= oob; + v.push_back(any3); +#ifdef REFCNT + std::cerr << "refcount: " << oob->_PR_getobj()->pd_refCount << std::endl; +#endif + + eo::Obj_ptr xobj; + *any2 >>= xobj; +#ifdef REFCNT + std::cerr << "refcount: " << xobj->_PR_getobj()->pd_refCount << std::endl; +#endif + eo::Obj_ptr yobj; + *any2 >>= yobj; +#ifdef REFCNT + std::cerr << "refcount: " << yobj->_PR_getobj()->pd_refCount << std::endl; +#endif + + CORBA::Object_var zobj ; + *any2 >>= CORBA::Any::to_object(zobj) ; +#ifdef REFCNT + std::cerr << "refcount: " << zobj->_PR_getobj()->pd_refCount << std::endl; +#endif + + // Build an Any from vector v + int homog=1; + CORBA::TypeCode_var tc; + + if(v.size() != 0) + { + // Check if it's an homogeneous vector : all TypeCodes must be equivalent + CORBA::TypeCode_var any_tc=v[0]->type(); + tc=orb->create_sequence_tc(0,any_tc); + + for(iter=v.begin();iter!=v.end();iter++) + { + CORBA::Any* a=*iter; + CORBA::TypeCode_var tc2=a->type(); + if(!tc2->equivalent(any_tc)) + { + // It's a non homogeneous vector : create a sequence of any + tc=orb->create_sequence_tc(0,CORBA::_tc_any); + homog=0; + break; + } + } + // It's a homogeneous vector : create a sequence of the homogeneous type + } + else + { + // It's an empty vector : create a sequence of any + tc=orb->create_sequence_tc(0,CORBA::_tc_any); + homog=0; + } + + DynamicAny::DynAny_var dynany = dynFactory->create_dyn_any_from_type_code(tc); + DynamicAny::DynSequence_var ds = DynamicAny::DynSequence::_narrow(dynany); + + ds->set_length(v.size()); + for(iter=v.begin();iter!=v.end();iter++) + { + DynamicAny::DynAny_var temp=ds->current_component(); + CORBA::Any* a=*iter; + if(homog) + temp->from_any(*a); + else + ds->insert_any(*a); + //delete intermediate any + delete a; + ds->next(); + } + CORBA::Any_var seqany=ds->to_any(); + ds->destroy(); + + //DynStruct from map + std::map m; + CORBA::Any *any4 = new CORBA::Any(); + *any4 <<= oob; + //*any4 <<= cob; + m["ob"]=any4; + CORBA::Any *any5 = new CORBA::Any(); + *any5 <<= 1.0; + m["x"]=any5; + CORBA::Any *any6 = new CORBA::Any(); + *any6 <<= (long)1; + m["y"]=any6; + CORBA::Any *any7 = new CORBA::Any(); + *any7 <<= (const char*)"coucou"; + m["s"]=any7; + CORBA::Any *any8 = new CORBA::Any(); + *any8 <<= CORBA::Any::from_boolean(1); + m["b"]=any8; + +/* + struct S3 + { + double x; + long y; + string s; + boolean b; + Obj ob; + }; +*/ + + int nMember=5; + CORBA::StructMemberSeq mseq; + mseq.length(nMember); + mseq[0].name=CORBA::string_dup("x"); + mseq[0].type=CORBA::TypeCode::_duplicate(CORBA::_tc_double); + mseq[1].name=CORBA::string_dup("y"); + mseq[1].type=CORBA::TypeCode::_duplicate(CORBA::_tc_long); + mseq[2].name=CORBA::string_dup("s"); + mseq[2].type=CORBA::TypeCode::_duplicate(CORBA::_tc_string); + mseq[3].name=CORBA::string_dup("b"); + mseq[3].type=CORBA::TypeCode::_duplicate(CORBA::_tc_boolean); + mseq[4].name=CORBA::string_dup("ob"); + mseq[4].type=content_type; + for(int i=0;itype(); + } + } + CORBA::TypeCode_var ts= orb->create_struct_tc("","",mseq); + //CORBA::TypeCode_var ts= orb->create_struct_tc("IDL:eo/S3:1.0","S3",mseq); + dynany = dynFactory->create_dyn_any_from_type_code(ts); + DynamicAny::DynStruct_var dst = DynamicAny::DynStruct::_narrow(dynany); + + for(int i=0;icurrent_component(); + const char* name=mseq[i].name; + std::cerr << name << std::endl; + CORBA::Any* a=m[name]; + temp->from_any(*a); + //delete intermediate any + delete a; + dst->next(); + } + CORBA::Any_var structany=dst->to_any(); + dst->destroy(); + + /* + for(int i=0;imemberName(i); + //TypeCode* tm=tst->memberType(i); + //do not test member presence : test has been done in ToYacs convertor + CORBA::Any* a=m[name]; + members[i].id=CORBA::string_dup(name); + members[i].value=*a; + //delete intermediate any + delete a; + } + */ + + + //DII invoke + CORBA::TypeCode_var tcout=orb->create_sequence_tc(0,content_type); + + CORBA::Request_var req = echoref->_request("echoStruct2"); + //CORBA::Request_var req = echoref->_request("echoObjectVec"); + CORBA::NVList_ptr arguments = req->arguments() ; + + arguments->add_value( "s1" , structany , CORBA::ARG_IN ) ; + //arguments->add_value( "s1" , seqany , CORBA::ARG_IN ) ; + + CORBA::Any out; + out.replace(ts, (void*) 0); + //out.replace(tcout, (void*) 0); + arguments->add_value( "s2" , out , CORBA::ARG_OUT ); + + req->set_return_type(CORBA::_tc_void); + //user exceptions + //req->exceptions()->add(eo::_tc_SALOME_Exception); + + req->invoke(); + CORBA::Exception *exc =req->env()->exception(); + if( exc ) + { + std::cerr << "The raised exception is of Type:" << exc->_name() << std::endl; + if(strcmp(exc->_name(),"MARSHAL") == 0) + { + const char* ms = ((CORBA::MARSHAL*)exc)->NP_minorString(); + if (ms) + std::cerr << "(CORBA::MARSHAL: minor = " << ms << ")" << std::endl; + } + } + + //DII on echoObj2 + std::cerr << "Before request" << std::endl; + req = echoref->_request("echoObj2"); + std::cerr << "After request" << std::endl; + req->add_in_arg() <<= Objref; + std::cerr << "After add_in_arg" << std::endl; + req->add_out_arg() <<= Objout; + std::cerr << "After add_out_arg" << std::endl; + req->set_return_type(CORBA::_tc_void); + std::cerr << "After set_return_type" << std::endl; + req->invoke(); + std::cerr << "After invoke" << std::endl; + exc =req->env()->exception(); + if( exc ) + { + std::cerr << "The raised exception is of Type:" << exc->_name() << std::endl; + } + //end of DII on echoObj2 + + //DII on echoObjVec + req = echoref->_request("echoObjVec"); + CORBA::Any *aAny = new CORBA::Any(); + *aAny <<= oob; + + CORBA::TypeCode_var any_tc2=aAny->type(); + CORBA::TypeCode_var tc2=orb->create_sequence_tc(0,any_tc2); + DynamicAny::DynAny_var dynany2 = dynFactory->create_dyn_any_from_type_code(tc2); + DynamicAny::DynSequence_var ds2 = DynamicAny::DynSequence::_narrow(dynany2); + ds2->set_length(2); + DynamicAny::DynAny_var temp=ds2->current_component(); + temp->from_any(*aAny); + ds2->next(); + temp=ds2->current_component(); + CORBA::Any *aAny2 = new CORBA::Any(); + *aAny2 <<= cob; + CORBA::Object_var zzobj ; + *aAny2 >>= CORBA::Any::to_object(zzobj) ; + temp->insert_reference(zzobj); + ds2->next(); + + CORBA::Any_var seqany2=ds2->to_any(); + ds2->destroy(); + + arguments = req->arguments() ; + arguments->add_value( "s1" , seqany2 , CORBA::ARG_IN ) ; + + CORBA::Any out2; + out2.replace(tc2, (void*) 0); + arguments->add_value( "s2" , out2 , CORBA::ARG_OUT ); + req->set_return_type(CORBA::_tc_void); + req->invoke(); + + CORBA::Exception *exc2 =req->env()->exception(); + if( exc2 ) + { + std::cerr << "The raised exception is of Type:" << exc2->_name() << std::endl; + if(strcmp(exc2->_name(),"MARSHAL") == 0) + { + const char* ms = ((CORBA::MARSHAL*)exc2)->NP_minorString(); + if (ms) + std::cerr << "(CORBA::MARSHAL: minor = " << ms << ")" << std::endl; + } + } + else + { + CORBA::Any *ob=arguments->item(1)->value(); + DynamicAny::DynAny_var dynany= dynFactory->create_dyn_any(*ob); + DynamicAny::DynSequence_ptr ds=DynamicAny::DynSequence::_narrow(dynany); + DynamicAny::AnySeq_var as=ds->get_elements(); + int length=as->length(); + DEBTRACE(length); + for(int i=0;iid()); + eo::Obj_ptr xobj; + as[i] >>= xobj; + DEBTRACE(xobj->_PD_repoId); + xobj->echoLong(12); + }; + } + + //end of DII on echoObjVec + + // Delete allocated objects to remove memory leaks (valgrind tests) + + orb->destroy(); + } + catch(DynamicAny::DynAny::TypeMismatch& ex) + { + std::cerr << "Caught a DynamicAny::DynAny::TypeMismatch exception" << std::endl; } - Dref->echoLong2(10); - - eo::D_var dout; - echoref->echoD(Dref,dout); - std::cerr << dout->echoLong2(10) << std::endl; - - eo::D_var ddout; - echoref->echoD(dout,ddout); - std::cerr << dout->echoLong2(10) << std::endl; - - CORBA::Object_var oob = orb->string_to_object("corbaname:rir:#test.my_context/Obj.Object"); - eo::Obj_var Objref = eo::Obj::_narrow(oob); - Objref->echoLong(10); - eo::Obj_var Objout; - echoref->echoObj2(Objref,Objout); - std::cerr << Objout->echoLong(10) << std::endl; - - CORBA::Object_var cob = orb->string_to_object("corbaname:rir:#test.my_context/C.Object"); - eo::C_var Cref = eo::C::_narrow(cob); - eo::C_var Cout; - echoref->echoC(Cref,Cout); - - echoref->echoObj2(Cref,Objout); - //echoref->echoC(Cref,Objout); compilation impossible - //echoref->echoObj2(Cref,Cout); compilation impossible - //echoref->echoC(Objref,Cout); compilation impossible - - orb->destroy(); - } - catch(CORBA::COMM_FAILURE& ex) { - std::cerr << "Caught system exception COMM_FAILURE -- unable to contact the " - << "object." << std::endl; - } - catch(CORBA::SystemException&) { + catch(DynamicAny::DynAny::InvalidValue& ex) + { + std::cerr << "Caught a DynamicAny::DynAny::InvalidValue exception" << std::endl; + } + catch(CORBA::COMM_FAILURE& ex) + { + std::cerr << "Caught system exception COMM_FAILURE -- unable to contact the object." << std::endl; + } + catch(CORBA::SystemException&) + { std::cerr << "Caught a CORBA::SystemException." << std::endl; - } - catch(CORBA::Exception&) { + } + catch(CORBA::Exception&) + { std::cerr << "Caught CORBA::Exception." << std::endl; - } - catch(omniORB::fatalException& fe) { + } + catch(omniORB::fatalException& fe) + { std::cerr << "Caught omniORB::fatalException:" << std::endl; std::cerr << " file: " << fe.file() << std::endl; std::cerr << " line: " << fe.line() << std::endl; std::cerr << " mesg: " << fe.errmsg() << std::endl; - } - catch(...) { + } + catch(...) + { std::cerr << "Caught unknown exception." << std::endl; - } + } return 0; } diff --git a/src/runtime/Test/runtimeTest.cxx b/src/runtime/Test/runtimeTest.cxx index 46844d343..878044852 100644 --- a/src/runtime/Test/runtimeTest.cxx +++ b/src/runtime/Test/runtimeTest.cxx @@ -67,7 +67,7 @@ void RuntimeTest::setUp() if (_ltc.size() == 0) { _ltc.push_back((TypeCodeObjref *)_tc_obj); - _tc_C = TypeCode::interfaceTc("eo:C","C",_ltc); + _tc_C = TypeCode::interfaceTc("IDL:eo/C:1.0","C",_ltc); _tc_seqC = TypeCode::sequenceTc("eo:seqC","seqC",_tc_C); } } @@ -205,7 +205,7 @@ void RuntimeTest::createBloc() bloc->edAddChild(_nodeMap["Node_0"]); bloc->edAddChild(_nodeMap["Node_1"]); { - set setelem = bloc->getRecursiveConstituents(); + list setelem = bloc->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 2); } } @@ -248,9 +248,9 @@ void RuntimeTest::createRecursiveBlocs() } { - set setelem = _blocMap["Bloc_2"]->getRecursiveConstituents(); + list setelem = _blocMap["Bloc_2"]->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == 4); - for (set::iterator it=setelem.begin(); it!=setelem.end(); it++) + for (list::iterator it=setelem.begin(); it!=setelem.end(); it++) { DEBTRACE(" elem name = " << (*it)->getName()); } @@ -729,7 +729,7 @@ void RuntimeTest::createBloc2() bloc->edAddChild(_nodeMap[sn]); } { - set setelem = bloc->getRecursiveConstituents(); + list setelem = bloc->getRecursiveConstituents(); CPPUNIT_ASSERT(setelem.size() == _inode - 10); } } @@ -1496,7 +1496,6 @@ void RuntimeTest::executeCppNode() DEBTRACE("execute a CppNode with an external C++ implementation (in a dynamic library)"); - setenv("TESTCOMPONENT_ROOT_DIR", LOCATION, 1); node = _myRuntime->createCompoNode("Cpp", "test"); CppComponent * C = new CppComponent("TestComponent"); node->setComponent(C); @@ -1532,7 +1531,6 @@ void RuntimeTest::executeCppNode() void RuntimeTest::createGraphWithCppNodes() { - setenv("TESTCOMPONENT_ROOT_DIR", LOCATION, 1); ElementaryNode * n1, * n2; InputPort *in1, *in2; OutputPort *out1, *out2; diff --git a/src/runtime/Test/runtimeTest.sh b/src/runtime/Test/runtimeTest.sh index ce2bf720c..cc8c9247f 100644 --- a/src/runtime/Test/runtimeTest.sh +++ b/src/runtime/Test/runtimeTest.sh @@ -23,10 +23,20 @@ omniNames -start 2910 & pidomni=$! echo $pidomni +#wait enough time to let omniNames start +sleep 2 + ./echoSrv & pidecho=$! echo $pidecho +mkdir -p lib/salome +cp .libs/libTestComponentLocal.so lib/salome +export TESTCOMPONENT_ROOT_DIR=`pwd` + +#wait enough time to let echoSrv start and register +sleep 2 + ./TestRuntime ret=$? diff --git a/src/runtime/TypeConversions.cxx b/src/runtime/TypeConversions.cxx index c51ca9ae2..799f70bad 100644 --- a/src/runtime/TypeConversions.cxx +++ b/src/runtime/TypeConversions.cxx @@ -10,8 +10,10 @@ #include "TypeConversions.hxx" #include "ConversionException.hxx" #include "RuntimeSALOME.hxx" +#include "Salome_file_i.hxx" #include "TypeCode.hxx" #include "Cstr2d.hxx" +#include "SALOME_GenericObj.hh" #include #include @@ -25,6 +27,24 @@ namespace YACS { namespace ENGINE { + std::string getImplName(ImplType impl) + { + switch(impl) + { + case CORBAImpl: + return "CORBA"; + case PYTHONImpl: + return "PYTHON"; + case NEUTRALImpl: + return "NEUTRAL"; + case XMLImpl: + return "XML"; + case CPPImpl: + return "CPP"; + default: + return "UNKNOWN"; + } + } /* * Functions to return a CORBA TypeCode equivalent to a YACS TypeCode */ @@ -216,7 +236,7 @@ namespace YACS { if(t1->kind() == Struct) { - if( t1->isA(t2->id()) ) + if( t1->isA(t2) ) return 1; } return 0; @@ -672,8 +692,8 @@ namespace YACS else { stringstream msg; - msg << "Problem in Python to xml conversion: kind= " << t->kind() ; - msg << " : " << __FILE__ << ":" << __LINE__; + msg << "Not a python boolean. kind=" << t->kind() ; + msg << " ( " << __FILE__ << ":" << __LINE__ << ")"; throw YACS::ENGINE::ConversionException(msg.str()); } return l; @@ -690,6 +710,11 @@ namespace YACS return PyString_AS_STRING(o); } PyObject *pystring=PyObject_CallMethod(getSALOMERuntime()->getPyOrb(),"object_to_string","O",o); + if(pystring==NULL) + { + PyErr_Print(); + throw YACS::ENGINE::ConversionException("Problem in convertToYacsObjref& v) { + if(!PySequence_Check(o)) + { + stringstream msg; + msg << "Problem in conversion: the python object is not a sequence " << std::endl; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw YACS::ENGINE::ConversionException(msg.str()); + } int length=PySequence_Size(o); DEBTRACE("length: " << length ); v.resize(length); @@ -798,10 +830,7 @@ namespace YACS { static inline PyObject* convert(const TypeCode *t,std::string& o) { - std::string::size_type pos=o.find_first_of(":"); - std::string prefix=o.substr(0,pos); - DEBTRACE(prefix); - if(prefix == "file") + if(t->isA(Runtime::_tc_file)) { //It's an objref file. Convert it specially return PyString_FromString(o.c_str()); @@ -841,12 +870,46 @@ namespace YACS msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw YACS::ENGINE::ConversionException(msg.str()); } - //hold_lock is true: caller is supposed to hold the GIL. - //omniorb will not take the GIL #ifdef REFCNT DEBTRACE("obref refCount: " << obref->_PR_getobj()->pd_refCount); #endif +#ifdef _DEVDEBUG_ + std::cerr << "_PD_repoId: " << obref->_PD_repoId << std::endl; + std::cerr << "_mostDerivedRepoId: " << obref->_PR_getobj()->_mostDerivedRepoId() << std::endl; +#endif + + //hold_lock is true: caller is supposed to hold the GIL. + //omniorb will not take the GIL PyObject* ob= getSALOMERuntime()->getApi()->cxxObjRefToPyObjRef(obref, 1); + +#ifdef _DEVDEBUG_ + PyObject_Print(ob,stderr,Py_PRINT_RAW); + std::cerr << std::endl; + std::cerr << "obref is a generic: " << obref->_is_a("IDL:SALOME/GenericObj:1.0") << std::endl; + PyObject_Print(getSALOMERuntime()->get_omnipy(),stderr,Py_PRINT_RAW); + std::cerr << std::endl; +#endif + + //ob is a CORBA::Object. Try to convert it to more specific type SALOME/GenericObj + if(obref->_is_a("IDL:SALOME/GenericObj:1.0")) + { + PyObject *result = PyObject_CallMethod(getSALOMERuntime()->get_omnipy(), "narrow", "Osi",ob,"IDL:SALOME/GenericObj:1.0",1); + if(result==NULL) + PyErr_Clear();//Exception during narrow. Keep ob + else if(result==Py_None) + Py_DECREF(result); //Can't narrow. Keep ob + else + { + //Can narrow. Keep result +#ifdef _DEVDEBUG_ + PyObject_Print(result,stderr,Py_PRINT_RAW); + std::cerr << std::endl; +#endif + Py_DECREF(ob); + ob=result; + } + } + #ifdef REFCNT DEBTRACE("obref refCount: " << obref->_PR_getobj()->pd_refCount); #endif @@ -905,7 +968,7 @@ namespace YACS { static inline double convert(const TypeCode *t,xmlDocPtr doc,xmlNodePtr cur) { - double d; + double d=0; cur = cur->xmlChildrenNode; while (cur != NULL) { @@ -914,9 +977,16 @@ namespace YACS //wait a double, got a double xmlChar * s = NULL; s = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - DEBTRACE( "convertToYacsDouble " << (const char *)s ); - d=Cstr2d((const char *)s); - xmlFree(s); + if (s) + { + DEBTRACE( "convertToYacsDouble " << (const char *)s ); + d=Cstr2d((const char *)s); + xmlFree(s); + } + else + { + DEBTRACE("############### workaround to improve..."); + } return d; } else if ((!xmlStrcmp(cur->name, (const xmlChar *)"int"))) @@ -924,16 +994,23 @@ namespace YACS //wait a double, got an int xmlChar * s = NULL; s = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - DEBTRACE( "convertToYacsDouble " << (const char *)s ); - d=Cstr2d((const char *)s); - xmlFree(s); + if (s) + { + DEBTRACE( "convertToYacsDouble " << (const char *)s ); + d=Cstr2d((const char *)s); + xmlFree(s); + } + else + { + DEBTRACE("############### workaround to improve..."); + } return d; } cur = cur->next; } stringstream msg; - msg << "Problem in Xml to TOUT conversion: kind= " << t->kind() ; - msg << " : " << __FILE__ << ":" << __LINE__; + msg << "Problem in conversion from Xml to " << getImplName(IMPLOUT) << " with type: " << t->id() ; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw YACS::ENGINE::ConversionException(msg.str()); } }; @@ -942,25 +1019,31 @@ namespace YACS { static inline long convert(const TypeCode *t,xmlDocPtr doc,xmlNodePtr cur) { - long d; + long d=0; cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *)"int"))) { - //wait a double, got an int xmlChar * s = NULL; s = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - DEBTRACE( "convertToYacsInt " << (const char *)s ); - d=atol((const char *)s); - xmlFree(s); + if (s) + { + DEBTRACE( "convertToYacsInt " << (const char *)s ); + d=atol((const char *)s); + xmlFree(s); + } + else + { + DEBTRACE("############### workaround to improve..."); + } return d; } cur = cur->next; } stringstream msg; - msg << "Problem in Xml to TOUT conversion: kind= " << t->kind() ; - msg << " : " << __FILE__ << ":" << __LINE__; + msg << "Problem in conversion from Xml to " << getImplName(IMPLOUT) << " with type: " << t->id() ; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw YACS::ENGINE::ConversionException(msg.str()); } }; @@ -986,8 +1069,8 @@ namespace YACS cur = cur->next; } stringstream msg; - msg << "Problem in Xml to TOUT conversion: kind= " << t->kind() ; - msg << " : " << __FILE__ << ":" << __LINE__; + msg << "Problem in conversion from Xml to " << getImplName(IMPLOUT) << " with type: " << t->id() ; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw YACS::ENGINE::ConversionException(msg.str()); } }; @@ -1004,16 +1087,24 @@ namespace YACS //wait a boolean, got a boolean xmlChar * s = NULL; s = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - DEBTRACE( "convertToYacsBool " << (const char *)s ); - bool ob=atoi((const char*)s)!=0; - xmlFree(s); + bool ob =false; + if (s) + { + DEBTRACE( "convertToYacsBool " << (const char *)s ); + ob=atoi((const char*)s)!=0; + xmlFree(s); + } + else + { + DEBTRACE("############### workaround to improve..."); + } return ob; } cur = cur->next; } stringstream msg; - msg << "Problem in Xml to TOUT conversion: kind= " << t->kind() ; - msg << " : " << __FILE__ << ":" << __LINE__; + msg << "Problem in conversion from Xml to " << getImplName(IMPLOUT) << " with type: " << t->id() ; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw YACS::ENGINE::ConversionException(msg.str()); } }; @@ -1029,16 +1120,24 @@ namespace YACS { //we wait a objref, we have got a objref xmlChar * s = NULL; + std::string mystr = ""; s = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); - DEBTRACE( "convertToYacsObjref " << (const char *)s ); - std::string mystr((const char *)s); - xmlFree(s); + if (s) + { + DEBTRACE( "convertToYacsObjref " << (const char *)s ); + mystr = (const char *)s; + xmlFree(s); + } + else + { + DEBTRACE("############### workaround to improve..."); + } return mystr; } cur = cur->next; } stringstream msg; - msg << "Problem in conversion: a objref is expected " ; + msg << "Problem in conversion from Xml to " << getImplName(IMPLOUT) << " with type: " << t->id() ; msg << " (" << __FILE__ << ":" << __LINE__ << ")"; throw YACS::ENGINE::ConversionException(msg.str()); } @@ -1261,7 +1360,12 @@ namespace YACS { static inline long convert(const TypeCode *t,YACS::ENGINE::Any* o,void*) { - return o->getIntValue(); + if(o->getType()->kind()==Int) + return o->getIntValue(); + stringstream msg; + msg << "Problem in conversion: a int is expected " ; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw YACS::ENGINE::ConversionException(msg.str()); } }; template @@ -1269,7 +1373,12 @@ namespace YACS { static inline std::string convert(const TypeCode *t,YACS::ENGINE::Any* o,void*) { - return o->getStringValue(); + if(o->getType()->kind()==String) + return o->getStringValue(); + stringstream msg; + msg << "Problem in conversion: a string is expected " ; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw YACS::ENGINE::ConversionException(msg.str()); } }; template @@ -1284,6 +1393,7 @@ namespace YACS stringstream msg; msg << "Problem in conversion: a bool or int is expected " ; msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw YACS::ENGINE::ConversionException(msg.str()); } }; template @@ -1291,7 +1401,12 @@ namespace YACS { static inline std::string convert(const TypeCode *t,YACS::ENGINE::Any* o,void*) { - return o->getStringValue(); + if(o->getType()->kind()==String) + return o->getStringValue(); + stringstream msg; + msg << "Problem in conversion: a objref(string) is expected " ; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw YACS::ENGINE::ConversionException(msg.str()); } }; template @@ -1412,8 +1527,12 @@ namespace YACS static inline long convert(const TypeCode *t,CORBA::Any* o,void*) { CORBA::Long d; - *o >>= d; - return d; + if(*o >>= d) + return d; + stringstream msg; + msg << "Problem in CORBA to TOUT conversion: kind= " << t->kind() ; + msg << " : " << __FILE__ << ":" << __LINE__; + throw YACS::ENGINE::ConversionException(msg.str()); } }; template @@ -1422,8 +1541,12 @@ namespace YACS static inline std::string convert(const TypeCode *t,CORBA::Any* o,void*) { const char *s; - *o >>=s; - return s; + if(*o >>=s) + return s; + stringstream msg; + msg << "Problem in CORBA to TOUT conversion: kind= " << t->kind() ; + msg << " : " << __FILE__ << ":" << __LINE__; + throw YACS::ENGINE::ConversionException(msg.str()); } }; template @@ -1445,10 +1568,26 @@ namespace YACS { static inline std::string convert(const TypeCode *t,CORBA::Any* o,void*) { - CORBA::Object_var ObjRef ; - *o >>= (CORBA::Any::to_object ) ObjRef ; - CORBA::String_var objref = getSALOMERuntime()->getOrb()->object_to_string(ObjRef); - return (char *)objref; + char file[]="/tmp/XXXXXX"; + if(t->isA(Runtime::_tc_file)) + { + Engines::Salome_file_ptr sf; + *o >>= sf; + Salome_file_i* f=new Salome_file_i(); + mkstemp(file); + f->setDistributedFile(file); + f->connect(sf); + f->recvFiles(); + delete f; + return file; + } + else + { + CORBA::Object_var ObjRef ; + *o >>= CORBA::Any::to_object(ObjRef) ; + CORBA::String_var objref = getSALOMERuntime()->getOrb()->object_to_string(ObjRef); + return (char *)objref; + } } }; template @@ -1574,17 +1713,40 @@ namespace YACS { static inline CORBA::Any* convert(const TypeCode *t,std::string& o) { - /* - std::string::size_type pos=o.find_first_of(":"); - std::string prefix=o.substr(0,pos); - DEBTRACE(prefix); - if(prefix == "file") + CORBA::Object_var obref; + if(t->isA(Runtime::_tc_file)) { //It's an objref file. Convert it specially + Salome_file_i* aSalome_file = new Salome_file_i(); + try + { + aSalome_file->setLocalFile(o.c_str()); + obref = aSalome_file->_this(); + aSalome_file->_remove_ref(); + } + catch (const SALOME::SALOME_Exception& e) + { + stringstream msg; + msg << e.details.text; + msg << " : " << __FILE__ << ":" << __LINE__; + throw YACS::ENGINE::ConversionException(msg.str()); + } + } + else + { + try + { + obref=getSALOMERuntime()->getOrb()->string_to_object(o.c_str()); + } + catch(CORBA::Exception& ex) + { + throw ConversionException("Can't get reference to object"); + } + if( CORBA::is_nil(obref) ) + { + throw ConversionException("Can't get reference to object"); + } } - */ - CORBA::Object_var obref = - getSALOMERuntime()->getOrb()->string_to_object(o.c_str()); #ifdef REFCNT DEBTRACE("ObjRef refCount: " << obref->_PR_getobj()->pd_refCount); #endif @@ -1602,52 +1764,40 @@ namespace YACS { static inline CORBA::Any* convert(const TypeCode *t,std::vector& v) { - CORBA::Any *any; - CORBA::TypeCode_ptr seqTC; + CORBA::ORB_ptr orb=getSALOMERuntime()->getOrb(); + std::vector::const_iterator iter; - //the equivalent CORBA TypeCode - seqTC=getCorbaTC(t); -#ifdef REFCNT - DEBTRACE("refcount CORBA seqTC: " << ((omni::TypeCode_base*)seqTC)->pd_ref_count); -#endif - DynamicAny::DynAny_ptr dynany = - getSALOMERuntime()->getDynFactory()->create_dyn_any_from_type_code(seqTC); - CORBA::release(seqTC); - DynamicAny::DynSequence_ptr ds = - DynamicAny::DynSequence::_narrow(dynany); - CORBA::release(dynany); + // Build an Any from vector v + int isObjref=0; + if(t->contentType()->kind() == Objref) + isObjref=1; + + CORBA::TypeCode_var tc=getCorbaTC(t); + + DynamicAny::DynAny_var dynany=getSALOMERuntime()->getDynFactory()->create_dyn_any_from_type_code(tc); + DynamicAny::DynSequence_var ds = DynamicAny::DynSequence::_narrow(dynany); + ds->set_length(v.size()); - std::vector::const_iterator iter; - DynamicAny::AnySeq as ; - as.length(v.size()); - int i=0; for(iter=v.begin();iter!=v.end();iter++) { - //Can we avoid making a copy ? + DynamicAny::DynAny_var temp=ds->current_component(); CORBA::Any* a=*iter; - as[i]=*a; - i++; + if(isObjref) + { + CORBA::Object_var zzobj ; + *a >>= CORBA::Any::to_object(zzobj) ; + temp->insert_reference(zzobj); + } + else + temp->from_any(*a); + //delete intermediate any delete a; + ds->next(); } - try - { - ds->set_elements(as); - } - catch(DynamicAny::DynAny::TypeMismatch& ex) - { - throw YACS::ENGINE::ConversionException("type mismatch"); - } - catch(DynamicAny::DynAny::InvalidValue& ex) - { - throw YACS::ENGINE::ConversionException("invalid value"); - } - any=ds->to_any(); + + CORBA::Any *any=ds->to_any(); ds->destroy(); - CORBA::release(ds); -#ifdef REFCNT - DEBTRACE("refcount CORBA seqTC: " << ((omni::TypeCode_base*)seqTC)->pd_ref_count); -#endif return any; } }; @@ -1656,69 +1806,41 @@ namespace YACS { static inline CORBA::Any* convert(const TypeCode *t,std::map& m) { - CORBA::Any *any; - CORBA::TypeCode_ptr structTC; + CORBA::ORB_ptr orb=getSALOMERuntime()->getOrb(); - //the equivalent CORBA TypeCode - structTC=getCorbaTC(t); -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif YACS::ENGINE::TypeCodeStruct* tst=(YACS::ENGINE::TypeCodeStruct*)t; int nMember=tst->memberCount(); DEBTRACE("nMember="<getDynFactory()->create_dyn_any_from_type_code(structTC); -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif - CORBA::release(structTC); -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif - DynamicAny::DynStruct_ptr ds=DynamicAny::DynStruct::_narrow(da); - CORBA::release(da); -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif - DynamicAny::NameValuePairSeq members; - members.length(nMember); + + CORBA::StructMemberSeq mseq; + mseq.length(nMember); for(int i=0;imemberName(i); + if(m.count(name) !=0) + { + mseq[i].type=m[name]->type(); + } + } + CORBA::TypeCode_var tc= orb->create_struct_tc("","",mseq); + DynamicAny::DynAny_var dynany=getSALOMERuntime()->getDynFactory()->create_dyn_any_from_type_code(tc); + DynamicAny::DynStruct_var ds = DynamicAny::DynStruct::_narrow(dynany); + + for(int i=0;icurrent_component(); const char * name=tst->memberName(i); DEBTRACE("Member name="<memberType(i); //do not test member presence : test has been done in ToYacs convertor CORBA::Any* a=m[name]; - members[i].id=CORBA::string_dup(name); - members[i].value=*a; + temp->from_any(*a); //delete intermediate any delete a; + ds->next(); } -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif - ds->set_members(members); -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif - any=ds->to_any(); -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif + CORBA::Any *any=ds->to_any(); ds->destroy(); - CORBA::release(ds); -#ifdef REFCNT - DEBTRACE("refcount CORBA structTC: " << ((omni::TypeCode_base*)structTC)->pd_ref_count); - DEBTRACE("refcount CORBA tc_double: " << ((omni::TypeCode_base*)CORBA::_tc_double)->pd_ref_count); -#endif + return any; } }; diff --git a/src/runtime/TypeConversions.hxx b/src/runtime/TypeConversions.hxx index e04f1b9e8..0a316a746 100644 --- a/src/runtime/TypeConversions.hxx +++ b/src/runtime/TypeConversions.hxx @@ -5,7 +5,7 @@ #include #include #include -#include "Any.hxx" +#include namespace YACS { @@ -22,6 +22,7 @@ namespace YACS } ImplType; class TypeCode; + class Any; CORBA::TypeCode_ptr getCorbaTC(const TypeCode *t); diff --git a/src/runtime/VisitorSaveSalomeSchema.cxx b/src/runtime/VisitorSaveSalomeSchema.cxx new file mode 100644 index 000000000..8ad231d4f --- /dev/null +++ b/src/runtime/VisitorSaveSalomeSchema.cxx @@ -0,0 +1,161 @@ + +#include "VisitorSaveSalomeSchema.hxx" +#include "DataNode.hxx" +#include "PresetNode.hxx" +#include "OutNode.hxx" +#include "StudyNodes.hxx" +#include "ComposedNode.hxx" +#include "PresetPorts.hxx" +#include "StudyPorts.hxx" +#include "TypeCode.hxx" + +#include +#include +#include +#include + + +using namespace YACS::ENGINE; +using namespace std; + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +VisitorSaveSalomeSchema::VisitorSaveSalomeSchema(ComposedNode *root) + : VisitorSaveSchema(root) +{ +} + +VisitorSaveSalomeSchema::~VisitorSaveSalomeSchema() +{ +} + +void VisitorSaveSalomeSchema::visitPresetNode(DataNode *node) +{ + DEBTRACE("START visitPresetNode " << _root->getChildName(node)); + beginCase(node); + int depth = depthNode(node); + _out << indent(depth) << "getName() << "\""; + string ref = node->getRef(); + if (!ref.empty()) _out << " ref=\"" << ref << "\""; + if (node->getState() == YACS::DISABLED) + _out << " state=\"disabled\">" << endl; + else + _out << ">" << endl; + writeProperties(node); + writeDataNodeParameters(node); + _out << indent(depth) << "" << endl; + endCase(node); + DEBTRACE("END visitPresetNode " << _root->getChildName(node)); +} + +void VisitorSaveSalomeSchema::visitOutNode(DataNode *node) +{ + DEBTRACE("START visitOutNode " << _root->getChildName(node)); + beginCase(node); + int depth = depthNode(node); + _out << indent(depth) << "getName() << "\""; + string ref = node->getRef(); + if (!ref.empty()) _out << " ref=\"" << ref << "\""; + if (node->getState() == YACS::DISABLED) + _out << " state=\"disabled\">" << endl; + else + _out << ">" << endl; + writeProperties(node); + writeOutNodeParameters(node); + _out << indent(depth) << "" << endl; + endCase(node); + DEBTRACE("END visitOutNode " << _root->getChildName(node)); +} + +void VisitorSaveSalomeSchema::visitStudyInNode(DataNode *node) +{ + DEBTRACE("START visitStudyInNode " << _root->getChildName(node)); + beginCase(node); + int depth = depthNode(node); + _out << indent(depth) << "getName() << "\" kind=\"study\""; + string ref = node->getRef(); + if (!ref.empty()) _out << " ref=\"" << ref << "\""; + if (node->getState() == YACS::DISABLED) + _out << " state=\"disabled\">" << endl; + else + _out << ">" << endl; + writeProperties(node); + writeStudyInNodeParameters(node); + _out << indent(depth) << "" << endl; + endCase(node); + DEBTRACE("END visitStudyInNode " << _root->getChildName(node)); +} + +void VisitorSaveSalomeSchema::visitStudyOutNode(DataNode *node) +{ + DEBTRACE("START visitStudyOutNode " << _root->getChildName(node)); + beginCase(node); + int depth = depthNode(node); + _out << indent(depth) << "getName() << "\" kind=\"study\""; + string ref = node->getRef(); + if (!ref.empty()) _out << " ref=\"" << ref << "\""; + if (node->getState() == YACS::DISABLED) + _out << " state=\"disabled\">" << endl; + else + _out << ">" << endl; + writeProperties(node); + writeStudyOutNodeParameters(node); + _out << indent(depth) << "" << endl; + endCase(node); + DEBTRACE("END visitStudyOutNode " << _root->getChildName(node)); +} + +void VisitorSaveSalomeSchema::writeDataNodeParameters(DataNode *node) +{ + int depth = depthNode(node)+1; + list listOfOutputPorts = node->getSetOfOutputPort(); + for (list::iterator it = listOfOutputPorts.begin(); it != listOfOutputPorts.end(); ++it) + { + _out << indent(depth) << "getName() << "\" type=\"" + << (*it)->edGetType()->name() << "\">" << endl; + OutputPresetPort *outp = dynamic_cast(*it); + assert(outp); + _out << indent(depth+1) << outp->getData(); + _out << indent(depth) << "" << endl; + } +} + +void VisitorSaveSalomeSchema::writeStudyInNodeParameters(DataNode *node) +{ + int depth = depthNode(node)+1; + list listOfOutputPorts = node->getSetOfOutputPort(); + for (list::iterator it = listOfOutputPorts.begin(); it != listOfOutputPorts.end(); ++it) + { + _out << indent(depth) << "getName() << "\" type=\"" + << (*it)->edGetType()->name() << "\" ref=\""; + OutputStudyPort *outp = dynamic_cast(*it); + assert(outp); + _out << outp->getData() << "\"/>" << endl; + } +} + +void VisitorSaveSalomeSchema::writeOutNodeParameters(DataNode *node) +{ + int depth = depthNode(node)+1; + list listOfInputPorts = node->getSetOfInputPort(); + for (list::iterator it = listOfInputPorts.begin(); it != listOfInputPorts.end(); ++it) + { + _out << indent(depth) << "getName() << "\" type=\"" + << (*it)->edGetType()->name() << "\"/>" << endl; + } +} + +void VisitorSaveSalomeSchema::writeStudyOutNodeParameters(DataNode *node) +{ + int depth = depthNode(node)+1; + list listOfInputPorts = node->getSetOfInputPort(); + for (list::iterator it = listOfInputPorts.begin(); it != listOfInputPorts.end(); ++it) + { + _out << indent(depth) << "getName() << "\" type=\"" + << (*it)->edGetType()->name() << "\" ref=\""; + InputStudyPort *inp = dynamic_cast(*it); + assert(inp); + _out << inp->getData() << "\"/>" << endl; + } +} diff --git a/src/runtime/VisitorSaveSalomeSchema.hxx b/src/runtime/VisitorSaveSalomeSchema.hxx new file mode 100644 index 000000000..510569213 --- /dev/null +++ b/src/runtime/VisitorSaveSalomeSchema.hxx @@ -0,0 +1,28 @@ +#ifndef __VISITORSAVESALOMESCHEMA_HXX__ +#define __VISITORSAVESALOMESCHEMA_HXX__ + +#include "VisitorSaveSchema.hxx" + +namespace YACS +{ + namespace ENGINE + { + class VisitorSaveSalomeSchema: public VisitorSaveSchema + { + public: + VisitorSaveSalomeSchema(ComposedNode *root); + virtual ~VisitorSaveSalomeSchema(); + virtual void visitPresetNode(DataNode *node); + virtual void visitOutNode(DataNode *node); + virtual void visitStudyInNode(DataNode *node); + virtual void visitStudyOutNode(DataNode *node); + protected: + virtual void writeDataNodeParameters(DataNode *node); + virtual void writeStudyInNodeParameters(DataNode *node); + virtual void writeOutNodeParameters(DataNode *node); + virtual void writeStudyOutNodeParameters(DataNode *node); + }; + } +} + +#endif diff --git a/src/runtime/XMLCORBAConv.cxx b/src/runtime/XMLCORBAConv.cxx index 608d8d66e..1d41720b6 100644 --- a/src/runtime/XMLCORBAConv.cxx +++ b/src/runtime/XMLCORBAConv.cxx @@ -2,6 +2,8 @@ #include "TypeConversions.hxx" #include "XMLCORBAConv.hxx" #include "CORBAXMLConv.hxx" +#include "CORBAPorts.hxx" +#include "TypeCode.hxx" #include #include @@ -33,7 +35,7 @@ void XmlCorba::put(const char *data) throw(ConversionException) DEBTRACE(data); xmlDocPtr doc; xmlNodePtr cur; - CORBA::Any *a; + CORBA::Any *a=NULL; doc = xmlParseMemory(data, strlen(data)); if (doc == NULL ) @@ -76,6 +78,14 @@ void XmlCorba::put(const char *data) throw(ConversionException) cur = cur->next; } xmlFreeDoc(doc); + if(a==NULL) + { + stringstream msg; + msg << "Problem in conversion: incorrect XML value"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw ConversionException(msg.str()); + } + //xmlCleanupParser(); _port->put(a); _port->setStringRef(data); diff --git a/src/runtime/XMLCORBAConv.hxx b/src/runtime/XMLCORBAConv.hxx index fd314c5c7..c6af8bae7 100644 --- a/src/runtime/XMLCORBAConv.hxx +++ b/src/runtime/XMLCORBAConv.hxx @@ -1,12 +1,14 @@ #ifndef __XMLCORBACONV_HXX__ #define __XMLCORBACONV_HXX__ -#include "CORBAPorts.hxx" +#include "InputPort.hxx" namespace YACS { namespace ENGINE { + class InputCorbaPort; + //Adaptator Ports Xml->Corba for several types class XmlCorba : public ProxyPort diff --git a/src/runtime/XMLCppConv.cxx b/src/runtime/XMLCppConv.cxx index 6fd7f7ddf..b51e7de8b 100644 --- a/src/runtime/XMLCppConv.cxx +++ b/src/runtime/XMLCppConv.cxx @@ -43,7 +43,7 @@ namespace YACS DEBTRACE("XmlCpp::put " << data); xmlDocPtr doc; xmlNodePtr cur; - Any *ob; + Any *ob=NULL; { doc = xmlParseMemory(data, strlen(data)); if (doc == NULL ) @@ -72,7 +72,13 @@ namespace YACS cur = cur->next; } xmlFreeDoc(doc); - //xmlCleanupParser(); + if(ob==NULL) + { + stringstream msg; + msg << "Problem in conversion: incorrect XML value"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw ConversionException(msg.str()); + } } _port->put(ob); ob->decrRef(); diff --git a/src/runtime/XMLNeutralConv.cxx b/src/runtime/XMLNeutralConv.cxx index e0d1f40fb..1caad739c 100644 --- a/src/runtime/XMLNeutralConv.cxx +++ b/src/runtime/XMLNeutralConv.cxx @@ -34,7 +34,7 @@ void XmlNeutral::put(const char *data) throw(ConversionException) DEBTRACE("XmlNeutral::put " << data); xmlDocPtr doc; xmlNodePtr cur; - YACS::ENGINE::Any *ob; + YACS::ENGINE::Any *ob=NULL; { doc = xmlParseMemory(data, strlen(data)); if (doc == NULL ) @@ -63,7 +63,13 @@ void XmlNeutral::put(const char *data) throw(ConversionException) cur = cur->next; } xmlFreeDoc(doc); - //xmlCleanupParser(); + if(ob==NULL) + { + stringstream msg; + msg << "Problem in conversion: incorrect XML value"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw ConversionException(msg.str()); + } } _port->put(ob); ob->decrRef(); diff --git a/src/runtime/XMLNode.cxx b/src/runtime/XMLNode.cxx index 6265b5eb6..275807e69 100644 --- a/src/runtime/XMLNode.cxx +++ b/src/runtime/XMLNode.cxx @@ -50,6 +50,11 @@ void XmlNode::setScript(const std::string& script) _script=script; } +std::string XmlNode::getScript() const +{ + return _script; +} + std::string XmlNode::getKind() const { return KIND; @@ -96,11 +101,12 @@ void XmlNode::execute() run << _ref << "> stdout 2>&1 " << std::endl; else run << "../"<<_ref << "> stdout 2>&1 " << std::endl; - run << "cat stdout" << std::endl; + //run << "cat stdout" << std::endl; run.close(); chmod(call.c_str(),00777); - int ret=system(call.c_str()); + std::string call2="/bin/sh "+call; + int ret=system(call2.c_str()); if(ret) { std::cerr << "Problem: " << ret << std::endl; diff --git a/src/runtime/XMLNode.hxx b/src/runtime/XMLNode.hxx index c88fe84ec..9ea695de6 100644 --- a/src/runtime/XMLNode.hxx +++ b/src/runtime/XMLNode.hxx @@ -19,6 +19,7 @@ namespace YACS virtual void load() { } virtual void setRef(const std::string& ref); virtual void setScript(const std::string& script); + virtual std::string getScript() const; virtual ServiceNode* createNode(const std::string& name) { throw Exception("not implemented"); } virtual std::string getKind() const; diff --git a/src/runtime/XMLPythonConv.cxx b/src/runtime/XMLPythonConv.cxx index 264c994f7..115d0ddc0 100644 --- a/src/runtime/XMLPythonConv.cxx +++ b/src/runtime/XMLPythonConv.cxx @@ -33,7 +33,7 @@ void XmlPython::put(const char *data) throw(ConversionException) DEBTRACE(data); xmlDocPtr doc; xmlNodePtr cur; - PyObject *ob; + PyObject *ob=NULL; { InterpreterUnlocker l; doc = xmlParseMemory(data, strlen(data)); @@ -63,6 +63,13 @@ void XmlPython::put(const char *data) throw(ConversionException) cur = cur->next; } xmlFreeDoc(doc); + if(ob==NULL) + { + stringstream msg; + msg << "Problem in conversion: incorrect XML value"; + msg << " (" << __FILE__ << ":" << __LINE__ << ")"; + throw ConversionException(msg.str()); + } // xmlCleanupParser(); #ifdef _DEVDEBUG_ PyObject_Print(ob,stderr,Py_PRINT_RAW); diff --git a/src/salomeloader/ElementPath.py b/src/salomeloader/ElementPath.py new file mode 100644 index 000000000..8d8d28df3 --- /dev/null +++ b/src/salomeloader/ElementPath.py @@ -0,0 +1,196 @@ +# +# ElementTree +# $Id$ +# +# limited xpath support for element trees +# +# history: +# 2003-05-23 fl created +# 2003-05-28 fl added support for // etc +# 2003-08-27 fl fixed parsing of periods in element names +# +# Copyright (c) 2003-2004 by Fredrik Lundh. All rights reserved. +# +# fredrik@pythonware.com +# http://www.pythonware.com +# +# -------------------------------------------------------------------- +# The ElementTree toolkit is +# +# Copyright (c) 1999-2004 by Fredrik Lundh +# +# By obtaining, using, and/or copying this software and/or its +# associated documentation, you agree that you have read, understood, +# and will comply with the following terms and conditions: +# +# Permission to use, copy, modify, and distribute this software and +# its associated documentation for any purpose and without fee is +# hereby granted, provided that the above copyright notice appears in +# all copies, and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Secret Labs AB or the author not be used in advertising or publicity +# pertaining to distribution of the software without specific, written +# prior permission. +# +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- +# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# -------------------------------------------------------------------- + +## +# Implementation module for XPath support. There's usually no reason +# to import this module directly; the ElementTree does this for +# you, if needed. +## + +import re + +xpath_tokenizer = re.compile( + "(::|\.\.|\(\)|[/.*:\[\]\(\)@=])|((?:\{[^}]+\})?[^/:\[\]\(\)@=\s]+)|\s+" + ).findall + +class xpath_descendant_or_self: + pass + +## +# Wrapper for a compiled XPath. + +class Path: + + ## + # Create an Path instance from an XPath expression. + + def __init__(self, path): + tokens = xpath_tokenizer(path) + # the current version supports 'path/path'-style expressions only + self.path = [] + self.tag = None + if tokens and tokens[0][0] == "/": + raise SyntaxError("cannot use absolute path on element") + while tokens: + op, tag = tokens.pop(0) + if tag or op == "*": + self.path.append(tag or op) + elif op == ".": + pass + elif op == "/": + self.path.append(xpath_descendant_or_self()) + continue + else: + raise SyntaxError("unsupported path syntax (%s)" % op) + if tokens: + op, tag = tokens.pop(0) + if op != "/": + raise SyntaxError( + "expected path separator (%s)" % (op or tag) + ) + if self.path and isinstance(self.path[-1], xpath_descendant_or_self): + raise SyntaxError("path cannot end with //") + if len(self.path) == 1 and isinstance(self.path[0], type("")): + self.tag = self.path[0] + + ## + # Find first matching object. + + def find(self, element): + tag = self.tag + if tag is None: + nodeset = self.findall(element) + if not nodeset: + return None + return nodeset[0] + for elem in element: + if elem.tag == tag: + return elem + return None + + ## + # Find text for first matching object. + + def findtext(self, element, default=None): + tag = self.tag + if tag is None: + nodeset = self.findall(element) + if not nodeset: + return default + return nodeset[0].text or "" + for elem in element: + if elem.tag == tag: + return elem.text or "" + return default + + ## + # Find all matching objects. + + def findall(self, element): + nodeset = [element] + index = 0 + while 1: + try: + path = self.path[index] + index = index + 1 + except IndexError: + return nodeset + set = [] + if isinstance(path, xpath_descendant_or_self): + try: + tag = self.path[index] + if not isinstance(tag, type("")): + tag = None + else: + index = index + 1 + except IndexError: + tag = None # invalid path + for node in nodeset: + new = list(node.getiterator(tag)) + if new and new[0] is node: + set.extend(new[1:]) + else: + set.extend(new) + else: + for node in nodeset: + for node in node: + if path == "*" or node.tag == path: + set.append(node) + if not set: + return [] + nodeset = set + +_cache = {} + +## +# (Internal) Compile path. + +def _compile(path): + p = _cache.get(path) + if p is not None: + return p + p = Path(path) + if len(_cache) >= 100: + _cache.clear() + _cache[path] = p + return p + +## +# Find first matching object. + +def find(element, path): + return _compile(path).find(element) + +## +# Find text for first matching object. + +def findtext(element, path, default=None): + return _compile(path).findtext(element, default) + +## +# Find all matching objects. + +def findall(element, path): + return _compile(path).findall(element) + diff --git a/src/salomeloader/ElementTree.py b/src/salomeloader/ElementTree.py new file mode 100644 index 000000000..8ea3c7979 --- /dev/null +++ b/src/salomeloader/ElementTree.py @@ -0,0 +1,1254 @@ +# +# ElementTree +# $Id$ +# +# light-weight XML support for Python 1.5.2 and later. +# +# history: +# 2001-10-20 fl created (from various sources) +# 2001-11-01 fl return root from parse method +# 2002-02-16 fl sort attributes in lexical order +# 2002-04-06 fl TreeBuilder refactoring, added PythonDoc markup +# 2002-05-01 fl finished TreeBuilder refactoring +# 2002-07-14 fl added basic namespace support to ElementTree.write +# 2002-07-25 fl added QName attribute support +# 2002-10-20 fl fixed encoding in write +# 2002-11-24 fl changed default encoding to ascii; fixed attribute encoding +# 2002-11-27 fl accept file objects or file names for parse/write +# 2002-12-04 fl moved XMLTreeBuilder back to this module +# 2003-01-11 fl fixed entity encoding glitch for us-ascii +# 2003-02-13 fl added XML literal factory +# 2003-02-21 fl added ProcessingInstruction/PI factory +# 2003-05-11 fl added tostring/fromstring helpers +# 2003-05-26 fl added ElementPath support +# 2003-07-05 fl added makeelement factory method +# 2003-07-28 fl added more well-known namespace prefixes +# 2003-08-15 fl fixed typo in ElementTree.findtext (Thomas Dartsch) +# 2003-09-04 fl fall back on emulator if ElementPath is not installed +# 2003-10-31 fl markup updates +# 2003-11-15 fl fixed nested namespace bug +# 2004-03-28 fl added XMLID helper +# 2004-06-02 fl added default support to findtext +# 2004-06-08 fl fixed encoding of non-ascii element/attribute names +# 2004-08-23 fl take advantage of post-2.1 expat features +# 2005-02-01 fl added iterparse implementation +# 2005-03-02 fl fixed iterparse support for pre-2.2 versions +# +# Copyright (c) 1999-2005 by Fredrik Lundh. All rights reserved. +# +# fredrik@pythonware.com +# http://www.pythonware.com +# +# -------------------------------------------------------------------- +# The ElementTree toolkit is +# +# Copyright (c) 1999-2005 by Fredrik Lundh +# +# By obtaining, using, and/or copying this software and/or its +# associated documentation, you agree that you have read, understood, +# and will comply with the following terms and conditions: +# +# Permission to use, copy, modify, and distribute this software and +# its associated documentation for any purpose and without fee is +# hereby granted, provided that the above copyright notice appears in +# all copies, and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Secret Labs AB or the author not be used in advertising or publicity +# pertaining to distribution of the software without specific, written +# prior permission. +# +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- +# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# -------------------------------------------------------------------- + +__all__ = [ + # public symbols + "Comment", + "dump", + "Element", "ElementTree", + "fromstring", + "iselement", "iterparse", + "parse", + "PI", "ProcessingInstruction", + "QName", + "SubElement", + "tostring", + "TreeBuilder", + "VERSION", "XML", + "XMLTreeBuilder", + ] + +## +# The Element type is a flexible container object, designed to +# store hierarchical data structures in memory. The type can be +# described as a cross between a list and a dictionary. +#

+# Each element has a number of properties associated with it: +#

    +#
  • a tag. This is a string identifying what kind of data +# this element represents (the element type, in other words).
  • +#
  • a number of attributes, stored in a Python dictionary.
  • +#
  • a text string.
  • +#
  • an optional tail string.
  • +#
  • a number of child elements, stored in a Python sequence
  • +#
+# +# To create an element instance, use the {@link #Element} or {@link +# #SubElement} factory functions. +#

+# The {@link #ElementTree} class can be used to wrap an element +# structure, and convert it from and to XML. +## + +import string, sys, re + +class _SimpleElementPath: + # emulate pre-1.2 find/findtext/findall behaviour + def find(self, element, tag): + for elem in element: + if elem.tag == tag: + return elem + return None + def findtext(self, element, tag, default=None): + for elem in element: + if elem.tag == tag: + return elem.text or "" + return default + def findall(self, element, tag): + if tag[:3] == ".//": + return element.getiterator(tag[3:]) + result = [] + for elem in element: + if elem.tag == tag: + result.append(elem) + return result + +try: + import ElementPath +except ImportError: + # FIXME: issue warning in this case? + ElementPath = _SimpleElementPath() + +# TODO: add support for custom namespace resolvers/default namespaces +# TODO: add improved support for incremental parsing + +VERSION = "1.2.6" + +## +# Internal element class. This class defines the Element interface, +# and provides a reference implementation of this interface. +#

+# You should not create instances of this class directly. Use the +# appropriate factory functions instead, such as {@link #Element} +# and {@link #SubElement}. +# +# @see Element +# @see SubElement +# @see Comment +# @see ProcessingInstruction + +class _ElementInterface: + # text...tail + + ## + # (Attribute) Element tag. + + tag = None + + ## + # (Attribute) Element attribute dictionary. Where possible, use + # {@link #_ElementInterface.get}, + # {@link #_ElementInterface.set}, + # {@link #_ElementInterface.keys}, and + # {@link #_ElementInterface.items} to access + # element attributes. + + attrib = None + + ## + # (Attribute) Text before first subelement. This is either a + # string or the value None, if there was no text. + + text = None + + ## + # (Attribute) Text after this element's end tag, but before the + # next sibling element's start tag. This is either a string or + # the value None, if there was no text. + + tail = None # text after end tag, if any + + def __init__(self, tag, attrib): + self.tag = tag + self.attrib = attrib + self._children = [] + + def __repr__(self): + return "" % (self.tag, id(self)) + + ## + # Creates a new element object of the same type as this element. + # + # @param tag Element tag. + # @param attrib Element attributes, given as a dictionary. + # @return A new element instance. + + def makeelement(self, tag, attrib): + return Element(tag, attrib) + + ## + # Returns the number of subelements. + # + # @return The number of subelements. + + def __len__(self): + return len(self._children) + + ## + # Returns the given subelement. + # + # @param index What subelement to return. + # @return The given subelement. + # @exception IndexError If the given element does not exist. + + def __getitem__(self, index): + return self._children[index] + + ## + # Replaces the given subelement. + # + # @param index What subelement to replace. + # @param element The new element value. + # @exception IndexError If the given element does not exist. + # @exception AssertionError If element is not a valid object. + + def __setitem__(self, index, element): + assert iselement(element) + self._children[index] = element + + ## + # Deletes the given subelement. + # + # @param index What subelement to delete. + # @exception IndexError If the given element does not exist. + + def __delitem__(self, index): + del self._children[index] + + ## + # Returns a list containing subelements in the given range. + # + # @param start The first subelement to return. + # @param stop The first subelement that shouldn't be returned. + # @return A sequence object containing subelements. + + def __getslice__(self, start, stop): + return self._children[start:stop] + + ## + # Replaces a number of subelements with elements from a sequence. + # + # @param start The first subelement to replace. + # @param stop The first subelement that shouldn't be replaced. + # @param elements A sequence object with zero or more elements. + # @exception AssertionError If a sequence member is not a valid object. + + def __setslice__(self, start, stop, elements): + for element in elements: + assert iselement(element) + self._children[start:stop] = list(elements) + + ## + # Deletes a number of subelements. + # + # @param start The first subelement to delete. + # @param stop The first subelement to leave in there. + + def __delslice__(self, start, stop): + del self._children[start:stop] + + ## + # Adds a subelement to the end of this element. + # + # @param element The element to add. + # @exception AssertionError If a sequence member is not a valid object. + + def append(self, element): + assert iselement(element) + self._children.append(element) + + ## + # Inserts a subelement at the given position in this element. + # + # @param index Where to insert the new subelement. + # @exception AssertionError If the element is not a valid object. + + def insert(self, index, element): + assert iselement(element) + self._children.insert(index, element) + + ## + # Removes a matching subelement. Unlike the find methods, + # this method compares elements based on identity, not on tag + # value or contents. + # + # @param element What element to remove. + # @exception ValueError If a matching element could not be found. + # @exception AssertionError If the element is not a valid object. + + def remove(self, element): + assert iselement(element) + self._children.remove(element) + + ## + # Returns all subelements. The elements are returned in document + # order. + # + # @return A list of subelements. + # @defreturn list of Element instances + + def getchildren(self): + return self._children + + ## + # Finds the first matching subelement, by tag name or path. + # + # @param path What element to look for. + # @return The first matching element, or None if no element was found. + # @defreturn Element or None + + def find(self, path): + return ElementPath.find(self, path) + + ## + # Finds text for the first matching subelement, by tag name or path. + # + # @param path What element to look for. + # @param default What to return if the element was not found. + # @return The text content of the first matching element, or the + # default value no element was found. Note that if the element + # has is found, but has no text content, this method returns an + # empty string. + # @defreturn string + + def findtext(self, path, default=None): + return ElementPath.findtext(self, path, default) + + ## + # Finds all matching subelements, by tag name or path. + # + # @param path What element to look for. + # @return A list or iterator containing all matching elements, + # in document order. + # @defreturn list of Element instances + + def findall(self, path): + return ElementPath.findall(self, path) + + ## + # Resets an element. This function removes all subelements, clears + # all attributes, and sets the text and tail attributes to None. + + def clear(self): + self.attrib.clear() + self._children = [] + self.text = self.tail = None + + ## + # Gets an element attribute. + # + # @param key What attribute to look for. + # @param default What to return if the attribute was not found. + # @return The attribute value, or the default value, if the + # attribute was not found. + # @defreturn string or None + + def get(self, key, default=None): + return self.attrib.get(key, default) + + ## + # Sets an element attribute. + # + # @param key What attribute to set. + # @param value The attribute value. + + def set(self, key, value): + self.attrib[key] = value + + ## + # Gets a list of attribute names. The names are returned in an + # arbitrary order (just like for an ordinary Python dictionary). + # + # @return A list of element attribute names. + # @defreturn list of strings + + def keys(self): + return self.attrib.keys() + + ## + # Gets element attributes, as a sequence. The attributes are + # returned in an arbitrary order. + # + # @return A list of (name, value) tuples for all attributes. + # @defreturn list of (string, string) tuples + + def items(self): + return self.attrib.items() + + ## + # Creates a tree iterator. The iterator loops over this element + # and all subelements, in document order, and returns all elements + # with a matching tag. + #

+ # If the tree structure is modified during iteration, the result + # is undefined. + # + # @param tag What tags to look for (default is to return all elements). + # @return A list or iterator containing all the matching elements. + # @defreturn list or iterator + + def getiterator(self, tag=None): + nodes = [] + if tag == "*": + tag = None + if tag is None or self.tag == tag: + nodes.append(self) + for node in self._children: + nodes.extend(node.getiterator(tag)) + return nodes + +# compatibility +_Element = _ElementInterface + +## +# Element factory. This function returns an object implementing the +# standard Element interface. The exact class or type of that object +# is implementation dependent, but it will always be compatible with +# the {@link #_ElementInterface} class in this module. +#

+# The element name, attribute names, and attribute values can be +# either 8-bit ASCII strings or Unicode strings. +# +# @param tag The element name. +# @param attrib An optional dictionary, containing element attributes. +# @param **extra Additional attributes, given as keyword arguments. +# @return An element instance. +# @defreturn Element + +def Element(tag, attrib={}, **extra): + attrib = attrib.copy() + attrib.update(extra) + return _ElementInterface(tag, attrib) + +## +# Subelement factory. This function creates an element instance, and +# appends it to an existing element. +#

+# The element name, attribute names, and attribute values can be +# either 8-bit ASCII strings or Unicode strings. +# +# @param parent The parent element. +# @param tag The subelement name. +# @param attrib An optional dictionary, containing element attributes. +# @param **extra Additional attributes, given as keyword arguments. +# @return An element instance. +# @defreturn Element + +def SubElement(parent, tag, attrib={}, **extra): + attrib = attrib.copy() + attrib.update(extra) + element = parent.makeelement(tag, attrib) + parent.append(element) + return element + +## +# Comment element factory. This factory function creates a special +# element that will be serialized as an XML comment. +#

+# The comment string can be either an 8-bit ASCII string or a Unicode +# string. +# +# @param text A string containing the comment string. +# @return An element instance, representing a comment. +# @defreturn Element + +def Comment(text=None): + element = Element(Comment) + element.text = text + return element + +## +# PI element factory. This factory function creates a special element +# that will be serialized as an XML processing instruction. +# +# @param target A string containing the PI target. +# @param text A string containing the PI contents, if any. +# @return An element instance, representing a PI. +# @defreturn Element + +def ProcessingInstruction(target, text=None): + element = Element(ProcessingInstruction) + element.text = target + if text: + element.text = element.text + " " + text + return element + +PI = ProcessingInstruction + +## +# QName wrapper. This can be used to wrap a QName attribute value, in +# order to get proper namespace handling on output. +# +# @param text A string containing the QName value, in the form {uri}local, +# or, if the tag argument is given, the URI part of a QName. +# @param tag Optional tag. If given, the first argument is interpreted as +# an URI, and this argument is interpreted as a local name. +# @return An opaque object, representing the QName. + +class QName: + def __init__(self, text_or_uri, tag=None): + if tag: + text_or_uri = "{%s}%s" % (text_or_uri, tag) + self.text = text_or_uri + def __str__(self): + return self.text + def __hash__(self): + return hash(self.text) + def __cmp__(self, other): + if isinstance(other, QName): + return cmp(self.text, other.text) + return cmp(self.text, other) + +## +# ElementTree wrapper class. This class represents an entire element +# hierarchy, and adds some extra support for serialization to and from +# standard XML. +# +# @param element Optional root element. +# @keyparam file Optional file handle or name. If given, the +# tree is initialized with the contents of this XML file. + +class ElementTree: + + def __init__(self, element=None, file=None): + assert element is None or iselement(element) + self._root = element # first node + if file: + self.parse(file) + + ## + # Gets the root element for this tree. + # + # @return An element instance. + # @defreturn Element + + def getroot(self): + return self._root + + ## + # Replaces the root element for this tree. This discards the + # current contents of the tree, and replaces it with the given + # element. Use with care. + # + # @param element An element instance. + + def _setroot(self, element): + assert iselement(element) + self._root = element + + ## + # Loads an external XML document into this element tree. + # + # @param source A file name or file object. + # @param parser An optional parser instance. If not given, the + # standard {@link XMLTreeBuilder} parser is used. + # @return The document root element. + # @defreturn Element + + def parse(self, source, parser=None): + if not hasattr(source, "read"): + source = open(source, "rb") + if not parser: + parser = XMLTreeBuilder() + while 1: + data = source.read(32768) + if not data: + break + parser.feed(data) + self._root = parser.close() + return self._root + + ## + # Creates a tree iterator for the root element. The iterator loops + # over all elements in this tree, in document order. + # + # @param tag What tags to look for (default is to return all elements) + # @return An iterator. + # @defreturn iterator + + def getiterator(self, tag=None): + assert self._root is not None + return self._root.getiterator(tag) + + ## + # Finds the first toplevel element with given tag. + # Same as getroot().find(path). + # + # @param path What element to look for. + # @return The first matching element, or None if no element was found. + # @defreturn Element or None + + def find(self, path): + assert self._root is not None + if path[:1] == "/": + path = "." + path + return self._root.find(path) + + ## + # Finds the element text for the first toplevel element with given + # tag. Same as getroot().findtext(path). + # + # @param path What toplevel element to look for. + # @param default What to return if the element was not found. + # @return The text content of the first matching element, or the + # default value no element was found. Note that if the element + # has is found, but has no text content, this method returns an + # empty string. + # @defreturn string + + def findtext(self, path, default=None): + assert self._root is not None + if path[:1] == "/": + path = "." + path + return self._root.findtext(path, default) + + ## + # Finds all toplevel elements with the given tag. + # Same as getroot().findall(path). + # + # @param path What element to look for. + # @return A list or iterator containing all matching elements, + # in document order. + # @defreturn list of Element instances + + def findall(self, path): + assert self._root is not None + if path[:1] == "/": + path = "." + path + return self._root.findall(path) + + ## + # Writes the element tree to a file, as XML. + # + # @param file A file name, or a file object opened for writing. + # @param encoding Optional output encoding (default is US-ASCII). + + def write(self, file, encoding="us-ascii"): + assert self._root is not None + if not hasattr(file, "write"): + file = open(file, "wb") + if not encoding: + encoding = "us-ascii" + elif encoding != "utf-8" and encoding != "us-ascii": + file.write("\n" % encoding) + self._write(file, self._root, encoding, {}) + + def _write(self, file, node, encoding, namespaces): + # write XML to file + tag = node.tag + if tag is Comment: + file.write("" % _escape_cdata(node.text, encoding)) + elif tag is ProcessingInstruction: + file.write("" % _escape_cdata(node.text, encoding)) + else: + items = node.items() + xmlns_items = [] # new namespaces in this scope + try: + if isinstance(tag, QName) or tag[:1] == "{": + tag, xmlns = fixtag(tag, namespaces) + if xmlns: xmlns_items.append(xmlns) + except TypeError: + _raise_serialization_error(tag) + file.write("<" + _encode(tag, encoding)) + if items or xmlns_items: + items.sort() # lexical order + for k, v in items: + try: + if isinstance(k, QName) or k[:1] == "{": + k, xmlns = fixtag(k, namespaces) + if xmlns: xmlns_items.append(xmlns) + except TypeError: + _raise_serialization_error(k) + try: + if isinstance(v, QName): + v, xmlns = fixtag(v, namespaces) + if xmlns: xmlns_items.append(xmlns) + except TypeError: + _raise_serialization_error(v) + file.write(" %s=\"%s\"" % (_encode(k, encoding), + _escape_attrib(v, encoding))) + for k, v in xmlns_items: + file.write(" %s=\"%s\"" % (_encode(k, encoding), + _escape_attrib(v, encoding))) + if node.text or len(node): + file.write(">") + if node.text: + file.write(_escape_cdata(node.text, encoding)) + for n in node: + self._write(file, n, encoding, namespaces) + file.write("") + else: + file.write(" />") + for k, v in xmlns_items: + del namespaces[v] + if node.tail: + file.write(_escape_cdata(node.tail, encoding)) + +# -------------------------------------------------------------------- +# helpers + +## +# Checks if an object appears to be a valid element object. +# +# @param An element instance. +# @return A true value if this is an element object. +# @defreturn flag + +def iselement(element): + # FIXME: not sure about this; might be a better idea to look + # for tag/attrib/text attributes + return isinstance(element, _ElementInterface) or hasattr(element, "tag") + +## +# Writes an element tree or element structure to sys.stdout. This +# function should be used for debugging only. +#

+# The exact output format is implementation dependent. In this +# version, it's written as an ordinary XML file. +# +# @param elem An element tree or an individual element. + +def dump(elem): + # debugging + if not isinstance(elem, ElementTree): + elem = ElementTree(elem) + elem.write(sys.stdout) + tail = elem.getroot().tail + if not tail or tail[-1] != "\n": + sys.stdout.write("\n") + +def _encode(s, encoding): + try: + return s.encode(encoding) + except AttributeError: + return s # 1.5.2: assume the string uses the right encoding + +if sys.version[:3] == "1.5": + _escape = re.compile(r"[&<>\"\x80-\xff]+") # 1.5.2 +else: + _escape = re.compile(eval(r'u"[&<>\"\u0080-\uffff]+"')) + +_escape_map = { + "&": "&", + "<": "<", + ">": ">", + '"': """, +} + +_namespace_map = { + # "well-known" namespace prefixes + "http://www.w3.org/XML/1998/namespace": "xml", + "http://www.w3.org/1999/xhtml": "html", + "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf", + "http://schemas.xmlsoap.org/wsdl/": "wsdl", +} + +def _raise_serialization_error(text): + raise TypeError( + "cannot serialize %r (type %s)" % (text, type(text).__name__) + ) + +def _encode_entity(text, pattern=_escape): + # map reserved and non-ascii characters to numerical entities + def escape_entities(m, map=_escape_map): + out = [] + append = out.append + for char in m.group(): + text = map.get(char) + if text is None: + text = "&#%d;" % ord(char) + append(text) + return string.join(out, "") + try: + return _encode(pattern.sub(escape_entities, text), "ascii") + except TypeError: + _raise_serialization_error(text) + +# +# the following functions assume an ascii-compatible encoding +# (or "utf-16") + +def _escape_cdata(text, encoding=None, replace=string.replace): + # escape character data + try: + if encoding: + try: + text = _encode(text, encoding) + except UnicodeError: + return _encode_entity(text) + text = replace(text, "&", "&") + text = replace(text, "<", "<") + text = replace(text, ">", ">") + return text + except (TypeError, AttributeError): + _raise_serialization_error(text) + +def _escape_attrib(text, encoding=None, replace=string.replace): + # escape attribute value + try: + if encoding: + try: + text = _encode(text, encoding) + except UnicodeError: + return _encode_entity(text) + text = replace(text, "&", "&") + text = replace(text, "'", "'") # FIXME: overkill + text = replace(text, "\"", """) + text = replace(text, "<", "<") + text = replace(text, ">", ">") + return text + except (TypeError, AttributeError): + _raise_serialization_error(text) + +def fixtag(tag, namespaces): + # given a decorated tag (of the form {uri}tag), return prefixed + # tag and namespace declaration, if any + if isinstance(tag, QName): + tag = tag.text + namespace_uri, tag = string.split(tag[1:], "}", 1) + prefix = namespaces.get(namespace_uri) + if prefix is None: + prefix = _namespace_map.get(namespace_uri) + if prefix is None: + prefix = "ns%d" % len(namespaces) + namespaces[namespace_uri] = prefix + if prefix == "xml": + xmlns = None + else: + xmlns = ("xmlns:%s" % prefix, namespace_uri) + else: + xmlns = None + return "%s:%s" % (prefix, tag), xmlns + +## +# Parses an XML document into an element tree. +# +# @param source A filename or file object containing XML data. +# @param parser An optional parser instance. If not given, the +# standard {@link XMLTreeBuilder} parser is used. +# @return An ElementTree instance + +def parse(source, parser=None): + tree = ElementTree() + tree.parse(source, parser) + return tree + +## +# Parses an XML document into an element tree incrementally, and reports +# what's going on to the user. +# +# @param source A filename or file object containing XML data. +# @param events A list of events to report back. If omitted, only "end" +# events are reported. +# @return A (event, elem) iterator. + +class iterparse: + + def __init__(self, source, events=None): + if not hasattr(source, "read"): + source = open(source, "rb") + self._file = source + self._events = [] + self._index = 0 + self.root = self._root = None + self._parser = XMLTreeBuilder() + # wire up the parser for event reporting + parser = self._parser._parser + append = self._events.append + if events is None: + events = ["end"] + for event in events: + if event == "start": + try: + parser.ordered_attributes = 1 + parser.specified_attributes = 1 + def handler(tag, attrib_in, event=event, append=append, + start=self._parser._start_list): + append((event, start(tag, attrib_in))) + parser.StartElementHandler = handler + except AttributeError: + def handler(tag, attrib_in, event=event, append=append, + start=self._parser._start): + append((event, start(tag, attrib_in))) + parser.StartElementHandler = handler + elif event == "end": + def handler(tag, event=event, append=append, + end=self._parser._end): + append((event, end(tag))) + parser.EndElementHandler = handler + elif event == "start-ns": + def handler(prefix, uri, event=event, append=append): + try: + uri = _encode(uri, "ascii") + except UnicodeError: + pass + append((event, (prefix or "", uri))) + parser.StartNamespaceDeclHandler = handler + elif event == "end-ns": + def handler(prefix, event=event, append=append): + append((event, None)) + parser.EndNamespaceDeclHandler = handler + + def next(self): + while 1: + try: + item = self._events[self._index] + except IndexError: + if self._parser is None: + self.root = self._root + try: + raise StopIteration + except NameError: + raise IndexError + # load event buffer + del self._events[:] + self._index = 0 + data = self._file.read(16384) + if data: + self._parser.feed(data) + else: + self._root = self._parser.close() + self._parser = None + else: + self._index = self._index + 1 + return item + + try: + iter + def __iter__(self): + return self + except NameError: + def __getitem__(self, index): + return self.next() + +## +# Parses an XML document from a string constant. This function can +# be used to embed "XML literals" in Python code. +# +# @param source A string containing XML data. +# @return An Element instance. +# @defreturn Element + +def XML(text): + parser = XMLTreeBuilder() + parser.feed(text) + return parser.close() + +## +# Parses an XML document from a string constant, and also returns +# a dictionary which maps from element id:s to elements. +# +# @param source A string containing XML data. +# @return A tuple containing an Element instance and a dictionary. +# @defreturn (Element, dictionary) + +def XMLID(text): + parser = XMLTreeBuilder() + parser.feed(text) + tree = parser.close() + ids = {} + for elem in tree.getiterator(): + id = elem.get("id") + if id: + ids[id] = elem + return tree, ids + +## +# Parses an XML document from a string constant. Same as {@link #XML}. +# +# @def fromstring(text) +# @param source A string containing XML data. +# @return An Element instance. +# @defreturn Element + +fromstring = XML + +## +# Generates a string representation of an XML element, including all +# subelements. +# +# @param element An Element instance. +# @return An encoded string containing the XML data. +# @defreturn string + +def tostring(element, encoding=None): + class dummy: + pass + data = [] + file = dummy() + file.write = data.append + ElementTree(element).write(file, encoding) + return string.join(data, "") + +## +# Generic element structure builder. This builder converts a sequence +# of {@link #TreeBuilder.start}, {@link #TreeBuilder.data}, and {@link +# #TreeBuilder.end} method calls to a well-formed element structure. +#

+# You can use this class to build an element structure using a custom XML +# parser, or a parser for some other XML-like format. +# +# @param element_factory Optional element factory. This factory +# is called to create new Element instances, as necessary. + +class TreeBuilder: + + def __init__(self, element_factory=None): + self._data = [] # data collector + self._elem = [] # element stack + self._last = None # last element + self._tail = None # true if we're after an end tag + if element_factory is None: + element_factory = _ElementInterface + self._factory = element_factory + + ## + # Flushes the parser buffers, and returns the toplevel documen + # element. + # + # @return An Element instance. + # @defreturn Element + + def close(self): + assert len(self._elem) == 0, "missing end tags" + assert self._last != None, "missing toplevel element" + return self._last + + def _flush(self): + if self._data: + if self._last is not None: + text = string.join(self._data, "") + if self._tail: + assert self._last.tail is None, "internal error (tail)" + self._last.tail = text + else: + assert self._last.text is None, "internal error (text)" + self._last.text = text + self._data = [] + + ## + # Adds text to the current element. + # + # @param data A string. This should be either an 8-bit string + # containing ASCII text, or a Unicode string. + + def data(self, data): + self._data.append(data) + + ## + # Opens a new element. + # + # @param tag The element name. + # @param attrib A dictionary containing element attributes. + # @return The opened element. + # @defreturn Element + + def start(self, tag, attrs): + self._flush() + self._last = elem = self._factory(tag, attrs) + if self._elem: + self._elem[-1].append(elem) + self._elem.append(elem) + self._tail = 0 + return elem + + ## + # Closes the current element. + # + # @param tag The element name. + # @return The closed element. + # @defreturn Element + + def end(self, tag): + self._flush() + self._last = self._elem.pop() + assert self._last.tag == tag,\ + "end tag mismatch (expected %s, got %s)" % ( + self._last.tag, tag) + self._tail = 1 + return self._last + +## +# Element structure builder for XML source data, based on the +# expat parser. +# +# @keyparam target Target object. If omitted, the builder uses an +# instance of the standard {@link #TreeBuilder} class. +# @keyparam html Predefine HTML entities. This flag is not supported +# by the current implementation. +# @see #ElementTree +# @see #TreeBuilder + +class XMLTreeBuilder: + + def __init__(self, html=0, target=None): + try: + from xml.parsers import expat + except ImportError: + raise ImportError( + "No module named expat; use SimpleXMLTreeBuilder instead" + ) + self._parser = parser = expat.ParserCreate(None, "}") + if target is None: + target = TreeBuilder() + self._target = target + self._names = {} # name memo cache + # callbacks + parser.DefaultHandlerExpand = self._default + parser.StartElementHandler = self._start + parser.EndElementHandler = self._end + parser.CharacterDataHandler = self._data + # let expat do the buffering, if supported + try: + self._parser.buffer_text = 1 + except AttributeError: + pass + # use new-style attribute handling, if supported + try: + self._parser.ordered_attributes = 1 + self._parser.specified_attributes = 1 + parser.StartElementHandler = self._start_list + except AttributeError: + pass + encoding = None + if not parser.returns_unicode: + encoding = "utf-8" + # target.xml(encoding, None) + self._doctype = None + self.entity = {} + + def _fixtext(self, text): + # convert text string to ascii, if possible + try: + return _encode(text, "ascii") + except UnicodeError: + return text + + def _fixname(self, key): + # expand qname, and convert name string to ascii, if possible + try: + name = self._names[key] + except KeyError: + name = key + if "}" in name: + name = "{" + name + self._names[key] = name = self._fixtext(name) + return name + + def _start(self, tag, attrib_in): + fixname = self._fixname + tag = fixname(tag) + attrib = {} + for key, value in attrib_in.items(): + attrib[fixname(key)] = self._fixtext(value) + return self._target.start(tag, attrib) + + def _start_list(self, tag, attrib_in): + fixname = self._fixname + tag = fixname(tag) + attrib = {} + if attrib_in: + for i in range(0, len(attrib_in), 2): + attrib[fixname(attrib_in[i])] = self._fixtext(attrib_in[i+1]) + return self._target.start(tag, attrib) + + def _data(self, text): + return self._target.data(self._fixtext(text)) + + def _end(self, tag): + return self._target.end(self._fixname(tag)) + + def _default(self, text): + prefix = text[:1] + if prefix == "&": + # deal with undefined entities + try: + self._target.data(self.entity[text[1:-1]]) + except KeyError: + from xml.parsers import expat + raise expat.error( + "undefined entity %s: line %d, column %d" % + (text, self._parser.ErrorLineNumber, + self._parser.ErrorColumnNumber) + ) + elif prefix == "<" and text[:9] == "": + self._doctype = None + return + text = string.strip(text) + if not text: + return + self._doctype.append(text) + n = len(self._doctype) + if n > 2: + type = self._doctype[1] + if type == "PUBLIC" and n == 4: + name, type, pubid, system = self._doctype + elif type == "SYSTEM" and n == 3: + name, type, system = self._doctype + pubid = None + else: + return + if pubid: + pubid = pubid[1:-1] + self.doctype(name, pubid, system[1:-1]) + self._doctype = None + + ## + # Handles a doctype declaration. + # + # @param name Doctype name. + # @param pubid Public identifier. + # @param system System identifier. + + def doctype(self, name, pubid, system): + pass + + ## + # Feeds data to the parser. + # + # @param data Encoded data. + + def feed(self, data): + self._parser.Parse(data, 0) + + ## + # Finishes feeding data to the parser. + # + # @return An element structure. + # @defreturn Element + + def close(self): + self._parser.Parse("", 1) # end of data + tree = self._target.close() + del self._target, self._parser # get rid of circular references + return tree diff --git a/src/salomeloader/Makefile.am b/src/salomeloader/Makefile.am index 68d186ffe..cb5a359e7 100644 --- a/src/salomeloader/Makefile.am +++ b/src/salomeloader/Makefile.am @@ -1,5 +1,6 @@ include $(top_srcdir)/adm/unix/make_begin.am -pkgpython_PYTHON = salomeloader.py +dist_salomescript_SCRIPTS =salomeloader.sh +salomepython_PYTHON = salomeloader.py ElementTree.py ElementPath.py graph.py include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/salomeloader/graph.py b/src/salomeloader/graph.py new file mode 100644 index 000000000..9bdd99b2b --- /dev/null +++ b/src/salomeloader/graph.py @@ -0,0 +1,83 @@ +# -*- coding: iso-8859-1 -*- +""" + This module contains graph utilities + + Following functions : invert, reachable,InducedSubgraph,write_dot,display operate on a graph. + A graph is an object G which supports following operations: + - iteration on nodes (for n in G gives all nodes of the graph) + - iteration on next nodes (for v in G[n] gives all next nodes of node n) +""" + +import os +from sets import Set + +def invert(G): + """Construit le graphe inverse de G en inversant les liens de voisinage""" + I={} + for n in G: + I.setdefault(n,Set()) + for v in G[n]: + I.setdefault(v,Set()).add(n) + return I + +def reachable(G,n): + """Construit le set de noeuds atteignables depuis le noeud n + + Le noeud n n'est pas dans le set retourné sauf en cas de boucles + Ce cas n'est pas traité ici (limitation) + """ + s=G[n] + for v in G[n]: + s=s|reachable(G,v) + return s + +def InducedSubgraph(V,G,adjacency_list_type=Set): + """ Construit un sous graphe de G avec les noeuds contenus dans V """ + def neighbors(x): + for y in G[x]: + if y in V: + yield y + return dict([(x,adjacency_list_type(neighbors(x))) for x in G if x in V]) + +def write_dot(stream,G): + """Ecrit la representation (au format dot) du graphe G dans le fichier stream""" + name="toto" + stream.write('digraph %s {\nnode [ style="filled" ]\n' % name) + for node in G : + try: + label = "%s:%s"% (node.name,node.__class__.__name__) + except: + label=str(node) + color='green' + stream.write(' %s [fillcolor="%s" label=< %s >];\n' % ( id(node), color, label)) + for src in G: + for dst in G[src]: + stream.write(' %s -> %s;\n' % (id(src), id(dst))) + stream.write("}\n") + +def display(G,suivi="sync"): + """Affiche le graphe G avec l'outil dot""" + f=file("graph.dot", 'w') + write_dot(f,G) + f.close() + cmd="dot -Tpng graph.dot |display" + (suivi == "async" and "&" or "") + os.system(cmd) + + +def test(): + G={ + 1:Set([2,3]), + 2:Set([4]), + 3:Set([5]), + 4:Set([6]), + 5:Set([6]), + 6:Set(), + } + display(G) + I=invert(G) + print reachable(G,2) + print reachable(I,6) + print reachable(G,2) & reachable(I,6) + +if __name__ == "__main__": + test() diff --git a/src/salomeloader/salomeloader.py b/src/salomeloader/salomeloader.py index 4bc755887..0c6ab0382 100644 --- a/src/salomeloader/salomeloader.py +++ b/src/salomeloader/salomeloader.py @@ -1,15 +1,18 @@ # -*- coding: iso-8859-1 -*- -"""Ce module sert pour lire un schema de calcul Salome décrit en XML. - et le convertir en schema de calcul YACS - - Cette lecture est réalisée au moyen de la classe SalomeLoader - et de sa méthode load. +"""This module is used to parse a supervision graph Salome (XML) and convert it into + YACS calculation schema + This parsing is done with SalomeLoader class and its method load. """ import sys,os -import cElementTree as ElementTree +try: + import cElementTree as ElementTree +except ImportError: + import ElementTree + from sets import Set +import graph import pilot import SALOMERuntime @@ -17,102 +20,31 @@ class UnknownKind(Exception):pass debug=0 typeMap={} +objref=None + +def typeName(name): + """Replace :: in type name by /""" + return "/".join(name.split("::")) + streamTypes={ '0':"Unknown", - '1':"CALCIUM_int", + '1':"CALCIUM_integer", '3':"CALCIUM_real", } -#Les fonctions suivantes : invert, reachable,InducedSubgraph,write_dot,display -#permettent de realiser des operations sur un graphe. -#Est considere comme un graphe un objet G qui supporte les -#operations suivantes : l'iteration sur les noeuds (for n in G parcourt -#tous les noeuds du graphe) et l'iteration sur les suivants -# (for v in G[n] parcourt tous les suivants du noeud n) -def invert(G): - """Construit le graphe inverse de G en inversant les liens de voisinage""" - I={} - for n in G: - I.setdefault(n,Set()) - for v in G[n]: - I.setdefault(v,Set()).add(n) - return I - -def reachable(G,n): - """Construit le set de noeuds atteignables depuis le noeud n - - Le noeud n n'est pas dans le set retourné sauf en cas de boucles - Ce cas n'est pas traité ici (limitation) - """ - s=G[n] - for v in G[n]: - s=s|reachable(G,v) - return s - -def InducedSubgraph(V,G,adjacency_list_type=Set): - """ Construit un sous graphe de G avec les noeuds contenus dans V """ - def neighbors(x): - for y in G[x]: - if y in V: - yield y - return dict([(x,adjacency_list_type(neighbors(x))) for x in G if x in V]) - -def write_dot(stream,G): - """Ecrit la representation (au format dot) du graphe G dans le fichier stream""" - name="toto" - stream.write('digraph %s {\nnode [ style="filled" ]\n' % name) - for node in G : - try: - label = "%s:%s"% (node.name,node.__class__.__name__) - except: - label=str(node) - color='green' - stream.write(' %s [fillcolor="%s" label=< %s >];\n' % ( id(node), color, label)) - for src in G: - for dst in G[src]: - stream.write(' %s -> %s;\n' % (id(src), id(dst))) - stream.write("}\n") - -def display(G,suivi="sync"): - """Affiche le graphe G avec l'outil dot""" - f=file("graph.dot", 'w') - write_dot(f,G) - f.close() - cmd="dot -Tpng graph.dot |display" + (suivi == "async" and "&" or "") - os.system(cmd) - - -def test(): - G={ - 1:Set([2,3]), - 2:Set([4]), - 3:Set([5]), - 4:Set([6]), - 5:Set([6]), - 6:Set(), - } - display(G) - I=invert(G) - print reachable(G,2) - print reachable(I,6) - print reachable(G,2) & reachable(I,6) - -#Fin des fonctions graphe - currentProc=None class SalomeLoader: - """Loader de schéma Salome natif et convertisseur en schéma 'nouvelle formule'. - La méthode loadxml parse le fichier xml et retourne un objet SalomeProc - natif non converti - La méthode load parse le fichier xml et retourne un objet représentant - un schéma Salome converti (objet Proc de YACS) + """This class parses a Salome graph (version 3.2.x) and converts it into YACS schema. + + The loadxml method parses xml file and returns a SalomeProc object + + The load method calls the loadxml method and creates a YACS object of class Proc """ def loadxml(self,filename): """ - Lit un fichier XML du SUPERV de Salome et retourne la liste des - procedures (instances de SalomeProc) + Parse a XML file from Salome SUPERV and return a list of SalomeProc objects. """ tree = ElementTree.ElementTree(file=filename) root = tree.getroot() @@ -120,75 +52,139 @@ class SalomeLoader: procs=[] if root.tag == "dataflow": - #un seul dataflow + #only one dataflow dataflow=root if debug:print dataflow proc=SalomeProc(dataflow) procs.append(proc) else: - #un ou plusieurs dataflow. Le schema contient des macros. - # Toutes les macros sont - #décrites au meme niveau dans le fichier XML. + #one or more dataflows. The graph contains macros. + #All macros are defined at the same level in the XML file. for dataflow in root.findall("dataflow"): if debug:print dataflow proc=SalomeProc(dataflow) - if debug:print "nom du dataflow:",proc.name + if debug:print "dataflow name:",proc.name procs.append(proc) return procs def load(self,filename): - """Lit un fichier XML et convertit les procedures lues en procedures - nouvelle formule + """Parse a SUPERV XML file (method loadxml) and return a YACS Proc object. """ global currentProc procs=self.loadxml(filename) - #on récupère le schema de tete d'un coté et les éventuelles - #macros de l'autre: procs[0] + #Split the master proc from the possible macros. proc=procs.pop(0) #proc.display() - #Enregistrement des éventuelles macros dans macro_dict + #Put macros in macro_dict macro_dict={} for p in procs: if debug:print "proc_name:",p.name,"coupled_node:",p.coupled_node macro_dict[p.name]=p if debug:print filename - yacsproc=ProcNode(proc,macro_dict) + yacsproc=ProcNode(proc,macro_dict,filename) return yacsproc.createNode() +class Container: + """Class that defines a Salome Container""" + def __init__(self,mach,name): + self.mach=mach + self.name=name + self.components={} + def getName(self): + return self.mach+"/"+self.name + +_containers={} +def getContainer(name): + if not name: + name="localhost/FactoryServer" + elif "/" not in name: + #no machine name: use localhost + name="localhost/"+name + return _containers.get(name) + +def addContainer(name): + if not name: + mach="localhost" + name="FactoryServer" + elif "/" not in name: + #no machine name: use localhost for mach + mach="localhost" + else: + mach,name=name.split("/") + c=Container(mach,name) + _containers[mach+"/"+name]=c + return c + class Service: - """Classe pour porter les caractéristiques d'un service""" + """Class for Service properties""" class Parameter: - """Classe pour porter les caractéristiques d'un parametre""" + """Class for Parameter properties""" class Link: - """Classe pour porter les caractéristiques d'un link""" + """Class for Link properties""" class Data: - """Classe pour porter les caractéristiques d'un data""" + """Class for Data properties""" class Node: - """Node de calcul simple : classe de base à spécialiser """ + """Base class for all nodes """ label="Node: " def __init__(self): - self.links=[] # liste pour stocker les entrees sous forme de link - # le link doit avoir deux attributs : from_node qui donne le node origine - # et to_node qui donne le node cible + self.links=[] # list to store inputs as links + # a link has two attributes : from_node, the starting node + # to_node, the end node self.datas=[] - self.inStreamLinks=[] #liste des liens dataStream associés à ce node (in) - self.outStreamLinks=[] #liste des liens dataStream associés à ce node (out) + self.inStreamLinks=[] #list of dataStream links connected to this node (in) + self.outStreamLinks=[] #list of dataStream links connected to this node (out) + self.node=None def createNode(self): raise NotImplementedError def getInputPort(self,p): return self.node.getInputPort(".".join(p.split("__"))) def getOutputPort(self,p): + if not self.node: + self.createNode() return self.node.getOutputPort(".".join(p.split("__"))) def getInputDataStreamPort(self,p): return self.node.getInputDataStreamPort(p) def getOutputDataStreamPort(self,p): return self.node.getOutputDataStreamPort(p) + def initPort(self,l): + if l.type == 7: + #double (CORBA::tk_double) + try: + self.getInputPort(l.tonodeparam).edInitDbl(l.value) + except: + reason="Problem in initialization, not expected type (double): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + elif l.type == 3: + #int (CORBA::tk_long) + try: + self.getInputPort(l.tonodeparam).edInitInt(l.value) + except: + reason="Problem in initialization, not expected type (int): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + elif l.type == 14: + #objref (CORBA::tk_objref) + try: + self.getInputPort(l.tonodeparam).edInitString(l.value) + except: + reason="Problem in initialization, not expected type (objref): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + elif l.type == 18: + #string (CORBA::tk_string) + try: + self.getInputPort(l.tonodeparam).edInitString(l.value) + except: + reason="Problem in initialization, not expected type (string): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + else: + reason="Problem in initialization, not expected type (%s): %s %s" % (l.type,l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + class InlineNode(Node): - """Node de calcul inline salome : fonction dans self.codes[0]""" + """Inline Node salome : python function in self.codes[0]""" def __init__(self): Node.__init__(self) self.codes=[] @@ -204,42 +200,67 @@ class InlineNode(Node): for para in self.service.inParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] n.edAddInputPort(para.name,typeMap[para.type]) for para in self.service.outParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] n.edAddOutputPort(para.name,typeMap[para.type]) + for d in self.datas: + self.initPort(d) + return n class ComputeNode(Node): - """Node de calcul pour exécuter un service Salome""" + """Compute Node Salome execute a component service""" def createNode(self): + if self.node: + return self.node + r = pilot.getRuntime() - n=r.createCompoNode("",self.name) - n.setRef(self.sComponent) + if self.container.components.has_key(self.sComponent): + #a node for this component already exists + compo_node=self.container.components[self.sComponent] + #It's a node associated with another node of the same component instance + #It is not sure that the yacs node has been created ???? + master_node=compo_node.createNode() + n=master_node.createNode(self.name) + else: + #there is no node for this component. This node is first + self.container.components[self.sComponent]=self + #There is no component instance for this node + n=r.createCompoNode("",self.name) + n.setRef(self.sComponent) + n.setMethod(self.service.name) self.node=n + #set the container for the node + if self.container: + n.getComponent().setContainer(currentProc.containerMap[self.container.getName()]) - #ajout des ports in et out du service + #add dataflow ports in out for para in self.service.inParameters: if not typeMap.has_key(para.type): - #on cree le type manquant et on l'ajoute dans la table des types - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + #Create the missing type and adds it into types table + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] n.edAddInputPort(para.name,typeMap[para.type]) for para in self.service.outParameters: if not typeMap.has_key(para.type): - #on cree le type manquant et on l'ajoute dans la table des types - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + #Create the missing type and adds it into types table + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] pout=n.edAddOutputPort(para.name,typeMap[para.type]) - #ajout des ports datastream in et out + #add datastream ports in and out for para in self.inStreams: if debug:print para.name,para.type,para.dependency,para.schema, para.interpolation, if debug:print para.extrapolation @@ -248,61 +269,64 @@ class ComputeNode(Node): if debug:print para.name,para.type,para.dependency,para.values pout=n.edAddOutputDataStreamPort(para.name,typeMap[streamTypes[para.type]]) + for d in self.datas: + self.initPort(d) + return n class ComposedNode(Node): - """Node de calcul composite Salome (classe de base)""" + """Composed Node Salome (base class)""" def reduceLoop(self): - """Transforme un graphe de type Salome avec les boucles - a plat en un graphe hierarchique - Le graphe de depart (Salome) est dans self.G. - On le transforme en place + """Transform a Salome graph with loops on one level + in a hierarchical graph. + + The initial graph is in self.G. It is transformed in place. """ G=self.G - if debug:display(G) - #calcul du graphe inverse - I=invert(G) - #display(I) + if debug:graph.display(G) + #invert the graph + I=graph.invert(G) + #graph.display(I) - #on recherche toutes les boucles et leurs noeuds internes + #Get all loops and their internal nodes loops={} for n in G: if n.kind == 4: - #Debut de boucle - loops[n]=reachable(G,n)&reachable(I,n.endloop) + #Beginning of loop + loops[n]=graph.reachable(G,n)&graph.reachable(I,n.endloop) n.inner_nodes=loops[n] - n.G=InducedSubgraph(loops[n],G) + n.G=graph.InducedSubgraph(loops[n],G) - if debug:print "toutes les boucles du graphe" + if debug:print "all loops" if debug:print loops - #on recherche les boucles les plus externes + #Get most external loops outer_loops=loops.keys() for l in loops: for ll in outer_loops: if loops[l] < loops[ll]: - #boucle interne + #internal loop outer_loops.remove(l) ll.set_inner(l) break - #a la fin, les boucles restantes dans outer_loops sont les plus externes + #In the end all remaining loops in outer_loops are the most external if debug:print outer_loops - #on supprime les noeuds internes des boucles les plus externes + #We remove all internal nodes of most external loops for l in outer_loops: - #on enleve les noeuds internes + #Remove internal nodes for n in loops[l]: del G[n] - #on enleve le noeud endloop + #Remove endloop node suiv=G[l.endloop] del G[l.endloop] - #on remplace les noeuds suivants de loop par ceux de endloop + #Replace neighbours of loop by those of endloop G[l]= suiv - #on tente de transformer les liens entrants et sortants sur le noeud endloop - #en noeuds directs. On ne traite probablement pas tous les cas. + #Try to transform incoming and outcoming links of endloop in incoming and + #outcoming links of internal nodes. Probably not complete. inputs={} for link in l.endloop.links: if debug:print link.from_node,link.to_node,link.from_param,link.to_param @@ -314,73 +338,92 @@ class ComposedNode(Node): link.from_node,link.from_param=inputs[link.from_param] if debug:print link.from_node,link.to_node,link.from_param,link.to_param - if debug:display(G) + if debug:graph.display(G) - #on applique le traitement de reduction aux boucles les plus externes (recursif) + #Apply the reduction treatment to most external loops (recurse) for l in outer_loops: l.reduceLoop() def connect_macros(self,macro_dict): - """Cette methode rattache les macros salome contenues dans macro_dict - a la procedure YACS proc - On est ici dans le noeud auquel on veut rattacher une des macros - macro_dict est un dictionnaire dont la cle est le nom de la macro - et la valeur est un graphe Salome (objet SalomeProc) - Les noeuds concernes sont les MacroNode et les SalomeProc + """This method connects the salome macros in macro_dict to the master YACS Proc. + """ if debug:print "connect_macros",self.node,macro_dict for node in self.G: if isinstance(node,MacroNode): - #c'est une macro, il faut rattacher sa description - #p est le sous graphe Salome (objet SalomeProc) - #node est le MacroNode Salome qui utilise le sous graphe p - #node.node est le bloc YACS equivalent + #node is a macro, connect its definition to self. + #p is the Salome macro (class SalomeProc) + #node is the Salome MacroNode that has the subgraph p + #node.node is the YACS Bloc equivalent to node p=macro_dict[node.coupled_node] bloc=node.node if debug:print "macronode:",node.name,node.coupled_node,p - #a partir de la procédure salome a plat on cree un - #graphe d'exécution hiérarchique nouvelle formule + #Create a hierarchical graph from the salome graph G=p.create_graph() node.G=G for n in G: - #chaque noeud du graphe G cree un noeud YACS equivalent + #create an equivalent YACS node from each salome node nod=n.createNode() bloc.edAddChild(nod) - #on demande le rattachement des macros aux nodes du macroNode node + #Connect macros to node node.connect_macros(macro_dict) - #on ajoute les liens de controle + #add control links for n in G: for v in G[n]: bloc.edAddCFLink(n.node,v.node) - #on ajoute les liens de donnees et les initialisations + #add dataflow links and initializations for n in G: - #liens dataflow + #dataflow links for l in n.links: bloc.edAddLink(l.from_node.getOutputPort(l.from_param), l.to_node.getInputPort(l.to_param)) - #liens datastream + #datastream links for l in n.outStreamLinks: pout=l.from_node.getOutputDataStreamPort(l.from_param) pin=l.to_node.getInputDataStreamPort(l.to_param) bloc.edAddLink(pout,pin) - #initialisations + #initializations for l in n.datas: if l.type == 7: - #double - n.getInputPort(l.tonodeparam).edInitDbl(l.value) + #double (CORBA::tk_double) + try: + n.getInputPort(l.tonodeparam).edInitDbl(l.value) + except: + reason="Problem in initialization, not expected type (double): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) elif l.type == 3: - #int - n.getInputPort(l.tonodeparam).edInitInt(l.value) + #int (CORBA::tk_long) + try: + n.getInputPort(l.tonodeparam).edInitInt(l.value) + except: + reason="Problem in initialization, not expected type (int): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + elif l.type == 14: + #objref (CORBA::tk_objref) + try: + n.getInputPort(l.tonodeparam).edInitString(l.value) + except: + reason="Problem in initialization, not expected type (objref): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + elif l.type == 18: + #string (CORBA::tk_string) + try: + n.getInputPort(l.tonodeparam).edInitString(l.value) + except: + reason="Problem in initialization, not expected type (string): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + else: + reason="Problem in initialization, not expected type (%s): %s %s" % (l.type,l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) class LoopNode(ComposedNode): """Objet qui simule le comportement d'une boucle Salome.""" def __init__(self): ComposedNode.__init__(self) self.inner_loops=[] - #inner_nodes contient les noeuds internes au sens Salome (a plat - #avec les noeuds endloop) + #inner_nodes contains internal nodes as in Salome (on one level with endloop nodes) self.inner_nodes=[] def set_node(self,node): @@ -389,34 +432,30 @@ class LoopNode(ComposedNode): def set_inner(self,loop): for i in self.inner_loops: if loop.inner_nodes < i.inner_nodes: - #la boucle est contenue dans i + #the loop is contained in i i.set_inner(loop) break self.inner_loops.append(loop) def createNode(self): - """Cree l'objet boucle equivalent - - Un objet boucle Salome a n ports d'entrée et les memes ports en sortie. - La tete de boucle a 3 fonctions : init, next, more qui ont des signatures - tres voisines. init et next ont la meme signature : en entree les parametres - d'entree de la boucle et en sortie les parametres de sortie de la boucle c'est - à dire les memes qu'en entrée. more a les memes parametres d'entree et a un - parametre de sortie supplementaire qui vient en premiere position. Ce - parametre indique si la boucle doit etre poursuivie ou stoppée. - La fin de boucle a une fonction qui a la meme signature que next. - - Pour transformer ce type de boucle, on crée un ensemble de noeuds de calcul - regroupés dans un bloc. Dans ce bloc, on crée un noeud externe pour init suivi - d'une boucle while. - Ensuite on crée un bloc qui contiendra 2 noeuds (next et more) plus tous - les noeuds internes de la boucle. + """Create the equivalent YACS loop and store it in attribute node + + A Salome loop has n input ports and output ports with exactly same names. + The head of loop has 3 functions : init, next, more which have almost same + interface. init and next have same interface : on input, input loop parameters + on output, output loop parameters (same as input). more has one more output parameter + in first place. This parameter says if the loop must go on or not. + The endloop has a function with the same interface as next. + + To transform this node, create a YACS Bloc. In this bloc put a node for the init function + and a While node. In the while put all internal nodes plus 2 nodes for the next and more + functions. """ r = pilot.getRuntime() bloop=r.createBloc(self.name) - #noeud init + #init node init=r.createFuncNode("","init") #print self.codes[0] init.setScript(self.codes[0]) @@ -424,13 +463,15 @@ class LoopNode(ComposedNode): for para in self.service.inParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] init.edAddInputPort(para.name,typeMap[para.type]) for para in self.service.outParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] init.edAddOutputPort(para.name,typeMap[para.type]) bloop.edAddChild(init) @@ -443,7 +484,7 @@ class LoopNode(ComposedNode): cport=wh.edGetConditionPort() cport.edInitBool(True) - #noeud next + #next node next=r.createFuncNode("","next") #print self.codes[2] next.setScript(self.codes[2]) @@ -451,19 +492,21 @@ class LoopNode(ComposedNode): for para in self.service.inParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] next.edAddInputPort(para.name,typeMap[para.type]) for para in self.service.outParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] next.edAddOutputPort(para.name,typeMap[para.type]) blnode.edAddChild(next) self.next=next - #noeud more + #more node more=r.createFuncNode("","more") #print self.codes[1] more.setScript(self.codes[1]) @@ -471,14 +514,16 @@ class LoopNode(ComposedNode): for para in self.service.inParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] more.edAddInputPort(para.name,typeMap[para.type]) more.edAddOutputPort("DoLoop",typeMap["int"]) for para in self.service.outParameters: if not typeMap.has_key(para.type): #create the missing type and add it in type map - typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[]) + typeMap[para.type]= currentProc.createInterfaceTc("",para.type,[objref]) + if not currentProc.typeMap.has_key(para.type): currentProc.typeMap[para.type]=typeMap[para.type] more.edAddOutputPort(para.name,typeMap[para.type]) blnode.edAddChild(more) @@ -507,10 +552,13 @@ class LoopNode(ComposedNode): for n in self.G: for l in n.links: - print l.from_node.name,l.to_node.name - print l.from_param,l.to_param - blnode.edAddDFLink(l.from_node.getOutputPort(l.from_param), + try: + blnode.edAddDFLink(l.from_node.getOutputPort(l.from_param), l.to_node.getInputPort(l.to_param)) + except: + reason="Error while connecting output port: "+l.from_param+" from node: "+l.from_node.name + reason=reason+" to input port: "+l.to_param+" from node: "+l.to_node.name + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) return bloop @@ -521,8 +569,7 @@ class LoopNode(ComposedNode): return self.more.getOutputPort(p) class Bloc(ComposedNode): - """ Objet composé d'un ensemble de nodes enchaines et qui se - comporte comme un node simple. + """ Composed node containing a set of connected nodes """ label="Bloc: " def __init__(self): @@ -534,119 +581,172 @@ class Bloc(ComposedNode): if node2 not in self.nodes:self.nodes.append(node2) class MacroNode(Bloc): - """Objet qui représente une Macro Salome c'est a dire un node - composite avec une interface : ports in et out. + """Objet that represents a Salome Macro """ def createNode(self): - """Cree l'objet correspondant a une Macro Salome : un Bloc""" + """Create a YACS node (Bloc) equivalent to a Salome Macro """ r = pilot.getRuntime() macro=r.createBloc(self.name) self.node=macro return macro def is_loop(n): - """Indique si n est un node de début de boucle""" + """Return true if n is a head loop node""" return isinstance(n,LoopNode) class ProcNode(ComposedNode): - """Procedure YACS equivalente a une procedure Salome accompagnee - de ses macros + """Salome proc with its macros + + The Salome proc is stored in attribute proc + The Salome macros are stored in attribute macro_dict ({}) """ - def __init__(self,proc,macro_dict): + def __init__(self,proc,macro_dict,filename): ComposedNode.__init__(self) self.proc=proc self.macro_dict=macro_dict + self.filename=filename def createNode(self): - """Cree l'objet YACS equivalent""" - global currentProc + """Create the YACS node (Proc) equivalent a Salome proc""" + global currentProc,objref r = pilot.getRuntime() - #create_graph retourne un graphe representatif de la - #procedure Salome transformee en un graphe hierarchique + #create_graph gives a hierarchical graph equivalent to the Salome proc G=self.proc.create_graph() self.G=G - #on utilise le graphe G pour construire la - #procedure YACS equivalente p + #Create the YACS proc with its elements (types, nodes, containers) p=r.createProc("pr") self.node=p currentProc=p + p.filename=self.filename typeMap["double"]=p.typeMap["double"] + typeMap["float"]=p.typeMap["double"] typeMap["int"]=p.typeMap["int"] + typeMap["short"]=p.typeMap["int"] typeMap["long"]=p.typeMap["int"] typeMap["string"]=p.typeMap["string"] + typeMap["char"]=p.typeMap["string"] + typeMap["boolean"]=p.typeMap["bool"] typeMap["bool"]=p.typeMap["bool"] + + objref=p.createInterfaceTc("IDL:omg.org/CORBA/Object:1.0","Object",[]) + typeMap["objref"]=objref typeMap["Unknown"]=p.createInterfaceTc("","Unknown",[]) - typeMap["GEOM_Object"]=p.createInterfaceTc("","GEOM_Object",[]) + typeMap["GEOM_Object"]=p.createInterfaceTc("IDL:GEOM/GEOM_Object:1.0","GEOM_Object",[objref]) typeMap["GEOM_Shape"]=typeMap["GEOM_Object"] - typeMap["CALCIUM_int"]=p.createInterfaceTc("","CALCIUM_int",[]) - typeMap["CALCIUM_real"]=p.createInterfaceTc("","CALCIUM_real",[]) + + typeMap["CALCIUM_integer"]=p.createInterfaceTc("IDL:Ports/Calcium_Ports/Calcium_Integer_Port:1.0","CALCIUM_integer",[]) + typeMap["CALCIUM_real"]=p.createInterfaceTc("IDL:Ports/Calcium_Ports/Calcium_Real_Port:1.0","CALCIUM_real",[]) + typeMap["CALCIUM_double"]=p.createInterfaceTc("IDL:Ports/Calcium_Ports/Calcium_Double_Port:1.0","CALCIUM_double",[]) + typeMap["CALCIUM_string"]=p.createInterfaceTc("IDL:Ports/Calcium_Ports/Calcium_String_Port:1.0","CALCIUM_string",[]) + typeMap["CALCIUM_boolean"]=p.createInterfaceTc("IDL:Ports/Calcium_Ports/Calcium_Logical_Port:1.0","CALCIUM_boolean",[]) + + typeMap["SuperVisionTest::Adder"]=p.createInterfaceTc("","SuperVisionTest/Adder",[objref]) + typeMap["Adder"]=typeMap["SuperVisionTest::Adder"] + + currentProc.typeMap["Object"]=typeMap["objref"] currentProc.typeMap["Unknown"]=typeMap["Unknown"] currentProc.typeMap["GEOM_Object"]=typeMap["GEOM_Object"] currentProc.typeMap["GEOM_Shape"]=typeMap["GEOM_Shape"] - currentProc.typeMap["CALCIUM_int"]=typeMap["CALCIUM_int"] + currentProc.typeMap["CALCIUM_integer"]=typeMap["CALCIUM_integer"] currentProc.typeMap["CALCIUM_real"]=typeMap["CALCIUM_real"] + #create all containers + for name,container in _containers.items(): + cont=r.createContainer() + cont.setName(name) + cont.setProperty("hostname",container.mach) + cont.setProperty("container_name",container.name) + currentProc.containerMap[name]=cont + for n in G: - #chaque noeud du graphe G cree un noeud YACS equivalent + #each node in G creates an equivalent YACS node. node=n.createNode() p.edAddChild(node) - #on demande le rattachement des macros aux nodes de la procédure p + #Connect Salome macros to nodes of proc p. self.connect_macros(self.macro_dict) - #on ajoute les liens de controle + #add control links for n in G: for v in G[n]: p.edAddCFLink(n.node,v.node) - #on ajoute les liens de donnees et les initialisations + #add dataflow links and initializations for n in G: - #liens dataflow + #dataflow links for l in n.links: - print l.from_node.name,l.to_node.name - print l.from_param,l.to_param - p.edAddLink(l.from_node.getOutputPort(l.from_param), + try: + p.edAddLink(l.from_node.getOutputPort(l.from_param), l.to_node.getInputPort(l.to_param)) + except: + reason="Error while connecting output port: "+l.from_param+" from node: "+l.from_node.name + reason=reason+" to input port: "+l.to_param+" from node: "+l.to_node.name + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) - #liens datastream + #datastream links for l in n.outStreamLinks: pout=l.from_node.getOutputDataStreamPort(l.from_param) pin=l.to_node.getInputDataStreamPort(l.to_param) p.edAddLink(pout,pin) - #initialisations + #initializations for l in n.datas: if l.type == 7: - #double - n.getInputPort(l.tonodeparam).edInitDbl(l.value) + #double (CORBA::tk_double) + try: + n.getInputPort(l.tonodeparam).edInitDbl(l.value) + except: + reason="Problem in initialization, not expected type (double): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) elif l.type == 3: - #int - n.getInputPort(l.tonodeparam).edInitInt(l.value) + #int (CORBA::tk_long) + port=n.getInputPort(l.tonodeparam) + try: + port.edInitInt(l.value) + except: + reason="Problem in initialization, not expected type (int): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + elif l.type == 14: + #objref (CORBA::tk_objref) + try: + n.getInputPort(l.tonodeparam).edInitString(l.value) + except: + reason="Problem in initialization, not expected type (objref): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + elif l.type == 18: + #string (CORBA::tk_string) + try: + n.getInputPort(l.tonodeparam).edInitString(l.value) + except: + reason="Problem in initialization, not expected type (string): %s %s" % (l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) + else: + reason="Problem in initialization, not expected type (%s): %s %s" % (l.type,l.tonodeparam,l.value) + currentProc.getLogger("parser").error(reason,currentProc.filename,-1) return p class SalomeProc(ComposedNode): - """Objet pour décrire un schéma Salome natif avec ses liens - dataflow, datastream et gate - L'objet est construit en parsant un fichier XML + """Salome proc with all its dataflow, datastream and control links + The object is built by parsing an XML file. """ def __init__(self,dataflow): self.name="name" self.parse(dataflow) - #self.links : liste des liens dataflow du graphe (objets Link) - #self.nodes : liste des noeuds du graphe - #self.node_dict : le dictionnaire des noeuds (nom,node) - #self.datas : liste des datas du graphe - #chaque noeud a 2 listes de liens datastream (inStreams, outStreams) + #self.links : list of dataflow links (Link objects) + #self.nodes : list of graph nodes + #self.node_dict : nodes dict ({name:node}) + #self.datas : list of graph datas + #each node has 2 lists of datastream links (inStreams, outStreams) def parse(self,dataflow): - if debug:print "Tous les noeuds XML" + if debug:print "All XML nodes" for node in dataflow: if debug:print node.tag,node - #Récupération des informations du dataflow + #Parse dataflow info-list self.dataflow_info=self.parseService(dataflow.find("info-list/node/service")) if debug:print self.dataflow_info if debug:print self.dataflow_info.inParameters @@ -658,31 +758,38 @@ class SalomeProc(ComposedNode): self.name=dataflow.findtext("info-list/node/node-name") self.coupled_node=dataflow.findtext("info-list/node/coupled-node") - if debug:print "Tous les noeuds XML dataflow/node-list" + if debug:print "All XML nodes dataflow/node-list" nodes=[] node_dict={} - #on parcourt tous les noeuds + #Parse all nodes for n in dataflow.findall('node-list/node'): - #n est un node de node-list + #n is a node-list node kind=n.findtext("kind") - comp=n.find("component-name").text - name=n.find("node-name").text - coupled_node=n.find("coupled-node").text - interface=n.find("interface-name").text - container=n.find("container").text + comp=n.findtext("component-name") + name=n.findtext("node-name") + coupled_node=n.findtext("coupled-node") + interface=n.findtext("interface-name") + container=n.findtext("container") #kind=1 : dataflow ? #kind=2 : ? - #kind=9 : schema avec datastream ? + #kind=9 : datastream graph ? + #kind=6 : ?? + #kind=8 : ?? if kind == "0": - #Il s'agit d'un service + #It's a service node=ComputeNode() node.kind=0 node.sComponent = comp node.interface=interface + node.container= getContainer(container) + if not node.container: + node.container=addContainer(container) + if debug:print "\tcontainer",node.container + elif kind == "3": - #il s'agit d'une fonction + #It's a python function node=InlineNode() node.kind=3 codes=[] @@ -692,9 +799,10 @@ class SalomeProc(ComposedNode): codes.append(self.parsePyFunction(pyfunc)) node.fnames=fnames node.codes=codes + elif kind == "4": - #si kind vaut 4 on a une boucle : on crée un LoopNode - #les fonctions python (next, more, init) sont stockées dans codes + #It's a loop : make a LoopNode + #python functions (next, more, init) are found in codes node=LoopNode() node.kind=4 codes=[] @@ -704,8 +812,9 @@ class SalomeProc(ComposedNode): codes.append(self.parsePyFunction(pyfunc)) node.fnames=fnames node.codes=codes + elif kind == "5": - #noeud de fin de boucle : on crée un InlineNode + #End of loop : make an InlineNode node=InlineNode() node.kind=5 codes=[] @@ -715,30 +824,29 @@ class SalomeProc(ComposedNode): codes.append(self.parsePyFunction(pyfunc)) node.fnames=fnames node.codes=codes + elif kind == "10": - #si kind vaut 10 on a un noeud Macro : on cree un MacroNode + # It's a Macro node : make a MacroNode node=MacroNode() node.kind=10 else: raise UnknownKind,kind node.name=name - node.container=container node.service=None node.coupled_node=coupled_node - #on stocke les noeuds dans un dictionnaire pour faciliter les recherches + #Put nodes in a dict to ease search node_dict[node.name]=node if debug:print "\tnode-name",node.name if debug:print "\tkind",node.kind,node.__class__.__name__ - if debug:print "\tcontainer",node.container s=n.find("service") if s: node.service=self.parseService(s) - #on parcourt les ports datastream - if debug:print "DataStream" + #Parse datastream ports + if debug:print "DataStream ports" inStreams=[] for indata in n.findall("DataStream-list/inParameter"): inStreams.append(self.parseInData(indata)) @@ -756,8 +864,8 @@ class SalomeProc(ComposedNode): self.nodes=nodes self.node_dict=node_dict - #Le parcours des noeuds est fini. - #On parcourt les connexions dataflow et datastream + #Nodes parsing is finished. + #Parse dataflow and datastream links. """ Node_A_1 @@ -767,7 +875,7 @@ class SalomeProc(ComposedNode): """ - if debug:print "Tous les noeuds XML dataflow/link-list" + if debug:print "All XML nodes dataflow/link-list" links=[] if debug:print "\t++++++++++++++++++++++++++++++++++++++++++++" for link in dataflow.findall('link-list/link'): @@ -784,7 +892,7 @@ class SalomeProc(ComposedNode): if debug:print "\t++++++++++++++++++++++++++++++++++++++++++++" self.links=links - if debug:print "Tous les noeuds XML dataflow/data-list" + if debug:print "All XML nodes dataflow/data-list" datas=[] for data in dataflow.findall('data-list/data'): d=self.parseData(data) @@ -806,7 +914,7 @@ class SalomeProc(ComposedNode): for inParam in s.findall("inParameter-list/inParameter"): p=Parameter() p.name=inParam.findtext("inParameter-name") - p.type=inParam.findtext("inParameter-type") + p.type=typeName(inParam.findtext("inParameter-type")) if debug:print "\tinParameter-name",p.name if debug:print "\tinParameter-type",p.type inParameters.append(p) @@ -817,7 +925,7 @@ class SalomeProc(ComposedNode): for outParam in s.findall("outParameter-list/outParameter"): p=Parameter() p.name=outParam.findtext("outParameter-name") - p.type=outParam.findtext("outParameter-type") + p.type=typeName(outParam.findtext("outParameter-type")) if debug:print "\toutParameter-name",p.name if debug:print "\toutParameter-type",p.type outParameters.append(p) @@ -841,7 +949,8 @@ class SalomeProc(ComposedNode): text="" for cdata in pyfunc.findall("PyFunc"): if text:text=text+'\n' - text=text+ cdata.text + if cdata.text != '?': + text=text+ cdata.text return text """1 @@ -863,7 +972,7 @@ class SalomeProc(ComposedNode): if debug:print d.tag,":",d p=Parameter() p.name=d.findtext("inParameter-name") - p.type=d.findtext("inParameter-type") + p.type=typeName(d.findtext("inParameter-type")) p.dependency=d.findtext("inParameter-dependency") p.schema=d.findtext("inParameter-schema") p.interpolation=d.findtext("inParameter-interpolation") @@ -875,92 +984,91 @@ class SalomeProc(ComposedNode): if debug:print d.tag,":",d p=Parameter() p.name=d.findtext("outParameter-name") - p.type=d.findtext("outParameter-type") + p.type=typeName(d.findtext("outParameter-type")) p.dependency=d.findtext("outParameter-dependency") p.values=d.findtext("outParameter-values") if debug:print "\toutParameter-name",p.name return p def create_graph(self): - #un graphe est un dictionnaire dont la clé est un noeud et la valeur - #est la liste (en fait un set sans doublon) des noeuds voisins suivants - #for v in graphe (python >= 2.3): parcourt les noeuds du graphe - #for v in graphe[noeud] parcourt les voisins (suivants) de noeud + #a graph is a dict {node:neighbours} + #neighbours is a Set of neighbour nodes (of course) + #for v in graph (python >= 2.3): iterate through graph nodes + #for v in graph[node] iterate through node neighbours G={} - #on cree tous les noeuds avec un voisinage (suivants) vide + #create all nodes without neighbours for n in self.nodes: G[n]=Set() - #on construit le voisinage en fonction des divers liens + #calculate neighbours with links for link in self.links: from_node=self.node_dict[link.from_name] if link.from_param == "Gate" or link.to_param == "Gate": - #control link salome : on ajoute le noeud to_name dans les voisins - if debug:print "ajout control link",link.from_name,link.to_name + #control link salome : add to_name node to neighbours + if debug:print "add control link",link.from_name,link.to_name G[self.node_dict[link.from_name]].add(self.node_dict[link.to_name]) elif from_node.outStreams_dict.has_key(link.from_param): - #lien datastream salome : - # 1- on ajoute le lien dans les listes de liens des noeuds - # 2- on ajoute dans le lien des pointeurs sur les noeuds (from_node et to_node) - if debug:print "ajout stream link",link.from_name,link.to_name + # datastream link : + # 1- add link in link list + # 2- add in link references on from_node and to_node + if debug:print "add stream link",link.from_name,link.to_name self.node_dict[link.to_name].inStreamLinks.append(link) self.node_dict[link.from_name].outStreamLinks.append(link) link.from_node=self.node_dict[link.from_name] link.to_node=self.node_dict[link.to_name] else: - #autre lien salome - #si c'est un lien entre Loop node et EndOfLoop node, on l'ignore - #tous les autres sont conservés + # other salome link + # if link from Loop node to EndOfLoop node, we ignore it + # all others are kept from_node=self.node_dict[link.from_name] to_node=self.node_dict[link.to_name] if isinstance(to_node,LoopNode): - #Est-ce le lien entre EndOfLoop et Loop ? Si oui, on ne le garde pas + # If it's the link from EndOfLoop to Loop , we ignore it if to_node.coupled_node == from_node.name: - if debug:print "lien arriere loop:",from_node,to_node - #lien ignoré + if debug:print "backlink loop:",from_node,to_node + #ignored continue - if debug:print "ajout dataflow link",link.from_name,link.to_name + if debug:print "add dataflow link",link.from_name,link.to_name G[self.node_dict[link.from_name]].add(self.node_dict[link.to_name]) if link.from_param != "DoLoop" and link.to_param != "DoLoop": - #Les liens sur parametre DoLoop servent au superviseur Salome, on les ignore - #on ajoute dans le lien des pointeurs sur les noeuds (from_node et to_node) - #on ajoute ce lien à la liste des liens du noeud cible (to) + #Links on DoLoop are used by Salome supervisor. We ignore them. + #Add in the link references on nodes (from_node and to_node) + #Add this link into the list of links of to_node node. self.node_dict[link.to_name].links.append(link) link.from_node=self.node_dict[link.from_name] link.to_node=self.node_dict[link.to_name] - #Dans un graphe salome avec boucles, les noeuds de tete et de fin - #de boucle sont reliés par 2 liens de sens opposés - #on stocke le noeud de fin dans l'attribut endloop du noeud de tete. + #In a Salome graph with loops, head node and end node are connected + #with 2 opposite links + #Store the endloop in attribute endloop of head node. if link.from_param == "DoLoop" and link.to_param == "DoLoop" \ and is_loop(self.node_dict[link.from_name]) \ and isinstance(self.node_dict[link.to_name],InlineNode): - #on repère le node inline de fin de boucle en le stockant - #dans l'attribut endloop du node loop - #self.node_dict[link.to_name] est le node de fin de boucle - #de self.node_dict[link.from_name] - if debug:print "ajout loop",link.from_name,link.to_name + #Store the end loop inline node in attribute endloop + #self.node_dict[link.to_name] is the end node of the head loop node self.node_dict[link.from_name] + if debug:print "add loop",link.from_name,link.to_name self.node_dict[link.from_name].endloop=self.node_dict[link.to_name] self.node_dict[link.to_name].loop=self.node_dict[link.from_name] for data in self.datas: + if debug:print "datas",data self.node_dict[data.tonode].datas.append(data) self.G=G - #on modifie le graphe en place : - # transformation des boucles a plat en graphe hierarchique + #Transform the graph in place + # Transform one level loops in hierarchical graph self.reduceLoop() - #on peut maintenant créer le schéma de calcul YACS + #Return the hierarchical graph that can be transform into YACS objects. return G def display(self,suivi="sync"): - """Visualise la procedure Salome avec dot""" - #pour visualiser : dot -Tpng salome.dot |display + """Display Salome proc with graphviz (dot file)""" + #to display : dot -Tpng salome.dot |display f=file("salome.dot", 'w') self.write_dot(f) f.close() @@ -968,7 +1076,7 @@ class SalomeProc(ComposedNode): os.system(cmd) def write_dot(self,stream): - """Dumpe la procedure Salome dans stream au format dot""" + """Dump Salome proc into stream with dot format""" stream.write('digraph %s {\nnode [ style="filled" ]\n' % self.name) for node in self.nodes: label = "%s:%s"% (node.name,node.__class__.__name__) @@ -982,8 +1090,8 @@ class SalomeProc(ComposedNode): stream.write(' %s -> %s;\n' % (id(from_node), id(to_node))) stream.write("}\n") -if __name__ == "__main__": +def main(): import traceback usage ="""Usage: %s salomeFile convertedFile where salomeFile is the name of the input schema file (old Salome syntax) @@ -994,7 +1102,7 @@ if __name__ == "__main__": convertedFile=sys.argv[2] except : print usage%(sys.argv[0]) - sys.exit(1) + sys.exit(3) SALOMERuntime.RuntimeSALOME_setRuntime() loader=SalomeLoader() @@ -1004,7 +1112,15 @@ if __name__ == "__main__": s= pilot.SchemaSave(p) s.save(convertedFile) except: - traceback.print_exc() + traceback.print_exc(file=sys.stdout) f=open(convertedFile,'w') f.write("\n") + sys.exit(2) + + logger=p.getLogger("parser") + if not logger.isEmpty(): + print logger.getStr() + sys.exit(1) +if __name__ == "__main__": + main() diff --git a/src/salomeloader/salomeloader.sh b/src/salomeloader/salomeloader.sh new file mode 100755 index 000000000..34ef1d34a --- /dev/null +++ b/src/salomeloader/salomeloader.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env python +import salomeloader +salomeloader.main() diff --git a/src/salomeloader/samples/GeomGraph.xml b/src/salomeloader/samples/GeomGraph.xml new file mode 100644 index 000000000..f56de4313 --- /dev/null +++ b/src/salomeloader/samples/GeomGraph.xml @@ -0,0 +1,496 @@ + + + + + +? + ? + GeomGraph + 1 + ? + +GeomGraph + + +long + SetStudyID__theStudyID + +double + MakeBox__theX1 + +double + MakeBox__theY1 + +double + MakeBox__theZ1 + +double + MakeBox__theX2 + +double + MakeBox__theY2 + +double + MakeBox__theZ2 + +double + TranslateDXDYDZ__theDX + +double + TranslateDXDYDZ__theDY + +double + TranslateDXDYDZ__theDZ + +double + MakeSphere_1__theX + +double + MakeSphere_1__theY + +double + MakeSphere_1__theZ + +double + MakeSphere_1__theRadius + + +GEOM_Object + MakeFuse_1__return + + + 29/10/2004 - 10:52:34 + 6/6/2005 - 10:39:55 + 2.0 + ? + ? + ? + 0 + 0 + + +GEOM_Superv + GEOM_Superv + SetStudyID + 0 + ? + +SetStudyID + + +long + theStudyID + + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + SetStudyID from GEOM_Superv + 14 + 241 + +GEOM_Superv + GEOM_Superv + MakeBox + 0 + ? + +MakeBox + + +double + theX1 + +double + theY1 + +double + theZ1 + +double + theX2 + +double + theY2 + +double + theZ2 + + +GEOM_Object + return + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + MakeBox from GEOM_Superv + 198 + 46 + +GEOM_Superv + GEOM_Superv + MakeCopy + 0 + ? + +MakeCopy + + +GEOM_Object + theOriginal + + +GEOM_Object + return + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + MakeCopy from GEOM_Superv + 383 + 46 + +GEOM_Superv + GEOM_Superv + TranslateDXDYDZ + 0 + ? + +TranslateDXDYDZ + + +GEOM_Object + theObject + +double + theDX + +double + theDY + +double + theDZ + + +GEOM_Object + return + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + TranslateDXDYDZ from GEOM_Superv + 579 + 46 + +GEOM_Superv + GEOM_Superv + MakeCopy_1 + 0 + ? + +MakeCopy + + +GEOM_Object + theOriginal + + +GEOM_Object + return + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + MakeCopy from GEOM_Superv + 384 + 168 + +GEOM_Superv + GEOM_Superv + MakeSphere_1 + 0 + ? + +MakeSphere + + +double + theX + +double + theY + +double + theZ + +double + theRadius + + +GEOM_Object + return + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + MakeSphere from GEOM_Superv + 201 + 332 + +GEOM_Superv + GEOM_Superv + MakeFuse + 0 + ? + +MakeFuse + + +GEOM_Object + theShape1 + +GEOM_Object + theShape2 + + +GEOM_Object + return + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + MakeFuse from GEOM_Superv + 790 + 148 + +GEOM_Superv + GEOM_Superv + MakeFuse_1 + 0 + ? + +MakeFuse + + +GEOM_Object + theShape1 + +GEOM_Object + theShape2 + + +GEOM_Object + return + + + 6/6/2005 - 10:39:55 + 6/6/2005 - 10:39:55 + 2.0 + ? + localhost/FactoryServer + MakeFuse from GEOM_Superv + 993 + 312 + + +SetStudyID + Gate + MakeBox + Gate + + +SetStudyID + Gate + MakeSphere_1 + Gate + + +MakeBox + return + MakeCopy + theOriginal + + +MakeBox + return + MakeCopy_1 + theOriginal + + +MakeCopy + return + TranslateDXDYDZ + theObject + + +TranslateDXDYDZ + return + MakeFuse + theShape1 + + +MakeCopy_1 + return + MakeFuse + theShape2 + + +MakeSphere_1 + return + MakeFuse_1 + theShape2 + + +MakeFuse + return + MakeFuse_1 + theShape1 + + + +GeomGraph + SetStudyID__theStudyID + SetStudyID + theStudyID + +3 + 1 + + +GeomGraph + MakeBox__theX1 + MakeBox + theX1 + +7 + 0 + + +GeomGraph + MakeBox__theY1 + MakeBox + theY1 + +7 + 0 + + +GeomGraph + MakeBox__theZ1 + MakeBox + theZ1 + +7 + 0 + + +GeomGraph + MakeBox__theX2 + MakeBox + theX2 + +7 + 50 + + +GeomGraph + MakeBox__theY2 + MakeBox + theY2 + +7 + 50 + + +GeomGraph + MakeBox__theZ2 + MakeBox + theZ2 + +7 + 50 + + +GeomGraph + TranslateDXDYDZ__theDX + TranslateDXDYDZ + theDX + +7 + 10 + + +GeomGraph + TranslateDXDYDZ__theDY + TranslateDXDYDZ + theDY + +7 + 10 + + +GeomGraph + TranslateDXDYDZ__theDZ + TranslateDXDYDZ + theDZ + +7 + 10 + + +GeomGraph + MakeSphere_1__theX + MakeSphere_1 + theX + +7 + 0 + + +GeomGraph + MakeSphere_1__theY + MakeSphere_1 + theY + +7 + 0 + + +GeomGraph + MakeSphere_1__theZ + MakeSphere_1 + theZ + +7 + 0 + + +GeomGraph + MakeSphere_1__theRadius + MakeSphere_1 + theRadius + +7 + 12 + diff --git a/src/salomeloader/samples/GeomGraphGates.xml b/src/salomeloader/samples/GeomGraphGates.xml new file mode 100644 index 000000000..f93072969 --- /dev/null +++ b/src/salomeloader/samples/GeomGraphGates.xml @@ -0,0 +1,671 @@ + + + + + + ? + ? + GeomGraph + 1 + ? + + GeomGraph + + + long + SetStudyID__theStudyID + + + double + MakeBox__theX1 + + + double + MakeBox__theY1 + + + double + MakeBox__theZ1 + + + double + MakeBox__theX2 + + + double + MakeBox__theY2 + + + double + MakeBox__theZ2 + + + double + TranslateDXDYDZ__theDX + + + double + TranslateDXDYDZ__theDY + + + double + TranslateDXDYDZ__theDZ + + + double + MakeSphere_1__theX + + + double + MakeSphere_1__theY + + + double + MakeSphere_1__theZ + + + double + MakeSphere_1__theRadius + + + + + GEOM_Object + MakeFuse_1__return + + + + + + 29/10/2004 - 10:52:34 + 14/12/2005 - 14:40:22 + 2.0 + ? + ? + ? + 0 + 0 + + + + + GEOM_Superv + GEOM_Superv + SetStudyID + 0 + ? + + SetStudyID + + + long + theStudyID + + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + SetStudyID from GEOM_Superv + 14 + 241 + + + GEOM_Superv + GEOM_Superv + MakeBox + 0 + ? + + MakeBox + + + double + theX1 + + + double + theY1 + + + double + theZ1 + + + double + theX2 + + + double + theY2 + + + double + theZ2 + + + + + GEOM_Object + return + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + MakeBox from GEOM_Superv + 198 + 46 + + + GEOM_Superv + GEOM_Superv + MakeCopy + 0 + ? + + MakeCopy + + + GEOM_Object + theOriginal + + + + + GEOM_Object + return + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + MakeCopy from GEOM_Superv + 383 + 46 + + + GEOM_Superv + GEOM_Superv + TranslateDXDYDZ + 0 + ? + + TranslateDXDYDZ + + + GEOM_Object + theObject + + + double + theDX + + + double + theDY + + + double + theDZ + + + + + GEOM_Object + return + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + TranslateDXDYDZ from GEOM_Superv + 579 + 46 + + + GEOM_Superv + GEOM_Superv + MakeCopy_1 + 0 + ? + + MakeCopy + + + GEOM_Object + theOriginal + + + + + GEOM_Object + return + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + MakeCopy from GEOM_Superv + 384 + 168 + + + GEOM_Superv + GEOM_Superv + MakeSphere_1 + 0 + ? + + MakeSphere + + + double + theX + + + double + theY + + + double + theZ + + + double + theRadius + + + + + GEOM_Object + return + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + MakeSphere from GEOM_Superv + 604 + 348 + + + GEOM_Superv + GEOM_Superv + MakeFuse + 0 + ? + + MakeFuse + + + GEOM_Object + theShape1 + + + GEOM_Object + theShape2 + + + + + GEOM_Object + return + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + MakeFuse from GEOM_Superv + 790 + 148 + + + GEOM_Superv + GEOM_Superv + MakeFuse_1 + 0 + ? + + MakeFuse + + + GEOM_Object + theShape1 + + + GEOM_Object + theShape2 + + + + + GEOM_Object + return + + + + + + 14/12/2005 - 14:39:18 + 14/12/2005 - 14:39:18 + 2.0 + ? + localhost/FactoryServer + MakeFuse from GEOM_Superv + 993 + 312 + + + + + SetStudyID + Gate + MakeBox + Gate + + + + MakeBox + return + MakeCopy + theOriginal + + + + MakeBox + return + MakeCopy_1 + theOriginal + + + + MakeBox + Gate + MakeCopy + Gate + + + + MakeCopy + return + TranslateDXDYDZ + theObject + + + + MakeCopy + Gate + MakeCopy_1 + Gate + + + 363 + 263 + + + 564 + 141 + + + + + TranslateDXDYDZ + return + MakeFuse + theShape1 + + + + TranslateDXDYDZ + Gate + MakeFuse + Gate + + + + MakeCopy_1 + return + MakeFuse + theShape2 + + + + MakeCopy_1 + Gate + MakeSphere_1 + Gate + + + 572 + 503 + + + 572 + 263 + + + + + MakeSphere_1 + return + MakeFuse_1 + theShape2 + + + + MakeSphere_1 + Gate + TranslateDXDYDZ + Gate + + + + MakeFuse + return + MakeFuse_1 + theShape1 + + + + MakeFuse + Gate + MakeFuse_1 + Gate + + + + + + GeomGraph + SetStudyID__theStudyID + SetStudyID + theStudyID + + 3 + 1 + + + + + GeomGraph + MakeBox__theX1 + MakeBox + theX1 + + 7 + 0 + + + + + GeomGraph + MakeBox__theY1 + MakeBox + theY1 + + 7 + 0 + + + + + GeomGraph + MakeBox__theZ1 + MakeBox + theZ1 + + 7 + 0 + + + + + GeomGraph + MakeBox__theX2 + MakeBox + theX2 + + 7 + 50 + + + + + GeomGraph + MakeBox__theY2 + MakeBox + theY2 + + 7 + 50 + + + + + GeomGraph + MakeBox__theZ2 + MakeBox + theZ2 + + 7 + 50 + + + + + GeomGraph + TranslateDXDYDZ__theDX + TranslateDXDYDZ + theDX + + 7 + 10 + + + + + GeomGraph + TranslateDXDYDZ__theDY + TranslateDXDYDZ + theDY + + 7 + 10 + + + + + GeomGraph + TranslateDXDYDZ__theDZ + TranslateDXDYDZ + theDZ + + 7 + 10 + + + + + GeomGraph + MakeSphere_1__theX + MakeSphere_1 + theX + + 7 + 0 + + + + + GeomGraph + MakeSphere_1__theY + MakeSphere_1 + theY + + 7 + 0 + + + + + GeomGraph + MakeSphere_1__theZ + MakeSphere_1 + theZ + + 7 + 0 + + + + + GeomGraph + MakeSphere_1__theRadius + MakeSphere_1 + theRadius + + 7 + 12 + + + + + + + diff --git a/src/salomeloader/samples/GeomGraphGates_py.xml b/src/salomeloader/samples/GeomGraphGates_py.xml new file mode 100644 index 000000000..7d1418042 --- /dev/null +++ b/src/salomeloader/samples/GeomGraphGates_py.xml @@ -0,0 +1,754 @@ + + + + + + ? + ? + aNewDataFlow_1_4_2_1_1_2_2_1_1 + 1 + ? + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + + + double + MakeBox1__x1 + + + double + MakeBox1__y1 + + + double + MakeBox1__z1 + + + double + MakeBox1__x2 + + + double + MakeBox1__y2 + + + double + MakeBox1__z2 + + + double + MakeSphere_1__x1 + + + double + MakeSphere_1__y1 + + + double + MakeSphere_1__z1 + + + double + MakeSphere_1__radius + + + double + MakeTranslation_1__x1 + + + double + MakeTranslation_1__y1 + + + double + MakeTranslation_1__z1 + + + + + objref + MakeFuse_2__shape + + + + + + 25/8/2004 - 16:28:50 + 14/12/2005 - 14:41:59 + 2.0 + ? + ? + ? + 0 + 0 + + + + + ? + ? + gag + 3 + ? + + gag + + + + + + + gag + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 0 + 123 + + + ? + ? + MakeBox1 + 3 + ? + + MakeBox1 + + + double + x1 + + + double + y1 + + + double + z1 + + + double + x2 + + + double + y2 + + + double + z2 + + + + + objref + shape + + + + + + + MakeBox1 + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 194 + 3 + + + ? + ? + MakeCopy_1 + 3 + ? + + MakeCopy_1 + + + objref + shape1 + + + + + objref + shape + + + + + + + MakeCopy_1 + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 389 + 3 + + + ? + ? + MakeCopy_2 + 3 + ? + + MakeCopy_2 + + + objref + shape1 + + + + + objref + shape + + + + + + + MakeCopy_2 + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 389 + 136 + + + ? + ? + MakeSphere_1 + 3 + ? + + MakeSphere_1 + + + double + x1 + + + double + y1 + + + double + z1 + + + double + radius + + + + + objref + shape + + + + + + + MakeSphere_1 + + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 609 + 313 + + + ? + ? + MakeTranslation_1 + 3 + ? + + MakeTranslation_1 + + + objref + shape1 + + + double + x1 + + + double + y1 + + + double + z1 + + + + + objref + shape + + + + + + + MakeTranslation_1 + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 596 + 3 + + + ? + ? + MakeFuse_1 + 3 + ? + + MakeFuse_1 + + + objref + shape1 + + + objref + shape2 + + + + + objref + shape + + + + + + + MakeFuse_1 + + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 823 + 116 + + + ? + ? + MakeFuse_2 + 3 + ? + + MakeFuse_2 + + + objref + shape1 + + + objref + shape2 + + + + + objref + shape + + + + + + + MakeFuse_2 + + + + + + + + + + + + + + + 14/12/2005 - 14:41:8 + 14/12/2005 - 14:41:8 + 2.0 + ? + ? + Compute Node + 1049 + 295 + + + + + gag + Gate + MakeBox1 + Gate + + + + MakeBox1 + shape + MakeCopy_1 + shape1 + + + + MakeBox1 + shape + MakeCopy_2 + shape1 + + + 384 + 207 + + + + + MakeBox1 + Gate + MakeCopy_1 + Gate + + + + MakeCopy_1 + shape + MakeTranslation_1 + shape1 + + + + MakeCopy_1 + Gate + MakeCopy_2 + Gate + + + 366 + 231 + + + 570 + 98 + + + + + MakeCopy_2 + shape + MakeFuse_1 + shape2 + + + 674 + 207 + + + + + MakeCopy_2 + Gate + MakeSphere_1 + Gate + + + 554 + 468 + + + + + MakeSphere_1 + shape + MakeFuse_2 + shape2 + + + + MakeSphere_1 + Gate + MakeTranslation_1 + Gate + + + 573 + 158 + + + 796 + 468 + + + + + MakeTranslation_1 + shape + MakeFuse_1 + shape1 + + + + MakeTranslation_1 + Gate + MakeFuse_1 + Gate + + + + MakeFuse_1 + shape + MakeFuse_2 + shape1 + + + 1017 + 366 + + + 1017 + 187 + + + + + MakeFuse_1 + Gate + MakeFuse_2 + Gate + + + 987 + 410 + + + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__x1 + MakeBox1 + x1 + + 7 + 0 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__y1 + MakeBox1 + y1 + + 7 + 0 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__z1 + MakeBox1 + z1 + + 7 + 0 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__x2 + MakeBox1 + x2 + + 7 + 50 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__y2 + MakeBox1 + y2 + + 7 + 50 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__z2 + MakeBox1 + z2 + + 7 + 50 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__x1 + MakeSphere_1 + x1 + + 7 + 0 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__y1 + MakeSphere_1 + y1 + + 7 + 0 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__z1 + MakeSphere_1 + z1 + + 7 + 0 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__radius + MakeSphere_1 + radius + + 7 + 12 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeTranslation_1__x1 + MakeTranslation_1 + x1 + + 7 + 25 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeTranslation_1__y1 + MakeTranslation_1 + y1 + + 7 + 25 + + + + + aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeTranslation_1__z1 + MakeTranslation_1 + z1 + + 7 + 25 + + + + + + + diff --git a/src/salomeloader/samples/GeomGraph_py.xml b/src/salomeloader/samples/GeomGraph_py.xml new file mode 100644 index 000000000..60c55af14 --- /dev/null +++ b/src/salomeloader/samples/GeomGraph_py.xml @@ -0,0 +1,560 @@ + + + + + +? + ? + aNewDataFlow_1_4_2_1_1_2_2_1_1 + 1 + ? + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + + +double + MakeBox1__x1 + +double + MakeBox1__y1 + +double + MakeBox1__z1 + +double + MakeBox1__x2 + +double + MakeBox1__y2 + +double + MakeBox1__z2 + +double + MakeSphere_1__x1 + +double + MakeSphere_1__y1 + +double + MakeSphere_1__z1 + +double + MakeSphere_1__radius + +double + MakeTranslation_1__x1 + +double + MakeTranslation_1__y1 + +double + MakeTranslation_1__z1 + + +objref + MakeFuse_2__shape + + + 25/8/2004 - 16:28:50 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + ? + 0 + 0 + + +? + ? + gag + 3 + ? + +gag + + + + + +gag + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 0 + 123 + +? + ? + MakeBox1 + 3 + ? + +MakeBox1 + + +double + x1 + +double + y1 + +double + z1 + +double + x2 + +double + y2 + +double + z2 + + +objref + shape + + + +MakeBox1 + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 194 + 3 + +? + ? + MakeCopy_1 + 3 + ? + +MakeCopy_1 + + +objref + shape1 + + +objref + shape + + + +MakeCopy_1 + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 389 + 3 + +? + ? + MakeCopy_2 + 3 + ? + +MakeCopy_2 + + +objref + shape1 + + +objref + shape + + + +MakeCopy_2 + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 389 + 136 + +? + ? + MakeSphere_1 + 3 + ? + +MakeSphere_1 + + +double + x1 + +double + y1 + +double + z1 + +double + radius + + +objref + shape + + + +MakeSphere_1 + + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 203 + 315 + +? + ? + MakeTranslation_1 + 3 + ? + +MakeTranslation_1 + + +objref + shape1 + +double + x1 + +double + y1 + +double + z1 + + +objref + shape + + + +MakeTranslation_1 + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 596 + 3 + +? + ? + MakeFuse_1 + 3 + ? + +MakeFuse_1 + + +objref + shape1 + +objref + shape2 + + +objref + shape + + + +MakeFuse_1 + + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 823 + 116 + +? + ? + MakeFuse_2 + 3 + ? + +MakeFuse_2 + + +objref + shape1 + +objref + shape2 + + +objref + shape + + + +MakeFuse_2 + + + + + + + + + + + + + + + + 29/10/2004 - 10:50:25 + 29/10/2004 - 10:50:25 + 2.0 + ? + ? + Compute Node + 1049 + 295 + + +gag + Gate + MakeBox1 + Gate + + +gag + Gate + MakeSphere_1 + Gate + + +164 + 470 + +164 + 265 + +MakeBox1 + shape + MakeCopy_1 + shape1 + + +MakeBox1 + shape + MakeCopy_2 + shape1 + + +384 + 207 + +MakeCopy_1 + shape + MakeTranslation_1 + shape1 + + +MakeCopy_2 + shape + MakeFuse_1 + shape2 + + +674 + 207 + +MakeSphere_1 + shape + MakeFuse_2 + shape2 + + +MakeTranslation_1 + shape + MakeFuse_1 + shape1 + + +MakeFuse_1 + shape + MakeFuse_2 + shape1 + + +1017 + 366 + +1017 + 187 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__x1 + MakeBox1 + x1 + +7 + 0 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__y1 + MakeBox1 + y1 + +7 + 0 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__z1 + MakeBox1 + z1 + +7 + 0 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__x2 + MakeBox1 + x2 + +7 + 50 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__y2 + MakeBox1 + y2 + +7 + 50 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeBox1__z2 + MakeBox1 + z2 + +7 + 50 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__x1 + MakeSphere_1 + x1 + +7 + 0 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__y1 + MakeSphere_1 + y1 + +7 + 0 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__z1 + MakeSphere_1 + z1 + +7 + 0 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeSphere_1__radius + MakeSphere_1 + radius + +7 + 12 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeTranslation_1__x1 + MakeTranslation_1 + x1 + +7 + 25 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeTranslation_1__y1 + MakeTranslation_1 + y1 + +7 + 25 + + +aNewDataFlow_1_4_2_1_1_2_2_1_1 + MakeTranslation_1__z1 + MakeTranslation_1 + z1 + +7 + 25 + diff --git a/src/salomeloader/samples/Graph_couronne.xml b/src/salomeloader/samples/Graph_couronne.xml new file mode 100644 index 000000000..d65850b8d --- /dev/null +++ b/src/salomeloader/samples/Graph_couronne.xml @@ -0,0 +1,836 @@ + + + + + + ? + ? + test_superv_basic_loop_1_1 + 1 + ? + + test_superv_basic_loop_1_1 + + + long + Loop__index + + + long + Loop__min + + + double + MakeSphere__theY + + + double + MakeSphere__theZ + + + + + long + EndOfLoop__index + + + long + EndOfLoop__min + + + long + EndOfLoop__max + + + objref + EndOfLoop__couronne + + + double + EndOfLoop__Rcouronne + + + double + EndOfLoop__Rsphere + + + + + + 2/5/2003 - 13:43:38 + 18/10/2006 - 9:54:10 + 1.04 + ? + ? + ? + 0 + 0 + + + + + ? + ? + Loop + 4 + EndOfLoop + + Loop + + + long + index + + + long + min + + + long + max + + + GEOM_Object + couronne + + + double + Rcouronne + + + double + Rsphere + + + + + long + index + + + long + min + + + long + max + + + GEOM_Object + couronne + + + double + Rcouronne + + + double + Rsphere + + + + + + + Init + + min : ]]> + + + + + + + + + + + More + + + index : ]]> + + + + + + + + + Next + + + + + + + + + + 18/10/2006 - 9:33:31 + 18/10/2006 - 9:33:31 + 2.0 + ? + ? + Compute Node + 268 + 168 + + + ? + ? + EndOfLoop + 5 + Loop + + EndOfLoop + + + long + index + + + long + min + + + long + max + + + objref + couronne + + + double + Rcouronne + + + double + Rsphere + + + + + long + index + + + long + min + + + long + max + + + objref + couronne + + + double + Rcouronne + + + double + Rsphere + + + + + + + EndInit + + + + 18/10/2006 - 9:33:31 + 18/10/2006 - 9:33:31 + 2.0 + ? + ? + Compute Node + 1069 + 202 + + + ? + ? + Init_parameters + 3 + ? + + Init_parameters + + + + double + Rsphere + + + double + Rcouronne + + + long + Nbspheres + + + + + + + Init_parameters + + + + + + + + 18/10/2006 - 9:33:31 + 18/10/2006 - 9:33:31 + 2.0 + ? + ? + Compute Node + 8 + 7 + + + GEOM_Superv + GEOM_Superv + MakeSphere + 0 + ? + + MakeSphere + + + double + theX + + + double + theY + + + double + theZ + + + double + theRadius + + + + + GEOM_Object + return + + + + + + 18/10/2006 - 9:33:31 + 18/10/2006 - 9:33:31 + 2.0 + ? + localhost/FactoryServer + MakeSphere from GEOM_Superv + 78 + 394 + + + GEOM_Superv + GEOM_Superv + MakeSphere_1 + 0 + ? + + MakeSphere + + + double + theX + + + double + theY + + + double + theZ + + + double + theRadius + + + + + GEOM_Object + return + + + + + + 18/10/2006 - 9:33:31 + 18/10/2006 - 9:33:31 + 2.0 + ? + localhost/FactoryServer + MakeSphere from GEOM_Superv + 675 + 67 + + + GEOM_Superv + GEOM_Superv + MakeFuse + 0 + ? + + MakeFuse + + + GEOM_Object + theShape1 + + + GEOM_Object + theShape2 + + + + + GEOM_Object + return + + + + + + 18/10/2006 - 9:33:31 + 18/10/2006 - 9:33:31 + 2.0 + ? + localhost/FactoryServer + MakeFuse from GEOM_Superv + 871 + 222 + + + ? + ? + nouvelle_position + 3 + ? + + nouvelle_position + + + double + Rcouronne + + + double + NbSphere + + + long + index + + + + + double + x + + + double + y + + + double + z + + + + + + + nouvelle_position + + + + + + + + + + + + + + + 18/10/2006 - 9:40:1 + 18/10/2006 - 9:40:1 + 3.0 + ? + ? + Compute Node + 481 + 67 + + + + + Loop + DoLoop + EndOfLoop + DoLoop + + + + Loop + index + EndOfLoop + index + + + + Loop + index + nouvelle_position + index + + + 436 + 178 + + + + + Loop + min + EndOfLoop + min + + + + Loop + max + EndOfLoop + max + + + + Loop + max + nouvelle_position + NbSphere + + + 445 + 159 + + + 445 + 239 + + + + + Loop + couronne + MakeFuse + theShape2 + + + 856 + 313 + + + 856 + 344 + + + 479 + 344 + + + 479 + 259 + + + + + Loop + Rcouronne + EndOfLoop + Rcouronne + + + + Loop + Rcouronne + nouvelle_position + Rcouronne + + + 450 + 138 + + + 451 + 279 + + + + + Loop + Rsphere + EndOfLoop + Rsphere + + + + Loop + Rsphere + MakeSphere_1 + theRadius + + + 657 + 198 + + + 657 + 299 + + + + + EndOfLoop + DoLoop + Loop + DoLoop + + + + Init_parameters + Rsphere + Loop + Rsphere + + + 208 + 299 + + + 208 + 78 + + + + + Init_parameters + Rsphere + MakeSphere + theRadius + + + 36 + 525 + + + 36 + 299 + + + 208 + 299 + + + 208 + 78 + + + + + Init_parameters + Rcouronne + Loop + Rcouronne + + + 193 + 279 + + + 193 + 98 + + + + + Init_parameters + Rcouronne + MakeSphere + theX + + + 60 + 465 + + + 61 + 280 + + + 193 + 279 + + + 193 + 98 + + + + + Init_parameters + Nbspheres + Loop + max + + + 188 + 239 + + + 188 + 118 + + + + + MakeSphere + return + Loop + couronne + + + 226 + 260 + + + 227 + 371 + + + 265 + 371 + + + 265 + 465 + + + + + MakeSphere_1 + return + MakeFuse + theShape1 + + + 854 + 293 + + + 854 + 159 + + + + + MakeFuse + return + EndOfLoop + couronne + + + + nouvelle_position + x + MakeSphere_1 + theX + + + + nouvelle_position + y + MakeSphere_1 + theY + + + + nouvelle_position + z + MakeSphere_1 + theZ + + + + + + test_superv_basic_loop_1_1 + Loop__index + Loop + index + + 3 + 0 + + + + + test_superv_basic_loop_1_1 + Loop__min + Loop + min + + 3 + 0 + + + + + test_superv_basic_loop_1_1 + MakeSphere__theY + MakeSphere + theY + + 7 + 0 + + + + + test_superv_basic_loop_1_1 + MakeSphere__theZ + MakeSphere + theZ + + 7 + 0 + + + + + + + diff --git a/src/salomeloader/samples/testvisu20.xml b/src/salomeloader/samples/testvisu20.xml new file mode 100644 index 000000000..10f9867f0 --- /dev/null +++ b/src/salomeloader/samples/testvisu20.xml @@ -0,0 +1,494 @@ + + + + + +? + ? + TestVisu20 + 1 + ? + +aNewDataFlow_1 + + +long + Init__index + +long + Init__min + +long + Init__max + +double + Init__x1 + + +long + EndOfInit__index + +long + EndOfInit__min + +long + EndOfInit__max + +objref + EndOfInit__aVisu + +objref + EndOfInit__aView + +objref + EndOfInit__aResult + +double + EndOfInit__x1 + + + 13/11/2003 - 11:15:53 + 8/4/2005 - 14:3:47 + 1.05 + ? + ? + ? + 0 + 0 + + +? + ? + InitDisplay + 3 + ? + +InitDisplay + + + +objref + aVisu + +objref + aView + +objref + myResult + + + +InitDisplay + + + + + + + + + + + + + + + + + + + + + aVisu ", aVisu ]]> + + + aViewManager ", aViewManager ]]> + + + + aView ", aView ]]> + + + + + myResult ", myResult ]]> + + + 8/4/2005 - 14:3:47 + 8/4/2005 - 14:3:47 + 1.05 + ? + ? + Compute Node + 0 + 46 + +? + ? + Init + 4 + EndOfInit + +Init + + +long + index + +long + min + +long + max + +objref + aVisu + +objref + aView + +objref + aResult + +double + x1 + + +long + index + +long + min + +long + max + +objref + aVisu + +objref + aView + +objref + aResult + +double + x1 + + + +Init + + = min : ]]> + + + + + + +More + + = index : ]]> + + + + + + +Next + + + + + + 8/4/2005 - 14:3:47 + 8/4/2005 - 14:3:47 + 1.05 + ? + ? + Compute Node + 190 + 4 + +? + ? + EndOfInit + 5 + Init + +EndOfInit + + +long + index + +long + min + +long + max + +objref + aVisu + +objref + aView + +objref + aResult + +double + x1 + + +long + index + +long + min + +long + max + +objref + aVisu + +objref + aView + +objref + aResult + +double + x1 + + + +? + + 8/4/2005 - 14:3:47 + 8/4/2005 - 14:3:47 + 1.05 + ? + ? + Compute Node + 553 + 5 + +? + ? + DisplayVitesse + 3 + ? + +DisplayVitesse + + +long + index + +objref + aVisu + +objref + aView + +objref + aResult + +double + x1 + + +objref + theResult + + + +DisplayVitesse + + + + + + + + + + + + + + + + + + + + + + + + + + + 8/4/2005 - 14:3:47 + 8/4/2005 - 14:3:47 + 1.05 + ? + ? + Compute Node + 374 + 16 + + +InitDisplay + aVisu + Init + aVisu + + +InitDisplay + aView + Init + aView + + +InitDisplay + myResult + Init + aResult + + +Init + DoLoop + EndOfInit + DoLoop + + +Init + index + EndOfInit + index + + +Init + index + DisplayVitesse + index + + +351 + 96 + +350 + 38 + +Init + min + EndOfInit + min + + +Init + max + EndOfInit + max + + +Init + aVisu + EndOfInit + aVisu + + +Init + aVisu + DisplayVitesse + aVisu + + +Init + aView + EndOfInit + aView + + +Init + aView + DisplayVitesse + aView + + +Init + aResult + DisplayVitesse + aResult + + +Init + x1 + EndOfInit + x1 + + +Init + x1 + DisplayVitesse + x1 + + +EndOfInit + DoLoop + Init + DoLoop + + +DisplayVitesse + theResult + EndOfInit + aResult + + +548 + 183 + +548 + 97 + + +TestVisu20 + Init__index + Init + index + +3 + 1 + + +TestVisu20 + Init__min + Init + min + +3 + 1 + + +TestVisu20 + Init__max + Init + max + +3 + 100 + + +TestVisu20 + Init__x1 + Init + x1 + +7 + 1 + diff --git a/src/wrappergen/src/Makefile.am b/src/wrappergen/src/Makefile.am index cbb844717..b2299827b 100644 --- a/src/wrappergen/src/Makefile.am +++ b/src/wrappergen/src/Makefile.am @@ -1,9 +1,9 @@ bindir=${prefix}/bin/HXX2SALOME_Test -ENV_SH=${bindir}/env_HXX2SALOME.sh -ENV_CSH=${bindir}/env_HXX2SALOME.csh +ENV_SH=$(DESTDIR)${bindir}/env_HXX2SALOME.sh +ENV_CSH=$(DESTDIR)${bindir}/env_HXX2SALOME.csh -bin_SCRIPTS= hxx2salome hxx2salome_check hxx2salome_cpp hxx2salome_corba \ +HXX2SALOMESCRIPTS = hxx2salome hxx2salome_check hxx2salome_cpp hxx2salome_corba \ parse01.awk \ parse0.awk \ parse1.awk \ @@ -16,18 +16,27 @@ bin_SCRIPTS= hxx2salome hxx2salome_check hxx2salome_cpp hxx2salome_corba \ runIDLparser \ compile_HXX2SALOME_GENERIC_CLASS_NAME.sh +bin_SCRIPTS= $(HXX2SALOMESCRIPTS) + +EXTRA_DIST = $(HXX2SALOMESCRIPTS) HXX2SALOME_GENERIC_CLASS_NAME_SRC install-exec-hook: install_sh install_csh - \cp -rf ${srcdir}/HXX2SALOME_GENERIC_CLASS_NAME_SRC ${bindir} + \cp -rf ${srcdir}/HXX2SALOME_GENERIC_CLASS_NAME_SRC $(DESTDIR)${bindir} install_sh: echo "#------ HXX2SALOME ------" > ${ENV_SH} - echo "export HXX2SALOME_ROOT_DIR=${bindir}" >> ${ENV_SH} + echo "export HXX2SALOME_ROOT_DIR=$(DESTDIR)${bindir}" >> ${ENV_SH} echo "export PATH=\$${HXX2SALOME_ROOT_DIR}:\$${PATH}" >> ${ENV_SH} echo "##" >> ${ENV_SH} install_csh: echo "#------ HXX2SALOME ------" > ${ENV_CSH} - echo "setenv HXX2SALOME_ROOT_DIR ${bindir}" >> ${ENV_CSH} + echo "setenv HXX2SALOME_ROOT_DIR $(DESTDIR)${bindir}" >> ${ENV_CSH} echo "setenv PATH \$${HXX2SALOME_ROOT_DIR}:\$${PATH}" >> ${ENV_CSH} echo "##" >> ${ENV_CSH} + +uninstall-local: + if test -d $(DESTDIR)$(bindir)/HXX2SALOME_GENERIC_CLASS_NAME_SRC; then \ + chmod -R +w $(DESTDIR)$(bindir)/HXX2SALOME_GENERIC_CLASS_NAME_SRC ; fi + rm -rf $(DESTDIR)$(bindir)/HXX2SALOME_GENERIC_CLASS_NAME_SRC + rm -rf $(ENV_CSH) ${ENV_SH} diff --git a/src/yacsloader/LoadState.cxx b/src/yacsloader/LoadState.cxx index 10bc40637..a1b6ef6df 100644 --- a/src/yacsloader/LoadState.cxx +++ b/src/yacsloader/LoadState.cxx @@ -47,7 +47,7 @@ void stateParser::init(const xmlChar** p, xmlParserBase* father) _state = XMLNOCONTEXT; _father = father; _stackState.push(_state); - _nodeStateValue["INITED"] =YACS::INITED; + _nodeStateValue["READY"] =YACS::READY; _nodeStateValue["TOLOAD"] =YACS::TOLOAD; _nodeStateValue["LOADED"] =YACS::LOADED; _nodeStateValue["TOACTIVATE"] =YACS::TOACTIVATE; diff --git a/src/yacsloader/Makefile.am b/src/yacsloader/Makefile.am index ff401bdc8..2d53b2383 100644 --- a/src/yacsloader/Makefile.am +++ b/src/yacsloader/Makefile.am @@ -8,26 +8,38 @@ bin_PROGRAMS=driver debugger resume lib_LTLIBRARIES = libYACSloader.la libYACSloader_la_SOURCES = \ - parsers.cxx LoadState.cxx xmlParserBase.cxx \ + parsers.cxx parserBase.cxx dataParsers.cxx typeParsers.cxx \ + propertyParsers.cxx containerParsers.cxx xmlrpcParsers.cxx \ + rootParser.cxx codeParsers.cxx \ + LoadState.cxx xmlParserBase.cxx ProcCataLoader.cxx \ $(__dummy__) +salomeinclude_HEADERS = \ +blocParsers.hxx codeParsers.hxx containerParsers.hxx dataParsers.hxx factory.hxx \ +linkParsers.hxx LoadState.hxx loopParsers.hxx nodeParsers.hxx outputParsers.hxx \ +parserBase.hxx parsers.hxx portParsers.hxx presetParsers.hxx ProcCataLoader.hxx \ +procParsers.hxx propertyParsers.hxx rootParser.hxx switchParsers.hxx \ +typeParsers.hxx xmlParserBase.hxx xmlrpcParsers.hxx + EXTRA_libYACSloader_la_SOURCES = \ $(__dummy__) -libYACSloader_la_LIBADD = ../engine/libYACSEngine.la +libYACSloader_la_LIBADD = ../engine/libYACSlibEngine.la +libYACSloader_la_LDFLAGS = $(EXPAT_LIBS) AM_CXXFLAGS = \ $(THREAD_DEF) \ $(PYTHON_CPPFLAGS) \ $(OMNIORB_INCLUDES) \ $(OMNIORB_CXXFLAGS) \ + $(EXPAT_INCLUDES) \ -I$(srcdir) \ -I$(srcdir)/../bases \ - -I$(srcdir)/../engine \ - -I$(srcdir)/../runtime + -I$(srcdir)/../engine if SALOME_KERNEL SALOME_LIBS=-L$(KERNEL_ROOT_DIR)/lib/salome -lSalomeLifeCycleCORBA +SALOME_INCL_PATH=-I$(KERNEL_ROOT_DIR)/include/salome endif @@ -35,6 +47,7 @@ driver_SOURCES = driver.cxx driver_CXXFLAGS = -g -DYACS_PTHREAD \ $(PYTHON_CPPFLAGS) \ + $(SALOME_INCL_PATH) \ $(OMNIORB_INCLUDES) \ $(OMNIORB_CXXFLAGS) \ -I$(srcdir)/../bases \ @@ -43,13 +56,13 @@ driver_CXXFLAGS = -g -DYACS_PTHREAD \ driver_LDADD = libYACSloader.la \ ../runtime/libYACSRuntimeSALOME.la \ - ../engine/libYACSEngine.la \ + ../engine/libYACSlibEngine.la \ $(SALOME_LIBS) \ $(OMNIORB_LIBS) \ $(PYTHON_LDFLAGS) \ $(PYTHON_EXTRA_LIBS) -driver_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -lexpat -pthread -lxml2 +driver_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -pthread $(EXPAT_LIBS) $(LIBXML_LIBS) resume_SOURCES = resume.cxx @@ -64,13 +77,13 @@ resume_CXXFLAGS = -g -DYACS_PTHREAD \ resume_LDADD = libYACSloader.la \ ../runtime/libYACSRuntimeSALOME.la \ - ../engine/libYACSEngine.la \ + ../engine/libYACSlibEngine.la \ $(SALOME_LIBS) \ $(OMNIORB_LIBS) \ $(PYTHON_LDFLAGS) \ $(PYTHON_EXTRA_LIBS) -resume_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -lexpat -pthread -lxml2 +resume_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -pthread $(EXPAT_LIBS) $(LIBXML_LIBS) debugger_SOURCES = debugger.cxx @@ -85,20 +98,25 @@ debugger_CXXFLAGS = -g -DYACS_PTHREAD \ debugger_LDADD = libYACSloader.la \ ../runtime/libYACSRuntimeSALOME.la \ - ../engine/libYACSEngine.la \ + ../engine/libYACSlibEngine.la \ $(SALOME_LIBS) \ $(OMNIORB_LIBS) \ $(PYTHON_LDFLAGS) \ $(PYTHON_EXTRA_LIBS) -debugger_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -lexpat -pthread -lxml2 +debugger_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -pthread $(EXPAT_LIBS) $(LIBXML_LIBS) SWIG_PYTHON_INCLUDES = -noexcept -I$(srcdir)/../bases -I$(srcdir)/../engine BUILT_SOURCES = loaderWRAP.cxx -pkgpython_PYTHON = loader.py -pkgpyexec_LTLIBRARIES = _loader.la +SWIGINCLUDES=parsers.hxx LoadState.hxx xmlParserBase.hxx ProcCataLoader.hxx ../engine/engtypemaps.i ../engine/pilot.i + +loaderWRAP.cxx loaderWRAP.h: loader.i $(SWIGINCLUDES) + $(SWIG) $(SWIG_PYTHON_OPT) $(SWIG_PYTHON_INCLUDES) $(MYSWIG_FLAGS) -o loaderWRAP.cxx $(srcdir)/loader.i + +salomepython_PYTHON = loader.py +salomepyexec_LTLIBRARIES = _loader.la _loader_la_SOURCES = \ loaderWRAP.cxx @@ -109,13 +127,15 @@ _loader_la_CXXFLAGS = \ $(OMNIORB_INCLUDES) \ $(OMNIORB_CXXFLAGS) \ -I$(srcdir)/../bases \ - -I$(srcdir)/../engine \ - -I$(srcdir)/../runtime + -I$(srcdir)/../engine -_loader_la_LDFLAGS = -module -lexpat -pthread -lxml2 +_loader_la_LDFLAGS = -module -_loader_la_LIBADD = libYACSloader.la \ - ../runtime/libYACSRuntimeSALOME.la \ - ../engine/libYACSEngine.la +_loader_la_LIBADD = libYACSloader.la $(OMNIORB_LIBS) + +EXTRA_DIST = loader.i samples + +dist-hook: + rm -rf `find $(distdir) -name CVS` include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/yacsloader/ProcCataLoader.cxx b/src/yacsloader/ProcCataLoader.cxx new file mode 100644 index 000000000..9fe3a9f22 --- /dev/null +++ b/src/yacsloader/ProcCataLoader.cxx @@ -0,0 +1,97 @@ +#include "ProcCataLoader.hxx" +#include "parsers.hxx" +#include "Proc.hxx" +#include "Logger.hxx" +#include "TypeCode.hxx" + +#include +#include +#include +#include + + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +using namespace YACS::ENGINE; + +ProcCataLoader::ProcCataLoader(YACS::YACSLoader* xmlLoader,const std::string& path):CatalogLoader(path),_xmlLoader(xmlLoader) +{ + //path should be a file path +} + +ProcCataLoader::~ProcCataLoader() +{ + DEBTRACE ("ProcCataLoader::~ProcCataLoader"); +} + +void ProcCataLoader::loadCata(Catalog* cata) +{ + DEBTRACE("ProcCataLoader::load"); + Proc* p; + try + { + p=_xmlLoader->load(_path.c_str()); + if(p==0) + { + std::string msg="the file is probably not a YACS schema file"; + cata->setErrors(msg); + std::cerr << msg << std::endl; + return; + } + } + catch (YACS::Exception& e) + { + std::string msg="Caught a YACS exception"; + msg=msg + e.what(); + std::cerr << msg << std::endl; + cata->setErrors(msg); + return ; + } + catch (const std::invalid_argument& e) + { + cata->setErrors(e.what()); + return ; + } + catch (const std::ios_base::failure&) + { + std::string msg="Caught an io failure exception"; + std::cerr << msg << std::endl; + cata->setErrors(msg); + return ; + } + + //Get the parser logger + Logger* logger=p->getLogger("parser"); + //Print errors logged if any + if(!logger->isEmpty()) + { + std::string msg=logger->getStr(); + std::cerr << msg << std::endl; + cata->setErrors(msg); + } + + std::map& typeMap=cata->_typeMap; + std::map& nodeMap=cata->_nodeMap; + std::map& composednodeMap=cata->_composednodeMap; + std::map& componentMap=cata->_componentMap; + + std::map::iterator it=p->typeMap.begin(); + while(it != p->typeMap.end()) + { + typeMap[it->first]=it->second; + it->second->incrRef(); + it++; + } + + std::list s=p->getChildren(); + for(std::list::iterator iter=s.begin();iter!=s.end();iter++) + { + YACS::ENGINE::ComposedNode * cnode= dynamic_cast(*iter); + if(cnode) + composednodeMap[cnode->getName()]=(YACS::ENGINE::ComposedNode *) cnode->clone(0); + else + nodeMap[(*iter)->getName()]=(*iter)->clone(0); + } + delete p; +} diff --git a/src/yacsloader/ProcCataLoader.hxx b/src/yacsloader/ProcCataLoader.hxx new file mode 100644 index 000000000..85459bf40 --- /dev/null +++ b/src/yacsloader/ProcCataLoader.hxx @@ -0,0 +1,30 @@ +#ifndef _PROCCATALOADER_HXX_ +#define _PROCCATALOADER_HXX_ + +#include "Catalog.hxx" + +#include +#include +#include + +namespace YACS +{ + class YACSLoader; + + namespace ENGINE + { + class ProcCataLoader: public CatalogLoader + { + public: + ProcCataLoader(YACS::YACSLoader* xmlLoader):CatalogLoader(),_xmlLoader(xmlLoader){}; + ProcCataLoader(YACS::YACSLoader* xmlLoader,const std::string& path); + virtual ~ProcCataLoader(); + virtual void loadCata(Catalog* cata); + virtual CatalogLoader* newLoader(const std::string& path) {return new ProcCataLoader(_xmlLoader,path);} + protected: + YACS::YACSLoader* _xmlLoader; + }; + } +} + +#endif diff --git a/src/yacsloader/Test/Makefile.am b/src/yacsloader/Test/Makefile.am index ffb9943d1..76178bade 100644 --- a/src/yacsloader/Test/Makefile.am +++ b/src/yacsloader/Test/Makefile.am @@ -14,6 +14,7 @@ check_SCRIPTS = \ bin_SCRIPTS = display.sh + TESTS = YacsLoaderTest.sh TESTS_ENVIRONMENT=$(SHELL) -x @@ -27,11 +28,11 @@ TestYacsLoader_LDADD = \ $(PYTHON_EXTRA_LIBS) \ ../libYACSloader.la \ ../../runtime/libYACSRuntimeSALOME.la \ - ../../engine/libYACSEngine.la \ + ../../engine/libYACSlibEngine.la \ ../../bases/libYACSBases.la TestYacsLoader_LDFLAGS = \ - @CPPUNIT_LIBS@ -pthread -ldl -lxml2 -lexpat + @CPPUNIT_LIBS@ -pthread -ldl $(EXPAT_LIBS) $(LIBXML_LIBS) TestYacsLoader_CXXFLAGS = \ $(THREAD_DEF) \ @@ -44,16 +45,22 @@ TestYacsLoader_CXXFLAGS = \ -I$(srcdir)/../../bases/Test \ -I$(srcdir)/../../runtime \ -I$(srcdir)/../../engine \ - -I/usr/include/libxml2 + $(LIBXML_INCLUDES) IDL_FILES = echo.idl IDL_SOURCES = echoSK.cc -BUILT_SOURCES = $(IDL_SOURCES) echo_idl.py xmlrun.sh +BUILT_SOURCES = $(IDL_SOURCES) echo_idl.py xmlrun.sh + +EXTRA_DIST = $(IDL_FILES) \ +echoclt.py genPascal.py genTriangle.py testEdit.py testExec.py \ +testLoader.py testResume.py testSave.py \ +waitContainers.py xmlrun_orig.sh YacsLoaderTest.hxx xmlrun.sh:xmlrun_orig.sh cp $(srcdir)/xmlrun_orig.sh xmlrun.sh -echoSrv_SOURCES = echoSrv.cxx $(IDL_SOURCES) +echoSrv_SOURCES = echoSrv.cxx +nodist_echoSrv_SOURCES = $(IDL_SOURCES) echoSrv_CXXFLAGS = \ -I$(srcdir)/../../bases \ @@ -66,11 +73,22 @@ echoSrv_LDFLAGS = \ AM_CXXFLAGS = $(THREAD_DEF) install-exec-local: $(IDL_FILES) - $(INSTALL) -d $(pkgpythondir) + $(INSTALL) -d $(DESTDIR)$(salomepythondir) ls $^ | while read file; do \ - $(OMNIORB_IDL) -bpython -C$(pkgpythondir) $$file ; \ + $(OMNIORB_IDL) -bpython -C$(DESTDIR)$(salomepythondir) $$file ; \ done +uninstall-local: + rm -rf $(DESTDIR)$(salomepythondir)/echo_idl.py + rm -rf $(DESTDIR)$(salomepythondir)/eo + rm -rf $(DESTDIR)$(salomepythondir)/eo__POA + +clean-local: + rm -rf yacs* schema1_* schema2_* dump1_* dump2_* eo eo__POA dump*.xml CatalogResources.xml traceExec_* + rm -f samples toto titi log1 xmlrun.sh echo_idl.py echo.hh echoSK.cc g.data + if test -f "./bin/salome/appli_clean.sh"; then ./bin/salome/appli_clean.sh ; fi + + check-local: cat /tmp/${USER}/UnitTestsResult diff --git a/src/yacsloader/Test/YacsLoaderInSessionTest.sh.in b/src/yacsloader/Test/YacsLoaderInSessionTest.sh.in index 8db9d0ab5..3b2f03cda 100755 --- a/src/yacsloader/Test/YacsLoaderInSessionTest.sh.in +++ b/src/yacsloader/Test/YacsLoaderInSessionTest.sh.in @@ -15,6 +15,7 @@ echo $pidecho > "/tmp/YACSTEST_PidEcho" # --- launch unit tests export ROOT_SAMPLES=@ROOT_SRCDIR@/src/yacsloader/samples +export TESTCOMPONENT_ROOT_DIR=@top_builddir@/src/runtime/Test ./TestYacsLoader ret=$? diff --git a/src/yacsloader/Test/YacsLoaderInSessionTest2.sh.in b/src/yacsloader/Test/YacsLoaderInSessionTest2.sh.in index 854a15b86..ddc26c508 100644 --- a/src/yacsloader/Test/YacsLoaderInSessionTest2.sh.in +++ b/src/yacsloader/Test/YacsLoaderInSessionTest2.sh.in @@ -6,24 +6,44 @@ export ROOT_SAMPLES=@ROOT_SRCDIR@/src/yacsloader/samples -export PYTHONPATH=..:../.libs:${PYTHONPATH} -export PYTHONPATH=../../runtime:../../runtime/.libs:${PYTHONPATH} -export PYTHONPATH=../../engine:../../engine/.libs:${PYTHONPATH} +export PYTHONPATH=..:../.libs:@top_srcdir@/src/yacsloader:${PYTHONPATH} +export PYTHONPATH=../../runtime:../../runtime/.libs:@top_srcdir@/src/runtime:${PYTHONPATH} +export PYTHONPATH=../../engine:../../engine/.libs:@top_srcdir@/src/engine:${PYTHONPATH} python @srcdir@/testExec.py ret0=$? +if [ $ret0 -gt 0 ]; then + echo "exec status testExec : " $ret0 + exit $ret0 +fi python @srcdir@/testResume.py ret1=$? +if [ $ret1 -gt 0 ]; then + echo "exec status testResume : " $ret1 + exit $ret1 +fi python @srcdir@/testLoader.py ret2=$? +if [ $ret2 -gt 0 ]; then + echo "exec status testLoader : " $ret2 + exit $ret2 +fi python @srcdir@/testEdit.py ret3=$? +if [ $ret3 -gt 0 ]; then + echo "exec status testEdit : " $ret3 + exit $ret3 +fi python @srcdir@/testSave.py ret4=$? +if [ $ret4 -gt 0 ]; then + echo "exec status testSave : " $ret4 + exit $ret4 +fi let ret=$ret0+$ret1+$ret2+$ret3+$ret4 diff --git a/src/yacsloader/Test/YacsLoaderTest.cxx b/src/yacsloader/Test/YacsLoaderTest.cxx index fc76e21ca..ae9ee2fc5 100644 --- a/src/yacsloader/Test/YacsLoaderTest.cxx +++ b/src/yacsloader/Test/YacsLoaderTest.cxx @@ -697,6 +697,12 @@ void YacsLoaderTest::structs() ret = driverTest(p, "samples/struct1.xml"); CPPUNIT_ASSERT(ret == 0); CPPUNIT_ASSERT(p->getEffectiveState() == YACS::DONE ); + delete p; + + ret = driverTest(p, "samples/struct2.xml"); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(p->getEffectiveState() == YACS::DONE ); + delete p; } void YacsLoaderTest::cpps() @@ -708,3 +714,13 @@ void YacsLoaderTest::cpps() CPPUNIT_ASSERT(p->getEffectiveState() == YACS::DONE ); delete p; } + +void YacsLoaderTest::datanodes() +{ + Proc *p = 0; + int ret; + ret = driverTest(p, "samples/datanode0.xml"); + CPPUNIT_ASSERT(ret == 0); + CPPUNIT_ASSERT(p->getEffectiveState() == YACS::DONE ); + delete p; +} diff --git a/src/yacsloader/Test/YacsLoaderTest.hxx b/src/yacsloader/Test/YacsLoaderTest.hxx index 61dbfdee4..566a5fd1c 100644 --- a/src/yacsloader/Test/YacsLoaderTest.hxx +++ b/src/yacsloader/Test/YacsLoaderTest.hxx @@ -50,6 +50,7 @@ namespace YACS CPPUNIT_TEST(objrefs); CPPUNIT_TEST(structs); CPPUNIT_TEST(cpps); + CPPUNIT_TEST(datanodes); CPPUNIT_TEST_SUITE_END(); public: @@ -96,6 +97,7 @@ namespace YACS void objrefs(); void structs(); void cpps(); + void datanodes(); protected: diff --git a/src/yacsloader/Test/YacsLoaderTest.sh.in b/src/yacsloader/Test/YacsLoaderTest.sh.in index c3f73149e..6279e5a3c 100755 --- a/src/yacsloader/Test/YacsLoaderTest.sh.in +++ b/src/yacsloader/Test/YacsLoaderTest.sh.in @@ -12,8 +12,7 @@ if test -f @KERNEL_ROOT_DIR@/bin/salome/appli_gen.py ; then cat > CatalogResources.xml << EOF - + EOF diff --git a/src/yacsloader/Test/echo.idl b/src/yacsloader/Test/echo.idl index e3c642009..bccfceefb 100644 --- a/src/yacsloader/Test/echo.idl +++ b/src/yacsloader/Test/echo.idl @@ -58,6 +58,14 @@ module eo{ { S1 s; }; + struct S3 + { + double x; + long y; + string s; + boolean b; + Obj ob; + }; interface Echo { @@ -81,6 +89,10 @@ module eo{ void echoAll(in double d,in long l,in string m,in Obj o,out double dd,out long ll,out string s,out Obj p); void sleepLong(in double time1,out double time2) ; S2 echoStruct(in S2 s); + S3 echoStruct2(in S3 s); + + // Shuts down the server. + void shutdown(); }; interface SubEcho:Echo { diff --git a/src/yacsloader/Test/echoSrv.cxx b/src/yacsloader/Test/echoSrv.cxx index c8e270cb0..52eb5453f 100644 --- a/src/yacsloader/Test/echoSrv.cxx +++ b/src/yacsloader/Test/echoSrv.cxx @@ -11,6 +11,7 @@ using namespace std; +CORBA::ORB_var orb; static CORBA::Boolean bindObjectToName(CORBA::ORB_ptr, CORBA::Object_ptr,const char*); static ostream& operator<<(ostream& os, const CORBA::Exception& e) @@ -89,6 +90,8 @@ public: void echoAll(CORBA::Double d,CORBA::Long l,const char * m,eo::Obj_ptr o,CORBA::Double& dd,CORBA::Long& ll,CORBA::String_out s,eo::Obj_out oo); void sleepLong(CORBA::Double time1,CORBA::Double& time2) ; virtual eo::S2* echoStruct(const eo::S2&); + virtual eo::S3* echoStruct2(const eo::S3&); + virtual void shutdown(); virtual PortableServer::POA_ptr _default_POA(); protected: int _ctr; @@ -111,6 +114,13 @@ PortableServer::POA_ptr Echo_i::_default_POA() } +void Echo_i::shutdown() +{ + // Shutdown the ORB (but do not wait for completion). This also + // causes the main thread to unblock from CORBA::ORB::run(). + orb->shutdown(0); +} + char* Echo_i::echoString(const char* mesg) { DEBTRACE("Echo_i::echoString " << mesg); @@ -273,6 +283,7 @@ void Echo_i::sleepLong(CORBA::Double time1, CORBA::Double& time2) DEBTRACE("Echo_i::sleepLong stop " << num); time2 = time1; } + eo::S2* Echo_i::echoStruct(const eo::S2& s) { DEBTRACE("Echo_i::echoStruct " << s.s.x << " " << s.s.y); @@ -284,6 +295,19 @@ eo::S2* Echo_i::echoStruct(const eo::S2& s) return s2; } +eo::S3* Echo_i::echoStruct2(const eo::S3& s) +{ + DEBTRACE("Echo_i::echoStruct " << s.x << " " << s.y); + if( !CORBA::is_nil(s.ob) ) + { + std::cerr << s.ob->echoLong(10) << std::endl; + } + eo::S3* s2=new eo::S3; + s2->x=10.; + s2->y=2; + return s2; +} + //Implementation Obj CORBA::Long Obj_i::echoLong(CORBA::Long i ){ DEBTRACE("Obj_i::echoLong " << i ); @@ -322,7 +346,6 @@ CORBA::Long E_i::echoLong(CORBA::Long i ){ return j; } -CORBA::ORB_ptr orb; eo::Echo_var myechoref; int main(int argc, char** argv) @@ -338,52 +361,56 @@ int main(int argc, char** argv) poa_man->activate(); // Create a new POA with the shortcut policy + /* CORBA::PolicyList pl2; pl2.length(2); CORBA::Any v; v <<= omniPolicy::LOCAL_CALLS_SHORTCUT; pl2[0] = orb->create_policy(omniPolicy::LOCAL_SHORTCUT_POLICY_TYPE, v); pl2[1] = root_poa->create_implicit_activation_policy(PortableServer::IMPLICIT_ACTIVATION); - PortableServer::POA_ptr shortcut_poa = root_poa->create_POA("shortcut", poa_man, pl2); + PortableServer::POA_var shortcut_poa = root_poa->create_POA("shortcut", poa_man, pl2); + */ // Create and activate servant Echo_i* myecho = new Echo_i(); - // Obtain a reference to the object, and print it out as a - // stringified IOR. - obj = myecho->_this(); - CORBA::String_var sior(orb->object_to_string(obj)); - DEBTRACE("'" << (char*)sior << "'"); - myechoref = eo::Echo::_narrow(obj); - - if( !bindObjectToName(orb, myechoref,"Echo") ) return 1; - + // Obtain a reference to the object + CORBA::Object_var obj2 = myecho->_this(); + myechoref = eo::Echo::_narrow(obj2); // Decrement the reference count of the object implementation, so // that it will be properly cleaned up when the POA has determined // that it is no longer needed. myecho->_remove_ref(); + // print the reference as a stringified IOR. + CORBA::String_var sior(orb->object_to_string(obj2)); + DEBTRACE("'" << (char*)sior << "'"); + + if( !bindObjectToName(orb, myechoref,"Echo") ) return 1; + //create object C and register it in naming service C_i* myC = new C_i(); - obj=myC->_this(); - eo::C_var myCref=eo::C::_narrow(obj); + CORBA::Object_var obj3 =myC->_this(); + eo::C_var myCref=eo::C::_narrow(obj3); myC->_remove_ref(); if( !bindObjectToName(orb, myCref,"C") ) return 1; //create object D and register it in naming service D_i* myD = new D_i(); - obj=myD->_this(); - eo::D_var myDref=eo::D::_narrow(obj); + CORBA::Object_var obj4=myD->_this(); + eo::D_var myDref=eo::D::_narrow(obj4); myD->_remove_ref(); if( !bindObjectToName(orb, myDref,"D") ) return 1; //create object Obj and register it in naming service Obj_i* myObj = new Obj_i(); - obj=myObj->_this(); - eo::Obj_var myObjref=eo::Obj::_narrow(obj); + CORBA::Object_var obj5=myObj->_this(); + eo::Obj_var myObjref=eo::Obj::_narrow(obj5); myObj->_remove_ref(); if( !bindObjectToName(orb, myObjref,"Obj") ) return 1; } orb->run(); + std::cout << "Returned from orb->run()." << std::endl; + orb->destroy(); } catch(CORBA::SystemException&) { DEBTRACE("Caught CORBA::SystemException."); diff --git a/src/yacsloader/Test/echoclt.py b/src/yacsloader/Test/echoclt.py new file mode 100644 index 000000000..bff547c7f --- /dev/null +++ b/src/yacsloader/Test/echoclt.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +import sys + +# Import the CORBA module +from omniORB import CORBA +import CosNaming + +import eo + +# Initialise the ORB +orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID) + +# Obtain a reference to the root naming context +obj = orb.resolve_initial_references("NameService") +rootContext = obj._narrow(CosNaming.NamingContext) + +if rootContext is None: + print "Failed to narrow the root naming context" + sys.exit(1) + +# Resolve the name "test.my_context/Echo.Object" +name = [CosNaming.NameComponent("test", "my_context"), + CosNaming.NameComponent("Echo", "Object")] + +try: + obj = rootContext.resolve(name) + +except CosNaming.NamingContext.NotFound, ex: + print "Name not found" + sys.exit(1) + +# Narrow the object to an eo::Echo +echo = obj._narrow(eo.Echo) + +if echo is None: + print "Object reference is not an eo::Echo" + sys.exit(1) + +# Invoke the echoString operation +message = "Hello from Python" +result = echo.echoString(message) + +print "I said '%s'. The object said '%s'." % (message,result) + +""" + struct S1 + { + double x; + long y; + string s; + boolean b; + DoubleVec vd; + }; + struct S2 + { + S1 s; + }; +""" + +s1=eo.S1(x=1,y=2,s="aa",b=True,vd=[1,2]) +s2=eo.S2(s1) + +r=echo.echoStruct(s2) +print r + +s3=eo.S3(x=1,y=2,s="aa",b=True,ob=None) +r=echo.echoStruct2(s3) +print r + +ob=echo.createObj(3) +print ob +oc=echo.createC() +print oc + +s3=eo.S3(x=1,y=2,s="aa",b=True,ob=ob) +r=echo.echoStruct2(s3) +print r + +s3=eo.S3(x=1,y=2,s="aa",b=True,ob=oc) +r=echo.echoStruct2(s3) +print r + +r=echo.echoObjectVec([ob,ob]) +print r + +r=echo.echoObjectVec([oc,oc]) +print r + +r=echo.echoObjectVec([ob,oc]) +print r + +#echo.shutdown() diff --git a/src/yacsloader/Test/testEdit.py b/src/yacsloader/Test/testEdit.py index 6d61edcb6..a8556002a 100644 --- a/src/yacsloader/Test/testEdit.py +++ b/src/yacsloader/Test/testEdit.py @@ -49,7 +49,7 @@ class TestEdit(unittest.TestCase): inport=n.getInputPort("p1"); retex=None try: - inport.edInit("XML","5") + inport.edInitXML("5") except ValueError, ex: print "Value Error: ", ex retex=ex @@ -57,7 +57,7 @@ class TestEdit(unittest.TestCase): print "YACS exception:",ex.what() retex=ex.what() self.assert_(retex is not None, "exception not raised, or wrong type") - inport.edInit("XML","5") + inport.edInitXML("5") # --- create script node node2 n2=self.r.createScriptNode("","node2") diff --git a/src/yacsloader/Test/testLoader.py b/src/yacsloader/Test/testLoader.py index d091e7ff3..f15b13d61 100644 --- a/src/yacsloader/Test/testLoader.py +++ b/src/yacsloader/Test/testLoader.py @@ -13,6 +13,11 @@ class TestLoader(unittest.TestCase): self.e = pilot.ExecutorSwig() pass + def tearDown(self): + del self.r + del self.l + del self.e + def test1_FileNotExist(self): # --- File does not exist retex=None @@ -35,18 +40,19 @@ class TestLoader(unittest.TestCase): except ValueError,ex: print "Caught ValueError Exception:",ex retex = ex - self.assert_(retex is not None, "exception not raised, or wrong type") + expected="LogRecord: parser:ERROR:from node node5 does not exist in control link: node5->b2 context: b1. (samples/bid.xml:33)\n" + self.assert_(p.getLogger("parser").getStr() == expected, "error not found") pass def test3_normal(self): # --- File exists and no parsing problem try: p = self.l.load("samples/aschema.xml") + print p.getLogger("parser").getStr() print p print p.getName() for k in p.typeMap: print k for k in p.nodeMap: print k - for k in p.names: print k for k in p.inlineMap: print k for k in p.serviceMap: print k print self.e.getTasksToLoad() diff --git a/src/yacsloader/blocParsers.hxx b/src/yacsloader/blocParsers.hxx new file mode 100644 index 000000000..05b46940d --- /dev/null +++ b/src/yacsloader/blocParsers.hxx @@ -0,0 +1,412 @@ +#ifndef _BLOCPARSER_HXX_ +#define _BLOCPARSER_HXX_ + +#include "parserBase.hxx" +#include "linkParsers.hxx" +#include "xmlrpcParsers.hxx" +#include "nodeParsers.hxx" + + +#include "Proc.hxx" +#include "Logger.hxx" +#include "Runtime.hxx" +#include "ForLoop.hxx" +#include "ForEachLoop.hxx" +#include "WhileLoop.hxx" +#include "Switch.hxx" +#include "Bloc.hxx" +#include "Exception.hxx" +#include "InlineNode.hxx" +#include "DataNode.hxx" +#include "ServiceNode.hxx" +#include "ServiceInlineNode.hxx" +#include "OutputDataStreamPort.hxx" +#include "InputDataStreamPort.hxx" + +#include + +extern YACS::ENGINE::Proc* currentProc; +extern YACS::ENGINE::Runtime* theRuntime; + +namespace YACS +{ + +template +struct bloctypeParser:parser +{ + static bloctypeParser blocParser; + + bloctypeParser():parser() + { + _orders["property"]=0; + _orders["inline"]=2; + _orders["service"]=2; + _orders["sinline"]=2; + _orders["node"]=2; + _orders["datanode"]=2; + _orders["outnode"]=2; + _orders["forloop"]=2; + _orders["foreach"]=2; + _orders["while"]=2; + _orders["switch"]=2; + _orders["bloc"]=2; + _orders["control"]=3; + _orders["datalink"]=3; + _orders["stream"]=3; + _orders["parameter"]=3; + } + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr) + { + this->required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "state")state(attr[i+1]); + } + } + void name (const std::string& name) + { + } + virtual void state (const std::string& name){ + DEBTRACE( "bloc_state: " << name ) + _state=name; + if(_state == "disabled") + { + DEBTRACE( "Bloc disabled: " << _bloc->getName()) + _bloc->exDisabledState(); + } + } + virtual void property (const myprop& prop) + { + DEBTRACE( "property_set: " << prop._name << prop._value ) + _bloc->setProperty(prop._name,prop._value); + } + virtual void inline_ (YACS::ENGINE::InlineNode* const& n) + { + DEBTRACE( "bloc_pynode_set: " << n->getName() ) + _bloc->edAddChild(n); + std::string fullname = currentProc->names.back()+n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->inlineMap[fullname]=n; + } + virtual void sinline (YACS::ENGINE::ServiceInlineNode* const& n) + { + DEBTRACE( "bloc_sinline: " << n->getName() ) + _bloc->edAddChild(n); + std::string fullname = currentProc->names.back()+n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->serviceMap[fullname]=n; + } + virtual void service (YACS::ENGINE::ServiceNode* const& n) + { + DEBTRACE( "bloc_service_set: " << n->getName() ) + _bloc->edAddChild(n); + std::string fullname = currentProc->names.back()+n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->serviceMap[fullname]=n; + } + virtual void node (YACS::ENGINE::InlineNode* const& n) + { + DEBTRACE( "bloc_node_set: " << n->getName() ) + _bloc->edAddChild(n); + std::string fullname = currentProc->names.back()+n->getName(); + DEBTRACE( "bloc_node_set fullname = " << fullname ) + currentProc->nodeMap[fullname]=n; + currentProc->inlineMap[fullname]=n; + } + virtual void forloop (YACS::ENGINE::ForLoop* const& b) + { + DEBTRACE( "bloc_forloop_set: " << b->getName() ) + _bloc->edAddChild(b); + std::string fullname = currentProc->names.back()+b->getName(); + currentProc->nodeMap[fullname]=b; + } + virtual void foreach (YACS::ENGINE::ForEachLoop* const& b) + { + DEBTRACE( "bloc_foreach_set: " << b->getName() ) + _bloc->edAddChild(b); + std::string fullname = currentProc->names.back()+b->getName(); + currentProc->nodeMap[fullname]=b; + fullname += ".splitter"; + currentProc->nodeMap[fullname]=b->getChildByShortName("splitter"); + } + virtual void while_ (YACS::ENGINE::WhileLoop* const& b) + { + DEBTRACE( "bloc_while_set: " << b->getName() ) + _bloc->edAddChild(b); + std::string fullname = currentProc->names.back()+b->getName(); + currentProc->nodeMap[fullname]=b; + } + virtual void switch_ (YACS::ENGINE::Switch* const& b) + { + DEBTRACE( "bloc_switch_set: " << b->getName() ) + _bloc->edAddChild(b); + std::string fullname = currentProc->names.back()+b->getName(); + currentProc->nodeMap[fullname]=b; + } + virtual void bloc (YACS::ENGINE::Bloc* const& b) + { + DEBTRACE( "bloc_bloc_set: " << b->getName() ) + _bloc->edAddChild(b); + std::string fullname=currentProc->names.back()+ b->getName(); + currentProc->nodeMap[fullname]=b; + } + virtual void control (const mycontrol& l) + { + DEBTRACE( "bloc_control_set: " << l.fromnode() << " "<< l.tonode() ) + std::string msg; + + if(currentProc->nodeMap.count(currentProc->names.back()+l.fromnode()) == 0) + { + msg="from node " + l.fromnode() + " does not exist in control link: "; + msg=msg+l.fromnode()+"->"+l.tonode(); + msg=msg+ " context: "+currentProc->names.back(); + this->logError(msg); + return; + } + if(currentProc->nodeMap.count(currentProc->names.back()+l.tonode()) == 0) + { + msg="to node " + l.tonode() + " does not exist in control link: "; + msg=msg+l.fromnode()+"->"+l.tonode(); + msg=msg+ " context: "+currentProc->names.back(); + this->logError(msg); + return; + } + // We only link local nodes + try + { + _bloc->edAddCFLink(currentProc->nodeMap[currentProc->names.back()+l.fromnode()], + currentProc->nodeMap[currentProc->names.back()+l.tonode()]); + } + catch(YACS::Exception& e) + { + this->logError(e.what()); + } + } + virtual void datalink (const mylink& l) + { + DEBTRACE( "bloc_datalink_set: "<"<names.back()+l.fromnode(); + if(currentProc->nodeMap.count(fromname) == 0) + { + msg="from node " + l.fromnode() + " does not exist in data link: "; + msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; + this->logError(msg); + return; + } + //Try relative name for to node and then absolute one + std::string toname = currentProc->names.back()+l.tonode(); + if(currentProc->nodeMap.count(toname) == 0) + { + //It's not a relative name. Try an absolute one (I think it's not possible) + toname=l.tonode(); + if(currentProc->nodeMap.count(toname) == 0) + { + // The TO node does not exist -> error + msg="to node " + l.tonode() + " does not exist in data link: "; + msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; + this->logError(msg); + return; + } + } + // We only link local node and other nodes (relative or absolute name in this order) + DEBTRACE(fromname <<":"<edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), + currentProc->nodeMap[toname]->getInputPort(l.toport())); + else + _bloc->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), + currentProc->nodeMap[toname]->getInputPort(l.toport())); + } + catch(YACS::Exception& e) + { + this->logError(e.what()); + } + } + virtual void stream (const mystream& l) + { + DEBTRACE( "bloc_stream_set: " << l.fromnode() << l.fromport() << l.tonode() << l.toport() ) + std::string msg; + std::string fromname = currentProc->names.back()+l.fromnode(); + std::string toname = currentProc->names.back()+l.tonode(); + //only relative names + if(currentProc->nodeMap.count(fromname) == 0) + { + msg="from node " + l.fromnode() + " does not exist in stream link: "; + msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; + this->logError(msg); + return; + } + if(currentProc->nodeMap.count(toname) == 0) + { + msg="to node " + l.tonode() + " does not exist in stream link: "; + msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; + this->logError(msg); + return; + } + YACS::ENGINE::OutputDataStreamPort* pout=currentProc->nodeMap[fromname]->getOutputDataStreamPort(l.fromport()); + YACS::ENGINE::InputDataStreamPort* pin=currentProc->nodeMap[toname]->getInputDataStreamPort(l.toport()); + _bloc->edAddLink(pout,pin); + // Set all properties for this link + std::map::const_iterator pt; + for(pt=l._props.begin();pt!=l._props.end();pt++) + { + pin->setProperty((*pt).first,(*pt).second); + pout->setProperty((*pt).first,(*pt).second); + } + } + virtual void parameter (const myparam& param) + { + DEBTRACE( "++++++++++++++++++++Parameter+++++++++++++++++++++" ); + std::string msg; + std::string toname = currentProc->names.back()+param._tonode; + if(currentProc->nodeMap.count(toname) == 0) + { + msg="to node " + param._tonode + " does not exist in parameter: "; + msg=msg+"->"+param._tonode+"("+param._toport+")"; + this->logError(msg); + return; + } + YACS::ENGINE::InputPort* inport=currentProc->nodeMap[toname]->getInputPort(param._toport); + //We don't know the parameter type. So we try to initialize the port + //with the value. If it's not the right type, edInit throws an exception + try + { + inport->edInit("XML",param._value.c_str()); + } + catch(YACS::Exception& e) + { + this->logError(e.what()); + } + DEBTRACE( "++++++++++++++++++++End parameter+++++++++++++++++++++" ); + } + + virtual void preset (ENGINE::DataNode* const& n); + virtual void outnode (ENGINE::DataNode* const& n); + + T post() + { + DEBTRACE( "bloc_post" ) + currentProc->names.pop_back(); + T b=_bloc; + _blocs.pop_back(); + if(_blocs.empty()) + _bloc=NULL; + else + _bloc=_blocs.back(); + return b; + } + + T _bloc; + std::string _state; + std::vector _blocs; +}; + +template bloctypeParser bloctypeParser::blocParser; + +template +void bloctypeParser::preset (ENGINE::DataNode* const& n) +{ + DEBTRACE("bloc_preset_set: " << n->getName() ); + _bloc->edAddChild(n); + std::string fullname = currentProc->names.back()+n->getName(); + currentProc->nodeMap[fullname]=n; +} + +template +void bloctypeParser::outnode (ENGINE::DataNode* const& n) +{ + DEBTRACE("bloc_outnode: " << n->getName() ); + _bloc->edAddChild(n); + std::string fullname = currentProc->names.back()+n->getName(); + currentProc->nodeMap[fullname]=n; +} + +template <> +void bloctypeParser::name (const std::string& name) +{ + DEBTRACE( "bloc_name: " << name ) + std::string fullname=currentProc->names.back()+name; + _bloc=theRuntime->createBloc(name); + _blocs.push_back(_bloc); + currentProc->names.push_back(fullname+'.'); +} + +} + +#include "loopParsers.hxx" +#include "switchParsers.hxx" +#include "presetParsers.hxx" +#include "outputParsers.hxx" + +namespace YACS +{ + +template +void bloctypeParser::onStart(const XML_Char* el, const XML_Char** attr) +{ + DEBTRACE( "bloctypeParser::onStart: " << el ) + std::string element(el); + checkOrder(element); + parser* pp=&parser::main_parser; + if(element == "property")pp=&propertytypeParser::propertyParser; + + else if(element == "inline")pp=&inlinetypeParser<>::inlineParser; + else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser; + else if(element == "service")pp=&servicetypeParser<>::serviceParser; + else if(element == "node")pp=&nodetypeParser<>::nodeParser; + else if(element == "datanode")pp=&presettypeParser<>::presetParser; + else if(element == "outnode")pp=&outnodetypeParser<>::outnodeParser; + + else if(element == "bloc")pp=&bloctypeParser<>::blocParser; + else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser; + else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser; + else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser; + else if(element == "switch")pp=&switchtypeParser::switchParser; + + else if(element == "control")pp=&controltypeParser<>::controlParser; + else if(element == "datalink")pp=&linktypeParser<>::linkParser; + else if(element == "stream")pp=&streamtypeParser<>::streamParser; + else if(element == "parameter")pp=¶metertypeParser::parameterParser; + + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); +} + +template +void bloctypeParser::onEnd(const char *el,parser* child) +{ + DEBTRACE( "bloctypeParser::onEnd: " << el ) + std::string element(el); + if(element == "property")property(((propertytypeParser*)child)->post()); + else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post()); + else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post()); + else if(element == "service")service(((servicetypeParser<>*)child)->post()); + else if(element == "node")node(((nodetypeParser<>*)child)->post()); + else if(element == "datanode")preset(((presettypeParser<>*)child)->post()); + else if(element == "outnode")outnode(((outnodetypeParser<>*)child)->post()); + + else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post()); + else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post()); + else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post()); + else if(element == "while")while_(((whilelooptypeParser<>*)child)->post()); + else if(element == "switch")switch_(((switchtypeParser*)child)->post()); + + else if(element == "control") control(((controltypeParser<>*)child)->post()); + else if(element == "datalink") datalink(((linktypeParser<>*)child)->post()); + else if(element == "stream") stream(((streamtypeParser<>*)child)->post()); + else if(element == "parameter") parameter(((parametertypeParser*)child)->post()); +} + +} + +#endif diff --git a/src/yacsloader/codeParsers.cxx b/src/yacsloader/codeParsers.cxx new file mode 100644 index 000000000..ab93e47c3 --- /dev/null +++ b/src/yacsloader/codeParsers.cxx @@ -0,0 +1,7 @@ +#include "codeParsers.hxx" + +namespace YACS +{ + functypeParser functypeParser::funcParser; + codetypeParser codetypeParser::codeParser; +} diff --git a/src/yacsloader/codeParsers.hxx b/src/yacsloader/codeParsers.hxx new file mode 100644 index 000000000..55f2847f9 --- /dev/null +++ b/src/yacsloader/codeParsers.hxx @@ -0,0 +1,79 @@ + +#ifndef _CODEPARSERS_HXX_ +#define _CODEPARSERS_HXX_ + +#include "parserBase.hxx" +#include "dataParsers.hxx" + +#include "factory.hxx" + +namespace YACS +{ + +/*! \brief Class for code parser in inline nodes. + * + */ +struct codetypeParser: parser +{ + static codetypeParser codeParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "code")pp=&stringtypeParser::stringParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + virtual void onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "code")code(((stringtypeParser*)child)->post()); + } + virtual void pre (){_code="";} + virtual void code (const std::string& s) + { + if(_code == "") + _code=s; + else + _code=_code + '\n' + s; + } + virtual myfunc post () + { + _func._name="script"; + _func._code=_code; + return _func; + } + std::string _code; + myfunc _func; +}; + +/*! \brief Class for function parser in inline nodes. + * + */ +struct functypeParser: codetypeParser +{ + static functypeParser funcParser; + virtual void buildAttr(const XML_Char** attr) + { + required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + } + } + virtual void name (const std::string& name) + { + _func._name=name; + } + virtual myfunc post () + { + _func._code=_code; + return _func; + } +}; + +} + +#endif diff --git a/src/yacsloader/containerParsers.cxx b/src/yacsloader/containerParsers.cxx new file mode 100644 index 000000000..e3f573f5d --- /dev/null +++ b/src/yacsloader/containerParsers.cxx @@ -0,0 +1,88 @@ + +#include "containerParsers.hxx" +#include "propertyParsers.hxx" + +namespace YACS +{ + containertypeParser containertypeParser::containerParser; + machinetypeParser machinetypeParser::machineParser; + loadtypeParser loadtypeParser::loadParser; + + void machinetypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + } + } + void machinetypeParser::pre (){_mach._name="";} + void machinetypeParser::name(const std::string& name){ _mach._name=name; } + machine machinetypeParser::post() + { + return _mach; + } + + void containertypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + } + } + void containertypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "machine")pp=&machinetypeParser::machineParser; + if(element == "property")pp=&propertytypeParser::propertyParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void containertypeParser::onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "machine")machine_(((machinetypeParser*)child)->post()); + if(element == "property")property(((propertytypeParser*)child)->post()); + } + void containertypeParser::pre () + { + _container._machs.clear(); + _container._props.clear(); + } + void containertypeParser::name(const std::string& name){ _container._name=name; } + void containertypeParser::machine_(const machine& m) + { + DEBTRACE( "machine: " << m._name ) + _container._machs.push_back(m); + } + void containertypeParser::property (const myprop& prop) + { + DEBTRACE( "property_set: " << prop._name << " " << prop._value ); + _container._props[prop._name]=prop._value; + } + mycontainer containertypeParser::post() + { + //mincount("machine",1); + return _container; + } + + void loadtypeParser::buildAttr(const XML_Char** attr) + { + required("container",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "container")container(attr[i+1]); + } + } + void loadtypeParser::pre (){_loadon._container="";} + void loadtypeParser::container(const std::string& name){ _loadon._container=name; } + loadon loadtypeParser::post() + { + return _loadon; + } + +} diff --git a/src/yacsloader/containerParsers.hxx b/src/yacsloader/containerParsers.hxx new file mode 100644 index 000000000..1e2605e7e --- /dev/null +++ b/src/yacsloader/containerParsers.hxx @@ -0,0 +1,84 @@ + +#ifndef _CONTAINERPARSER_HXX_ +#define _CONTAINERPARSER_HXX_ + +#include "parserBase.hxx" +#include "factory.hxx" + +namespace YACS +{ + +/*! \brief Class for machine parser. + * + * Class used to parse computer adress on which container must be started + * + * XML schema is + \verbatim + + + + \endverbatim + */ +struct machinetypeParser: parser +{ + static machinetypeParser machineParser; + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void name(const std::string& name); + machine post(); + machine _mach; +}; + +/*! \brief Class for container parser + * + * Class used to parse container description + * + * XML schema is + \verbatim + + + + + + + + \endverbatim + */ +struct containertypeParser: parser +{ + static containertypeParser containerParser; + virtual void buildAttr(const XML_Char** attr); + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void pre (); + virtual void name(const std::string& name); + virtual void machine_(const machine& m); + virtual void property (const myprop& prop); + mycontainer post(); + mycontainer _container; +}; + +/*! \brief Class for loading parser + * + * Class used to parse service node loading information + * + * XML schema is + \verbatim + + + + \endverbatim + */ +struct loadtypeParser: parser +{ + static loadtypeParser loadParser; + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void container(const std::string& name); + loadon post(); + loadon _loadon; +}; + +} + +#endif diff --git a/src/yacsloader/dataParsers.cxx b/src/yacsloader/dataParsers.cxx new file mode 100644 index 000000000..31b9d900e --- /dev/null +++ b/src/yacsloader/dataParsers.cxx @@ -0,0 +1,49 @@ + +#include "dataParsers.hxx" +#include "Cstr2d.hxx" +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +namespace YACS +{ + stringtypeParser stringtypeParser::stringParser; + doubletypeParser doubletypeParser::doubleParser; + inttypeParser inttypeParser::intParser; + booltypeParser booltypeParser::boolParser; + +std::string stringtypeParser::post() + { + return _content; + } + + double doubletypeParser::post() + { + return Cstr2d(_content.c_str()); +// std::istringstream s(_content.c_str()); +// double a; +// if (!(s >> a)) +// throw YACS::Exception::Exception("problem in conversion from string to double"); +// std::cerr << "--------------_content s a "<< _content.c_str() << " " << s.str() << " " << a << std::endl; +// return a; + } + + int inttypeParser::post() + { + return atoi(_content.c_str()); + } + + bool booltypeParser::post() + { + DEBTRACE( _content ) + if(_content == "true")return true; + if(_content == "false")return false; + std::stringstream temp(_content); + bool b ; + temp >> b; + //std::cerr << b << std::endl; + return b; + } + +} diff --git a/src/yacsloader/dataParsers.hxx b/src/yacsloader/dataParsers.hxx new file mode 100644 index 000000000..c671e0b1d --- /dev/null +++ b/src/yacsloader/dataParsers.hxx @@ -0,0 +1,50 @@ +#ifndef _DATAPARSERS_HXX_ +#define _DATAPARSERS_HXX_ + +#include "parserBase.hxx" + +namespace YACS +{ +/*! \brief Class for string parser. + * + * Class used to parse string + */ +struct stringtypeParser:parser +{ + static stringtypeParser stringParser; + std::string post(); +}; + +/*! \brief Class for double parser. + * + * Class used to parse double + */ +struct doubletypeParser:parser +{ + static doubletypeParser doubleParser; + double post(); +}; + +/*! \brief Class for integer parser. + * + * Class used to parse integer + */ +struct inttypeParser:parser +{ + static inttypeParser intParser; + int post(); +}; + +/*! \brief Class for boolean parser. + * + * Class used to parse bool + */ +struct booltypeParser:parser +{ + static booltypeParser boolParser; + bool post(); +}; + +} + +#endif diff --git a/src/yacsloader/driver.cxx b/src/yacsloader/driver.cxx index c623d3d99..558324d7d 100644 --- a/src/yacsloader/driver.cxx +++ b/src/yacsloader/driver.cxx @@ -1,13 +1,21 @@ +#include "yacsconfig.h" #include "RuntimeSALOME.hxx" #include "Proc.hxx" +#include "Logger.hxx" #include "Exception.hxx" #include "Executor.hxx" #include "parsers.hxx" #include "VisitorSaveState.hxx" -#include "VisitorSaveSchema.hxx" +#include "VisitorSaveSalomeSchema.hxx" #include "LoadState.hxx" #include "Dispatcher.hxx" +#include "LinkInfo.hxx" + +#ifdef SALOME_KERNEL +#include "SALOME_NamingService.hxx" +#include "SALOME_ModuleCatalog.hh" +#endif #include #include @@ -137,17 +145,93 @@ main (int argc, char* argv[]) RuntimeSALOME::setRuntime(); + // Try to load the session catalog if it exists + try + { + YACS::ENGINE::RuntimeSALOME* runTime = YACS::ENGINE::getSALOMERuntime(); + CORBA::ORB_ptr orb = runTime->getOrb(); + if (orb) + { + SALOME_NamingService namingService(orb); + CORBA::Object_var obj = namingService.Resolve("/Kernel/ModulCatalog"); + SALOME_ModuleCatalog::ModuleCatalog_var aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj); + if (! CORBA::is_nil(aModuleCatalog)) + { + CORBA::String_var anIOR = orb->object_to_string( aModuleCatalog ); + YACS::ENGINE::Catalog* aCatalog = runTime->loadCatalog( "session", anIOR.in() ); + runTime->addCatalog(aCatalog); + } + } + } + catch(ServiceUnreachable& e) + { + //Naming service unreachable don't add catalog + } + YACSLoader loader; Executor executor; try { Proc* p=loader.load(myArgs.args[0]); + if(p==0) + { + std::cerr << "The imported file is probably not a YACS schema file" << std::endl; + return 1; + } + //Get the parser logger + Logger* logger=p->getLogger("parser"); + //Print errors logged if any + if(!logger->isEmpty()) + { + std::cerr << "The imported file has errors" << std::endl; + std::cerr << logger->getStr() << std::endl; + } + //Don't execute if there are errors + if(logger->hasErrors()) + { + delete p; + Runtime* r=YACS::ENGINE::getRuntime(); + Dispatcher* disp=Dispatcher::getDispatcher(); + r->fini(); + delete r; + delete disp; + return 1; + } + + if(!p->isValid()) + { + std::string report=p->getErrorReport(); + std::cerr << "The schema is not valid and can not be executed" << std::endl; + std::cerr << report << std::endl; + Runtime* r=YACS::ENGINE::getRuntime(); + Dispatcher* disp=Dispatcher::getDispatcher(); + r->fini(); + delete r; + delete disp; + return 1; + } + // Check consistency + LinkInfo info(LinkInfo::ALL_DONT_STOP); + p->checkConsistency(info); + if(info.areWarningsOrErrors()) + { + std::cerr << "The schema is not consistent and can not be executed" << std::endl; + std::cerr << info.getGlobalRepr() << std::endl; + Runtime* r=YACS::ENGINE::getRuntime(); + Dispatcher* disp=Dispatcher::getDispatcher(); + r->fini(); + delete r; + delete disp; + return 1; + } + + //execution bool isXmlSchema = (strlen(myArgs.xmlSchema) != 0); if (isXmlSchema) { - YACS::ENGINE::VisitorSaveSchema vss(p); + YACS::ENGINE::VisitorSaveSalomeSchema vss(p); vss.openFileSchema(myArgs.xmlSchema); p->accept(&vss); vss.closeFileSchema(); @@ -178,6 +262,13 @@ main (int argc, char* argv[]) cerr << "+++++++++++++++++++ end calculation +++++++++++++++++++" << endl; cerr << "Proc state : " << p->getEffectiveState() << endl; + if(p->getEffectiveState() != YACS::DONE) + { + std::string report=p->getErrorReport(); + std::cerr << "Execution has ended in error" << std::endl; + std::cerr << report << std::endl; + } + std::ofstream g("titi"); p->writeDot(g); g.close(); diff --git a/src/yacsloader/linkParsers.hxx b/src/yacsloader/linkParsers.hxx new file mode 100644 index 000000000..7767c197a --- /dev/null +++ b/src/yacsloader/linkParsers.hxx @@ -0,0 +1,134 @@ + +#ifndef _LINKPARSERS_HXX_ +#define _LINKPARSERS_HXX_ + +#include "parserBase.hxx" +#include "dataParsers.hxx" +#include "propertyParsers.hxx" + +#include "factory.hxx" + +namespace YACS +{ +template +struct controltypeParser: parser +{ + static controltypeParser controlParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + parser* pp=&parser::main_parser; + this->maxcount("fromnode",1,element); + this->maxcount("tonode",1,element); + if(element == "fromnode")pp=&stringtypeParser::stringParser; + else if(element == "tonode")pp=&stringtypeParser::stringParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + virtual void onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "fromnode")fromnode(((stringtypeParser*)child)->post()); + else if(element == "tonode")tonode(((stringtypeParser*)child)->post()); + } + virtual void pre () + { + _link.clear(); + } + virtual void fromnode (const std::string& name) + { + _link.fromnode(name); + } + virtual void tonode (const std::string& name) + { + _link.tonode(name); + } + virtual void property (const myprop& prop) + { + DEBTRACE( "property_set: " << prop._name << prop._value ) + _link.setProperty(prop._name,prop._value); + } + virtual T& post() + { + mincount("fromnode",1); + mincount("tonode",1); + return _link; + } + T _link; +}; + +template +struct linktypeParser: controltypeParser +{ + static linktypeParser linkParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + this->maxcount("fromnode",1,element); + this->maxcount("tonode",1,element); + this->maxcount("fromport",1,element); + this->maxcount("toport",1,element); + parser* pp=&parser::main_parser; + if(element == "fromnode")pp=&stringtypeParser::stringParser; + else if(element == "tonode")pp=&stringtypeParser::stringParser; + else if(element == "toport")pp=&stringtypeParser::stringParser; + else if(element == "fromport")pp=&stringtypeParser::stringParser; + else if(element == "property")pp=&propertytypeParser::propertyParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + virtual void onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "fromnode")this->fromnode(((stringtypeParser*)child)->post()); + else if(element == "tonode")this->tonode(((stringtypeParser*)child)->post()); + else if(element == "toport")toport(((stringtypeParser*)child)->post()); + else if(element == "fromport")fromport(((stringtypeParser*)child)->post()); + else if(element == "property")this->property(((propertytypeParser*)child)->post()); + } + virtual void buildAttr(const XML_Char** attr) + { + for (int i = 0; attr[i]; i += 2) + { + if((std::string(attr[i]) == "control") + && (std::string(attr[i+1]) == "false")) + this->_link._withControl=false; + } + } + virtual void fromport (const std::string& name) + { + this->_link.fromport(name); + } + virtual void toport (const std::string& name) + { + this->_link.toport(name); + } + virtual T& post() + { + this->mincount("fromnode",1); + this->mincount("tonode",1); + this->mincount("fromport",1); + this->mincount("toport",1); + return this->_link; + } +}; + +template +struct streamtypeParser: linktypeParser +{ + static streamtypeParser streamParser; +}; + +template streamtypeParser streamtypeParser::streamParser; +template controltypeParser controltypeParser::controlParser; +template linktypeParser linktypeParser::linkParser; + +} + +#endif diff --git a/src/yacsloader/loader.i b/src/yacsloader/loader.i index 0f0206b26..61e2f10e5 100644 --- a/src/yacsloader/loader.i +++ b/src/yacsloader/loader.i @@ -1,74 +1,41 @@ // ---------------------------------------------------------------------------- %define LOADERDOCSTRING -"Loader docstring -loads an XML file." +"Module to load an calculation schema from a XML file." %enddef %module(docstring=LOADERDOCSTRING) loader -%feature("autodoc", "0"); +//work around SWIG bug #1863647 +#define PySwigIterator loader_PySwigIterator -%include std_string.i +%feature("autodoc", "1"); + +%include "engtypemaps.i" // ---------------------------------------------------------------------------- %{ -#include -#include -#include - -#include "Proc.hxx" -#include "Exception.hxx" #include "parsers.hxx" #include "LoadState.hxx" - -using namespace YACS::ENGINE; -using namespace std; - +#include "TypeCode.hxx" %} -%exception load { - try { - $action - } catch(YACS::Exception& _e) { - PyErr_SetString(PyExc_ValueError,_e.what()); - return NULL; - } catch(std::invalid_argument& _e) { - PyErr_SetString(PyExc_IOError ,_e.what()); - return NULL; - } -} +%types(YACS::ENGINE::Node *); +%types(YACS::ENGINE::InputPort *,YACS::ENGINE::OutputPort *,YACS::ENGINE::InputDataStreamPort *,YACS::ENGINE::OutputDataStreamPort *); +%types(YACS::ENGINE::InGate *,YACS::ENGINE::OutGate *,YACS::ENGINE::InPort *,YACS::ENGINE::OutPort *,YACS::ENGINE::Port *); -namespace YACS -{ - class YACSLoader - { - public: - YACSLoader(); -%feature("autodoc", "load(self, file) -> YACS::ENGINE::Proc"); -%feature("docstring") "loads a XML file which name is given by file argument" ; - virtual YACS::ENGINE::Proc* load(char *); - }; -} +%import "pilot.i" -class xmlParserBase -{ -}; +/* + * Ownership section + */ +//Take ownership : it is not the default (constructor) as it is a factory +%newobject YACS::YACSLoader::load; +/* + * End of Ownership section + */ -namespace YACS -{ - namespace ENGINE - { - class stateParser: public xmlParserBase - { - }; +%include "parsers.hxx" +%import "xmlParserBase.hxx" +%include "LoadState.hxx" - class stateLoader: public xmlReader - { - public: - stateLoader(xmlParserBase* parser, - YACS::ENGINE::Proc* p); - virtual void parse(std::string xmlState); - }; - } -} diff --git a/src/yacsloader/loopParsers.hxx b/src/yacsloader/loopParsers.hxx new file mode 100644 index 000000000..a480b8020 --- /dev/null +++ b/src/yacsloader/loopParsers.hxx @@ -0,0 +1,483 @@ +#ifndef _LOOPPARSER_HXX_ +#define _LOOPPARSER_HXX_ + +#include "parserBase.hxx" + +#include "Bloc.hxx" +#include "Proc.hxx" +#include "Logger.hxx" +#include "Exception.hxx" +#include "InlineNode.hxx" +#include "ServiceNode.hxx" +#include "ServiceInlineNode.hxx" +#include "OutputDataStreamPort.hxx" +#include "InputDataStreamPort.hxx" +#include "ForLoop.hxx" +#include "WhileLoop.hxx" +#include "Switch.hxx" +#include "ForEachLoop.hxx" + +#include +#include +#include + +namespace YACS +{ + +template +struct looptypeParser:parser +{ + void onStart(const XML_Char* el, const XML_Char** attr); + void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void name (const std::string& name); + virtual void state (const std::string& name); + virtual void property (const myprop& prop); + virtual void inline_ (ENGINE::InlineNode* const& n); + virtual void sinline (ENGINE::ServiceInlineNode* const& n); + virtual void service (ENGINE::ServiceNode* const& n); + virtual void node (ENGINE::InlineNode* const& n); + virtual void forloop (ENGINE::ForLoop* const& b); + virtual void foreach (ENGINE::ForEachLoop* const& b); + virtual void while_ (ENGINE::WhileLoop* const& b); + virtual void switch_ (ENGINE::Switch* const& b); + virtual void bloc (ENGINE::Bloc* const& b); + virtual void datalink (const mylink& l); + std::string _state; + T _cnode; + std::vector _cnodes; +}; + +} + +namespace YACS +{ + // A loop can contain forloop, whileloop or foreachloop + // We must respect the order : definition of loop, then while, for, .. and then onStart, onEnd for loop !!! + // + static std::string t3[]={"inline","sinline","service","node","forloop","foreach","while","switch","bloc",""}; + +template +void looptypeParser::buildAttr(const XML_Char** attr) + { + this->required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "state")state(attr[i+1]); + } + } +template +void looptypeParser::pre () + { + _state=""; + _cnode=0; + } +template +void looptypeParser::name (const std::string& name) + { + DEBTRACE( "bloc_name: " << name ); + } +template +void looptypeParser::state (const std::string& name) + { + DEBTRACE( "bloc_state: " << name ); + _state=name; + } +template +void looptypeParser::property (const myprop& prop) + { + DEBTRACE( "property_set" << prop._name << prop._value ); + } + +template +void looptypeParser::inline_ (ENGINE::InlineNode* const& n) + { + DEBTRACE( "loop_inline" << n->getName() ); + _cnode->edSetNode(n); + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->inlineMap[fullname]=n; + } +template +void looptypeParser::sinline (ENGINE::ServiceInlineNode* const& n) + { + DEBTRACE( "loop_sinline" << n->getName() ) + _cnode->edSetNode(n); + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->serviceMap[fullname]=n; + } +template +void looptypeParser::service (ENGINE::ServiceNode* const& n) + { + DEBTRACE( "loop_service" << n->getName() ) + _cnode->edSetNode(n); + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->serviceMap[fullname]=n; + } +template +void looptypeParser::node (ENGINE::InlineNode* const& n) + { + DEBTRACE( "loop_node" << n->getName() ) + _cnode->edSetNode(n); + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->inlineMap[fullname]=n; + } +template +void looptypeParser::forloop (ENGINE::ForLoop* const& b) + { + DEBTRACE( "loop_forloop" << b->getName() ) + _cnode->edSetNode(b); + std::string fullname=currentProc->names.back()+ b->getName(); + currentProc->nodeMap[fullname]=b; + } +template +void looptypeParser::foreach (ENGINE::ForEachLoop* const& b) + { + DEBTRACE("loop_foreach" << b->getName()) + _cnode->edSetNode(b); + std::string fullname=currentProc->names.back()+ b->getName(); + currentProc->nodeMap[fullname]=b; + fullname += ".splitter"; + currentProc->nodeMap[fullname]=b->getChildByShortName("splitter"); + } +template +void looptypeParser::while_ (ENGINE::WhileLoop* const& b) + { + DEBTRACE( "loop_while: " << b->getName() ) + _cnode->edSetNode(b); + std::string fullname=currentProc->names.back()+ b->getName(); + currentProc->nodeMap[fullname]=b; + } +template +void looptypeParser::switch_ (ENGINE::Switch* const& b) + { + DEBTRACE( "loop_switch: " << b->getName() ) + _cnode->edSetNode(b); + std::string fullname=currentProc->names.back()+ b->getName(); + currentProc->nodeMap[fullname]=b; + } +template +void looptypeParser::bloc (ENGINE::Bloc* const& b) + { + DEBTRACE( "loop_bloc " << b->getName() ) + _cnode->edSetNode(b); + std::string fullname=currentProc->names.back()+ b->getName(); + currentProc->nodeMap[fullname]=b; + } + +template +void looptypeParser::datalink (const mylink& l) + { + DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport()) + std::string msg; + + //Try only relative name for from node + std::string fromname = currentProc->names.back()+l.fromnode(); + if(currentProc->nodeMap.count(fromname) == 0) + { + msg="from node " + l.fromnode() + " does not exist in data link: "; + msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; + this->logError(msg); + return; + } + //Try relative name for to node and then absolute one + std::string toname = currentProc->names.back()+l.tonode(); + if(currentProc->nodeMap.count(toname) == 0) + { + //It's not a relative name. Try an absolute one (I think it's not possible) + toname=l.tonode(); + if(currentProc->nodeMap.count(toname) == 0) + { + // The TO node does not exist -> error + msg="to node " + l.tonode() + " does not exist in data link: "; + msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; + this->logError(msg); + return; + } + } + // We only link local node and other nodes (relative or absolute name in this order) + DEBTRACE(fromname <<":"<edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), + currentProc->nodeMap[toname]->getInputPort(l.toport())); + else + _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), + currentProc->nodeMap[toname]->getInputPort(l.toport())); + } + catch(Exception& e) + { + this->logError(e.what()); + } + } + + +} + +namespace YACS +{ + + // While loop specialization + +template +struct whilelooptypeParser:looptypeParser +{ + static whilelooptypeParser whileloopParser; + virtual void name (const std::string& name); + virtual T post(); +}; + +template whilelooptypeParser whilelooptypeParser::whileloopParser; + +template +void whilelooptypeParser::name (const std::string& name) + { + DEBTRACE( "while_name: " << name ) + std::string fullname=currentProc->names.back()+name; + this->_cnode=theRuntime->createWhileLoop(name); + currentProc->nodeMap[fullname]=this->_cnode; + this->_cnodes.push_back(this->_cnode); + currentProc->names.push_back(fullname+'.'); + } + +template +T whilelooptypeParser::post() + { + DEBTRACE( "while_post" << this->_cnode->getName() ) + this->minchoice(t3,1); + ENGINE::InputPort *cond=this->_cnode->edGetConditionPort(); + cond->edInit(true); + T b=this->_cnode; + this->_cnodes.pop_back(); + currentProc->names.pop_back(); + this->_cnode=this->_cnodes.back(); + return b; + } +} + + + + +namespace YACS +{ + // For loop specialization + +template +struct forlooptypeParser:looptypeParser +{ + static forlooptypeParser forloopParser; + virtual void buildAttr(const XML_Char** attr); + virtual void name (const std::string& name); + virtual void nsteps (const int& n); + virtual T post(); + int _nsteps; +}; + +template forlooptypeParser forlooptypeParser::forloopParser; + +template +void forlooptypeParser::buildAttr(const XML_Char** attr) + { + this->required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "state")this->state(attr[i+1]); + if(std::string(attr[i]) == "nsteps")nsteps(atoi(attr[i+1])); + } + } + +template + void forlooptypeParser::name (const std::string& name) + { + DEBTRACE( "forloop_name: " << name ); + std::string fullname=currentProc->names.back()+name; + this->_cnode=theRuntime->createForLoop(name); + currentProc->nodeMap[fullname]=this->_cnode; + this->_cnodes.push_back(this->_cnode); + currentProc->names.push_back(fullname+'.'); + _nsteps=0; + } + +template +void forlooptypeParser::nsteps (const int& n) + { + DEBTRACE( "forloop_nsteps: " << n ) + if(!this->_cnode) + throw Exception("Node name must be defined before nsteps"); + ENGINE::InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort(); + iNbTimes->edInit(n); + } + +template + T forlooptypeParser::post() + { + DEBTRACE( "forloop_post" ) + this->minchoice(t3,1); + T b=this->_cnode; + this->_cnodes.pop_back(); + currentProc->names.pop_back(); + this->_cnode=this->_cnodes.back(); + return b; + } + +} + +namespace YACS +{ + // Foreach loop specialization + +template +struct foreachlooptypeParser:looptypeParser +{ + static foreachlooptypeParser foreachloopParser; + + virtual void buildAttr(const XML_Char** attr) + { + this->required("name",attr); + this->required("type",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "state")this->state(attr[i+1]); + if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1])); + if(std::string(attr[i]) == "type")datatype(attr[i+1]); + } + postAttr(); + } + virtual void pre () + { + _nbranch=0; + this->looptypeParser::pre(); + } + virtual void name (const std::string& name) + { + DEBTRACE("foreach_name: " << name) + _name=name; + _fullname=currentProc->names.back()+name; + } + virtual void nbranch (const int& n) + { + DEBTRACE("foreach_nbranch: " << n ) + _nbranch=n; + } + virtual void datatype (const std::string& type) + { + DEBTRACE("foreach_datatype: "<< type) + _datatype=type; + } + virtual void postAttr() + { + if(currentProc->typeMap.count(_datatype)==0) + { + //Check if the typecode is defined in the runtime + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(_datatype); + if(t==0) + { + std::stringstream msg; + msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")"; + throw Exception(msg.str()); + } + else + { + currentProc->typeMap[_datatype]=t; + t->incrRef(); + } + } + this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]); + //set number of branches + if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch); + this->_cnodes.push_back(this->_cnode); + currentProc->names.push_back(_fullname + '.'); + } + virtual T post() + { + DEBTRACE("foreach_post" << this->_cnode->getName()) + this->minchoice(t3,1); + T b=this->_cnode; + this->_cnodes.pop_back(); + currentProc->names.pop_back(); + if(this->_cnodes.size() == 0) + this->_cnode=0; + else + this->_cnode=this->_cnodes.back(); + return b; + } + int _nbranch; + std::string _fullname; + std::string _name; + std::string _datatype; +}; + +template foreachlooptypeParser foreachlooptypeParser::foreachloopParser; + +} + +#include "blocParsers.hxx" +#include "switchParsers.hxx" + +namespace YACS +{ + +template +void looptypeParser::onStart(const XML_Char* el, const XML_Char** attr) +{ + DEBTRACE( "looptypeParser::onStart: " << el ) + std::string element(el); + this->maxcount("inline",1,element); + this->maxcount("sinline",1,element); + this->maxcount("service",1,element); + this->maxcount("node",1,element); + this->maxcount("forloop",1,element); + this->maxcount("foreach",1,element); + this->maxcount("while",1,element); + this->maxcount("switch",1,element); + this->maxcount("bloc",1,element); + this->maxchoice(t3,1,element); + parser* pp=&parser::main_parser; + if(element == "property")pp=&propertytypeParser::propertyParser; + else if(element == "inline")pp=&inlinetypeParser<>::inlineParser; + else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser; + else if(element == "service")pp=&servicetypeParser<>::serviceParser; + else if(element == "node")pp=&nodetypeParser<>::nodeParser; + + else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser; + else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser; + else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser; + else if(element == "switch")pp=&switchtypeParser::switchParser; + else if(element == "bloc")pp=&bloctypeParser<>::blocParser; + else if(element == "datalink")pp=&linktypeParser<>::linkParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); +} + +template +void looptypeParser::onEnd(const char *el,parser* child) +{ + DEBTRACE( "looptypeParser::onEnd: " << el ) + std::string element(el); + if(element == "property")property(((propertytypeParser*)child)->post()); + else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post()); + else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post()); + else if(element == "service")service(((servicetypeParser<>*)child)->post()); + else if(element == "node")node(((nodetypeParser<>*)child)->post()); + + else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post()); + else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post()); + else if(element == "while")while_(((whilelooptypeParser<>*)child)->post()); + else if(element == "switch")switch_(((switchtypeParser*)child)->post()); + else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post()); + + else if(element == "datalink") datalink(((linktypeParser<>*)child)->post()); +} + +} +#endif diff --git a/src/yacsloader/nodeParsers.hxx b/src/yacsloader/nodeParsers.hxx new file mode 100644 index 000000000..0db06ee45 --- /dev/null +++ b/src/yacsloader/nodeParsers.hxx @@ -0,0 +1,580 @@ + +#ifndef _NODEPARSERS_HXX_ +#define _NODEPARSERS_HXX_ + +#include "parserBase.hxx" +#include "containerParsers.hxx" +#include "dataParsers.hxx" +#include "portParsers.hxx" +#include "codeParsers.hxx" +#include "propertyParsers.hxx" + +#include "Proc.hxx" +#include "TypeCode.hxx" +#include "InlineNode.hxx" +#include "ServiceNode.hxx" +#include "ServiceInlineNode.hxx" +#include "Exception.hxx" +#include "Runtime.hxx" +#include "OutputDataStreamPort.hxx" +#include "InputDataStreamPort.hxx" +#include "ComponentInstance.hxx" +#include "factory.hxx" + +extern YACS::ENGINE::Proc* currentProc; +extern YACS::ENGINE::Runtime* theRuntime; + +namespace YACS +{ + +/*! \brief Class for node parser. + * + * This class is a base class for other parsers + */ +template +struct nodetypeParser: parser +{ + static nodetypeParser nodeParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE( "nodetypeParser::onStart: " << el ) + std::string element(el); + parser* pp=&parser::main_parser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + virtual void onEnd(const char *el,parser* child) + { + DEBTRACE( "nodetypeParser::onEnd: " << el ) + std::string element(el); + } + virtual void buildAttr(const XML_Char** attr) + { + required("name",attr); + required("type",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "state")state(attr[i+1]); + if(std::string(attr[i]) == "type")type(attr[i+1]); + } + } + virtual void pre() + { + _node=0; + _container=""; + } + virtual void name (const std::string& name) + { + DEBTRACE( "inline_name: " << name ) + _name=name; + } + virtual void state (const std::string& name) + { + _state=name; + } + virtual void type (const std::string& name) + { + DEBTRACE( "node_type " << name ) + _type=name; + } + virtual void property (const myprop& prop); + virtual T post(); + std::string _type; + std::string _name; + std::string _state; + std::string _container; + T _node; +}; + +template nodetypeParser nodetypeParser::nodeParser; + +template +void nodetypeParser::property (const myprop& prop) +{ + _node->setProperty(prop._name,prop._value); +} + +template +T nodetypeParser::post() +{ + return _node; +} + +template <> +YACS::ENGINE::InlineNode* nodetypeParser::post () +{ + std::string fullname = currentProc->names.back()+_type; + if(currentProc->inlineMap.count(_type) != 0) + { + //InlineNode type with absolute name found + YACS::ENGINE::InlineNode* n=currentProc->inlineMap[_type]; + _node=n->cloneNode(_name); + } + else if(currentProc->inlineMap.count(fullname) != 0) + { + //InlineNode type with relative name found + YACS::ENGINE::InlineNode* n=currentProc->inlineMap[fullname]; + _node=n->cloneNode(_name); + } + else + { + throw YACS::Exception("Unknown InlineNode type"); + } + if(_state == "disabled")_node->exDisabledState(); + DEBTRACE( "node_post " << _node->getName() ) + return _node; +} + +static std::string t1[]={"script","function",""}; + +template +struct inlinetypeParser:public nodetypeParser +{ + static inlinetypeParser inlineParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child) + { + DEBTRACE( "inlinetypeParser::onEnd: " << el ) + std::string element(el); + if(element == "kind")kind(((stringtypeParser*)child)->post()); + else if(element == "script")script(((codetypeParser*)child)->post()); + else if(element == "function")function(((functypeParser*)child)->post()); + else if(element == "property")this->property(((propertytypeParser*)child)->post()); + else if(element == "inport") inport(((inporttypeParser*)child)->post()); + else if(element == "outport") outport(((outporttypeParser*)child)->post()); + } + virtual void buildAttr(const XML_Char** attr) + { + this->required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")this->name(attr[i+1]); + if(std::string(attr[i]) == "state")this->state(attr[i+1]); + } + } + virtual void pre () + { + this->_node=0; + _kind=""; + this->_state=""; + this->_container=""; + } + virtual void kind (const std::string& name) + { + DEBTRACE( "inline_kind " << name ) + _kind=name; + } + + virtual void script (const myfunc& f){} + virtual void function (const myfunc& f) {} + + virtual void inport (const myinport& p) + { + DEBTRACE( "inline_inport: " << p._name <<":"<_node==0) + throw YACS::Exception("Node must be completely defined before defining its ports"); + + if(currentProc->typeMap.count(p._type)==0) + { + //Check if the typecode is defined in the runtime + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(p._type); + if(t==0) + { + std::string msg="Unknown InPort Type: "; + msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; + throw YACS::Exception(msg); + } + else + { + currentProc->typeMap[p._type]=t; + t->incrRef(); + } + } + this->_node->edAddInputPort(p._name,currentProc->typeMap[p._type]); + } + virtual void outport (const myoutport& p) + { + DEBTRACE( "inline_outport: " << p._name <<":"<_node==0) + throw YACS::Exception("Node must be completely defined before defining its ports"); + + if(currentProc->typeMap.count(p._type)==0) + { + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(p._type); + if(t==0) + { + std::string msg="Unknown OutPort Type: "; + msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; + throw YACS::Exception(msg); + } + else + { + currentProc->typeMap[p._type]=t; + t->incrRef(); + } + } + this->_node->edAddOutputPort(p._name,currentProc->typeMap[p._type]); + } + virtual T post() + { + DEBTRACE( "inline_post " << this->_node->getName() ) + if(this->_state == "disabled")this->_node->exDisabledState(); + /* + std::list::iterator iter; + std::list s=_node->getSetOfOutputPort(); + for(iter=s.begin();iter!=s.end();iter++) + { + std::cerr << "port name: " << (*iter)->getName() << std::endl; + std::cerr << "port kind: " << (*iter)->edGetType()->kind() << std::endl; + } + */ + return this->_node; + } + std::string _kind; +}; + +template inlinetypeParser inlinetypeParser::inlineParser; + +template <> +void inlinetypeParser::script (const myfunc& f) +{ + DEBTRACE( "inline_script: " << f._code ) + _node=theRuntime->createScriptNode(_kind,_name); + _node->setScript(f._code); +} + +template <> +void inlinetypeParser::function (const myfunc& f) +{ + DEBTRACE( "inline_function: " << f._code ) + YACS::ENGINE::InlineFuncNode *fnode; + fnode=theRuntime->createFuncNode(_kind,_name); + fnode->setScript(f._code); + fnode->setFname(f._name); + _node=fnode; +} + +/*! \brief Class for parsing ServiceInlineNode description + * + * + */ +template +struct sinlinetypeParser:public inlinetypeParser +{ + static sinlinetypeParser sinlineParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child) + { + DEBTRACE( "sinlinetypeParser::onEnd: " << el ) + std::string element(el); + if(element == "kind")this->kind(((stringtypeParser*)child)->post()); + else if(element == "function")this->function(((functypeParser*)child)->post()); + else if(element == "load") load(((loadtypeParser*)child)->post()); + else if(element == "property")this->property(((propertytypeParser*)child)->post()); + else if(element == "inport") this->inport(((inporttypeParser*)child)->post()); + else if(element == "outport") this->outport(((outporttypeParser*)child)->post()); + } + //virtual void service (const myfunc& f) {} + virtual void load (const loadon& l) + { + DEBTRACE( "sinline_load: " ) + this->_container=l._container; + } + virtual T post() + { + DEBTRACE( "sinline_post " << this->_node->getName() ); + if(this->_state == "disabled")this->_node->exDisabledState(); + + if(currentProc->containerMap.count(this->_container) != 0) + { + this->_node->getComponent()->setContainer(currentProc->containerMap[this->_container]); + } + else if(this->_container == "") + { + if(currentProc->containerMap.count("DefaultContainer") != 0) + { + //a default container is defined : use it + this->_node->getComponent()->setContainer(currentProc->containerMap["DefaultContainer"]); + } + } + else + { + std::cerr << "WARNING: Unknown container " << this->_container << " ignored" << std::endl; + } + + return this->_node; + } +}; +template sinlinetypeParser sinlinetypeParser::sinlineParser; + +// sinline ???? +template <> +void inlinetypeParser::function (const myfunc& f) +{ + DEBTRACE( "sinline_function: " << f._code ) + YACS::ENGINE::ServiceInlineNode *fnode; + fnode=theRuntime->createSInlineNode(_kind,_name); + fnode->setScript(f._code); + fnode->setMethod(f._name); + fnode->setComponent(theRuntime->createComponentInstance("PyCompo","SalomePy")); + //fnode->setRef("PyCompo"); + _node=fnode; +} + +static std::string t2[]={"ref","node","component",""}; + +template +struct servicetypeParser:public inlinetypeParser +{ + static servicetypeParser serviceParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child) + { + DEBTRACE( "servicetypeParser::onEnd: " << el ) + std::string element(el); + if(element == "kind")this->kind(((stringtypeParser*)child)->post()); + else if(element == "ref") ref(((stringtypeParser*)child)->post()); + else if(element == "component") component(((stringtypeParser*)child)->post()); + else if(element == "node") node(((stringtypeParser*)child)->post()); + else if(element == "method") method(((stringtypeParser*)child)->post()); + else if(element == "load") load(((loadtypeParser*)child)->post()); + else if(element == "property")this->property(((propertytypeParser*)child)->post()); + else if(element == "inport") this->inport(((inporttypeParser*)child)->post()); + else if(element == "outport") this->outport(((outporttypeParser*)child)->post()); + else if(element == "instream") instream(((inporttypeParser*)child)->post()); + else if(element == "outstream") outstream(((outporttypeParser*)child)->post()); + } + virtual void ref (const std::string& name) + { + DEBTRACE( "service_ref: " << name ) + this->_node=theRuntime->createRefNode(this->_kind,this->_name); + this->_node->setRef(name); + } + virtual void component (const std::string& name) + { + DEBTRACE( "service_component: " << name ) + this->_node=theRuntime->createCompoNode(this->_kind,this->_name); + this->_node->setRef(name); + } + virtual void node (const std::string& name) + { + DEBTRACE( "service_node: " << name ) + std::string fullname = currentProc->names.back()+name; + if(currentProc->serviceMap.count(name) != 0) + { + //ServiceNode with absolute name found + YACS::ENGINE::ServiceNode* n=currentProc->serviceMap[name]; + this->_node =n->createNode(this->_name); + } + else if(currentProc->serviceMap.count(fullname) != 0) + { + //ServiceNode with relative name found + //TODO: must be a short name (possible only in the same context) + YACS::ENGINE::ServiceNode* n=currentProc->serviceMap[fullname]; + this->_node =n->createNode(this->_name); + } + else + { + throw YACS::Exception("Unknown ServiceNode"); + } + } + + virtual void method (const std::string& name) + { + DEBTRACE( "service_method: " << name ) + if(this->_node==0) + throw YACS::Exception("ServiceNode must be completely defined before defining its method"); + if(name == "") + { + this->logError("a service name must be a non empty string"); + return; + } + this->_node->setMethod(name); + } + + virtual void load (const loadon& l) + { + DEBTRACE( "service_load: " ); + this->_container=l._container; + } + + virtual void instream (const myinport& p) + { + DEBTRACE( "service_instream" ) + DEBTRACE( p._type ) + DEBTRACE( p._name ) + if(this->_node==0) + throw YACS::Exception("ServiceNode must be completely defined before defining its ports"); + + if(currentProc->typeMap.count(p._type)==0) + { + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(p._type); + if(t==0) + { + std::string msg="Unknown InStreamPort Type: "; + msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; + throw YACS::Exception(msg); + } + else + { + currentProc->typeMap[p._type]=t; + t->incrRef(); + } + } + YACS::ENGINE::InputDataStreamPort* port; + port=this->_node->edAddInputDataStreamPort(p._name,currentProc->typeMap[p._type]); + // Set all properties for this port + std::map::const_iterator pt; + for(pt=p._props.begin();pt!=p._props.end();pt++) + port->setProperty((*pt).first,(*pt).second); + } + virtual void outstream (const myoutport& p) + { + DEBTRACE( "service_outstream" ) + DEBTRACE( p._type ) + DEBTRACE( p._name ) + if(this->_node==0) + throw YACS::Exception("ServiceNode must be completely defined before defining its ports"); + + if(currentProc->typeMap.count(p._type)==0) + { + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(p._type); + if(t==0) + { + std::string msg="Unknown OutStreamPort Type: "; + msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; + throw YACS::Exception(msg); + } + else + { + currentProc->typeMap[p._type]=t; + t->incrRef(); + } + } + YACS::ENGINE::OutputDataStreamPort* port; + port=this->_node->edAddOutputDataStreamPort(p._name,currentProc->typeMap[p._type]); + // Set all properties for this port + std::map::const_iterator pt; + for(pt=p._props.begin();pt!=p._props.end();pt++) + port->setProperty((*pt).first,(*pt).second); + } + virtual T post() + { + DEBTRACE( "service_post " << this->_node->getName() ) + this->mincount("method",1); + if(this->_state == "disabled")this->_node->exDisabledState(); + + if(currentProc->containerMap.count(this->_container) != 0) + { + this->_node->getComponent()->setContainer(currentProc->containerMap[this->_container]); + } + else if(this->_container == "") + { + if(currentProc->containerMap.count("DefaultContainer") != 0) + { + //a default container is defined : use it + this->_node->getComponent()->setContainer(currentProc->containerMap["DefaultContainer"]); + } + } + else + { + std::cerr << "WARNING: Unknown container " << this->_container << " ignored" << std::endl; + } + return this->_node; + } +}; + +template servicetypeParser servicetypeParser::serviceParser; + +} + + +namespace YACS +{ +template +void inlinetypeParser::onStart(const XML_Char* el, const XML_Char** attr) + + { + DEBTRACE( "inlinetypeParser::onStart: " << el ) + std::string element(el); + parser* pp=&parser::main_parser; + this->maxcount("kind",1,element); + this->maxcount("script",1,element); + this->maxcount("function",1,element); + this->maxchoice(t1,1,element); + if(element == "kind")pp=&stringtypeParser::stringParser; + else if(element == "script")pp=&codetypeParser::codeParser; + else if(element == "function")pp=&functypeParser::funcParser; + else if(element == "property")pp=&propertytypeParser::propertyParser; + else if(element == "inport")pp=&inporttypeParser<>::inportParser; + else if(element == "outport")pp=&outporttypeParser<>::outportParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + +template +void sinlinetypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE( "sinlinetypeParser::onStart: " << el ) + std::string element(el); + parser* pp=&parser::main_parser; + this->maxcount("kind",1,element); + this->maxcount("function",1,element); + this->maxcount("load",1,element); + if(element == "kind")pp=&stringtypeParser::stringParser; + else if(element == "function")pp=&functypeParser::funcParser; + else if(element == "load")pp=&loadtypeParser::loadParser; + else if(element == "property")pp=&propertytypeParser::propertyParser; + else if(element == "inport")pp=&inporttypeParser<>::inportParser; + else if(element == "outport")pp=&outporttypeParser<>::outportParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + +template +void servicetypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE( "servicetypeParser::onStart: " << el ) + std::string element(el); + parser* pp=&parser::main_parser; + this->maxcount("kind",1,element); + this->maxcount("ref",1,element); + this->maxcount("node",1,element); + this->maxcount("component",1,element); + this->maxcount("method",1,element); + this->maxcount("load",1,element); + this->maxchoice(t2,1,element); + if(element == "kind")pp=&stringtypeParser::stringParser; + else if(element == "ref")pp=&stringtypeParser::stringParser; + else if(element == "component")pp=&stringtypeParser::stringParser; + else if(element == "node")pp=&stringtypeParser::stringParser; + else if(element == "method")pp=&stringtypeParser::stringParser; + else if(element == "load")pp=&loadtypeParser::loadParser; + else if(element == "property")pp=&propertytypeParser::propertyParser; + else if(element == "inport")pp=&inporttypeParser<>::inportParser; + else if(element == "outport")pp=&outporttypeParser<>::outportParser; + else if(element == "instream")pp=&inporttypeParser<>::inportParser; + else if(element == "outstream")pp=&outporttypeParser<>::outportParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + + + + +} + +#endif diff --git a/src/yacsloader/outputParsers.hxx b/src/yacsloader/outputParsers.hxx new file mode 100644 index 000000000..e8334e683 --- /dev/null +++ b/src/yacsloader/outputParsers.hxx @@ -0,0 +1,214 @@ +#ifndef _OUTPUTPARSERS_HXX_ +#define _OUTPUTPARSERS_HXX_ + +#include "nodeParsers.hxx" + +#include "factory.hxx" + +#include "DataNode.hxx" + +namespace YACS +{ + +/*! \brief Class for outputdata parser. + * + * Its XML schema is: + \verbatim + + + + + + \endverbatim + */ +struct outputdatatypeParser: parser +{ + static outputdatatypeParser outputdataParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE("outputdatatypeParser::onStart"); + std::string element(el); + parser* pp=&parser::main_parser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + virtual void onEnd(const char *el,parser* child) + { + } + virtual void buildAttr(const XML_Char** attr) + { + DEBTRACE("outputdatatypeParser::buildAttr"); + required("name",attr); + required("type",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "type")type(attr[i+1]); + if(std::string(attr[i]) == "ref")ref(attr[i+1]); + } + } + virtual void name (const std::string& name) + { + DEBTRACE("outputdatatypeParser::name"); + _param._name=name; + } + virtual void type (const std::string& type) + { + DEBTRACE("outputdatatypeParser::type"); + _param._type=type; + } + virtual void ref (const std::string& ref) + { + _param.setProperty("ref",ref); + } + + virtual void pre () + { + DEBTRACE("outputdatatypeParser::pre"); + _param.clear(); + } + virtual myoutport& post() + { + return _param; + } + myoutport _param; +}; + +/*! \brief Class for OutNode parser. + * + * Its XML schema is: + \verbatim + + + + + + + \endverbatim + */ +template +struct outnodetypeParser:public nodetypeParser +{ + static outnodetypeParser outnodeParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void name (const std::string& name); + virtual void kind (const std::string& kind); + virtual void ref (const std::string& ref); + virtual void create (); + virtual void parameter (myoutport& p); + virtual T post(); + std::string _name; + std::string _kind; + std::string _ref; +}; + +template outnodetypeParser outnodetypeParser::outnodeParser; + + +template +void outnodetypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE("outnodetypeParser::onStart"); + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "parameter")pp=&outputdatatypeParser::outputdataParser; + if(element == "property")pp=&propertytypeParser::propertyParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + +template +void outnodetypeParser::onEnd(const char *el,parser* child) + { + DEBTRACE("outnodetypeParser::onEnd"); + std::string element(el); + if(element == "parameter")parameter(((outputdatatypeParser*)child)->post()); + if(element == "property")this->property(((propertytypeParser*)child)->post()); + } + +template +void outnodetypeParser::buildAttr(const XML_Char** attr) + { + DEBTRACE("outnodetypeParser::buildAttr"); + this->required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "kind")kind(attr[i+1]); + if(std::string(attr[i]) == "ref")ref(attr[i+1]); + } + create(); + } + +template +void outnodetypeParser::pre () +{ + this->_node=0; + _kind=""; + _ref=""; +} + +template +void outnodetypeParser::name (const std::string& name) +{ + _name=name; +} +template +void outnodetypeParser::kind (const std::string& kind) +{ + _kind=kind; +} +template +void outnodetypeParser::ref (const std::string& ref) +{ + _ref=ref; +} + +template +void outnodetypeParser::create () +{ + this->_node = theRuntime->createOutDataNode(_kind,_name); +} + +template +void outnodetypeParser::parameter (myoutport& p) +{ + DEBTRACE("outnodetypeParser::parameter"); + if(currentProc->typeMap.count(p._type)==0) + { + //Check if the typecode is defined in the runtime + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(p._type); + if(t==0) + { + std::string msg="Unknown Type: "; + msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; + this->logError(msg); + return; + } + else + { + currentProc->typeMap[p._type]=t; + t->incrRef(); + } + } + ENGINE::InputPort *port = this->_node->edAddInputPort(p._name,currentProc->typeMap[p._type]); + this->_node->setData(port,p._props["ref"]); +} + +template +T outnodetypeParser::post() +{ + this->_node->setRef(_ref); + return this->_node; +} + +} +#endif diff --git a/src/yacsloader/parserBase.cxx b/src/yacsloader/parserBase.cxx new file mode 100644 index 000000000..a7ab83a15 --- /dev/null +++ b/src/yacsloader/parserBase.cxx @@ -0,0 +1,225 @@ + +#include "parserBase.hxx" +#include "Exception.hxx" +#include "Proc.hxx" +#include "Logger.hxx" +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +YACS::ENGINE::Proc* currentProc; +XML_Parser p ; +std::stack sp; + +namespace YACS +{ + parser parser::main_parser; + +parser::~parser() +{ + if(_level==0) + { + delete _counts; + } + else + { + DEBTRACE("Problem with parser: final stack level should be 0 and not " << _level); + } +} + +std::stack& parser::getStack() +{ + return sp; +} + +void parser::SetUserDataAndPush(parser* pp) +{ + XML_SetUserData(p,pp); + sp.push(pp); + DEBTRACE("parser::SetUserDataAndPush, stack size: " << sp.size()); +} + +void XMLCALL parser::start(void *data, const XML_Char* el, const XML_Char** attr) +{ + DEBTRACE("parser::start, stack size: " << sp.size()); + parser* pp=static_cast (data); + pp->incrCount(el); + pp->onStart(el,attr); +} + +void parser::onEnd(const XML_Char *el,parser* child) +{ + DEBTRACE("parser::onEnd: " << el) +} + +void XMLCALL parser::end(void *data, const char *el) +{ + DEBTRACE("parser::end: " << el); + parser* child=static_cast (data); + sp.pop(); + DEBTRACE("parser::end, stack size: " << sp.size()); + parser* pp=sp.top(); + XML_SetUserData(p,pp); + pp->onEnd(el,child); + child->endParser(); +} + +void parser::charData(const XML_Char *s, int len) +{ + _content=_content+std::string(s,len); +} + +void XMLCALL parser::charac(void *data, const XML_Char *s, int len) +{ + parser* pp=static_cast (data); + pp->charData(s,len); +} + +void parser::endParser() +{ + DEBTRACE("parser::endParser, level: " <<_level); + _level=_level-1; + if(_level>0) + { + delete _counts; + _counts=_stackCount.top(); + _orderState=_stackOrder.top(); + _stackCount.pop(); + _stackOrder.pop(); + } +} + +void parser::init () +{ + DEBTRACE("parser::init, level: " <<_level); + if(_level>0) + { + _stackCount.push(_counts); + _stackOrder.push(_orderState); + _counts=new std::map; + } + _level=_level+1; + _counts->clear(); + _orderState=0; +} + +void parser::incrCount(const XML_Char *el) +{ + if(_counts->count(el)==0) + (*_counts)[el]=1; + else + (*_counts)[el]=(*_counts)[el]+1; +} + +void parser::checkOrder(std::string& el) +{ + if(_orders.count(el)==0)return; + if(_orders[el] < _orderState) + { + std::string msg="unexpected "+el+" element (wrong order)"; + throw YACS::Exception::Exception(msg); + } + else if(_orders[el] > _orderState) + { + _orderState=_orders[el]; + } +} + +void parser::maxcount(std::string name, int max, std::string& el) +{ + if(el!=name)return; + if((*_counts)[name]>max) + { + std::stringstream msg; + msg <<"unexpected "+name+" element (count="<<(*_counts)[name]; + msg <<" > maxOccurs=" << max << ")"; + throw YACS::Exception::Exception(msg.str()); + } +} + +void parser::mincount(std::string name,int min ) +{ + if((*_counts)[name]max) + { + std::stringstream msg; + msg<<"unexpected "+el+" element (choice count="< maxOccurs=" << max << ")"; + throw YACS::Exception::Exception(msg.str()); + } +} + +void parser::minchoice(std::string *names, int min) +{ + int i=0; + int ncount=0; + while (names[i]!= "") + { + ncount=ncount+(*_counts)[names[i]]; + ++i; + } + if(ncountgetLogger("parser")->error(reason,main_parser._file.c_str(),XML_GetCurrentLineNumber(p)); +} + +} diff --git a/src/yacsloader/parserBase.hxx b/src/yacsloader/parserBase.hxx new file mode 100644 index 000000000..6ef4f8120 --- /dev/null +++ b/src/yacsloader/parserBase.hxx @@ -0,0 +1,78 @@ +#ifndef _PARSERBASE_HXX_ +#define _PARSERBASE_HXX_ + +#include +#include +#include +#include +#include + +namespace YACS +{ + +struct parser +{ + static parser main_parser; + + parser():_level(0),_defaultParsersMap(0) + { + _counts=new std::map; + } + virtual ~parser(); + + virtual void SetUserDataAndPush(parser* pp); + virtual void onStart(const XML_Char *el, const XML_Char** attr); + static void XMLCALL start(void *data, const XML_Char* el, const XML_Char** attr); + + virtual void onEnd(const XML_Char *el,parser* child); + + static void XMLCALL end(void *data, const char *el); + + virtual void charData(const XML_Char *s, int len); + + static void XMLCALL charac(void *data, const XML_Char *s, int len); + + virtual void endParser(); + + virtual void init(); + + virtual void incrCount(const XML_Char *el); + + virtual void checkOrder(std::string& el); + + virtual void maxcount(std::string name, int max, std::string& el); + + virtual void mincount(std::string name,int min ); + + virtual void maxchoice(std::string *names, int max, std::string& el); + + virtual void minchoice(std::string *names, int min); + + virtual void pre(){_content="";}; + virtual void required(const std::string& name, const XML_Char** attr); + + virtual void buildAttr(const XML_Char** attr); + + std::stack& getStack(); + + template + T post() { } + + void logError(const std::string& reason); + + std::string _file; + std::string _content; + std::map *_counts; + std::map _orders; + int _orderState; + int _level; + std::stack*> _stackCount; + std::stack _stackOrder; + // OCC: san -- Allow external parsers for handling of unknown elements + // and attributes. This capability is used by YACS GUI to read + // graph presentation data + std::map *_defaultParsersMap; +}; + +} +#endif diff --git a/src/yacsloader/parsers.cxx b/src/yacsloader/parsers.cxx index 19f307f58..6e44fc12c 100644 --- a/src/yacsloader/parsers.cxx +++ b/src/yacsloader/parsers.cxx @@ -1,2950 +1,53 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "parsers.hxx" -#include "factory.hxx" -#include "Runtime.hxx" -#include "Exception.hxx" -#include "Cstr2d.hxx" -#include "TypeCode.hxx" -#include "Loop.hxx" -#include "ForLoop.hxx" -#include "ForEachLoop.hxx" -#include "WhileLoop.hxx" -#include "Switch.hxx" -#include "Bloc.hxx" -#include "Proc.hxx" -#include "InlineNode.hxx" -#include "ServiceNode.hxx" -#include "ServiceInlineNode.hxx" -#include "OutputPort.hxx" -#include "InputPort.hxx" -#include "OutputDataStreamPort.hxx" -#include "InputDataStreamPort.hxx" -#include "ComponentInstance.hxx" -#include "Container.hxx" - -using namespace YACS; -using YACS::ENGINE::Runtime; -using YACS::ENGINE::getRuntime; - -using YACS::ENGINE::TypeCode; -using YACS::Exception; -using YACS::ENGINE::TypeCodeObjref; -using YACS::ENGINE::TypeCodeStruct; -using YACS::ENGINE::Objref; -using YACS::ENGINE::InlineNode; -using YACS::ENGINE::InlineFuncNode; -using YACS::ENGINE::ServiceNode; -using YACS::ENGINE::ServiceInlineNode; -using YACS::ENGINE::Node; -using YACS::ENGINE::Loop; -using YACS::ENGINE::ForLoop; -using YACS::ENGINE::ForEachLoop; -using YACS::ENGINE::WhileLoop; -using YACS::ENGINE::Switch; -using YACS::ENGINE::Bloc; -using YACS::ENGINE::Proc; -using YACS::ENGINE::InputPort; -using YACS::ENGINE::OutputPort; -using YACS::ENGINE::InputDataStreamPort; -using YACS::ENGINE::OutputDataStreamPort; - -//#define _DEVDEBUG_ -#include "YacsTrace.hxx" - -Runtime* theRuntime=0; -static Proc* currentProc; - -#define BUFFSIZE 8192 - -char Buff[BUFFSIZE]; - -XML_Parser p ; - -std::stack sp; - -parser::~parser() -{ - if(_level==0) - { - delete _counts; - } - else - { - DEBTRACE("Problem with parser: final stack level should be 0 and not " << _level); - } -} - -void parser::SetUserDataAndPush(parser* pp) -{ - XML_SetUserData(p,pp); - sp.push(pp); -} - -void XMLCALL parser::start(void *data, const XML_Char* el, const XML_Char** attr) -{ - parser* pp=static_cast (data); - pp->incrCount(el); - pp->onStart(el,attr); -} - -void parser::onEnd(const XML_Char *el,parser* child) -{ - DEBTRACE("parser::onEnd: " << el) -} - -void XMLCALL parser::end(void *data, const char *el) -{ - DEBTRACE("parser::end: " << el); - parser* child=static_cast (data); - sp.pop(); - parser* pp=sp.top(); - XML_SetUserData(p,pp); - pp->onEnd(el,child); - child->end(); -} - -void parser::charData(const XML_Char *s, int len) -{ - _content=_content+std::string(s,len); -} - -void XMLCALL parser::charac(void *data, const XML_Char *s, int len) -{ - parser* pp=static_cast (data); - pp->charData(s,len); -} - -void parser::end () -{ - _level=_level-1; - if(_level>0) - { - delete _counts; - _counts=_stackCount.top(); - _orderState=_stackOrder.top(); - _stackCount.pop(); - _stackOrder.pop(); - } -} - -void parser::init () -{ - if(_level>0) - { - _stackCount.push(_counts); - _stackOrder.push(_orderState); - _counts=new std::map; - } - _level=_level+1; - _counts->clear(); - _orderState=0; -} - -void parser::incrCount(const XML_Char *el) -{ - if(_counts->count(el)==0) - (*_counts)[el]=1; - else - (*_counts)[el]=(*_counts)[el]+1; -} - -void parser::checkOrder(std::string& el) -{ - if(_orders.count(el)==0)return; - if(_orders[el] < _orderState) - { - std::string msg="unexpected "+el+" element (wrong order)"; - throw YACS::Exception::Exception(msg); - } - else if(_orders[el] > _orderState) - { - _orderState=_orders[el]; - } -} - -void parser::maxcount(std::string name, int max, std::string& el) -{ - if(el!=name)return; - if((*_counts)[name]>max) - { - std::stringstream msg; - msg <<"unexpected "+name+" element (count="<<(*_counts)[name]; - msg <<" > maxOccurs=" << max << ")"; - throw YACS::Exception::Exception(msg.str()); - } -} - -void parser::mincount(std::string name,int min ) -{ - if((*_counts)[name]max) - { - std::stringstream msg; - msg<<"unexpected "+el+" element (choice count="< maxOccurs=" << max << ")"; - throw YACS::Exception::Exception(msg.str()); - } -} - -void parser::minchoice(std::string *names, int min) -{ - int i=0; - int ncount=0; - while (names[i]!= "") - { - ncount=ncount+(*_counts)[names[i]]; - ++i; - } - if(ncount> a)) -// throw YACS::Exception::Exception("problem in conversion from string to double"); -// std::cerr << "--------------_content s a "<< _content.c_str() << " " << s.str() << " " << a << std::endl; -// return a; - } -}; -static doubletypeParser doubleParser; - -/*! \brief Class for integer parser. - * - * Class used to parse integer - */ -struct inttypeParser:parser -{ - int post() - { - return atoi(_content.c_str()); - } -}; -static inttypeParser intParser; - -/*! \brief Class for boolean parser. - * - * Class used to parse bool - */ -struct booltypeParser:parser -{ - bool post() - { - DEBTRACE( _content ) - if(_content == "true")return true; - if(_content == "false")return false; - std::stringstream temp(_content); - bool b ; - temp >> b; - //std::cerr << b << std::endl; - return b; - } -}; -static booltypeParser boolParser; - -/*! \brief Class for property parser. - * - * Class used to parse a property - * A property is a pair of name(string), value(string) - * XML schema is - * - * - * - * - * - */ -struct propertytypeParser: parser -{ - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - required("value",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "value")value(attr[i+1]); - } - } - virtual void name(const std::string& name){ _prop._name=name; } - virtual void value(const std::string& name){ _prop._value=name; } - myprop post(){return _prop;} - myprop _prop; -}; -static propertytypeParser propertyParser; - -/*! \brief Class for type parser. - * - * Class used to parse a type definition (class TypeCode in implementation) - * with a name and a kind (reserved to atomic types) - * XML schema is - * - * - * - * - * - */ -struct typetypeParser: parser -{ - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - required("kind",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "kind")kind(attr[i+1]); - } - } - virtual void pre (){} - virtual void name(const std::string& name) - { - DEBTRACE( "type_name: " << name ) - _name=name; - } - virtual void kind(const std::string& name) - { - DEBTRACE( "type_kind: " << name ) - _kind=name; - } - virtual mytype post() - { - DEBTRACE( "type_post" ) - mytype t; - t._kind=_kind; - t._name=_name; - return t; - } - std::string _name; - std::string _kind; -}; -static typetypeParser typeParser; - -/*! \brief Class for sequence parser. - * - * Class used to parse a sequence (type) definition (class TypeCodeSeq in implementation) - * XML schema is - * - * - * - * - * - */ -struct seqtypeParser:public parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "seqtypeParser::onStart: " << el ) - parser* pp=&main_parser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "seqtypeParser::onEnd: " << el ) - } - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - required("content",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "content")content(attr[i+1]); - } - } - void name(const std::string& name) - { - DEBTRACE( "seqtype_name: " << name ) - _name=name; - } - void content(const std::string& name) - { - DEBTRACE( "seqtype_content: " << name ) - if(currentProc->typeMap.count(name)==0) - { - std::stringstream msg; - msg << "Type " << name << " does not exist" << " (" <<__FILE__ << ":" << __LINE__ << ")"; - throw Exception(msg.str()); - } - _contentType=currentProc->typeMap[name]; - - } - TypeCode* post() - { - DEBTRACE( "seqtype_post" ) - TypeCode *t = currentProc->createSequenceTc(_name,_name,_contentType); - return t; - } - TypeCode* _contentType; - std::string _name; -}; -static seqtypeParser seqParser; - -/*! \brief Class for objref parser. - * - * Class used to parse a objref (type) definition (class TypeCodeObjref in implementation) - * XML schema is - * - * - * - * - * - * - * - * - */ -struct objtypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "objtypeParser::onStart: " << el ) - std::string element(el); - parser* pp=&main_parser; - if(element == "base")pp=&stringParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "objtypeParser::onEnd: " << el ) - std::string element(el); - if(element == "base")base(((stringtypeParser*)child)->post()); - } - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "id")id(attr[i+1]); - } - } - virtual void pre () - { - _id=""; - _ltc.clear(); - } - virtual void name(const std::string& name) - { - DEBTRACE( "objtype_name: " << name ) - _name=name; - } - virtual void id(const std::string& name) - { - DEBTRACE( "objtype_id: " << name ) - _id=name; - } - virtual void base(const std::string& name) - { - DEBTRACE( "base_name: " << name ) - if(currentProc->typeMap.count(name)==0) - { - std::stringstream msg; - msg << "Type " << name << " does not exist" ; - msg << " (" <<__FILE__ << ":" << __LINE__ << ")"; - throw Exception(msg.str()); - } - if(currentProc->typeMap[name]->kind() != Objref) - { - std::stringstream msg; - msg << "Type " << name << " is not an objref" ; - msg << " (" <<__FILE__ << ":" << __LINE__ << ")"; - throw Exception(msg.str()); - } - _ltc.push_back((TypeCodeObjref *)currentProc->typeMap[name]); - } - virtual TypeCode * post() - { - DEBTRACE( "objtype_post" ) - TypeCode *t = currentProc->createInterfaceTc(_id,_name,_ltc); - return t; - } - std::string _name; - std::string _id; - std::list _ltc; -}; -static objtypeParser objParser; - -/*! \brief Class for member parser. - * - * Class used to parse a struct member - * A struct member is a pair of name(string), type(string) - * XML schema is - * - * - * - * - * - */ -struct membertypeParser: parser -{ - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - required("type",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "type")type(attr[i+1]); - } - } - virtual void name(const std::string& name){ _prop._name=name; } - virtual void type(const std::string& name){ _prop._value=name; } - myprop post(){return _prop;} - myprop _prop; -}; -static membertypeParser memberParser; - -/*! \brief Class for struct parser. - * - * Class used to parse a struct (type) definition (class TypeCodeStruct in implementation) - * XML schema is - * - * - * - * - * - * - * - * - */ -struct structtypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "structtypeParser::onStart: " << el ) - std::string element(el); - parser* pp=&main_parser; - if(element == "member")pp=&memberParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "structtypeParser::onEnd: " << el ) - std::string element(el); - if(element == "member")member(((membertypeParser*)child)->post()); - } - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "id")id(attr[i+1]); - } - } - virtual void pre () - { - _id=""; - _members.clear(); - } - virtual void name(const std::string& name) - { - DEBTRACE( "structtype_name: " << name ); - _name=name; - } - virtual void id(const std::string& name) - { - DEBTRACE( "structtype_id: " << name ); - _id=name; - } - virtual void member (const myprop& prop) - { - DEBTRACE( "structtype_member: " << prop._name << prop._value ); - if(currentProc->typeMap.count(prop._value)!=0) - _members.push_back(prop); - else - { - std::string msg="Unknown type " + prop._value + " for member " + prop._name + " in struct " + _name; - throw Exception(msg); - } - } - virtual TypeCode * post() - { - DEBTRACE( "structtype_post" ); - TypeCodeStruct *t; - if(currentProc->typeMap.count(_name)!=0) - { - //reuse a forward declaration - TypeCode* tt=currentProc->typeMap[_name]; - if(tt->kind()==YACS::ENGINE::Struct) - { - t=(TypeCodeStruct*)tt; - } - else - { - std::string msg="Forward declaration must be a struct type but " + std::string(tt->name()) + " is not one" ; - throw Exception(msg); - } - } - else - { - t = (TypeCodeStruct*)currentProc->createStructTc(_id,_name); - } - std::vector::const_iterator iter; - for(iter=_members.begin();iter!=_members.end();iter++) - { - DEBTRACE("member: " << iter->_name << " " <_value); - t->addMember(iter->_name,currentProc->typeMap[iter->_value]); - } - return t; - } - std::string _name; - std::string _id; - std::vector _members; -}; -static structtypeParser structParser; - -/*! \brief Class for machine parser. - * - * Class used to parse computer adress on which container must be started - * XML schema is - * - * - * - */ -struct machinetypeParser: parser -{ - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - } - } - virtual void pre (){_mach._name="";} - virtual void name(const std::string& name){ _mach._name=name; } - machine post() - { - return _mach; - } - machine _mach; -}; -static machinetypeParser machineParser; - -/*! \brief Class for container parser - * - * Class used to parse container description - * XML schema is - * - * - * - * - * - * - * - */ -struct containertypeParser: parser -{ - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - } - } - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - parser* pp=&main_parser; - if(element == "machine")pp=&machineParser; - if(element == "property")pp=&propertyParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "machine")machine_(((machinetypeParser*)child)->post()); - if(element == "property")property(((propertytypeParser*)child)->post()); - } - virtual void pre (){_container._machs.clear();} - virtual void name(const std::string& name){ _container._name=name; } - virtual void machine_(const machine& m) - { - DEBTRACE( "machine: " << m._name ) - _container._machs.push_back(m); - } - virtual void property (const myprop& prop) - { - DEBTRACE( "property_set: " << prop._name << prop._value ) - _container._props[prop._name]=prop._value; - } - mycontainer post() - { - //mincount("machine",1); - return _container; - } - mycontainer _container; -}; -static containertypeParser containerParser; - -/*! \brief Class for loading parser - * - * Class used to parse service node loading information - * XML schema is - * - * - * - */ -struct loadtypeParser: parser -{ - virtual void buildAttr(const XML_Char** attr) - { - required("container",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "container")container(attr[i+1]); - } - } - virtual void pre (){_loadon._container="";} - virtual void container(const std::string& name){ _loadon._container=name; } - loadon post() - { - return _loadon; - } - loadon _loadon; -}; -static loadtypeParser loadParser; - -/*! \brief Class for Inport parser. - * - * This class is a base class for other inport parsers - * - * - * - * - * - * - * - * - */ -template -struct inporttypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - parser* pp=&main_parser; - if(element == "property")pp=&propertyParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "property")property(((propertytypeParser*)child)->post()); - } - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - required("type",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "type")type(attr[i+1]); - } - } - virtual void pre () - { - _port._name=""; - _port._type=""; - _port.clear(); - } - virtual void name(const std::string& name) - { - _port._name=name; - } - virtual void type(const std::string& type) - { - _port._type=type; - } - virtual void property (const myprop& prop) - { - DEBTRACE( "property_set: " << prop._name << prop._value ) - _port.setProperty(prop._name,prop._value); - } - virtual T& post() - { - return _port; - } -protected: - T _port; -}; -static inporttypeParser<> inportParser; - -/*! \brief Class for Outport parser. - * - * This class is also used for OutputDataStream Port - * same XML schema as inporttypeParser - */ -template -struct outporttypeParser:public inporttypeParser -{ -}; -static outporttypeParser<> outportParser; - -/*! \brief Class for node parser. - * - * This class is a base class for other parsers - */ -template -struct nodetypeParser:public parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "nodetypeParser::onStart: " << el ) - std::string element(el); - parser* pp=&main_parser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "nodetypeParser::onEnd: " << el ) - std::string element(el); - } - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - required("type",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "state")state(attr[i+1]); - if(std::string(attr[i]) == "type")type(attr[i+1]); - } - } - virtual void pre() - { - _node=0; - } - virtual void name (const std::string& name) - { - DEBTRACE( "inline_name: " << name ) - _name=name; - } - virtual void state (const std::string& name) - { - _state=name; - } - virtual void type (const std::string& name) - { - DEBTRACE( "node_type " << name ) - _type=name; - } - virtual T post() - { - return _node; - } - std::string _type; - std::string _name; - std::string _state; - T _node; -}; -static nodetypeParser<> nodeParser; - -template <> -InlineNode* nodetypeParser::post () -{ - std::string fullname = currentProc->names.back()+_type; - if(currentProc->inlineMap.count(_type) != 0) - { - //InlineNode type with absolute name found - InlineNode* n=currentProc->inlineMap[_type]; - _node=n->cloneNode(_name); - } - else if(currentProc->inlineMap.count(fullname) != 0) - { - //InlineNode type with relative name found - InlineNode* n=currentProc->inlineMap[fullname]; - _node=n->cloneNode(_name); - } - else - { - throw Exception("Unknown InlineNode type"); - } - if(_state == "disabled")_node->exDisabledState(); - DEBTRACE( "node_post " << _node->getName() ) - return _node; -} - -struct codetypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - parser* pp=&main_parser; - if(element == "code")pp=&stringParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "code")code(((stringtypeParser*)child)->post()); - } - virtual void pre (){_code="";} - virtual void code (const std::string& s) - { - if(_code == "") - _code=s; - else - _code=_code + '\n' + s; - } - virtual myfunc post () - { - _func._name="script"; - _func._code=_code; - return _func; - } - std::string _code; - myfunc _func; -}; -static codetypeParser codeParser; - -struct functypeParser: codetypeParser -{ - virtual void buildAttr(const XML_Char** attr) - { - required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - } - } - virtual void name (const std::string& name) - { - _func._name=name; - } - virtual myfunc post () - { - _func._code=_code; - return _func; - } -}; -static functypeParser funcParser; - -static std::string t1[]={"script","function",""}; - -template -struct inlinetypeParser:public nodetypeParser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "inlinetypeParser::onStart: " << el ) - std::string element(el); - parser* pp=&main_parser; - this->maxcount("kind",1,element); - this->maxcount("script",1,element); - this->maxcount("function",1,element); - this->maxchoice(t1,1,element); - if(element == "kind")pp=&stringParser; - else if(element == "script")pp=&codeParser; - else if(element == "function")pp=&funcParser; - else if(element == "inport")pp=&inportParser; - else if(element == "outport")pp=&outportParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "inlinetypeParser::onEnd: " << el ) - std::string element(el); - if(element == "kind")kind(((stringtypeParser*)child)->post()); - else if(element == "script")script(((codetypeParser*)child)->post()); - else if(element == "function")function(((functypeParser*)child)->post()); - else if(element == "inport") inport(((inporttypeParser*)child)->post()); - else if(element == "outport") outport(((outporttypeParser*)child)->post()); - } - virtual void buildAttr(const XML_Char** attr) - { - this->required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")this->name(attr[i+1]); - if(std::string(attr[i]) == "state")this->state(attr[i+1]); - } - } - virtual void pre () - { - this->_node=0; - _kind=""; - this->_state=""; - } - virtual void kind (const std::string& name) - { - DEBTRACE( "inline_kind " << name ) - _kind=name; - } - virtual void script (const myfunc& f){} - virtual void function (const myfunc& f) {} - virtual void inport (const myinport& p) - { - DEBTRACE( "inline_inport: " << p._name <<":"<_node==0) - throw Exception("Node must be completely defined before defining its ports"); - if(currentProc->typeMap.count(p._type)==0) - { - std::string msg="Unknown InPort Type: "; - msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; - throw Exception(msg); - } - this->_node->edAddInputPort(p._name,currentProc->typeMap[p._type]); - } - virtual void outport (const myoutport& p) - { - DEBTRACE( "inline_outport: " << p._name <<":"<_node==0) - throw Exception("Node must be completely defined before defining its ports"); - if(currentProc->typeMap.count(p._type)==0) - { - std::string msg="Unknown OutPort Type: "; - msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; - throw Exception(msg); - } - this->_node->edAddOutputPort(p._name,currentProc->typeMap[p._type]); - } - virtual T post() - { - DEBTRACE( "inline_post " << this->_node->getName() ) - if(this->_state == "disabled")this->_node->exDisabledState(); - /* - std::list::iterator iter; - std::list s=_node->getSetOfOutputPort(); - for(iter=s.begin();iter!=s.end();iter++) - { - std::cerr << "port name: " << (*iter)->getName() << std::endl; - std::cerr << "port kind: " << (*iter)->edGetType()->kind() << std::endl; - } - */ - return this->_node; - } - std::string _kind; -}; -static inlinetypeParser<> inlineParser; - -template <> -void inlinetypeParser::script (const myfunc& f) -{ - DEBTRACE( "inline_script: " << f._code ) - _node=theRuntime->createScriptNode(_kind,_name); - _node->setScript(f._code); -} -template <> -void inlinetypeParser::function (const myfunc& f) -{ - DEBTRACE( "inline_function: " << f._code ) - InlineFuncNode *fnode; - fnode=theRuntime->createFuncNode(_kind,_name); - fnode->setScript(f._code); - fnode->setFname(f._name); - _node=fnode; -} - -/*! \brief Class for parsing ServiceInlineNode description - * - * - */ -template -struct sinlinetypeParser:public inlinetypeParser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "sinlinetypeParser::onStart: " << el ) - std::string element(el); - parser* pp=&main_parser; - this->maxcount("kind",1,element); - this->maxcount("function",1,element); - this->maxcount("load",1,element); - if(element == "kind")pp=&stringParser; - else if(element == "function")pp=&funcParser; - else if(element == "load")pp=&loadParser; - else if(element == "inport")pp=&inportParser; - else if(element == "outport")pp=&outportParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "sinlinetypeParser::onEnd: " << el ) - std::string element(el); - if(element == "kind")this->kind(((stringtypeParser*)child)->post()); - else if(element == "function")this->function(((functypeParser*)child)->post()); - else if(element == "load") load(((loadtypeParser*)child)->post()); - else if(element == "inport") this->inport(((inporttypeParser*)child)->post()); - else if(element == "outport") this->outport(((outporttypeParser*)child)->post()); - } - //virtual void service (const myfunc& f) {} - virtual void load (const loadon& l) - { - DEBTRACE( "sinline_load: " ) - if(this->_node==0) - throw Exception("ServiceInlineNode must be completely defined before defining how to load it"); - - if(currentProc->containerMap.count(l._container) != 0) - { - //If it has already a container replace it ????? - this->_node->getComponent()->setContainer(currentProc->containerMap[l._container]); - } - else - { - std::cerr << "WARNING: Unknown container " << l._container << std::endl; - } - } -}; - -template <> -void inlinetypeParser::function (const myfunc& f) -{ - DEBTRACE( "sinline_function: " << f._code ) - ServiceInlineNode *fnode; - fnode=theRuntime->createSInlineNode(_kind,_name); - fnode->setScript(f._code); - fnode->setMethod(f._name); - fnode->setComponent(theRuntime->createComponentInstance("PyCompo","SalomePy")); - //fnode->setRef("PyCompo"); - _node=fnode; -} - -static sinlinetypeParser<> sinlineParser; - -static std::string t2[]={"ref","node","component",""}; - -template -struct servicetypeParser:public inlinetypeParser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "servicetypeParser::onStart: " << el ) - std::string element(el); - parser* pp=&main_parser; - this->maxcount("kind",1,element); - this->maxcount("ref",1,element); - this->maxcount("node",1,element); - this->maxcount("component",1,element); - this->maxcount("method",1,element); - this->maxcount("load",1,element); - this->maxchoice(t2,1,element); - if(element == "kind")pp=&stringParser; - else if(element == "ref")pp=&stringParser; - else if(element == "component")pp=&stringParser; - else if(element == "node")pp=&stringParser; - else if(element == "method")pp=&stringParser; - else if(element == "load")pp=&loadParser; - else if(element == "inport")pp=&inportParser; - else if(element == "outport")pp=&outportParser; - else if(element == "instream")pp=&inportParser; - else if(element == "outstream")pp=&outportParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "servicetypeParser::onEnd: " << el ) - std::string element(el); - if(element == "kind")this->kind(((stringtypeParser*)child)->post()); - else if(element == "ref") ref(((stringtypeParser*)child)->post()); - else if(element == "component") component(((stringtypeParser*)child)->post()); - else if(element == "node") node(((stringtypeParser*)child)->post()); - else if(element == "method") method(((stringtypeParser*)child)->post()); - else if(element == "load") load(((loadtypeParser*)child)->post()); - else if(element == "inport") this->inport(((inporttypeParser*)child)->post()); - else if(element == "outport") this->outport(((outporttypeParser*)child)->post()); - else if(element == "instream") instream(((inporttypeParser*)child)->post()); - else if(element == "outstream") outstream(((outporttypeParser*)child)->post()); - } - virtual void ref (const std::string& name) - { - DEBTRACE( "service_ref: " << name ) - this->_node=theRuntime->createRefNode(this->_kind,this->_name); - this->_node->setRef(name); - } - virtual void component (const std::string& name) - { - DEBTRACE( "service_component: " << name ) - this->_node=theRuntime->createCompoNode(this->_kind,this->_name); - this->_node->setRef(name); - } - virtual void node (const std::string& name) - { - DEBTRACE( "service_node: " << name ) - std::string fullname = currentProc->names.back()+name; - if(currentProc->serviceMap.count(name) != 0) - { - //ServiceNode with absolute name found - ServiceNode* n=currentProc->serviceMap[name]; - this->_node =n->createNode(this->_name); - } - else if(currentProc->serviceMap.count(fullname) != 0) - { - //ServiceNode with relative name found - //TODO: must be a short name (possible only in the same context) - ServiceNode* n=currentProc->serviceMap[fullname]; - this->_node =n->createNode(this->_name); - } - else - { - throw Exception("Unknown ServiceNode"); - } - } - virtual void method (const std::string& name) - { - DEBTRACE( "service_method: " << name ) - if(this->_node==0) - throw Exception("ServiceNode must be completely defined before defining its method"); - this->_node->setMethod(name); - } - - virtual void load (const loadon& l) - { - DEBTRACE( "service_load: " ) - if(this->_node==0) - throw Exception("ServiceNode must be completely defined before defining how to load it"); - - if(currentProc->containerMap.count(l._container) != 0) - { - //If it has already a container replace it ????? - this->_node->getComponent()->setContainer(currentProc->containerMap[l._container]); - } - else - { - std::cerr << "WARNING: Unknown container " << l._container << std::endl; - } - } - - virtual void instream (const myinport& p) - { - DEBTRACE( "service_instream" ) - DEBTRACE( p._type ) - DEBTRACE( p._name ) - if(this->_node==0) - throw Exception("ServiceNode must be completely defined before defining its ports"); - if(currentProc->typeMap.count(p._type)==0) - { - std::string msg="Unknown InPort Type: "; - msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; - throw Exception(msg); - } - InputDataStreamPort* port; - port=this->_node->edAddInputDataStreamPort(p._name,currentProc->typeMap[p._type]); - // Set all properties for this port - std::map::const_iterator pt; - for(pt=p._props.begin();pt!=p._props.end();pt++) - port->setProperty((*pt).first,(*pt).second); - } - virtual void outstream (const myoutport& p) - { - DEBTRACE( "service_outstream" ) - DEBTRACE( p._type ) - DEBTRACE( p._name ) - if(this->_node==0) - throw Exception("ServiceNode must be completely defined before defining its ports"); - if(currentProc->typeMap.count(p._type)==0) - { - std::string msg="Unknown OutPort Type: "; - msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; - throw Exception(msg); - } - OutputDataStreamPort* port; - port=this->_node->edAddOutputDataStreamPort(p._name,currentProc->typeMap[p._type]); - // Set all properties for this port - std::map::const_iterator pt; - for(pt=p._props.begin();pt!=p._props.end();pt++) - port->setProperty((*pt).first,(*pt).second); - } - virtual T post() - { - DEBTRACE( "service_post " << this->_node->getName() ) - this->mincount("method",1); - if(this->_state == "disabled")this->_node->exDisabledState(); - return this->_node; - } -}; -static servicetypeParser<> serviceParser; - -template -struct controltypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - parser* pp=&main_parser; - this->maxcount("fromnode",1,element); - this->maxcount("tonode",1,element); - if(element == "fromnode")pp=&stringParser; - else if(element == "tonode")pp=&stringParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "fromnode")fromnode(((stringtypeParser*)child)->post()); - else if(element == "tonode")tonode(((stringtypeParser*)child)->post()); - } - virtual void pre () - { - _link.clear(); - } - virtual void fromnode (const std::string& name) - { - _link.fromnode(name); - } - virtual void tonode (const std::string& name) - { - _link.tonode(name); - } - virtual void property (const myprop& prop) - { - DEBTRACE( "property_set: " << prop._name << prop._value ) - _link.setProperty(prop._name,prop._value); - } - virtual T& post() - { - mincount("fromnode",1); - mincount("tonode",1); - return _link; - } - T _link; -}; -static controltypeParser<> controlParser; - -template -struct linktypeParser: controltypeParser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - this->maxcount("fromnode",1,element); - this->maxcount("tonode",1,element); - this->maxcount("fromport",1,element); - this->maxcount("toport",1,element); - parser* pp=&main_parser; - if(element == "fromnode")pp=&stringParser; - else if(element == "tonode")pp=&stringParser; - else if(element == "toport")pp=&stringParser; - else if(element == "fromport")pp=&stringParser; - else if(element == "property")pp=&propertyParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "fromnode")this->fromnode(((stringtypeParser*)child)->post()); - else if(element == "tonode")this->tonode(((stringtypeParser*)child)->post()); - else if(element == "toport")toport(((stringtypeParser*)child)->post()); - else if(element == "fromport")fromport(((stringtypeParser*)child)->post()); - else if(element == "property")this->property(((propertytypeParser*)child)->post()); - } - virtual void buildAttr(const XML_Char** attr) - { - for (int i = 0; attr[i]; i += 2) - { - if((std::string(attr[i]) == "control") - && (std::string(attr[i+1]) == "false")) - this->_link._withControl=false; - } - } - virtual void fromport (const std::string& name) - { - this->_link.fromport(name); - } - virtual void toport (const std::string& name) - { - this->_link.toport(name); - } - virtual T& post() - { - this->mincount("fromnode",1); - this->mincount("tonode",1); - this->mincount("fromport",1); - this->mincount("toport",1); - return this->_link; - } -}; -static linktypeParser<> linkParser; - -template -struct streamtypeParser: linktypeParser -{ -}; -static streamtypeParser<> streamParser; - -static std::string t4[]={"string","objref","double","int","boolean","array","struct",""}; - -/*! \brief Class for XML-RPC value parser. - * - * This class is used to parse XML data that describes a sequence in XML-RPC format - * Its XML schema is: - * - * - * - * - * - * - * - * - * - * - * - */ -struct valuetypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr); - virtual void onEnd(const char *el,parser* child); - virtual void pre (){ } - virtual void int_ (const int& d) - { - std::ostringstream os; - os << "" << d<< ""; - _data=os.str(); - _v.push_back(_data); - } - virtual void boolean (const bool& d) - { - std::ostringstream os; - os << "" << d<< ""; - _data=os.str(); - _v.push_back(_data); - } - virtual void double_ (const double& d) - { - std::ostringstream os; - os << ""<< d<< ""; - _data=os.str(); - _v.push_back(_data); - } - virtual void string(const std::string& d) - { - _data=""+ d+ ""; - _v.push_back(_data); - } - virtual void objref(const std::string& d) - { - _data=""+ d+ ""; - _v.push_back(_data); - } - virtual void array (const std::string& d) - { - _v.push_back(d); - } - virtual void struct_ (const std::string& d) - { - _v.push_back(d); - } - virtual std::string post() - { - minchoice(t4,1); - std::string value=""+_v.back()+"\n"; - _v.pop_back(); - return value; - } - std::string _data; - std::vector _v; -}; -static valuetypeParser valueParser; - -/*! \brief Class for XML-RPC data parser. - * - * This class is used to parse XML data that describes a sequence in XML-RPC format - * Its XML schema is: - * - * - * - */ -struct datatypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - parser* pp=&main_parser; - if(element == "value")pp=&valueParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "value")value(((valuetypeParser*)child)->post()); - } - virtual void pre () - { - _datas.push_back(_data); - _data=""; - } - virtual void value (const std::string& v){ - _data=_data+v; - } - virtual std::string post() - { - mincount("value",1); - std::string d="\n"+_data+""; - _data=_datas.back(); - _datas.pop_back(); - return d; - } - std::string _data; - std::vector _datas; -}; -static datatypeParser dataParser; - -/*! \brief Class for XML-RPC member parser. - * - * This class is used to parse XML data that describes a sequence in XML-RPC format - * Its XML schema is: - * - * - * - * - */ -struct memberdatatypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - parser* pp=&main_parser; - if(element == "name")pp=&stringParser; - else if(element == "value")pp=&valueParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - this->maxcount("name",1,element); - this->maxcount("value",1,element); - if(element == "name")name(((stringtypeParser*)child)->post()); - else if(element == "value")value(((valuetypeParser*)child)->post()); - } - virtual void pre () - { - _datas.push_back(_data); - _data=""; - } - virtual void name (const std::string& v) - { - _data=_data+""+v+""; - } - virtual void value (const std::string& v) - { - _data=_data+v; - } - virtual std::string post() - { - mincount("value",1); - mincount("name",1); - std::string d="\n"+_data+""; - _data=_datas.back(); - _datas.pop_back(); - return d; - } - std::string _data; - std::vector _datas; -}; -static memberdatatypeParser memberdataParser; - -/*! \brief Class for XML-RPC struct parser. - * - * This class is used to parse XML data that describes a sequence in XML-RPC format - * Its XML schema is: - * - * - * - */ -struct structdatatypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - parser* pp=&main_parser; - if(element == "member")pp=&memberdataParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "member")member(((memberdatatypeParser*)child)->post()); - } - virtual void pre () - { - _membersStack.push_back(_members); - _members=""; - } - virtual void member (const std::string& d) - { - _members=_members+d; - } - virtual std::string post() - { - mincount("member",1); - std::string value=""+_members+""; - _members=_membersStack.back(); - _membersStack.pop_back(); - return value; - } - std::string _members; - std::vector _membersStack; -}; -static structdatatypeParser structdataParser; - -/*! \brief Class for XML-RPC array parser. - * - * This class is used to parse XML data that describes a sequence in XML-RPC format - * Its XML schema is: - * - * - * - */ -struct arraytypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - this->maxcount("data",1,element); - parser* pp=&main_parser; - if(element == "data")pp=&dataParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "data")data(((datatypeParser*)child)->post()); - } - virtual void pre (){ } - virtual void data (const std::string& d) - { - _arrays.push_back(d); - } - virtual std::string post() - { - mincount("data",1); - std::string value=""+_arrays.back()+""; - _arrays.pop_back(); - return value; - } - std::vector _arrays; -}; -static arraytypeParser arrayParser; - - -void valuetypeParser::onStart(const XML_Char* el, const XML_Char** attr) -{ - std::string element(el); - parser* pp=&main_parser; - this->maxcount("string",1,element); - this->maxcount("objref",1,element); - this->maxcount("double",1,element); - this->maxcount("int",1,element); - this->maxcount("boolean",1,element); - this->maxcount("array",1,element); - this->maxcount("struct",1,element); - this->maxchoice(t4,1,element); - if(element == "string")pp=&stringParser; - else if(element == "objref")pp=&stringParser; - else if(element == "double")pp=&doubleParser; - else if(element == "int")pp=&intParser; - else if(element == "boolean")pp=&boolParser; - else if(element == "array")pp=&arrayParser; - else if(element == "struct")pp=&structdataParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); -} - -void valuetypeParser::onEnd(const char *el,parser* child) -{ - std::string element(el); - if(element == "string")string(((stringtypeParser*)child)->post()); - else if(element == "objref")objref(((stringtypeParser*)child)->post()); - else if(element == "double")double_(((doubletypeParser*)child)->post()); - else if(element == "int")int_(((inttypeParser*)child)->post()); - else if(element == "boolean")boolean(((booltypeParser*)child)->post()); - else if(element == "array")array(((arraytypeParser*)child)->post()); - else if(element == "struct")struct_(((structdatatypeParser*)child)->post()); -} - -struct parametertypeParser: parser -{ - virtual void onStart(const XML_Char* el, const XML_Char** attr) - { - std::string element(el); - this->maxcount("tonode",1,element); - this->maxcount("toport",1,element); - this->maxcount("value",1,element); - parser* pp=&main_parser; - if(element == "tonode")pp=&stringParser; - else if(element == "toport")pp=&stringParser; - else if(element == "value")pp=&valueParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - std::string element(el); - if(element == "tonode")tonode(((stringtypeParser*)child)->post()); - else if(element == "toport")toport(((stringtypeParser*)child)->post()); - else if(element == "value")value(((valuetypeParser*)child)->post()); - } - virtual void pre (){} - virtual void tonode (const std::string& name){ - _param._tonode=name; - } - virtual void toport (const std::string& name){ - _param._toport=name; - } - virtual void value (const std::string& name){ - _param._value=name; - } - virtual myparam& post(){ - mincount("tonode",1); - mincount("toport",1); - mincount("value",1); - return _param; - } - myparam _param; -}; -static parametertypeParser paramParser; - -static std::string t3[]={"inline","sinline","service","node","forloop","foreach","while","switch","bloc",""}; - -struct casetypeParser:parser -{ - void onStart(const XML_Char* el, const XML_Char** attr); - void onEnd(const char *el,parser* child); - virtual void buildAttr(const XML_Char** attr) - { - this->required("id",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "id")id(atoi(attr[i+1])); - } - } - virtual void pre () - { - _cnode=0; - _id=0; - } - virtual void id (const int& n) - { - DEBTRACE( "case_id: " << n ) - _id=n; - //store this level id - _idStack.push_back(_id); - //store this level name - std::stringstream temp; - if (_id <0) temp << "m" << -_id << "_"; - else temp << "p" << _id << "_"; - std::string fullname=currentProc->names.back()+temp.str(); - DEBTRACE( "case_fullname: " << fullname ) - currentProc->names.push_back(fullname); - } - virtual void property (const myprop& prop) - { - DEBTRACE( "property_set: " << prop._name << prop._value ) - } - virtual void inline_ (InlineNode* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->inlineMap[fullname]=n; - } - virtual void sinline (ServiceInlineNode* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->serviceMap[fullname]=n; - } - virtual void service (ServiceNode* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->serviceMap[fullname]=n; - } - virtual void node (InlineNode* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->inlineMap[fullname]=n; - } - virtual void forloop (ForLoop* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - } - virtual void foreach (ForEachLoop* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - fullname += ".splitter"; - currentProc->nodeMap[fullname]=n->getChildByShortName("splitter"); - } - virtual void while_ (WhileLoop* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - } - virtual void switch_ (Switch* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - } - virtual void bloc (Bloc* const& n) - { - _cnode=n; - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - } - virtual std::pair post() - { - DEBTRACE( "case_post" ) - minchoice(t3,1); - //get back this level id - _id=_idStack.back(); - _idStack.pop_back(); - //pop back this level name - currentProc->names.pop_back(); - return std::pair(_id,_cnode); - } - Node* _cnode; - int _id; - std::vector _idStack; -}; -static casetypeParser caseParser; - -struct defaultcasetypeParser:casetypeParser -{ - virtual void buildAttr(const XML_Char** attr) - { - for (int i = 0; attr[i]; i += 2) - { - DEBTRACE( attr[i] << "=" << attr[i + 1] ) - } - } - virtual void pre () - { - _id=0; - _cnode=0; - //store this level id - _idStack.push_back(_id); - //store this level name - std::string fullname=currentProc->names.back()+"default_"; - DEBTRACE( "case_fullname: " << fullname ) - currentProc->names.push_back(fullname); - } -}; -static defaultcasetypeParser defaultcaseParser; - -struct switchtypeParser:parser -{ - void onStart(const XML_Char* el, const XML_Char** attr); - void onEnd(const char *el,parser* child); - virtual void buildAttr(const XML_Char** attr) - { - this->required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "state")state(attr[i+1]); - if(std::string(attr[i]) == "select")select(atoi(attr[i+1])); - } - } - virtual void pre (){_state="";} - virtual void case_ (const std::pair& p) - { - Switch* s=_cnodes.back(); - s->edSetNode(p.first,p.second); - } - virtual void default_ (const std::pair& p) - { - Switch* s=_cnodes.back(); - s->edSetDefaultNode(p.second); - } - virtual void name (const std::string& name) - { - Switch* s; - std::string fullname=currentProc->names.back()+name; - DEBTRACE( "switch_fullname: " << fullname ) - s=theRuntime->createSwitch(name); - _cnodes.push_back(s); - currentProc->names.push_back(fullname+'.'); - } - virtual void state (const std::string& state) - { - //state is an attribute (no order). It can be defined before name - //To be improved - Switch* s=_cnodes.back(); - if(_state == "disabled") - { - DEBTRACE( "Switch disabled: " << s->getName()) - s->exDisabledState(); - } - } - virtual void select (const int& s) - { - //select is an attribute - Switch* sw=_cnodes.back(); - InputPort *p=sw->edGetConditionPort(); - p->edInit(s); - } - virtual Switch* post () - { - DEBTRACE( "switch_post: " ) - Switch* sw=_cnodes.back(); - //pop back current level name and node - _cnodes.pop_back(); - currentProc->names.pop_back(); - return sw; - } - // stack to store switches in case of switch in switch - std::vector _cnodes; - std::string _state; -}; -static switchtypeParser switchParser; - -template -struct looptypeParser:parser -{ - void onStart(const XML_Char* el, const XML_Char** attr); - void onEnd(const char *el,parser* child); - virtual void buildAttr(const XML_Char** attr) - { - this->required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "state")state(attr[i+1]); - } - } - virtual void pre () - { - _state=""; - _cnode=0; - } - virtual void name (const std::string& name) - { - DEBTRACE( "bloc_name: " << name ); - } - virtual void state (const std::string& name) - { - DEBTRACE( "bloc_state: " << name ); - _state=name; - } - virtual void property (const myprop& prop) - { - DEBTRACE( "property_set" << prop._name << prop._value ); - } - virtual void inline_ (InlineNode* const& n) - { - DEBTRACE( "loop_inline" << n->getName() ); - _cnode->edSetNode(n); - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->inlineMap[fullname]=n; - } - virtual void sinline (ServiceInlineNode* const& n) - { - DEBTRACE( "loop_sinline" << n->getName() ) - _cnode->edSetNode(n); - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->serviceMap[fullname]=n; - } - virtual void service (ServiceNode* const& n) - { - DEBTRACE( "loop_service" << n->getName() ) - _cnode->edSetNode(n); - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->serviceMap[fullname]=n; - } - virtual void node (InlineNode* const& n) - { - DEBTRACE( "loop_node" << n->getName() ) - _cnode->edSetNode(n); - std::string fullname=currentProc->names.back()+ n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->inlineMap[fullname]=n; - } - virtual void forloop (ForLoop* const& b) - { - DEBTRACE( "loop_forloop" << b->getName() ) - _cnode->edSetNode(b); - std::string fullname=currentProc->names.back()+ b->getName(); - currentProc->nodeMap[fullname]=b; - } - virtual void foreach (ForEachLoop* const& b) - { - DEBTRACE("loop_foreach" << b->getName()) - _cnode->edSetNode(b); - std::string fullname=currentProc->names.back()+ b->getName(); - currentProc->nodeMap[fullname]=b; - fullname += ".splitter"; - currentProc->nodeMap[fullname]=b->getChildByShortName("splitter"); - } - virtual void while_ (WhileLoop* const& b) - { - DEBTRACE( "loop_while: " << b->getName() ) - _cnode->edSetNode(b); - std::string fullname=currentProc->names.back()+ b->getName(); - currentProc->nodeMap[fullname]=b; - } - virtual void switch_ (Switch* const& b) - { - DEBTRACE( "loop_switch: " << b->getName() ) - _cnode->edSetNode(b); - std::string fullname=currentProc->names.back()+ b->getName(); - currentProc->nodeMap[fullname]=b; - } - virtual void bloc (Bloc* const& b) - { - DEBTRACE( "loop_bloc " << b->getName() ) - _cnode->edSetNode(b); - std::string fullname=currentProc->names.back()+ b->getName(); - currentProc->nodeMap[fullname]=b; - } - - virtual void datalink (const mylink& l) - { - DEBTRACE( "loop_datalink: " << l.fromnode() << l.fromport() << l.tonode() << l.toport()) - std::string msg; - - //Try only relative name for from node - std::string fromname = currentProc->names.back()+l.fromnode(); - if(currentProc->nodeMap.count(fromname) == 0) - { - msg="from node " + l.fromnode() + " does not exist in data link: "; - msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; - throw Exception(msg); - } - //Try relative name for to node and then absolute one - std::string toname = currentProc->names.back()+l.tonode(); - if(currentProc->nodeMap.count(toname) == 0) - { - //It's not a relative name. Try an absolute one (I think it's not possible) - toname=l.tonode(); - if(currentProc->nodeMap.count(toname) == 0) - { - // The TO node does not exist -> error - msg="to node " + l.tonode() + " does not exist in data link: "; - msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; - throw Exception(msg); - } - } - // We only link local node and other nodes (relative or absolute name in this order) - DEBTRACE(fromname <<":"<edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), - currentProc->nodeMap[toname]->getInputPort(l.toport())); - else - _cnode->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), - currentProc->nodeMap[toname]->getInputPort(l.toport())); - } - - std::string _state; - T _cnode; - std::vector _cnodes; -}; - -template -struct forlooptypeParser:looptypeParser -{ - virtual void buildAttr(const XML_Char** attr) - { - this->required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "state")this->state(attr[i+1]); - if(std::string(attr[i]) == "nsteps")nsteps(atoi(attr[i+1])); - } - } - virtual void name (const std::string& name) - { - DEBTRACE( "forloop_name: " << name ); - std::string fullname=currentProc->names.back()+name; - this->_cnode=theRuntime->createForLoop(name); - currentProc->nodeMap[fullname]=this->_cnode; - this->_cnodes.push_back(this->_cnode); - currentProc->names.push_back(fullname+'.'); - _nsteps=0; - } - virtual void nsteps (const int& n) - { - DEBTRACE( "forloop_nsteps: " << n ) - if(!this->_cnode) - throw Exception("Node name must be defined before nsteps"); - InputPort *iNbTimes=this->_cnode->edGetNbOfTimesInputPort(); - iNbTimes->edInit(n); - } - virtual T post() - { - DEBTRACE( "forloop_post" ) - this->minchoice(t3,1); - T b=this->_cnode; - this->_cnodes.pop_back(); - currentProc->names.pop_back(); - this->_cnode=this->_cnodes.back(); - return b; - } - int _nsteps; -}; -static forlooptypeParser<> forloopParser; -template -struct whilelooptypeParser:looptypeParser -{ - virtual void name (const std::string& name) - { - DEBTRACE( "while_name: " << name ) - std::string fullname=currentProc->names.back()+name; - this->_cnode=theRuntime->createWhileLoop(name); - currentProc->nodeMap[fullname]=this->_cnode; - this->_cnodes.push_back(this->_cnode); - currentProc->names.push_back(fullname+'.'); - } - virtual T post() - { - DEBTRACE( "while_post" << this->_cnode->getName() ) - this->minchoice(t3,1); - InputPort *cond=this->_cnode->edGetConditionPort(); - cond->edInit(true); - T b=this->_cnode; - this->_cnodes.pop_back(); - currentProc->names.pop_back(); - this->_cnode=this->_cnodes.back(); - return b; - } -}; -static whilelooptypeParser<> whileloopParser; +#include "parsers.hxx" -template -struct foreachlooptypeParser:looptypeParser -{ - virtual void buildAttr(const XML_Char** attr) - { - this->required("name",attr); - this->required("type",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "state")this->state(attr[i+1]); - if(std::string(attr[i]) == "nbranch")nbranch(atoi(attr[i+1])); - if(std::string(attr[i]) == "type")datatype(attr[i+1]); - } - postAttr(); - } - virtual void pre () - { - _nbranch=0; - this->looptypeParser::pre(); - } - virtual void name (const std::string& name) - { - DEBTRACE("foreach_name: " << name) - _name=name; - _fullname=currentProc->names.back()+name; - } - virtual void nbranch (const int& n) - { - DEBTRACE("foreach_nbranch: " << n ) - _nbranch=n; - } - virtual void datatype (const std::string& type) - { - DEBTRACE("foreach_datatype: "<< type) - _datatype=type; - } - virtual void postAttr() - { - if(currentProc->typeMap.count(_datatype)==0) - { - std::stringstream msg; - msg << "Type "<< _datatype <<" does not exist"<<" ("<<__FILE__<<":"<<__LINE__<< ")"; - throw Exception(msg.str()); - } - this->_cnode=theRuntime->createForEachLoop(_name,currentProc->typeMap[_datatype]); - //set number of branches - if(_nbranch > 0)this->_cnode->edGetNbOfBranchesPort()->edInit(_nbranch); - this->_cnodes.push_back(this->_cnode); - currentProc->names.push_back(_fullname + '.'); - } - virtual T post() - { - DEBTRACE("foreach_post" << this->_cnode->getName()) - this->minchoice(t3,1); - T b=this->_cnode; - this->_cnodes.pop_back(); - currentProc->names.pop_back(); - if(this->_cnodes.size() == 0) - this->_cnode=0; - else - this->_cnode=this->_cnodes.back(); - return b; - } - int _nbranch; - std::string _fullname; - std::string _name; - std::string _datatype; -}; -static foreachlooptypeParser<> foreachloopParser; +#include +#include +#include -template -struct bloctypeParser:parser -{ - bloctypeParser():parser() - { - _orders["property"]=0; - _orders["inline"]=2; - _orders["service"]=2; - _orders["sinline"]=2; - _orders["node"]=2; - _orders["forloop"]=2; - _orders["foreach"]=2; - _orders["while"]=2; - _orders["switch"]=2; - _orders["bloc"]=2; - _orders["control"]=3; - _orders["datalink"]=3; - _orders["stream"]=3; - _orders["parameter"]=3; - } - virtual void onStart(const XML_Char* el, const XML_Char** attr); - virtual void onEnd(const char *el,parser* child); - virtual void buildAttr(const XML_Char** attr) - { - this->required("name",attr); - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "name")name(attr[i+1]); - if(std::string(attr[i]) == "state")state(attr[i+1]); - } - } - void name (const std::string& name) - { - } - virtual void state (const std::string& name){ - DEBTRACE( "bloc_state: " << name ) - _state=name; - if(_state == "disabled") - { - DEBTRACE( "Bloc disabled: " << _bloc->getName()) - _bloc->exDisabledState(); - } - } - virtual void property (const myprop& prop) - { - DEBTRACE( "property_set: " << prop._name << prop._value ) - _bloc->setProperty(prop._name,prop._value); - } - virtual void inline_ (InlineNode* const& n) - { - DEBTRACE( "bloc_pynode_set: " << n->getName() ) - _bloc->edAddChild(n); - std::string fullname = currentProc->names.back()+n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->inlineMap[fullname]=n; - } - virtual void sinline (ServiceInlineNode* const& n) - { - DEBTRACE( "bloc_sinline: " << n->getName() ) - _bloc->edAddChild(n); - std::string fullname = currentProc->names.back()+n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->serviceMap[fullname]=n; - } - virtual void service (ServiceNode* const& n) - { - DEBTRACE( "bloc_service_set: " << n->getName() ) - _bloc->edAddChild(n); - std::string fullname = currentProc->names.back()+n->getName(); - currentProc->nodeMap[fullname]=n; - currentProc->serviceMap[fullname]=n; - } - virtual void node (InlineNode* const& n) - { - DEBTRACE( "bloc_node_set: " << n->getName() ) - _bloc->edAddChild(n); - std::string fullname = currentProc->names.back()+n->getName(); - DEBTRACE( "bloc_node_set fullname = " << fullname ) - currentProc->nodeMap[fullname]=n; - currentProc->inlineMap[fullname]=n; - } - virtual void forloop (ForLoop* const& b) - { - DEBTRACE( "bloc_forloop_set: " << b->getName() ) - _bloc->edAddChild(b); - std::string fullname = currentProc->names.back()+b->getName(); - currentProc->nodeMap[fullname]=b; - } - virtual void foreach (ForEachLoop* const& b) - { - DEBTRACE( "bloc_foreach_set: " << b->getName() ) - _bloc->edAddChild(b); - std::string fullname = currentProc->names.back()+b->getName(); - currentProc->nodeMap[fullname]=b; - fullname += ".splitter"; - currentProc->nodeMap[fullname]=b->getChildByShortName("splitter"); - } - virtual void while_ (WhileLoop* const& b) - { - DEBTRACE( "bloc_while_set: " << b->getName() ) - _bloc->edAddChild(b); - std::string fullname = currentProc->names.back()+b->getName(); - currentProc->nodeMap[fullname]=b; - } - virtual void switch_ (Switch* const& b) - { - DEBTRACE( "bloc_switch_set: " << b->getName() ) - _bloc->edAddChild(b); - std::string fullname = currentProc->names.back()+b->getName(); - currentProc->nodeMap[fullname]=b; - } - virtual void bloc (Bloc* const& b) - { - DEBTRACE( "bloc_bloc_set: " << b->getName() ) - _bloc->edAddChild(b); - std::string fullname=currentProc->names.back()+ b->getName(); - currentProc->nodeMap[fullname]=b; - } - virtual void control (const mycontrol& l) - { - DEBTRACE( "bloc_control_set: " << l.fromnode() << " "<< l.tonode() ) - std::string msg; +#include "Runtime.hxx" +#include "Proc.hxx" +#include "ProcCataLoader.hxx" +#include "Logger.hxx" - if(currentProc->nodeMap.count(currentProc->names.back()+l.fromnode()) == 0) - { - msg="from node " + l.fromnode() + " does not exist in control link: "; - msg=msg+l.fromnode()+"->"+l.tonode(); - msg=msg+ " context: "+currentProc->names.back(); - throw Exception(msg); - } - if(currentProc->nodeMap.count(currentProc->names.back()+l.tonode()) == 0) - { - msg="to node " + l.tonode() + " does not exist in control link: "; - msg=msg+l.fromnode()+"->"+l.tonode(); - msg=msg+ " context: "+currentProc->names.back(); - throw Exception(msg); - } - // We only link local nodes - _bloc->edAddCFLink(currentProc->nodeMap[currentProc->names.back()+l.fromnode()], - currentProc->nodeMap[currentProc->names.back()+l.tonode()]); - } - virtual void datalink (const mylink& l) - { - DEBTRACE( "bloc_datalink_set: "<"<names.back()+l.fromnode(); - if(currentProc->nodeMap.count(fromname) == 0) - { - msg="from node " + l.fromnode() + " does not exist in data link: "; - msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; - throw Exception(msg); - } - //Try relative name for to node and then absolute one - std::string toname = currentProc->names.back()+l.tonode(); - if(currentProc->nodeMap.count(toname) == 0) - { - //It's not a relative name. Try an absolute one (I think it's not possible) - toname=l.tonode(); - if(currentProc->nodeMap.count(toname) == 0) - { - // The TO node does not exist -> error - msg="to node " + l.tonode() + " does not exist in data link: "; - msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; - throw Exception(msg); - } - } - // We only link local node and other nodes (relative or absolute name in this order) - DEBTRACE(fromname <<":"<edAddDFLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), - currentProc->nodeMap[toname]->getInputPort(l.toport())); - else - _bloc->edAddLink(currentProc->nodeMap[fromname]->getOutputPort(l.fromport()), - currentProc->nodeMap[toname]->getInputPort(l.toport())); - } - virtual void stream (const mystream& l) - { - DEBTRACE( "bloc_stream_set: " << l.fromnode() << l.fromport() << l.tonode() << l.toport() ) - std::string msg; - std::string fromname = currentProc->names.back()+l.fromnode(); - std::string toname = currentProc->names.back()+l.tonode(); - //only relative names - if(currentProc->nodeMap.count(fromname) == 0) - { - msg="from node " + l.fromnode() + " does not exist in stream link: "; - msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; - throw Exception(msg); - } - if(currentProc->nodeMap.count(toname) == 0) - { - msg="to node " + l.tonode() + " does not exist in stream link: "; - msg=msg+l.fromnode()+"("+l.fromport()+")->"+l.tonode()+"("+l.toport()+")"; - throw Exception(msg); - } - OutputDataStreamPort* pout=currentProc->nodeMap[fromname]->getOutputDataStreamPort(l.fromport()); - InputDataStreamPort* pin=currentProc->nodeMap[toname]->getInputDataStreamPort(l.toport()); - _bloc->edAddLink(pout,pin); - // Set all properties for this link - std::map::const_iterator pt; - for(pt=l._props.begin();pt!=l._props.end();pt++) - { - pin->setProperty((*pt).first,(*pt).second); - pout->setProperty((*pt).first,(*pt).second); - } - } - virtual void parameter (const myparam& p) - { - DEBTRACE( "++++++++++++++++++++Parameter+++++++++++++++++++++" ) - std::string msg; - std::string toname = currentProc->names.back()+p._tonode; - if(currentProc->nodeMap.count(toname) == 0) - { - msg="to node " + p._tonode + " does not exist in parameter: "; - msg=msg+"->"+p._tonode+"("+p._toport+")"; - throw Exception(msg); - } - InputPort* inport=currentProc->nodeMap[toname]->getInputPort(p._toport); - //We don't know the parameter type. So we try to initialize the port - //with the value. If it's not the right type, edInit throws an exception - //std::cerr << "----------------------------- " << p.value.c_str() << std::endl; - inport->edInit("XML",p._value.c_str()); - DEBTRACE( "++++++++++++++++++++End parameter+++++++++++++++++++++" ) - } - T post() - { - DEBTRACE( "bloc_post" ) - currentProc->names.pop_back(); - T b=_bloc; - _blocs.pop_back(); - if(_blocs.empty()) - _bloc=NULL; - else - _bloc=_blocs.back(); - return b; - } - T _bloc; - std::string _state; - std::vector _blocs; -}; -static bloctypeParser<> blocParser; +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" -template <> -void bloctypeParser::name (const std::string& name) -{ - DEBTRACE( "bloc_name: " << name ) - std::string fullname=currentProc->names.back()+name; - _bloc=theRuntime->createBloc(name); - _blocs.push_back(_bloc); - currentProc->names.push_back(fullname+'.'); -} +YACS::ENGINE::Runtime* theRuntime=0; -void switchtypeParser::onStart(const XML_Char* el, const XML_Char** attr) -{ - DEBTRACE( "switchtypeParser::onStart: " << el ) - std::string element(el); - this->maxcount("default",1,element); - parser* pp=&main_parser; - if(element == "case")pp=&caseParser; - else if(element == "default")pp=&defaultcaseParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); -} -void switchtypeParser::onEnd(const char *el,parser* child) -{ - DEBTRACE( "switchtypeParser::onEnd: " << el ) - std::string element(el); - if(element == "case")case_(((casetypeParser*)child)->post()); - else if(element == "default")default_(((defaultcasetypeParser*)child)->post()); -} +#define BUFFSIZE 8192 +char Buff[BUFFSIZE]; -void casetypeParser::onStart(const XML_Char* el, const XML_Char** attr) -{ - DEBTRACE( "casetypeParser::onStart: " << el ) - std::string element(el); - this->maxcount("inline",1,element); - this->maxcount("sinline",1,element); - this->maxcount("service",1,element); - this->maxcount("node",1,element); - this->maxcount("forloop",1,element); - this->maxcount("foreach",1,element); - this->maxcount("while",1,element); - this->maxcount("switch",1,element); - this->maxcount("bloc",1,element); - this->maxchoice(t3,1,element); - parser* pp=&main_parser; - if(element == "property")pp=&propertyParser; - else if(element == "inline")pp=&inlineParser; - else if(element == "sinline")pp=&sinlineParser; - else if(element == "service")pp=&serviceParser; - else if(element == "node")pp=&nodeParser; - else if(element == "forloop")pp=&forloopParser; - else if(element == "foreach")pp=&foreachloopParser; - else if(element == "while")pp=&whileloopParser; - else if(element == "switch")pp=&switchParser; - else if(element == "bloc")pp=&blocParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); -} +extern YACS::ENGINE::Proc* currentProc; +extern XML_Parser p ; -void casetypeParser::onEnd(const char *el,parser* child) +namespace YACS { - DEBTRACE( "casetypeParser::onEnd: " << el ) - std::string element(el); - if(element == "property")property(((propertytypeParser*)child)->post()); - else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post()); - else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post()); - else if(element == "service")service(((servicetypeParser<>*)child)->post()); - else if(element == "node")node(((nodetypeParser<>*)child)->post()); - else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post()); - else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post()); - else if(element == "while")while_(((whilelooptypeParser<>*)child)->post()); - else if(element == "switch")switch_(((switchtypeParser*)child)->post()); - else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post()); -} -template -void looptypeParser::onStart(const XML_Char* el, const XML_Char** attr) -{ - DEBTRACE( "looptypeParser::onStart: " << el ) - std::string element(el); - this->maxcount("inline",1,element); - this->maxcount("sinline",1,element); - this->maxcount("service",1,element); - this->maxcount("node",1,element); - this->maxcount("forloop",1,element); - this->maxcount("foreach",1,element); - this->maxcount("while",1,element); - this->maxcount("switch",1,element); - this->maxcount("bloc",1,element); - this->maxchoice(t3,1,element); - parser* pp=&main_parser; - if(element == "property")pp=&propertyParser; - else if(element == "inline")pp=&inlineParser; - else if(element == "sinline")pp=&sinlineParser; - else if(element == "service")pp=&serviceParser; - else if(element == "node")pp=&nodeParser; - else if(element == "forloop")pp=&forloopParser; - else if(element == "foreach")pp=&foreachloopParser; - else if(element == "while")pp=&whileloopParser; - else if(element == "switch")pp=&switchParser; - else if(element == "bloc")pp=&blocParser; - else if(element == "datalink")pp=&linkParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); -} -template -void looptypeParser::onEnd(const char *el,parser* child) +YACSLoader::YACSLoader() { - DEBTRACE( "looptypeParser::onEnd: " << el ) - std::string element(el); - if(element == "property")property(((propertytypeParser*)child)->post()); - else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post()); - else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post()); - else if(element == "service")service(((servicetypeParser<>*)child)->post()); - else if(element == "node")node(((nodetypeParser<>*)child)->post()); - else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post()); - else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post()); - else if(element == "while")while_(((whilelooptypeParser<>*)child)->post()); - else if(element == "switch")switch_(((switchtypeParser*)child)->post()); - else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post()); - else if(element == "datalink") datalink(((linktypeParser<>*)child)->post()); -} + _defaultParsersMap.clear(); -template -void bloctypeParser::onStart(const XML_Char* el, const XML_Char** attr) -{ - DEBTRACE( "bloctypeParser::onStart: " << el ) - std::string element(el); - checkOrder(element); - parser* pp=&main_parser; - if(element == "property")pp=&propertyParser; - else if(element == "inline")pp=&inlineParser; - else if(element == "sinline")pp=&sinlineParser; - else if(element == "service")pp=&serviceParser; - else if(element == "node")pp=&nodeParser; - else if(element == "forloop")pp=&forloopParser; - else if(element == "foreach")pp=&foreachloopParser; - else if(element == "while")pp=&whileloopParser; - else if(element == "switch")pp=&switchParser; - else if(element == "bloc")pp=&blocParser; - else if(element == "control")pp=&controlParser; - else if(element == "datalink")pp=&linkParser; - else if(element == "stream")pp=&streamParser; - else if(element == "parameter")pp=¶mParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); + theRuntime = ENGINE::getRuntime(); } -template -void bloctypeParser::onEnd(const char *el,parser* child) -{ - DEBTRACE( "bloctypeParser::onEnd: " << el ) - std::string element(el); - if(element == "property")property(((propertytypeParser*)child)->post()); - else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post()); - else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post()); - else if(element == "service")service(((servicetypeParser<>*)child)->post()); - else if(element == "node")node(((nodetypeParser<>*)child)->post()); - else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post()); - else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post()); - else if(element == "while")while_(((whilelooptypeParser<>*)child)->post()); - else if(element == "switch")switch_(((switchtypeParser*)child)->post()); - else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post()); - else if(element == "control") control(((controltypeParser<>*)child)->post()); - else if(element == "datalink") datalink(((linktypeParser<>*)child)->post()); - else if(element == "stream") stream(((streamtypeParser<>*)child)->post()); - else if(element == "parameter") parameter(((parametertypeParser*)child)->post()); -} - -template -struct proctypeParser:bloctypeParser -{ - proctypeParser():bloctypeParser() - { - this->_orders["type"]=1; - this->_orders["sequence"]=1; - this->_orders["objref"]=1; - } - void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "proctypeParser::onStart: " << el ) - std::string element(el); - this->checkOrder(element); - parser* pp=&main_parser; - if(element == "property")pp=&propertyParser; - else if(element == "type")pp=&typeParser; - else if(element == "sequence")pp=&seqParser; - else if(element == "objref")pp=&objParser; - else if(element == "struct")pp=&structParser; - else if(element == "container")pp=&containerParser; - else if(element == "inline")pp=&inlineParser; - else if(element == "sinline")pp=&sinlineParser; - else if(element == "service")pp=&serviceParser; - else if(element == "node")pp=&nodeParser; - else if(element == "forloop")pp=&forloopParser; - else if(element == "foreach")pp=&foreachloopParser; - else if(element == "while")pp=&whileloopParser; - else if(element == "switch")pp=&switchParser; - else if(element == "bloc")pp=&blocParser; - else if(element == "control")pp=&controlParser; - else if(element == "datalink")pp=&linkParser; - else if(element == "stream")pp=&streamParser; - else if(element == "parameter")pp=¶mParser; - else - { - // OCC: san -- Allow external parsers for handling of unknown elements - // and attributes. This capability is used by YACS GUI to read - // graph presentation data - if ( this->_defaultParsersMap ) - { - if((this->_defaultParsersMap)->count(element) != 0) - { - pp=(*(this->_defaultParsersMap))[element]; - } - else - { - std::cerr << "There is no parser for this element type. It will be ignored!" << std::endl; - } - } - } - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "proctypeParser::onEnd: " << el ) - std::string element(el); - if(element == "property")this->property(((propertytypeParser*)child)->post()); - else if(element == "type")type(((typetypeParser*)child)->post()); - else if(element == "sequence")sequence(((seqtypeParser*)child)->post()); - else if(element == "objref")objref(((objtypeParser*)child)->post()); - else if(element == "struct")struct_(((structtypeParser*)child)->post()); - else if(element == "container")container(((containertypeParser*)child)->post()); - else if(element == "inline")this->inline_(((inlinetypeParser<>*)child)->post()); - else if(element == "sinline")this->sinline(((sinlinetypeParser<>*)child)->post()); - else if(element == "service")this->service(((servicetypeParser<>*)child)->post()); - else if(element == "node")this->node(((nodetypeParser<>*)child)->post()); - else if(element == "forloop")this->forloop(((forlooptypeParser<>*)child)->post()); - else if(element == "foreach")this->foreach(((foreachlooptypeParser<>*)child)->post()); - else if(element == "while")this->while_(((whilelooptypeParser<>*)child)->post()); - else if(element == "switch")this->switch_(((switchtypeParser*)child)->post()); - else if(element == "bloc")this->bloc(((bloctypeParser<>*)child)->post()); - else if(element == "control") this->control(((controltypeParser<>*)child)->post()); - else if(element == "datalink") this->datalink(((linktypeParser<>*)child)->post()); - else if(element == "stream") this->stream(((streamtypeParser<>*)child)->post()); - else if(element == "parameter") this->parameter(((parametertypeParser*)child)->post()); - } - virtual void buildAttr(const XML_Char** attr) - { - for (int i = 0; attr[i]; i += 2) - { - if(std::string(attr[i]) == "state")this->state(attr[i+1]); - } - } - virtual void pre () - { - std::string name("proc"); - currentProc=theRuntime->createProc(name); - this->_bloc=currentProc; - currentProc->names.push_back(""); - } - virtual void type (const mytype& t) - { - DEBTRACE( "type_set" ) - currentProc->typeMap[t._name]=currentProc->createType(t._name,t._kind); - } - virtual void sequence (TypeCode* const& t) - { - DEBTRACE( "sequence_set" ) - currentProc->typeMap[t->name()]=t; - } - virtual void objref (TypeCode* const& t) - { - DEBTRACE( "objref_set" ) - currentProc->typeMap[t->name()]=t; - } - virtual void struct_ (TypeCode* const& t) - { - DEBTRACE( "struct_set" ) - currentProc->typeMap[t->name()]=t; - } - virtual void container (const mycontainer& t) - { - DEBTRACE( "container_set: " << t._name ) - std::vector::const_iterator iter; - for(iter=t._machs.begin();iter!=t._machs.end();iter++) - { - DEBTRACE( "machine name: " << (*iter)._name ) - } - - if(currentProc->containerMap.count(t._name) == 0) - { - YACS::ENGINE::Container* cont=theRuntime->createContainer(); - // Set all properties for this container - std::map::const_iterator pt; - for(pt=t._props.begin();pt!=t._props.end();pt++) - cont->setProperty((*pt).first,(*pt).second); - currentProc->containerMap[t._name]=cont; - } - else - { - std::cerr << "Warning: container " << t._name << " already defined. It will be ignored" << std::endl; - } - } - - T post(){return this->_bloc;} -}; -static proctypeParser<> procParser; - -struct roottypeParser:parser -{ - void onStart(const XML_Char* el, const XML_Char** attr) - { - DEBTRACE( "roottypeParser::onStart: " << el ) - std::string element(el); - parser* pp=&main_parser; - if(element == "proc")pp=&procParser; - XML_SetUserData(p,pp); - sp.push(pp); - pp->init(); - pp->pre(); - pp->buildAttr(attr); - } - virtual void onEnd(const char *el,parser* child) - { - DEBTRACE( "roottypeParser::onEnd: " << el ) - std::string element(el); - if(element == "proc")proc(((proctypeParser<>*)child)->post()); - } - virtual void proc (Proc* const& b) - { - DEBTRACE( "root_proc_set" << b->getName() ) - _proc=b; - } - Proc* _proc; -}; -static roottypeParser rootParser; -YACSLoader::YACSLoader() +void YACSLoader::registerProcCataLoader() { - theRuntime = getRuntime(); + YACS::ENGINE::ProcCataLoader* factory= new YACS::ENGINE::ProcCataLoader(this); + theRuntime->setCatalogLoaderFactory("proc",factory); } -Proc* YACSLoader::load(const char * file) +ENGINE::Proc* YACSLoader::load(const char * file) { + DEBTRACE("YACSLoader::load: " << file); FILE* fin=fopen(file,"r"); if (! fin) { std::cerr << "Couldn't open schema file" << std::endl; throw std::invalid_argument("Couldn't open schema file"); - //throw Exception("Couldn't open schema file"); } p = XML_ParserCreate(NULL); @@ -2955,14 +58,21 @@ Proc* YACSLoader::load(const char * file) } XML_SetElementHandler(p, parser::start,parser::end); XML_SetCharacterDataHandler(p,parser::charac ); - XML_SetUserData(p,&rootParser); - sp.push(&rootParser); + + parser::main_parser.SetUserDataAndPush(&YACS::roottypeParser::rootParser); + // OCC: san -- Allow external parsers for handling of unknown elements // and attributes. This capability is used by YACS GUI to read // graph presentation data if ( !_defaultParsersMap.empty() ) - procParser._defaultParsersMap = &_defaultParsersMap; + roottypeParser::rootParser.setDefaultMap(&_defaultParsersMap); + else + roottypeParser::rootParser.setDefaultMap(0); + parser::main_parser._file=file; + + currentProc=0; + try { for (;;) @@ -2980,7 +90,11 @@ Proc* YACSLoader::load(const char * file) if (XML_Parse(p, Buff, len, done) == XML_STATUS_ERROR) { - throw Exception(XML_ErrorString(XML_GetErrorCode(p))); + if(currentProc==0) + break; + YACS::ENGINE::Logger* logger=currentProc->getLogger("parser"); + logger->fatal(XML_ErrorString(XML_GetErrorCode(p)),file,XML_GetCurrentLineNumber(p)); + break; } if (done) @@ -2988,18 +102,21 @@ Proc* YACSLoader::load(const char * file) } XML_ParserFree (p); p=0; - return rootParser._proc; + return currentProc; } catch(Exception& e) { //get line number from XML parser - std::cerr << "Error at line: " << XML_GetCurrentLineNumber(p) << std::endl; - delete currentProc; - currentProc=0; - throw e; + YACS::ENGINE::Logger* logger=currentProc->getLogger("parser"); + logger->fatal(e.what(),file,XML_GetCurrentLineNumber(p)); + XML_ParserFree (p); + p=0; + return currentProc; } } YACSLoader::~YACSLoader() { } + +} diff --git a/src/yacsloader/parsers.hxx b/src/yacsloader/parsers.hxx index 4ae103547..df9d7b12a 100644 --- a/src/yacsloader/parsers.hxx +++ b/src/yacsloader/parsers.hxx @@ -1,84 +1,23 @@ #ifndef _PARSERS_HXX_ #define _PARSERS_HXX_ -#include +#include +#include -#include - -#include "Proc.hxx" - - -struct parser +namespace YACS { - parser():_level(0),_defaultParsersMap(0) + namespace ENGINE { - _counts=new std::map; + class Proc; } - virtual ~parser(); - - virtual void SetUserDataAndPush(parser* pp); - virtual void onStart(const XML_Char *el, const XML_Char** attr); - static void XMLCALL start(void *data, const XML_Char* el, const XML_Char** attr); - - virtual void onEnd(const XML_Char *el,parser* child); - - static void XMLCALL end(void *data, const char *el); - - virtual void charData(const XML_Char *s, int len); - - static void XMLCALL charac(void *data, const XML_Char *s, int len); - - virtual void end (); - - virtual void init (); - - virtual void incrCount(const XML_Char *el); - - virtual void checkOrder(std::string& el); - - virtual void maxcount(std::string name, int max, std::string& el); - - virtual void mincount(std::string name,int min ); - - virtual void maxchoice(std::string *names, int max, std::string& el); - - virtual void minchoice(std::string *names, int min); - - virtual void pre(){_content="";}; - virtual void required(const std::string& name, const XML_Char** attr); - - virtual void buildAttr(const XML_Char** attr); - - template - T post() - { - std::cerr << "post" << std::endl; - } - std::string _content; - std::map *_counts; - std::map _orders; - int _orderState; - int _level; - std::stack*> _stackCount; - std::stack _stackOrder; - // OCC: san -- Allow external parsers for handling of unknown elements - // and attributes. This capability is used by YACS GUI to read - // graph presentation data - std::map *_defaultParsersMap; -}; - -static parser main_parser; - - -namespace YACS -{ class YACSLoader { public: YACSLoader(); virtual ~YACSLoader(); - virtual YACS::ENGINE::Proc* load(const char *); + virtual YACS::ENGINE::Proc* load(const char * filename); + void registerProcCataLoader(); protected: std::map _defaultParsersMap; diff --git a/src/yacsloader/portParsers.hxx b/src/yacsloader/portParsers.hxx new file mode 100644 index 000000000..15e80ba1a --- /dev/null +++ b/src/yacsloader/portParsers.hxx @@ -0,0 +1,118 @@ + +#ifndef _PORTPARSERS_HXX_ +#define _PORTPARSERS_HXX_ + +#include "parserBase.hxx" +#include "propertyParsers.hxx" + +#include "factory.hxx" + +namespace YACS +{ + +/*! \brief Class for Inport parser. + * + * This class is a base class for other inport parsers + * + * XML schema: + \verbatim + + + + + + + + \endverbatim + * + */ +template +struct inporttypeParser: parser +{ + static inporttypeParser inportParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void name(const std::string& name); + virtual void type(const std::string& type); + virtual void property (const myprop& prop); + virtual T& post(); +protected: + T _port; +}; + +/*! \brief Class for Outport parser. + * + * This class is also used for OutputDataStream Port + * same XML schema as inporttypeParser + */ +template +struct outporttypeParser:public inporttypeParser +{ + static outporttypeParser outportParser; +}; + +template inporttypeParser inporttypeParser::inportParser; +template outporttypeParser outporttypeParser::outportParser; + +template + void inporttypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "property")pp=&propertytypeParser::propertyParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } +template + void inporttypeParser::onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "property")property(((propertytypeParser*)child)->post()); + } +template + void inporttypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + required("type",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "type")type(attr[i+1]); + } + } +template + void inporttypeParser::pre () + { + _port._name=""; + _port._type=""; + _port.clear(); + } +template + void inporttypeParser::name(const std::string& name) + { + _port._name=name; + } +template + void inporttypeParser::type(const std::string& type) + { + _port._type=type; + } +template + void inporttypeParser::property (const myprop& prop) + { + DEBTRACE( "property_set: " << prop._name << prop._value ) + _port.setProperty(prop._name,prop._value); + } +template + T& inporttypeParser::post() + { + return _port; + } + +} + +#endif diff --git a/src/yacsloader/presetParsers.hxx b/src/yacsloader/presetParsers.hxx new file mode 100644 index 000000000..299fd0e39 --- /dev/null +++ b/src/yacsloader/presetParsers.hxx @@ -0,0 +1,218 @@ +#ifndef _PRESETPARSERS_HXX_ +#define _PRESETPARSERS_HXX_ + +#include "nodeParsers.hxx" + +#include "factory.hxx" + +#include "DataNode.hxx" + +namespace YACS +{ + +/*! \brief Class for presetdata parser. + * + * Its XML schema is: + \verbatim + + + + + + \endverbatim + */ +struct presetdatatypeParser: parser +{ + static presetdatatypeParser presetdataParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE("presetdatatypeParser::onStart"); + std::string element(el); + this->maxcount("value",1,element); + parser* pp=&parser::main_parser; + if(element == "value")pp=&valuetypeParser::valueParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + virtual void onEnd(const char *el,parser* child) + { + DEBTRACE("presetdatatypeParser::onEnd"); + std::string element(el); + if(element == "value")value(((valuetypeParser*)child)->post()); + } + virtual void buildAttr(const XML_Char** attr) + { + DEBTRACE("presetdatatypeParser::buildAttr"); + required("name",attr); + required("type",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "type")type(attr[i+1]); + if(std::string(attr[i]) == "ref")ref(attr[i+1]); + } + } + virtual void name (const std::string& name) + { + DEBTRACE("presetdatatypeParser::name"); + _param._name=name; + _name=name; + } + virtual void type (const std::string& type) + { + DEBTRACE("presetdatatypeParser::type"); + _param._type=type; + _type=type; + } + + virtual void ref (const std::string& ref) + { + _ref=ref; + } + + virtual void pre () + { + DEBTRACE("presetdatatypeParser::pre"); + _ref=""; + _param.clear(); + } + virtual void value (const std::string& value) + { + DEBTRACE("presetdatatypeParser::value " << value); + _param.setProperty("value",value); + } + virtual myoutport& post() + { + DEBTRACE("presetdatatypeParser::post"); + //a parameter can have a ref attribute OR one value element + if(_ref == "") + mincount("value",1); + else + _param.setProperty("value",_ref); + return _param; + } + myoutport _param; + std::string _name; + std::string _type; + std::string _ref; +}; + +/*! \brief Class for PresetNode parser. + * + * Its XML schema is: + \verbatim + + + + + \endverbatim + */ +template +struct presettypeParser:public nodetypeParser +{ + static presettypeParser presetParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void create (); + virtual void pre (); + virtual void name (const std::string& name); + virtual void kind (const std::string& kind); + virtual void parameter (myoutport& p); + std::string _name; + std::string _kind; +}; + +template presettypeParser presettypeParser::presetParser; + + +template +void presettypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE("presettypeParser::onStart"); + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "parameter")pp=&presetdatatypeParser::presetdataParser; + if(element == "property")pp=&propertytypeParser::propertyParser; + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + +template +void presettypeParser::onEnd(const char *el,parser* child) + { + DEBTRACE("presettypeParser::onEnd"); + std::string element(el); + if(element == "parameter")parameter(((presetdatatypeParser*)child)->post()); + if(element == "property")this->property(((propertytypeParser*)child)->post()); + } + +template +void presettypeParser::buildAttr(const XML_Char** attr) + { + DEBTRACE("presettypeParser::buildAttr"); + this->required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "kind")kind(attr[i+1]); + } + create(); + } + +template +void presettypeParser::pre () +{ + _kind=""; +} + +template +void presettypeParser::name (const std::string& name) +{ + _name=name; +} + +template +void presettypeParser::kind (const std::string& kind) +{ + _kind=kind; +} + +template +void presettypeParser::create () +{ + this->_node = theRuntime->createInDataNode(_kind,_name); +} + +template +void presettypeParser::parameter (myoutport& p) +{ + DEBTRACE("presettypeParser::parameter"); + if(currentProc->typeMap.count(p._type)==0) + { + //Check if the typecode is defined in the runtime + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(p._type); + if(t==0) + { + std::string msg="Unknown Type: "; + msg=msg+p._type+" for node: "+this->_node->getName()+" port name: "+p._name; + this->logError(msg); + return; + } + else + { + currentProc->typeMap[p._type]=t; + t->incrRef(); + } + } + ENGINE::OutputPort *port = this->_node->edAddOutputPort(p._name,currentProc->typeMap[p._type]); + this->_node->setData(port,p._props["value"]); +} + +} +#endif diff --git a/src/yacsloader/procParsers.hxx b/src/yacsloader/procParsers.hxx new file mode 100644 index 000000000..d27e17d10 --- /dev/null +++ b/src/yacsloader/procParsers.hxx @@ -0,0 +1,186 @@ +#ifndef _PROCPARSER_HXX_ +#define _PROCPARSER_HXX_ + +#include "blocParsers.hxx" +#include "typeParsers.hxx" +#include "containerParsers.hxx" +#include "nodeParsers.hxx" + +#include "Proc.hxx" +#include "Container.hxx" + +extern YACS::ENGINE::Proc* currentProc; + +namespace YACS +{ + +template +struct proctypeParser: bloctypeParser +{ + + static proctypeParser procParser; + + proctypeParser():bloctypeParser() + { + this->_orders["type"]=1; + this->_orders["sequence"]=1; + this->_orders["objref"]=1; + } + void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr) + { + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "state")this->state(attr[i+1]); + } + } + virtual void pre () + { + std::string name("proc"); + currentProc=theRuntime->createProc(name); + this->_bloc=currentProc; + currentProc->names.push_back(""); + } + virtual void type (const mytype& t) + { + DEBTRACE( "type_set" ) + currentProc->typeMap[t._name]=currentProc->createType(t._name,t._kind); + } + virtual void sequence (ENGINE::TypeCode* const& t) + { + DEBTRACE( "sequence_set" ) + currentProc->typeMap[t->name()]=t; + } + virtual void objref (ENGINE::TypeCode* const& t) + { + DEBTRACE( "objref_set" ) + currentProc->typeMap[t->name()]=t; + } + virtual void struct_ (ENGINE::TypeCode* const& t) + { + DEBTRACE( "struct_set" ) + currentProc->typeMap[t->name()]=t; + } + virtual void container (const mycontainer& t) + { + DEBTRACE( "container_set: " << t._name ) + std::vector::const_iterator iter; + for(iter=t._machs.begin();iter!=t._machs.end();iter++) + { + DEBTRACE( "machine name: " << (*iter)._name ) + } + + if(currentProc->containerMap.count(t._name) == 0) + { + YACS::ENGINE::Container* cont=theRuntime->createContainer(); + cont->setName(t._name); + // Set all properties for this container + std::map::const_iterator pt; + for(pt=t._props.begin();pt!=t._props.end();pt++) + cont->setProperty((*pt).first,(*pt).second); + currentProc->containerMap[t._name]=cont; + } + else + { + std::cerr << "Warning: container " << t._name << " already defined. It will be ignored" << std::endl; + } + } + + T post(){return this->_bloc;} +}; + +template proctypeParser proctypeParser::procParser; + +} + +namespace YACS +{ +template +void proctypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE( "proctypeParser::onStart: " << el ) + std::string element(el); + this->checkOrder(element); + parser* pp=&parser::main_parser; + if(element == "property")pp=&propertytypeParser::propertyParser; + else if(element == "type")pp=&typetypeParser::typeParser; + else if(element == "sequence")pp=&seqtypeParser::seqParser; + else if(element == "objref")pp=&objtypeParser::objParser; + else if(element == "struct")pp=&structtypeParser::structParser; + else if(element == "container")pp=&containertypeParser::containerParser; + + else if(element == "inline")pp=&inlinetypeParser<>::inlineParser; + else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser; + else if(element == "service")pp=&servicetypeParser<>::serviceParser; + else if(element == "node")pp=&nodetypeParser<>::nodeParser; + else if(element == "datanode")pp=&presettypeParser<>::presetParser; + else if(element == "outnode")pp=&outnodetypeParser<>::outnodeParser; + + else if(element == "bloc")pp=&bloctypeParser<>::blocParser; + else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser; + else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser; + else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser; + else if(element == "switch")pp=&switchtypeParser::switchParser; + + else if(element == "control")pp=&controltypeParser<>::controlParser; + else if(element == "datalink")pp=&linktypeParser<>::linkParser; + else if(element == "stream")pp=&streamtypeParser<>::streamParser; + else if(element == "parameter")pp=¶metertypeParser::parameterParser; + else + { + // OCC: san -- Allow external parsers for handling of unknown elements + // and attributes. This capability is used by YACS GUI to read + // graph presentation data + if ( this->_defaultParsersMap ) + { + if((this->_defaultParsersMap)->count(element) != 0) + { + pp=(*(this->_defaultParsersMap))[element]; + } + else + { + std::cerr << "There is no parser for this element type. It will be ignored!" << std::endl; + } + } + } + this->SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + +template +void proctypeParser::onEnd(const char *el,parser* child) + { + DEBTRACE( "proctypeParser::onEnd: " << el ) + std::string element(el); + if(element == "property")this->property(((propertytypeParser*)child)->post()); + else if(element == "type")type(((typetypeParser*)child)->post()); + else if(element == "sequence")sequence(((seqtypeParser*)child)->post()); + else if(element == "objref")objref(((objtypeParser*)child)->post()); + else if(element == "struct")struct_(((structtypeParser*)child)->post()); + else if(element == "container")container(((containertypeParser*)child)->post()); + + else if(element == "inline")this->inline_(((inlinetypeParser<>*)child)->post()); + else if(element == "sinline")this->sinline(((sinlinetypeParser<>*)child)->post()); + else if(element == "service")this->service(((servicetypeParser<>*)child)->post()); + else if(element == "node")this->node(((nodetypeParser<>*)child)->post()); + else if(element == "datanode")this->preset(((presettypeParser<>*)child)->post()); + else if(element == "outnode")this->outnode(((outnodetypeParser<>*)child)->post()); + + else if(element == "bloc")this->bloc(((bloctypeParser<>*)child)->post()); + else if(element == "forloop")this->forloop(((forlooptypeParser<>*)child)->post()); + else if(element == "foreach")this->foreach(((foreachlooptypeParser<>*)child)->post()); + else if(element == "while")this->while_(((whilelooptypeParser<>*)child)->post()); + else if(element == "switch")this->switch_(((switchtypeParser*)child)->post()); + + else if(element == "control") this->control(((controltypeParser<>*)child)->post()); + else if(element == "datalink") this->datalink(((linktypeParser<>*)child)->post()); + else if(element == "stream") this->stream(((streamtypeParser<>*)child)->post()); + else if(element == "parameter") this->parameter(((parametertypeParser*)child)->post()); + } + +} + +#endif diff --git a/src/yacsloader/propertyParsers.cxx b/src/yacsloader/propertyParsers.cxx new file mode 100644 index 000000000..3b7b57cd7 --- /dev/null +++ b/src/yacsloader/propertyParsers.cxx @@ -0,0 +1,23 @@ + +#include "propertyParsers.hxx" + + +namespace YACS +{ + propertytypeParser propertytypeParser::propertyParser; + + void propertytypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + required("value",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "value")value(attr[i+1]); + } + } + void propertytypeParser::name(const std::string& name){ _prop._name=name; } + void propertytypeParser::value(const std::string& name){ _prop._value=name; } + myprop propertytypeParser::post(){return _prop;} + +} diff --git a/src/yacsloader/propertyParsers.hxx b/src/yacsloader/propertyParsers.hxx new file mode 100644 index 000000000..c3991d34b --- /dev/null +++ b/src/yacsloader/propertyParsers.hxx @@ -0,0 +1,40 @@ + +#ifndef _PROPERTYPARSER_HXX_ +#define _PROPERTYPARSER_HXX_ + +#include "parserBase.hxx" +#include "factory.hxx" + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +namespace YACS +{ + +/*! \brief Class for property parser. + * + * Class used to parse a property. + * A property is a pair of name(string), value(string) + * + XML schema is + \verbatim + + + + + \endverbatim + * + */ +struct propertytypeParser: parser +{ + static propertytypeParser propertyParser; + virtual void buildAttr(const XML_Char** attr); + virtual void name(const std::string& name); + virtual void value(const std::string& name); + myprop post(); + myprop _prop; +}; + +} + +#endif diff --git a/src/yacsloader/rootParser.cxx b/src/yacsloader/rootParser.cxx new file mode 100644 index 000000000..7aafd4d64 --- /dev/null +++ b/src/yacsloader/rootParser.cxx @@ -0,0 +1,44 @@ + +#include "rootParser.hxx" +#include "procParsers.hxx" + +namespace YACS +{ + roottypeParser roottypeParser::rootParser; + defaultcasetypeParser defaultcasetypeParser::defaultcaseParser; + switchtypeParser switchtypeParser::switchParser; + casetypeParser casetypeParser::caseParser; + presetdatatypeParser presetdatatypeParser::presetdataParser; + outputdatatypeParser outputdatatypeParser::outputdataParser; + +void roottypeParser::proc (YACS::ENGINE::Proc* const& b) +{ + DEBTRACE( "root_proc_set" << b->getName() ) + _proc=b; +} + +void roottypeParser::onStart(const XML_Char* el, const XML_Char** attr) +{ + DEBTRACE( "roottypeParser::onStart: " << el ) + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "proc")pp=&proctypeParser<>::procParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); +} + +void roottypeParser::onEnd(const char *el,parser* child) +{ + DEBTRACE( "roottypeParser::onEnd: " << el ) + std::string element(el); + if(element == "proc")proc(((proctypeParser<>*)child)->post()); +} + +void roottypeParser::setDefaultMap(std::map *defaultMap) +{ + proctypeParser<>::procParser._defaultParsersMap=defaultMap; +} + +} diff --git a/src/yacsloader/rootParser.hxx b/src/yacsloader/rootParser.hxx new file mode 100644 index 000000000..6a00064dd --- /dev/null +++ b/src/yacsloader/rootParser.hxx @@ -0,0 +1,25 @@ +#ifndef _ROOTPARSER_HXX_ +#define _ROOTPARSER_HXX_ + +#include "parserBase.hxx" + +#include "Proc.hxx" + +namespace YACS +{ + +struct roottypeParser:parser +{ + static roottypeParser rootParser; + + void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void proc (YACS::ENGINE::Proc* const& b); + void setDefaultMap(std::map *); + YACS::ENGINE::Proc* _proc; + const char* file; +}; + +} + +#endif diff --git a/src/yacsloader/samples/SchemaIOFile.xml b/src/yacsloader/samples/SchemaIOFile.xml new file mode 100644 index 000000000..94f6708ec --- /dev/null +++ b/src/yacsloader/samples/SchemaIOFile.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + -2.45 + + + + + PyScript0 OutNode0 + PresetNode0 PyScript0 + + PyScript0 b + OutNode0 a + + + PresetNode0 a + PyScript0 a + + + PyScript0a + 0 + + + + + + + + + + diff --git a/src/yacsloader/samples/SchemaInputOutputGeom.xml b/src/yacsloader/samples/SchemaInputOutputGeom.xml new file mode 100644 index 000000000..d870c7094 --- /dev/null +++ b/src/yacsloader/samples/SchemaInputOutputGeom.xml @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + GEOM_Superv + + MakeFuse + + + + + + + + + + SalomeNode0 + SetStudyID + + + StudyInNode0 PyScript0 + StudyInNode0 SalomeNode1 + PyScript0 SalomeNode0 + SalomeNode0 StudyOutNode0 + SalomeNode1 SalomeNode0 + + StudyInNode0 a + PyScript0 a + + + StudyInNode0 b + PyScript0 b + + + PyScript0 x + SalomeNode0 theShape1 + + + PyScript0 y + SalomeNode0 theShape2 + + + SalomeNode0 return + StudyOutNode0 a + + + SalomeNode1theStudyID + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/yacsloader/samples/datanode0.xml b/src/yacsloader/samples/datanode0.xml new file mode 100644 index 000000000..96e33ddc3 --- /dev/null +++ b/src/yacsloader/samples/datanode0.xml @@ -0,0 +1,36 @@ + + + + + 13.5 + + + + + + + + + + + + + + + + + + + + + + + ap1 + n2 p1 + ap1 + b.n2 p1 + b.n2p1 + out d1 + + + diff --git a/src/yacsloader/samples/err0.xml b/src/yacsloader/samples/err0.xml new file mode 100644 index 000000000..e068aaafa --- /dev/null +++ b/src/yacsloader/samples/err0.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + HELLO + makeBanner + + + + + + + + + + + + + + node0p1 + node1 p1 + + + diff --git a/src/yacsloader/samples/err1.xml b/src/yacsloader/samples/err1.xml new file mode 100644 index 000000000..f541d275b --- /dev/null +++ b/src/yacsloader/samples/err1.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + HELLO + makeBanner + + + + + + + + + + + + + + + node0p1 + node1 p1 + + + diff --git a/src/yacsloader/samples/err2.xml b/src/yacsloader/samples/err2.xml new file mode 100644 index 000000000..1ebe906eb --- /dev/null +++ b/src/yacsloader/samples/err2.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + HELLO + makeBanner + + + + + + + + + + + + + + node0p1 + node1 p1 + + + diff --git a/src/yacsloader/samples/err3.xml b/src/yacsloader/samples/err3.xml new file mode 100644 index 000000000..df7b3448f --- /dev/null +++ b/src/yacsloader/samples/err3.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + n b1 + b1 n2 + + nselect + b1 select + b1.p1_n2p1 + n2 p1 + b1.default_n2p1 + n2 p1 + + + b1.p1_n2 p1 + 23 + + + b1.p3_n2 p1 + 54 + + + b1.default_n2 p1 + 67 + + + diff --git a/src/yacsloader/samples/f.data b/src/yacsloader/samples/f.data new file mode 100644 index 000000000..28d0af969 --- /dev/null +++ b/src/yacsloader/samples/f.data @@ -0,0 +1 @@ +coucou diff --git a/src/yacsloader/samples/file1.xml b/src/yacsloader/samples/file1.xml new file mode 100644 index 000000000..842262b11 --- /dev/null +++ b/src/yacsloader/samples/file1.xml @@ -0,0 +1,79 @@ + + + + + + + f.data + + + + + + + + + + HELLO + makeBanner + + + + + + + + HELLO + makeBanner + + + + + + + + + + + + + + + + + + node2f2 + node3 p1 + + + node2f2 + out f1 + + + node2p1 + out d1 + + + afile1 + node1 f1 + + + node0p1 + node1 p1 + + + node0p1 + node2 p1 + + + node1f1 + node2 f2 + + + + diff --git a/src/yacsloader/samples/gobj1.xml b/src/yacsloader/samples/gobj1.xml new file mode 100644 index 000000000..31507340a --- /dev/null +++ b/src/yacsloader/samples/gobj1.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + FIELD + + + + + + + + + + + + + + + 5. + -1. + + + + + + + + + + + + Calculator + Constant + + + + + + + Calculator + Mul + + + + + + + Calculator + Add + + + + + + + + + + + + + + + + + + + noderesult + node3 field1 + + + noderesult + node2 field + + + node2result + node3 field2 + + + noderesult + pyth0 p1 + + + pyth0p1 + pyth1 p1 + + + + + + + + dc + l.b.node2 x + + + sb + node0 p1 + + + db + l.b.node x + + + node0p1 + l.b.node field + + + diff --git a/src/yacsloader/samples/objref2.xml b/src/yacsloader/samples/objref2.xml new file mode 100644 index 000000000..1f25b06e1 --- /dev/null +++ b/src/yacsloader/samples/objref2.xml @@ -0,0 +1,62 @@ + + + + + Obj + + + + + + + corbaname:rir:#test.my_context/Echo.Object + echoObj2 + + + + + + corbaname:rir:#test.my_context/Echo.Object + createC + + + + + + + + + + + + corbaname:rir:#test.my_context/Echo.Object + echoObjVec + + + + + + + corba0 p1 + corbaname:rir:#test.my_context/Obj.Object + + + + + corba0p1 + pyth0 p1 + + + corba1p1 + pyth0 p2 + + + pyth0p1 + corba2 p1 + + + diff --git a/src/yacsloader/samples/struct2.xml b/src/yacsloader/samples/struct2.xml new file mode 100644 index 000000000..5025ee7a5 --- /dev/null +++ b/src/yacsloader/samples/struct2.xml @@ -0,0 +1,102 @@ + + + + + + eo/Obj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + corbaname:rir:#test.my_context/Echo.Object + createObj + + + + + + corbaname:rir:#test.my_context/Echo.Object + createC + + + + + + + + + + + + + corbaname:rir:#test.my_context/Echo.Object + echoStruct2 + + + + + + corbaname:rir:#test.my_context/Echo.Object + echoObjectVec + + + + + + + corba0 p1 + 1 + + + + + corba0o1 + node0 o1 + + + + corba2o1 + node0 o2 + + + + node0s1 + corba1 s1 + + + + node0s2 + corba3 s1 + + + diff --git a/src/yacsloader/samples/study1.xml b/src/yacsloader/samples/study1.xml new file mode 100644 index 000000000..debe4058c --- /dev/null +++ b/src/yacsloader/samples/study1.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sb + node0 p1 + + + node0p1 + os b + + + diff --git a/src/yacsloader/samples/triangle5error.xml b/src/yacsloader/samples/triangle5error.xml new file mode 100644 index 000000000..3ed223fc0 --- /dev/null +++ b/src/yacsloader/samples/triangle5error.xml @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + node_0_0 node_1_0 + node_0_0 node_1_1 + node_1_0 node_2_0 + node_1_0 node_2_1 + node_1_1 node_2_1 + node_1_1 node_2_2 + node_2_0 node_3_0 + node_2_0 node_3_1 + node_2_1 node_3_1 + node_2_1 node_3_2 + node_2_2 node_3_2 + node_2_2 node_3_3 + node_3_0 node_4_0 + node_3_0 node_4_1 + node_3_1 node_4_1 + node_3_1 node_4_2 + node_3_2 node_4_2 + node_3_2 node_4_3 + node_3_3 node_4_3 + node_3_3 node_4_4 + node_4_0 node_5_0 + node_4_0 node_5_1 + node_4_1 node_5_1 + node_4_1 node_5_2 + node_4_2 node_5_2 + node_4_2 node_5_3 + node_4_3 node_5_3 + node_4_3 node_5_4 + node_4_4 node_5_4 + node_4_4 node_5_5 + + + + + + + node_0_0 c + node_1_0 b + + + node_0_0 c + node_1_1 a + + + node_1_0 c + node_2_0 b + + + node_1_0 c + node_2_1 a + + + node_1_1 c + node_2_1 b + + + node_1_1 c + node_2_2 a + + + node_2_0 c + node_3_0 b + + + node_2_0 c + node_3_1 a + + + node_2_1 c + node_3_1 b + + + node_2_1 c + node_3_2 a + + + node_2_2 c + node_3_2 b + + + node_2_2 c + node_3_3 a + + + node_3_0 c + node_4_0 b + + + node_3_0 c + node_4_1 a + + + node_3_1 c + node_4_1 b + + + node_3_1 c + node_4_2 a + + + node_3_2 c + node_4_2 b + + + node_3_2 c + node_4_3 a + + + node_3_3 c + node_4_3 b + + + node_3_3 c + node_4_4 a + + + node_4_0 c + node_5_0 b + + + node_4_0 c + node_5_1 a + + + node_4_1 c + node_5_1 b + + + node_4_1 c + node_5_2 a + + + node_4_2 c + node_5_2 b + + + node_4_2 c + node_5_3 a + + + node_4_3 c + node_5_3 b + + + node_4_3 c + node_5_4 a + + + node_4_4 c + node_5_4 b + + + node_4_4 c + node_5_5 a + + + + + + + + + node_0_0 a + 0 + + + node_0_0 b + 1 + + + + node_1_0 a + 0 + + + node_1_1 b + 0 + + + node_2_0 a + 0 + + + node_2_2 b + 0 + + + node_3_0 a + 0 + + + node_3_3 b + 0 + + + node_4_0 a + 0 + + + node_4_4 b + 0 + + + node_5_0 a + 0 + + + node_5_5 b + 0 + + + + + diff --git a/src/yacsloader/switchParsers.hxx b/src/yacsloader/switchParsers.hxx new file mode 100644 index 000000000..b2d80d3ee --- /dev/null +++ b/src/yacsloader/switchParsers.hxx @@ -0,0 +1,343 @@ + +#ifndef _SWITCHPARSERS_HXX_ +#define _SWITCHPARSERS_HXX_ + +#include "parserBase.hxx" +#include "propertyParsers.hxx" +#include "nodeParsers.hxx" + +#include "Loop.hxx" +#include "ForLoop.hxx" +#include "ForEachLoop.hxx" +#include "WhileLoop.hxx" +#include "Switch.hxx" +#include "Bloc.hxx" +#include "Proc.hxx" +#include "InlineNode.hxx" +#include "ServiceNode.hxx" +#include "ServiceInlineNode.hxx" +#include "Runtime.hxx" + +#include "factory.hxx" + +#include +#include +#include +#include + +extern YACS::ENGINE::Proc* currentProc; +extern YACS::ENGINE::Runtime* theRuntime; + +namespace YACS +{ + +struct casetypeParser:parser +{ + static casetypeParser caseParser; + void onStart(const XML_Char* el, const XML_Char** attr); + void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void id (const int& n); + virtual void property (const myprop& prop); + virtual void inline_ (ENGINE::InlineNode* const& n); + virtual void sinline (ENGINE::ServiceInlineNode* const& n); + virtual void service (ENGINE::ServiceNode* const& n); + virtual void node (ENGINE::InlineNode* const& n); + virtual void forloop (ENGINE::ForLoop* const& n); + virtual void foreach (ENGINE::ForEachLoop* const& n); + virtual void while_ (ENGINE::WhileLoop* const& n); + virtual void switch_ (ENGINE::Switch* const& n); + virtual void bloc (ENGINE::Bloc* const& n); + virtual std::pair post(); + ENGINE::Node* _cnode; + int _id; + std::vector _idStack; +}; + +struct defaultcasetypeParser:casetypeParser +{ + static defaultcasetypeParser defaultcaseParser; + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); +}; + +struct switchtypeParser:parser +{ + static switchtypeParser switchParser; + void onStart(const XML_Char* el, const XML_Char** attr); + void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void case_ (const std::pair& p); + virtual void default_ (const std::pair& p); + virtual void name (const std::string& name); + virtual void state (const std::string& state); + virtual void select (const int& s); + virtual ENGINE::Switch* post (); + // stack to store switches in case of switch in switch + std::vector _cnodes; + std::string _state; +}; + +} + +#include "loopParsers.hxx" + +namespace YACS +{ + + static std::string switch_t3[]={"inline","sinline","service","node","forloop","foreach","while","switch","bloc",""}; + + void casetypeParser::buildAttr(const XML_Char** attr) + { + this->required("id",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "id")id(atoi(attr[i+1])); + } + } + void casetypeParser::pre () + { + _cnode=0; + _id=0; + } + void casetypeParser::id (const int& n) + { + DEBTRACE( "case_id: " << n ) + _id=n; + //store this level id + _idStack.push_back(_id); + //store this level name + std::stringstream temp; + if (_id <0) temp << "m" << -_id << "_"; + else temp << "p" << _id << "_"; + std::string fullname=currentProc->names.back()+temp.str(); + DEBTRACE( "case_fullname: " << fullname ) + currentProc->names.push_back(fullname); + } + void casetypeParser::property (const myprop& prop) + { + DEBTRACE( "property_set: " << prop._name << prop._value ) + } + void casetypeParser::inline_ (ENGINE::InlineNode* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->inlineMap[fullname]=n; + } + void casetypeParser::sinline (ENGINE::ServiceInlineNode* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->serviceMap[fullname]=n; + } + void casetypeParser::service (ENGINE::ServiceNode* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->serviceMap[fullname]=n; + } + void casetypeParser::node (ENGINE::InlineNode* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + currentProc->inlineMap[fullname]=n; + } + void casetypeParser::forloop (ENGINE::ForLoop* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + } + void casetypeParser::foreach (ENGINE::ForEachLoop* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + fullname += ".splitter"; + currentProc->nodeMap[fullname]=n->getChildByShortName("splitter"); + } + void casetypeParser::while_ (ENGINE::WhileLoop* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + } + void casetypeParser::switch_ (ENGINE::Switch* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + } + void casetypeParser::bloc (ENGINE::Bloc* const& n) + { + _cnode=n; + std::string fullname=currentProc->names.back()+ n->getName(); + currentProc->nodeMap[fullname]=n; + } + std::pair casetypeParser::post() + { + DEBTRACE( "case_post" ) + minchoice(switch_t3,1); + //get back this level id + _id=_idStack.back(); + _idStack.pop_back(); + //pop back this level name + currentProc->names.pop_back(); + return std::pair(_id,_cnode); + } + + void defaultcasetypeParser::buildAttr(const XML_Char** attr) + { + for (int i = 0; attr[i]; i += 2) + { + DEBTRACE( attr[i] << "=" << attr[i + 1] ) + } + } + void defaultcasetypeParser::pre () + { + _id=0; + _cnode=0; + //store this level id + _idStack.push_back(_id); + //store this level name + std::string fullname=currentProc->names.back()+"default_"; + DEBTRACE( "case_fullname: " << fullname ) + currentProc->names.push_back(fullname); + } + + void switchtypeParser::buildAttr(const XML_Char** attr) + { + this->required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "state")state(attr[i+1]); + if(std::string(attr[i]) == "select")select(atoi(attr[i+1])); + } + } + void switchtypeParser::pre (){_state="";} + void switchtypeParser::case_ (const std::pair& p) + { + ENGINE::Switch* s=_cnodes.back(); + s->edSetNode(p.first,p.second); + } + void switchtypeParser::default_ (const std::pair& p) + { + ENGINE::Switch* s=_cnodes.back(); + s->edSetDefaultNode(p.second); + } + void switchtypeParser::name (const std::string& name) + { + ENGINE::Switch* s; + std::string fullname=currentProc->names.back()+name; + DEBTRACE( "switch_fullname: " << fullname ) + s=theRuntime->createSwitch(name); + _cnodes.push_back(s); + currentProc->names.push_back(fullname+'.'); + } + void switchtypeParser::state (const std::string& state) + { + //state is an attribute (no order). It can be defined before name + //To be improved + ENGINE::Switch* s=_cnodes.back(); + if(_state == "disabled") + { + DEBTRACE( "Switch disabled: " << s->getName()) + s->exDisabledState(); + } + } + void switchtypeParser::select (const int& s) + { + //select is an attribute + ENGINE::Switch* sw=_cnodes.back(); + ENGINE::InputPort *p=sw->edGetConditionPort(); + p->edInit(s); + } + ENGINE::Switch* switchtypeParser::post () + { + DEBTRACE( "switch_post: " ) + ENGINE::Switch* sw=_cnodes.back(); + //pop back current level name and node + _cnodes.pop_back(); + currentProc->names.pop_back(); + return sw; + } + +void switchtypeParser::onStart(const XML_Char* el, const XML_Char** attr) +{ + DEBTRACE( "switchtypeParser::onStart: " << el ) + std::string element(el); + this->maxcount("default",1,element); + parser* pp=&parser::main_parser; + if(element == "case")pp=&casetypeParser::caseParser; + else if(element == "default")pp=&defaultcasetypeParser::defaultcaseParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); +} + +void switchtypeParser::onEnd(const char *el,parser* child) +{ + DEBTRACE( "switchtypeParser::onEnd: " << el ) + std::string element(el); + if(element == "case")case_(((casetypeParser*)child)->post()); + else if(element == "default")default_(((defaultcasetypeParser*)child)->post()); +} + +void casetypeParser::onStart(const XML_Char* el, const XML_Char** attr) +{ + DEBTRACE( "casetypeParser::onStart: " << el ) + std::string element(el); + this->maxcount("inline",1,element); + this->maxcount("sinline",1,element); + this->maxcount("service",1,element); + this->maxcount("node",1,element); + this->maxcount("forloop",1,element); + this->maxcount("foreach",1,element); + this->maxcount("while",1,element); + this->maxcount("switch",1,element); + this->maxcount("bloc",1,element); + this->maxchoice(switch_t3,1,element); + parser* pp=&parser::main_parser; + if(element == "property")pp=&propertytypeParser::propertyParser; + else if(element == "inline")pp=&inlinetypeParser<>::inlineParser; + else if(element == "sinline")pp=&sinlinetypeParser<>::sinlineParser; + else if(element == "service")pp=&servicetypeParser<>::serviceParser; + else if(element == "node")pp=&nodetypeParser<>::nodeParser; + else if(element == "forloop")pp=&forlooptypeParser<>::forloopParser; + else if(element == "foreach")pp=&foreachlooptypeParser<>::foreachloopParser; + else if(element == "while")pp=&whilelooptypeParser<>::whileloopParser; + else if(element == "switch")pp=&switchtypeParser::switchParser; + else if(element == "bloc")pp=&bloctypeParser<>::blocParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); +} + +void casetypeParser::onEnd(const char *el,parser* child) +{ + DEBTRACE( "casetypeParser::onEnd: " << el ) + std::string element(el); + if(element == "property")property(((propertytypeParser*)child)->post()); + else if(element == "inline")inline_(((inlinetypeParser<>*)child)->post()); + else if(element == "sinline")sinline(((sinlinetypeParser<>*)child)->post()); + else if(element == "service")service(((servicetypeParser<>*)child)->post()); + else if(element == "node")node(((nodetypeParser<>*)child)->post()); + else if(element == "forloop")forloop(((forlooptypeParser<>*)child)->post()); + else if(element == "foreach")foreach(((foreachlooptypeParser<>*)child)->post()); + else if(element == "while")while_(((whilelooptypeParser<>*)child)->post()); + else if(element == "switch")switch_(((switchtypeParser*)child)->post()); + else if(element == "bloc")bloc(((bloctypeParser<>*)child)->post()); +} + +} + +#endif diff --git a/src/yacsloader/typeParsers.cxx b/src/yacsloader/typeParsers.cxx new file mode 100644 index 000000000..cb7cda2a5 --- /dev/null +++ b/src/yacsloader/typeParsers.cxx @@ -0,0 +1,294 @@ + +#include "typeParsers.hxx" +#include "dataParsers.hxx" +#include "Exception.hxx" +#include "Proc.hxx" +#include "Runtime.hxx" + +#include + +//#define _DEVDEBUG_ +#include "YacsTrace.hxx" + +extern YACS::ENGINE::Proc* currentProc; +extern YACS::ENGINE::Runtime* theRuntime; + +namespace YACS +{ + typetypeParser typetypeParser::typeParser; + seqtypeParser seqtypeParser::seqParser; + objtypeParser objtypeParser::objParser; + structtypeParser structtypeParser::structParser; + membertypeParser membertypeParser::memberParser; + + void typetypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + required("kind",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "kind")kind(attr[i+1]); + } + } + void typetypeParser::pre (){} + void typetypeParser::name(const std::string& name) + { + DEBTRACE( "type_name: " << name ) + _name=name; + } + void typetypeParser::kind(const std::string& name) + { + DEBTRACE( "type_kind: " << name ) + _kind=name; + } + mytype typetypeParser::post() + { + DEBTRACE( "type_post" ) + mytype t; + t._kind=_kind; + t._name=_name; + return t; + } + + void seqtypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE( "seqtypeParser::onStart: " << el ) + parser* pp=&parser::main_parser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void seqtypeParser::onEnd(const char *el,parser* child) + { + DEBTRACE( "seqtypeParser::onEnd: " << el ) + } + void seqtypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + required("content",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "content")content(attr[i+1]); + } + } + void seqtypeParser::name(const std::string& name) + { + DEBTRACE( "seqtype_name: " << name ) + _name=name; + } + void seqtypeParser::content(const std::string& name) + { + DEBTRACE( "seqtype_content: " << name ) + if(currentProc->typeMap.count(name)==0) + { + //Check if the typecode is defined in the runtime + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(name); + if(t==0) + { + std::stringstream msg; + msg << "Type " << name << " does not exist" << " (" <<__FILE__ << ":" << __LINE__ << ")"; + throw Exception(msg.str()); + } + else + { + currentProc->typeMap[name]=t; + t->incrRef(); + } + } + _contentType=currentProc->typeMap[name]; + + } + ENGINE::TypeCode* seqtypeParser::post() + { + DEBTRACE( "seqtype_post" ) + ENGINE::TypeCode *t = currentProc->createSequenceTc(_name,_name,_contentType); + return t; + } + + void objtypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE( "objtypeParser::onStart: " << el ) + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "base")pp=&stringtypeParser::stringParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void objtypeParser::onEnd(const char *el,parser* child) + { + DEBTRACE( "objtypeParser::onEnd: " << el ) + std::string element(el); + if(element == "base")base(((stringtypeParser*)child)->post()); + } + void objtypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "id")id(attr[i+1]); + } + } + void objtypeParser::pre () + { + _id=""; + _ltc.clear(); + } + void objtypeParser::name(const std::string& name) + { + DEBTRACE( "objtype_name: " << name ) + _name=name; + } + void objtypeParser::id(const std::string& name) + { + DEBTRACE( "objtype_id: " << name ) + _id=name; + } + void objtypeParser::base(const std::string& name) + { + DEBTRACE( "base_name: " << name ) + if(currentProc->typeMap.count(name)==0) + { + //Check if the typecode is defined in the runtime + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(name); + if(t==0) + { + std::stringstream msg; + msg << "Type " << name << " does not exist" << " (" <<__FILE__ << ":" << __LINE__ << ")"; + throw Exception(msg.str()); + } + else + { + currentProc->typeMap[name]=t; + t->incrRef(); + } + } + if(currentProc->typeMap[name]->kind() != ENGINE::Objref) + { + std::stringstream msg; + msg << "Type " << name << " is not an objref" ; + msg << " (" <<__FILE__ << ":" << __LINE__ << ")"; + throw Exception(msg.str()); + } + _ltc.push_back((ENGINE::TypeCodeObjref *)currentProc->typeMap[name]); + } + ENGINE::TypeCode * objtypeParser::post() + { + DEBTRACE( "objtype_post" ) + ENGINE::TypeCode *t = currentProc->createInterfaceTc(_id,_name,_ltc); + return t; + } + + void membertypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + required("type",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "type")type(attr[i+1]); + } + } + void membertypeParser::name(const std::string& name){ _prop._name=name; } + void membertypeParser::type(const std::string& name){ _prop._value=name; } + myprop membertypeParser::post(){return _prop;} + + void structtypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + DEBTRACE( "structtypeParser::onStart: " << el ) + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "member")pp=&membertypeParser::memberParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void structtypeParser::onEnd(const char *el,parser* child) + { + DEBTRACE( "structtypeParser::onEnd: " << el ) + std::string element(el); + if(element == "member")member(((membertypeParser*)child)->post()); + } + void structtypeParser::buildAttr(const XML_Char** attr) + { + required("name",attr); + for (int i = 0; attr[i]; i += 2) + { + if(std::string(attr[i]) == "name")name(attr[i+1]); + if(std::string(attr[i]) == "id")id(attr[i+1]); + } + } + void structtypeParser::pre () + { + _id=""; + _members.clear(); + } + void structtypeParser::name(const std::string& name) + { + DEBTRACE( "structtype_name: " << name ); + _name=name; + } + void structtypeParser::id(const std::string& name) + { + DEBTRACE( "structtype_id: " << name ); + _id=name; + } + void structtypeParser::member (const myprop& prop) + { + DEBTRACE( "structtype_member: " << prop._name << prop._value ); + if(currentProc->typeMap.count(prop._value)==0) + { + //Check if the typecode is defined in the runtime + YACS::ENGINE::TypeCode* t=theRuntime->getTypeCode(prop._value); + if(t==0) + { + std::string msg="Unknown type " + prop._value + " for member " + prop._name + " in struct " + _name; + throw Exception(msg); + } + else + { + currentProc->typeMap[prop._value]=t; + t->incrRef(); + } + } + + _members.push_back(prop); + } + ENGINE::TypeCode * structtypeParser::post() + { + DEBTRACE( "structtype_post" ); + ENGINE::TypeCodeStruct *t; + if(currentProc->typeMap.count(_name)!=0) + { + //reuse a forward declaration + ENGINE::TypeCode* tt=currentProc->typeMap[_name]; + if(tt->kind()==YACS::ENGINE::Struct) + { + t=(ENGINE::TypeCodeStruct*)tt; + } + else + { + std::string msg="Forward declaration must be a struct type but " + std::string(tt->name()) + " is not one" ; + throw Exception(msg); + } + } + else + { + t = (ENGINE::TypeCodeStruct*)currentProc->createStructTc(_id,_name); + } + std::vector::const_iterator iter; + for(iter=_members.begin();iter!=_members.end();iter++) + { + DEBTRACE("member: " << iter->_name << " " <_value); + t->addMember(iter->_name,currentProc->typeMap[iter->_value]); + } + return t; + } +} + diff --git a/src/yacsloader/typeParsers.hxx b/src/yacsloader/typeParsers.hxx new file mode 100644 index 000000000..1912f058d --- /dev/null +++ b/src/yacsloader/typeParsers.hxx @@ -0,0 +1,155 @@ + +#ifndef _TYPEPARSERS_HXX_ +#define _TYPEPARSERS_HXX_ + +#include "parserBase.hxx" +#include "TypeCode.hxx" +#include "factory.hxx" + +namespace YACS +{ + +/*! \brief Class for type parser. + * + * Class used to parse a type definition (class TypeCode in implementation) + * with a name and a kind (reserved to atomic types) + + XML schema is + \verbatim + + + + + \endverbatim + */ +struct typetypeParser: parser +{ + static typetypeParser typeParser; + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void name(const std::string& name); + virtual void kind(const std::string& name); + virtual mytype post(); + std::string _name; + std::string _kind; +}; + +/*! \brief Class for sequence parser. + * + * Class used to parse a sequence (type) definition (class TypeCodeSeq in implementation) + * + XML schema is + + \verbatim + + + + + \endverbatim + + */ +struct seqtypeParser:public parser +{ + static seqtypeParser seqParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + void name(const std::string& name); + void content(const std::string& name); + YACS::ENGINE::TypeCode* post(); + YACS::ENGINE::TypeCode* _contentType; + std::string _name; +}; + +/*! \brief Class for objref parser. + * + * Class used to parse a objref (type) definition (class TypeCodeObjref in implementation) + + XML schema is + \verbatim + + + + + + + + \endverbatim + + */ +struct objtypeParser: parser +{ + static objtypeParser objParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void name(const std::string& name); + virtual void id(const std::string& name); + virtual void base(const std::string& name); + virtual YACS::ENGINE::TypeCode * post(); + std::string _name; + std::string _id; + std::list _ltc; +}; + +/*! \brief Class for member parser. + * + * Class used to parse a struct member + * A struct member is a pair of name(string), type(string) + + XML schema is + \verbatim + + + + + \endverbatim + + */ +struct membertypeParser: parser +{ + static membertypeParser memberParser; + virtual void buildAttr(const XML_Char** attr); + virtual void name(const std::string& name); + virtual void type(const std::string& name); + myprop post(); + myprop _prop; +}; + +/*! \brief Class for struct parser. + * + * Class used to parse a struct (type) definition (class TypeCodeStruct in implementation) + * + * XML schema is + \verbatim + + + + + + + + \endverbatim + * + */ +struct structtypeParser: parser +{ + static structtypeParser structParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void buildAttr(const XML_Char** attr); + virtual void pre (); + virtual void name(const std::string& name); + virtual void id(const std::string& name); + virtual void member (const myprop& prop); + virtual YACS::ENGINE::TypeCode * post(); + std::string _name; + std::string _id; + std::vector _members; +}; + +} + +#endif diff --git a/src/yacsloader/xmlParserBase.hxx b/src/yacsloader/xmlParserBase.hxx index 066b11cc7..73c64e00c 100644 --- a/src/yacsloader/xmlParserBase.hxx +++ b/src/yacsloader/xmlParserBase.hxx @@ -62,6 +62,7 @@ protected: class xmlParserBase { public: +#ifndef SWIG static void XMLCALL start_document(void* userData); static void XMLCALL end_document (void* userData); static void XMLCALL start_element (void* userData, @@ -83,6 +84,7 @@ public: static void XMLCALL cdata_block (void* userData, const xmlChar* value, int len); +#endif static void cleanGarbage(); static int getGarbageSize() {return _garbage.size(); }; public: diff --git a/src/yacsloader/xmlrpcParsers.cxx b/src/yacsloader/xmlrpcParsers.cxx new file mode 100644 index 000000000..442cb7868 --- /dev/null +++ b/src/yacsloader/xmlrpcParsers.cxx @@ -0,0 +1,278 @@ + +#include "xmlrpcParsers.hxx" +#include "dataParsers.hxx" +#include + +namespace YACS +{ + arraytypeParser arraytypeParser::arrayParser; + valuetypeParser valuetypeParser::valueParser; + parametertypeParser parametertypeParser::parameterParser; + datatypeParser datatypeParser::dataParser; + memberdatatypeParser memberdatatypeParser::memberdataParser; + structdatatypeParser structdatatypeParser::structdataParser; + +static std::string t4[]={"string","objref","double","int","boolean","array","struct",""}; + + void valuetypeParser::pre (){ } + void valuetypeParser::int_ (const int& d) + { + std::ostringstream os; + os << "" << d<< ""; + _data=os.str(); + _v.push_back(_data); + } + void valuetypeParser::boolean (const bool& d) + { + std::ostringstream os; + os << "" << d<< ""; + _data=os.str(); + _v.push_back(_data); + } + void valuetypeParser::double_ (const double& d) + { + std::ostringstream os; + os << ""<< d<< ""; + _data=os.str(); + _v.push_back(_data); + } + void valuetypeParser::string(const std::string& d) + { + _data=""+ d+ ""; + _v.push_back(_data); + } + void valuetypeParser::objref(const std::string& d) + { + _data=""+ d+ ""; + _v.push_back(_data); + } + void valuetypeParser::array (const std::string& d) + { + _v.push_back(d); + } + void valuetypeParser::struct_ (const std::string& d) + { + _v.push_back(d); + } + std::string valuetypeParser::post() + { + minchoice(t4,1); + std::string value=""+_v.back()+"\n"; + _v.pop_back(); + return value; + } + + void datatypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "value")pp=&valuetypeParser::valueParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void datatypeParser::onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "value")value(((valuetypeParser*)child)->post()); + } + void datatypeParser::pre () + { + _datas.push_back(_data); + _data=""; + } + void datatypeParser::value (const std::string& v){ + _data=_data+v; + } + std::string datatypeParser::post() + { + mincount("value",1); + std::string d="\n"+_data+""; + _data=_datas.back(); + _datas.pop_back(); + return d; + } + + void memberdatatypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "name")pp=&stringtypeParser::stringParser; + else if(element == "value")pp=&valuetypeParser::valueParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void memberdatatypeParser::onEnd(const char *el,parser* child) + { + std::string element(el); + this->maxcount("name",1,element); + this->maxcount("value",1,element); + if(element == "name")name(((stringtypeParser*)child)->post()); + else if(element == "value")value(((valuetypeParser*)child)->post()); + } + void memberdatatypeParser::pre () + { + _datas.push_back(_data); + _data=""; + } + void memberdatatypeParser::name (const std::string& v) + { + _data=_data+""+v+""; + } + void memberdatatypeParser::value (const std::string& v) + { + _data=_data+v; + } + std::string memberdatatypeParser::post() + { + mincount("value",1); + mincount("name",1); + std::string d="\n"+_data+""; + _data=_datas.back(); + _datas.pop_back(); + return d; + } + + void structdatatypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + parser* pp=&parser::main_parser; + if(element == "member")pp=&memberdatatypeParser::memberdataParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void structdatatypeParser::onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "member")member(((memberdatatypeParser*)child)->post()); + } + void structdatatypeParser::pre () + { + _membersStack.push_back(_members); + _members=""; + } + void structdatatypeParser::member (const std::string& d) + { + _members=_members+d; + } + std::string structdatatypeParser::post() + { + mincount("member",1); + std::string value=""+_members+""; + _members=_membersStack.back(); + _membersStack.pop_back(); + return value; + } + + void arraytypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + this->maxcount("data",1,element); + parser* pp=&parser::main_parser; + if(element == "data")pp=&datatypeParser::dataParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void arraytypeParser::onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "data")data(((datatypeParser*)child)->post()); + } + void arraytypeParser::pre (){ } + void arraytypeParser::data (const std::string& d) + { + _arrays.push_back(d); + } + std::string arraytypeParser::post() + { + mincount("data",1); + std::string value=""+_arrays.back()+""; + _arrays.pop_back(); + return value; + } + + +void valuetypeParser::onStart(const XML_Char* el, const XML_Char** attr) +{ + std::string element(el); + parser* pp=&parser::main_parser; + this->maxcount("string",1,element); + this->maxcount("objref",1,element); + this->maxcount("double",1,element); + this->maxcount("int",1,element); + this->maxcount("boolean",1,element); + this->maxcount("array",1,element); + this->maxcount("struct",1,element); + this->maxchoice(t4,1,element); + if(element == "string")pp=&stringtypeParser::stringParser; + else if(element == "objref")pp=&stringtypeParser::stringParser; + else if(element == "double")pp=&doubletypeParser::doubleParser; + else if(element == "int")pp=&inttypeParser::intParser; + else if(element == "boolean")pp=&booltypeParser::boolParser; + else if(element == "array")pp=&arraytypeParser::arrayParser; + else if(element == "struct")pp=&structdatatypeParser::structdataParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); +} + +void valuetypeParser::onEnd(const char *el,parser* child) +{ + std::string element(el); + if(element == "string")string(((stringtypeParser*)child)->post()); + else if(element == "objref")objref(((stringtypeParser*)child)->post()); + else if(element == "double")double_(((doubletypeParser*)child)->post()); + else if(element == "int")int_(((inttypeParser*)child)->post()); + else if(element == "boolean")boolean(((booltypeParser*)child)->post()); + else if(element == "array")array(((arraytypeParser*)child)->post()); + else if(element == "struct")struct_(((structdatatypeParser*)child)->post()); +} + + void parametertypeParser::onStart(const XML_Char* el, const XML_Char** attr) + { + std::string element(el); + this->maxcount("tonode",1,element); + this->maxcount("toport",1,element); + this->maxcount("value",1,element); + parser* pp=&parser::main_parser; + if(element == "tonode")pp=&stringtypeParser::stringParser; + else if(element == "toport")pp=&stringtypeParser::stringParser; + else if(element == "value")pp=&valuetypeParser::valueParser; + SetUserDataAndPush(pp); + pp->init(); + pp->pre(); + pp->buildAttr(attr); + } + void parametertypeParser::onEnd(const char *el,parser* child) + { + std::string element(el); + if(element == "tonode")tonode(((stringtypeParser*)child)->post()); + else if(element == "toport")toport(((stringtypeParser*)child)->post()); + else if(element == "value")value(((valuetypeParser*)child)->post()); + } + void parametertypeParser::pre (){} + void parametertypeParser::tonode (const std::string& name){ + _param._tonode=name; + } + void parametertypeParser::toport (const std::string& name){ + _param._toport=name; + } + void parametertypeParser::value (const std::string& name){ + _param._value=name; + } + myparam& parametertypeParser::post(){ + mincount("tonode",1); + mincount("toport",1); + mincount("value",1); + return _param; + } + +} diff --git a/src/yacsloader/xmlrpcParsers.hxx b/src/yacsloader/xmlrpcParsers.hxx new file mode 100644 index 000000000..7a4904869 --- /dev/null +++ b/src/yacsloader/xmlrpcParsers.hxx @@ -0,0 +1,158 @@ + +#ifndef _XMLRPCPARSERS_HXX_ +#define _XMLRPCPARSERS_HXX_ + +#include "parserBase.hxx" +#include "factory.hxx" +#include +#include + +namespace YACS +{ +/*! \brief Class for XML-RPC value parser. + * + * This class is used to parse XML data that describes a sequence in XML-RPC format + * + * Its XML schema is: + \verbatim + + + + + + + + + + + + \endverbatim + */ +struct valuetypeParser: parser +{ + static valuetypeParser valueParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void pre (); + virtual void int_ (const int& d); + virtual void boolean (const bool& d); + virtual void double_ (const double& d); + virtual void string(const std::string& d); + virtual void objref(const std::string& d); + virtual void array (const std::string& d); + virtual void struct_ (const std::string& d); + virtual std::string post(); + std::string _data; + std::vector _v; +}; + +/*! \brief Class for XML-RPC data parser. + * + * This class is used to parse XML data that describes a sequence in XML-RPC format + * + * Its XML schema is: + \verbatim + + + + \endverbatim + */ +struct datatypeParser: parser +{ + static datatypeParser dataParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void pre (); + virtual void value (const std::string& v); + virtual std::string post(); + std::string _data; + std::vector _datas; +}; + +/*! \brief Class for XML-RPC member parser. + * + * This class is used to parse XML data that describes a sequence in XML-RPC format + * + * Its XML schema is: + \verbatim + + + + + \endverbatim + */ +struct memberdatatypeParser: parser +{ + static memberdatatypeParser memberdataParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void pre (); + virtual void name (const std::string& v); + virtual void value (const std::string& v); + virtual std::string post(); + std::string _data; + std::vector _datas; +}; + +/*! \brief Class for XML-RPC struct parser. + * + * This class is used to parse XML data that describes a sequence in XML-RPC format + * + * Its XML schema is: + \verbatim + + + + \endverbatim + */ +struct structdatatypeParser: parser +{ + static structdatatypeParser structdataParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void pre (); + virtual void member (const std::string& d); + virtual std::string post(); + std::string _members; + std::vector _membersStack; +}; + +/*! \brief Class for XML-RPC array parser. + * + * This class is used to parse XML data that describes a sequence in XML-RPC format + * + * Its XML schema is: + \verbatim + + + + \endverbatim + */ +struct arraytypeParser: parser +{ + static arraytypeParser arrayParser; + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void pre (); + virtual void data (const std::string& d); + virtual std::string post(); + std::vector _arrays; +}; + +struct parametertypeParser: parser +{ + static parametertypeParser parameterParser; + + virtual void onStart(const XML_Char* el, const XML_Char** attr); + virtual void onEnd(const char *el,parser* child); + virtual void pre (); + virtual void tonode (const std::string& name); + virtual void toport (const std::string& name); + virtual void value (const std::string& name); + virtual myparam& post(); + myparam _param; +}; + +} + +#endif diff --git a/src/yacsorb/CORBAEngineTest.py b/src/yacsorb/CORBAEngineTest.py new file mode 100644 index 000000000..123d2bee7 --- /dev/null +++ b/src/yacsorb/CORBAEngineTest.py @@ -0,0 +1,124 @@ +import time + +import salome +salome.salome_init() + +import YACS_ORB +comp = salome.lcc.FindOrLoadComponent( "YACSContainer","YACS" ) +yacsgen = comp._narrow(YACS_ORB.YACS_Gen) + +# ----------------------------------------------------------------------------- +# --- schema OK + +procEx = yacsgen.LoadProc("samples/legendre7.xml") +procEx.setExecMode(YACS_ORB.CONTINUE) +procEx.Run() + +# --- wait until executor is paused, finished or stopped + +isRunning = 1 +while isRunning: + time.sleep(0.5) + state = procEx.getExecutorState() + isRunning = (state < 304) + print "executorState: ", state + pass + +procEx.saveState("res.xml") +numids,names = procEx.getIds() + +dico = {} +i=0 +for name in names: + dico[name] = numids[i] + i+=1 + pass + +print procEx.getOutPortValue(dico["poly_7"],"Pn") +print procEx.getInPortValue(dico["poly_7"],"x") +print procEx.getInPortValue(dico["poly_7"],"notAPort") +print procEx.getInPortValue(dico["Legendre.loopIter"],"nsteps") + +# ----------------------------------------------------------------------------- +# --- schema with errors (echoSrv must be launched) + +procEx = yacsgen.LoadProc("samples/aschema.xml") +procEx.setExecMode(YACS_ORB.CONTINUE) +procEx.Run() + +# --- wait until executor is paused, finised or stopped + +isRunning = 1 +while isRunning: + time.sleep(0.5) + state = procEx.getExecutorState() + isRunning = (state < 304) + print "executorState: ", state + pass + +procEx.saveState("res2.xml") +numids,names = procEx.getIds() + +dico = {} +i=0 +for name in names: + dico[name] = numids[i] + i+=1 + pass + +print procEx.getErrorDetails(dico["c1"]) +print procEx.getErrorDetails(dico["node13"]) + +# ----------------------------------------------------------------------------- +# --- schema with errors + +procEx = yacsgen.LoadProc("samples/triangle5error.xml") +procEx.setExecMode(YACS_ORB.CONTINUE) +procEx.setStopOnError(1,"execError2.xml") +#procEx.unsetStopOnError() +procEx.Run() + +isRunning = 1 +while isRunning: + time.sleep(0.5) + state = procEx.getExecutorState() + isRunning = (state < 304) + print "executorState: ", state + pass + +#procEx.resumeCurrentBreakPoint() + +procEx.saveState("res3.xml") + +# ----------------------------------------------------------------------------- +# --- schema with breakpoints + +procEx = yacsgen.LoadProc("samples/legendre7.xml") +procEx.setListOfBreakPoints(["Legendre.loopIter.deuxIter.iter2"]) +procEx.setExecMode(YACS_ORB.STOPBEFORENODES) +procEx.Run() + +isRunning = 1 +while isRunning: + time.sleep(0.5) + state = procEx.getExecutorState() + isRunning = (state < 304) + print "executorState: ", state + pass + +procEx.saveState("partialExec.xml") + +procEx = yacsgen.LoadProc("samples/legendre7.xml") +procEx.setExecMode(YACS_ORB.CONTINUE) +procEx.RunFromState("partialExec.xml") + +isRunning = 1 +while isRunning: + time.sleep(0.5) + state = procEx.getExecutorState() + isRunning = (state < 304) + print "executorState: ", state + pass + +procEx.saveState("finishExec.xml") + diff --git a/src/yacsorb/Makefile.am b/src/yacsorb/Makefile.am index 52b29980d..00afb52ca 100644 --- a/src/yacsorb/Makefile.am +++ b/src/yacsorb/Makefile.am @@ -1,85 +1,7 @@ include $(top_srcdir)/adm/unix/make_begin.am -IDL_FILES = yacs.idl -IDL_SOURCES = yacsSK.cc -BUILT_SOURCES = $(IDL_SOURCES) yacs_idl.py -OMNIORB_IDL+= -I$(KERNEL_ROOT_DIR)/idl/salome -I$(GUI_ROOT_DIR)/idl/salome - -lib_LTLIBRARIES = libYACSorb.la - -nodist_libYACSorb_la_SOURCES = $(IDL_SOURCES) - -bin_PROGRAMS=yacsSrv yacs_clt - -yacsSrv_SOURCES = yacsSrv.cxx $(IDL_SOURCES) - -if SALOME_KERNEL -SALOME_LIBS=-L$(KERNEL_ROOT_DIR)/lib/salome -lSalomeLifeCycleCORBA -lSalomeDSCContainer -endif - -AM_CXXFLAGS= \ - -I$(KERNEL_ROOT_DIR)/include/salome \ - -I$(GUI_ROOT_DIR)/include/salome - -IDLPYFLAGS = \ - -I$(KERNEL_ROOT_DIR)/idl/salome - -yacsSrv_CXXFLAGS = -g -DYACS_PTHREAD \ - $(PYTHON_CPPFLAGS) \ - $(OMNIORB_INCLUDES) \ - $(OMNIORB_CXXFLAGS) \ - -I$(KERNEL_ROOT_DIR)/include/salome \ - -I$(GUI_ROOT_DIR)/include/salome \ - -I$(srcdir)/../bases \ - -I$(srcdir)/../engine \ - -I$(srcdir)/../yacsloader \ - -I$(srcdir)/../runtime - -yacsSrv_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -lexpat -pthread -lxml2 - -yacsSrv_LDADD = ../yacsloader/libYACSloader.la \ - ../runtime/libYACSRuntimeSALOME.la \ - ../engine/libYACSEngine.la \ - $(SALOME_LIBS) \ - $(OMNIORB_LIBS) \ - $(PYTHON_LDFLAGS) \ - $(PYTHON_EXTRA_LIBS) - -yacs_clt_SOURCES = yacs_clt.cxx $(IDL_SOURCES) - -yacs_clt_CXXFLAGS = \ - $(PYTHON_CPPFLAGS) \ - -I$(srcdir)/../bases \ - -I$(srcdir)/../engine \ - -I$(srcdir)/../yacsloader \ - -I$(srcdir)/../runtime \ - -I$(KERNEL_ROOT_DIR)/include/salome \ - -I$(GUI_ROOT_DIR)/include/salome \ - $(OMNIORB_INCLUDES) \ - $(OMNIORB_CXXFLAGS) - -yacs_clt_LDFLAGS = $(PYTHON_EXTRA_LDFLAGS) -lexpat -pthread -lxml2 - -yacs_clt_LDADD = ../yacsloader/libYACSloader.la \ - ../runtime/libYACSRuntimeSALOME.la \ - ../engine/libYACSEngine.la \ - $(SALOME_LIBS) \ - $(OMNIORB_LIBS) \ - $(PYTHON_LDFLAGS) \ - $(PYTHON_EXTRA_LIBS) - -pkgpython_PYTHON = YACSGui.py - -install-exec-local: install-pyidl - -install-pyidl: $(IDL_FILES) - $(INSTALL) -d $(pkgpythondir) - @for file in $^ dummy; do \ - if [ $$file != "dummy" ]; then \ - $(OMNIORB_IDL) -bpython $(IDLPYFLAGS) -C$(pkgpythondir) $$file ; \ - fi ; \ - done ; +salomepython_PYTHON = YACS.py include $(top_srcdir)/adm/unix/make_end.am diff --git a/src/yacsorb/YACSGui.py b/src/yacsorb/YACS.py similarity index 71% rename from src/yacsorb/YACSGui.py rename to src/yacsorb/YACS.py index f47876f82..ffa9ace67 100644 --- a/src/yacsorb/YACSGui.py +++ b/src/yacsorb/YACS.py @@ -16,8 +16,9 @@ # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com # -import YACSGui_ORB__POA -import YACSGui_ORB +import sys +import YACS_ORB__POA +import YACS_ORB import SALOME_ComponentPy import SALOME_DriverPy @@ -28,8 +29,9 @@ import SALOMERuntime import loader import salomeloader import pilot +import traceback -class proc_i(YACSGui_ORB__POA.ProcExec): +class proc_i(YACS_ORB__POA.ProcExec): def __init__(self, xmlFile): self.l = loader.YACSLoader() self.e = pilot.ExecutorSwig() @@ -44,6 +46,21 @@ class proc_i(YACSGui_ORB__POA.ProcExec): def getXMLState(self, numid): return self.p.getXMLState(numid) + def getInPortValue(self, nodeNumid, portName): + return self.p.getInPortValue(nodeNumid, portName) + + def getOutPortValue(self, nodeNumid, portName): + return self.p.getOutPortValue(nodeNumid, portName) + + def getErrorDetails(self, nodeNumid): + return self.p.getNodeErrorDetails(nodeNumid) + + def getErrorReport(self, nodeNumid): + return self.p.getNodeErrorReport(nodeNumid) + + def getContainerLog(self, nodeNumid): + return self.p.getNodeContainerLog(nodeNumid) + def getExecutorState(self): return self.e.getExecutorState() @@ -61,7 +78,7 @@ class proc_i(YACSGui_ORB__POA.ProcExec): def Run(self): execState = self.e.getExecutorState() if execState >= 305: - # --- not clean, value from define.hxx + # --- not clean, value from define.hxx (YACS::FINISHED) self.run1.join() self.run1 = None pass @@ -71,19 +88,50 @@ class proc_i(YACSGui_ORB__POA.ProcExec): pass pass + def RunFromState(self, xmlFile): + execState = self.e.getExecutorState() + if execState >= 305: + # --- not clean, value from define.hxx (YACS::FINISHED) + self.run1.join() + self.run1 = None + pass + try: + self.p.init() + self.p.exUpdateState(); + sp = loader.stateParser() + sl = loader.stateLoader(sp,self.p) + sl.parse(xmlFile) + except IOError, ex: + print "IO Error: ", ex + return None + except ValueError,ex: + print "Caught ValueError Exception:",ex + return None + except pilot.Exception,ex: + print ex.what() + return None + except: + print "Unknown exception!" + return None + if self.run1 is None: + self.run1 = threading.Thread(None, self.e.RunPy, "CORBAExec", (self.p,0)) + self.run1.start() + pass + pass + def addObserver(self, obs, numid, event): disp = SALOMERuntime.SALOMEDispatcher_getSALOMEDispatcher() disp.addObserver(obs, numid, event) pass def setExecMode(self, mode): - if mode == YACSGui_ORB.CONTINUE: + if mode == YACS_ORB.CONTINUE: self.e.setExecMode(0) pass - if mode == YACSGui_ORB.STEPBYSTEP: + if mode == YACS_ORB.STEPBYSTEP: self.e.setExecMode(1) pass - if mode == YACSGui_ORB.STOPBEFORENODES: + if mode == YACS_ORB.STOPBEFORENODES: self.e.setExecMode(2) pass pass @@ -115,21 +163,25 @@ class proc_i(YACSGui_ORB__POA.ProcExec): self.e.setStopOnError(dumpRequested, xmlFile) pass + def unsetStopOnError(self): + self.e.unsetStopOnError() + pass + pass -class YACSGui(YACSGui_ORB__POA.YACSGui_Gen, +class YACS(YACS_ORB__POA.YACS_Gen, SALOME_ComponentPy.SALOME_ComponentPy_i, SALOME_DriverPy.SALOME_DriverPy_i): """ To be a SALOME component, this Python class must have the component name - (YACSGui) and inherit the YACSGui_Gen class build from idl compilation + (YACS) and inherit the YACS_Gen class build from idl compilation with omniidl and also the class SALOME_ComponentPy_i which defines general SALOME component behaviour. """ def __init__ ( self, orb, poa, contID, containerName, instanceName, interfaceName ): - print "YACSGui.__init__: ", containerName, ';', instanceName + print "YACS.__init__: ", containerName, ';', instanceName SALOME_ComponentPy.SALOME_ComponentPy_i.__init__(self, orb, poa, contID, containerName, instanceName, interfaceName, 0) @@ -151,16 +203,16 @@ class YACSGui(YACSGui_ORB__POA.YACSGui_Gen, try: procExec_i = proc_i(xmlFile) except IOError, ex: - print "IO Error: ", ex + print >> sys.stderr ,"IO Error: ", ex return None except ValueError,ex: - print "Caught ValueError Exception:",ex + print >> sys.stderr ,"Caught ValueError Exception:",ex return None except pilot.Exception,ex: - print ex.what() + print >> sys.stderr ,ex.what() return None except: - print "Unknown exception!" + print >> sys.stderr ,"Unknown exception!" return None procExec_o = procExec_i._this() return procExec_o diff --git a/src/yacsorb/yacsSrv.cxx b/src/yacsorb/yacsSrv.cxx index c77de47f7..0088956dc 100644 --- a/src/yacsorb/yacsSrv.cxx +++ b/src/yacsorb/yacsSrv.cxx @@ -1,3 +1,4 @@ +#include #include #include "RuntimeSALOME.hxx" #include "Proc.hxx" @@ -102,14 +103,14 @@ char * Proc_i::getXMLState(CORBA::Long numid) void Proc_i::getIds(YACS_ORB::longArray_out numids,YACS_ORB::stringArray_out names) { - std::set nodes=_proc->getAllRecursiveNodes(); + std::list nodes=_proc->getAllRecursiveNodes(); int len=nodes.size(); names=new YACS_ORB::stringArray; numids=new YACS_ORB::longArray; names->length(len); numids->length(len); int i=0; - for(set::const_iterator iter=nodes.begin();iter!=nodes.end();iter++,i++) + for(list::const_iterator iter=nodes.begin();iter!=nodes.end();iter++,i++) { (*names)[i]=CORBA::string_dup((*iter)->getQualifiedName().c_str()); (*numids)[i]=(*iter)->getNumId(); diff --git a/src/yacsorb/yacs_clt.cxx b/src/yacsorb/yacs_clt.cxx index d74014c51..aa7ceca3e 100644 --- a/src/yacsorb/yacs_clt.cxx +++ b/src/yacsorb/yacs_clt.cxx @@ -1,3 +1,4 @@ +#include #include #include "RuntimeSALOME.hxx" #include "Proc.hxx" -- 2.30.2