Salome HOME
Fix for bug IPAL9817 : SIGSEGV appears after "InLine" node function edition.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Service.cxx
index 2b13b08f9d0f466ae2a8f7347aa5b00664b542c5..3afcebbf2ff55fe2c6be16c0feac03eb04271a4e 100644 (file)
 using namespace std;
 #include "SUPERVGUI_Service.h"
 #include "SUPERVGUI_Main.h"
+#include "SUPERVGUI_Library.h"
 #include "SUPERVGUI.h"
-#include "QAD_Tools.h"
-#include "QAD_FileDlg.h"
+
+#include "CAM_Application.h"
+#include "SUIT_Desktop.h"
+#include "SUIT_FileDlg.h"
+#include "SUIT_Session.h"
+#include "SUIT_Tools.h"
 
 #include "SALOME_NamingService.hxx"
 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
+#include <qlabel.h>
 #include <qlayout.h>
+#include <qhbox.h>
 #include <qtextstream.h>
-
+#include <qregexp.h>
 
 static const char * ComponentIcon[] = {
 "20 20 2 1",
@@ -93,8 +100,8 @@ static const char * InterfaceIcon[] = {
 
 
 SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
-    QDialog(QAD_Application::getDesktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
-    naming(ns)
+    QDialog(SUIT_Session::session()->activeApplication()->desktop(), 0, false, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
+    naming(ns), myMFile(0)
 {
   setSizeGripEnabled( true );
   setCaption(tr("TIT_SERVICES"));
@@ -127,16 +134,16 @@ SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
   //QHGroupBox* aAddBox = new QHGroupBox(tr("TIT_ADDNODE"), aCorbaPane); //!!
   //aAddBox->setInsideSpacing(20); //!!
 
-  QPushButton* aComputeCBtn = new QPushButton(tr("TIT_ADDCNODE"), aCorbaPane); //!!
-  connect(aComputeCBtn, SIGNAL(clicked()), this, SLOT(addComputeNode())); //!!
-  aComputeCBtn->setDefault(false); 
+//NRI   QPushButton* aComputeCBtn = new QPushButton(tr("TIT_ADDCNODE"), aCorbaPane); //!!
+//NRI   connect(aComputeCBtn, SIGNAL(clicked()), this, SLOT(addComputeNode())); //!!
+//NRI   aComputeCBtn->setDefault(false); 
 
   QPushButton* aComputeBtn = new QPushButton(tr("TIT_ADDFNODE"), aCorbaPane);
   connect(aComputeBtn, SIGNAL(clicked()), this, SLOT(addFactoryNode()));
   aComputeBtn->setDefault(true); 
 
   aBaseLayout->addWidget(aComputeBtn);
-  aBaseLayout->addWidget(aComputeCBtn); //!!
+  //NRI  aBaseLayout->addWidget(aComputeCBtn); //!!
 
   aBaseLayoutV->insertLayout(-1, aBaseLayout);
   myTabPane->addTab(aCorbaPane, tr("MODULES_PANE"));
@@ -152,14 +159,13 @@ SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
   QHGroupBox* aAddBox2 = new QHGroupBox(tr("TIT_ADDNODE"), aPythonPane);
   aAddBox2->setInsideSpacing(20);
 
-  QLabel* aTypeLbl = new QLabel(tr("LBL_NODETYPE"), aAddBox2);
+  /*QLabel* aTypeLbl = */new QLabel(tr("LBL_NODETYPE"), aAddBox2);
 
   myTypeCombo = new QComboBox(aAddBox2);
-  myTypeCombo->insertItem("Computation");
-  myTypeCombo->insertItem("Switch");
-  myTypeCombo->insertItem("Loop");
-  myTypeCombo->insertItem("GoTo");
-  //myTypeCombo->insertItem("Label");
+  myTypeCombo->insertItem( tr( "INLINE_COMP" ) );
+  myTypeCombo->insertItem( tr( "INLINE_SWTC" ) );
+  myTypeCombo->insertItem( tr( "INLINE_LOOP" ) );
+  myTypeCombo->insertItem( tr( "INLINE_GOTO") );
   connect(myTypeCombo, SIGNAL(activated(int)), this, SLOT(typeNodeSelected(int)));
 
   aPythonLayout->addWidget(aAddBox2);
@@ -168,18 +174,18 @@ SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
   myStackWidget = new QWidgetStack(aPythonPane);
 
   // other pane
-  myScriptPane = new SUPERVGUI_PythonEditPane(myStackWidget);
+  myScriptPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
   myOtherId = myStackWidget->addWidget(myScriptPane);
 
   // loop pane
   QTabWidget* aLoopTabPane = new QTabWidget(myStackWidget);
-  myInitPane = new SUPERVGUI_PythonEditPane(myStackWidget); 
+  myInitPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY ); 
   aLoopTabPane->addTab(myInitPane, "Init");
 
-  myMorePane = new SUPERVGUI_PythonEditPane(myStackWidget);
+  myMorePane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
   aLoopTabPane->addTab(myMorePane, "More");
 
-  myNextPane = new SUPERVGUI_PythonEditPane(myStackWidget);
+  myNextPane = new SUPERVGUI_PythonEditPane( myStackWidget, true, myX, myY );
   aLoopTabPane->addTab(myNextPane, "Next");
   myLoopId = myStackWidget->addWidget(aLoopTabPane);
 
@@ -194,6 +200,43 @@ SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
 
   myTabPane->addTab(aPythonPane, tr("INLINE_PANE"));
 
+  // Create Tab for Macro node only if environmental variable ENABLE_MACRO_NODE is set
+  if ( getenv( "ENABLE_MACRO_NODE" ) != NULL ) {
+    QWidget* aMacroPane = new QWidget(myTabPane);
+    QVBoxLayout* aMacroLayout = new QVBoxLayout(aMacroPane, 0, 4);
+    aMacroLayout->setMargin(5);
+    aMacroLayout->setSpacing(10);
+    
+    QHBoxLayout* aLoadLayout = new QHBoxLayout(aMacroPane); //!!
+    aLoadLayout->addStretch();
+    
+    QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), aMacroPane);
+    connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadGraph()));
+
+    aLoadLayout->addWidget(aLoadBtn);
+
+    aMacroLayout->addLayout(aLoadLayout);
+    myMacroPane = new QListView(aMacroPane);
+    myMacroPane->addColumn(tr("COL_COMPONENTS"));
+    myMacroPane->addColumn(tr("COL_PORTTYPE"));
+    myMacroPane->addColumn(tr("COL_PORTWAY"));
+    myMacroPane->setColumnAlignment(1, AlignLeft);
+    myMacroPane->setColumnAlignment(2, AlignLeft);
+    myMacroPane->setColumnAlignment(3, AlignLeft);
+    myMacroPane->setSelectionMode(QListView::Extended);
+    myMacroPane->setRootIsDecorated(true);
+    aMacroLayout->addWidget(myMacroPane); //!!
+    
+    QPushButton* aAddBtn = new QPushButton(tr("TIT_ADDFNODE"), aMacroPane);
+    connect(aAddBtn, SIGNAL(clicked()), this, SLOT(addMacroNode()));
+    aAddBtn->setDefault(true); 
+    
+    aMacroLayout->addWidget(aAddBtn);
+
+    myTabPane->addTab(aMacroPane, tr("MACRO_PANE"));
+  }
+  
   aMainLayout->addWidget(myTabPane);
 
   // Close button
@@ -213,6 +256,23 @@ SUPERVGUI_Service::SUPERVGUI_Service(SALOME_NamingService* ns):
 }
 
 
+char* getDataStreamParameterName(int aType)
+{
+  switch(aType) {
+  case 1:
+    return "integer";
+  case 2:
+    return "float";
+  case 3:
+    return "double";
+  case 4:
+    return "string";
+  case 6:
+    return "boolean";
+  default:
+    return "unknown";
+  }
+}
 
 void SUPERVGUI_Service::initialise() {
   CORBA::Object_ptr obj  = naming->Resolve("/Kernel/ModulCatalog");
@@ -223,20 +283,19 @@ void SUPERVGUI_Service::initialise() {
     return;
   }
   
-  QAD_ResourceMgr* aResMgr = QAD_Desktop::createResourceManager();
+  SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
 
   SALOME_ModuleCatalog::ListOfComponents_var lComponents = (*aModuleCatalog)->GetComponentList();
   long nbComp = lComponents->length();
   for (int i=0; i<nbComp; i++) {
     SALOME_ModuleCatalog::Acomponent_ptr C = (*aModuleCatalog)->GetComponent((char *)lComponents[i]);
-    QListViewItem* myComponentItem = new QListViewItem(components, (char*)lComponents[i]);
+    QListViewItem* myComponentItem = new QListViewItem(components, (char*)C->componentusername());
     myComponentItem->setSelectable(false);
     QString aIconName = C->component_icone();
     if (!aIconName.isEmpty()) {
-      QString resDir = aResMgr->findFile(aIconName, C->componentname()) ;
-      if (resDir) {
-       resDir = QAD_Tools::addSlash(resDir);
-       QPixmap aIcone(resDir + aIconName);
+      QString resFilePath = aResMgr->path(aResMgr->resSection(), C->componentname(), aIconName) ;
+      if ( resFilePath ) {
+       QPixmap aIcone(resFilePath);
        QIconSet aIconSet(aIcone);
        myComponentItem->setPixmap(0, aIconSet.pixmap(QIconSet::Small, QIconSet::Normal));
       } else {
@@ -258,19 +317,39 @@ void SUPERVGUI_Service::initialise() {
        SALOME_ModuleCatalog::Service* Service = &(Interface->interfaceservicelist[k]);
        QListViewItem* myServiceItem = new QListViewItem(myInterfaceItem, (char*)Service->ServiceName);
        myServiceItem->setSelectable(true);
-       components->ensureItemVisible(myServiceItem);
+       //components->ensureItemVisible(myServiceItem);
        
        long nbPortsOut = Service->ServiceoutParameter.length();
        for (int m=0; m<nbPortsOut; m++) {
          SALOME_ModuleCatalog::ServicesParameter* PortOut = &(Service->ServiceoutParameter[m]);
-         QListViewItem* myPortOutItem = new QListViewItem(myServiceItem, (char*)PortOut->Parametername, (char*)PortOut->Parametertype, "Out");
+         QListViewItem* myPortOutItem = 
+           new QListViewItem(myServiceItem, (char*)PortOut->Parametername, (char*)PortOut->Parametertype, "Out");
+         myPortOutItem->setSelectable(false);
+       }
+
+       long nbStreamPortsOut = Service->ServiceoutDataStreamParameter.length();
+       for (int m=0; m<nbStreamPortsOut; m++) {
+         SALOME_ModuleCatalog::ServicesDataStreamParameter* PortOut = &(Service->ServiceoutDataStreamParameter[m]);
+         QListViewItem* myPortOutItem = 
+           new QListViewItem(myServiceItem, (char*)PortOut->Parametername, 
+                             getDataStreamParameterName(PortOut->Parametertype), "DataStream Out");
          myPortOutItem->setSelectable(false);
        }
        
        long nbPortsIn = Service->ServiceinParameter.length();
        for (int l=0; l<nbPortsIn; l++) {
          SALOME_ModuleCatalog::ServicesParameter* PortIn = &(Service->ServiceinParameter[l]);
-         QListViewItem* myPortInItem = new QListViewItem(myServiceItem, (char*)PortIn->Parametername, (char*)PortIn->Parametertype, "In");
+         QListViewItem* myPortInItem = 
+           new QListViewItem(myServiceItem, (char*)PortIn->Parametername, (char*)PortIn->Parametertype, "In");
+         myPortInItem->setSelectable(false);
+       }
+
+       long nbStreamPortsIn = Service->ServiceinDataStreamParameter.length();
+       for (int l=0; l<nbStreamPortsIn; l++) {
+         SALOME_ModuleCatalog::ServicesDataStreamParameter* PortIn = &(Service->ServiceinDataStreamParameter[l]);
+         QListViewItem* myPortInItem = 
+           new QListViewItem(myServiceItem, (char*)PortIn->Parametername, 
+                             getDataStreamParameterName(PortIn->Parametertype), "DataStream In");
          myPortInItem->setSelectable(false);
        }
       }
@@ -282,18 +361,31 @@ void SUPERVGUI_Service::initialise() {
 
 SUPERVGUI_Service::~SUPERVGUI_Service() {
     Trace("SUPERVGUI_Service::~SUPERVGUI_Service")
+      if (myMFile) delete myMFile;
 }
 
 void SUPERVGUI_Service::addComputeNode() {
-  SUPERVGUI_Main* aMain = Supervision.getMain();
+  SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
+  CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
+  if ( !anApp ) return;
+  
+  SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
+  if ( !aSupMod ) {
+    MESSAGE("NULL Supervision module!");
+    return;
+  }
+
+  SUPERVGUI_Main* aMain = aSupMod->getMain();
   if (aMain==0) {
-    QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+    QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+  } else if (!aMain->isEditable()) {
+    QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));     
   } else {
     CORBA::Object_ptr obj  = naming->Resolve("/Kernel/ModulCatalog");
     SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
     *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
     if (CORBA::is_nil(*aModuleCatalog)) {
-      QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
+      QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
     } else {
       QListViewItem*        item;
       bool                  b = false;
@@ -304,42 +396,53 @@ void SUPERVGUI_Service::addComputeNode() {
          const char* service   = item->text(0).latin1();
          const char* interface = item->parent()->text(0).latin1();
          const char* component = item->parent()->parent()->text(0).latin1();
-         SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(component);
-         if (myComponent==NULL) {
-           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
-         } else {
+         SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(anApp->moduleName(component));
+         if ( myComponent == NULL ) {
+           QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
+         } 
+         else {
            const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
-           b  = true;
-           
-           SUPERV_CNode node = aMain->getDataflow()->CNode(*myService);
-           if (CORBA::is_nil(node)) {
-             QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));   
+           SUPERV_CNode aNode = aMain->getDataflow()->CNode(*myService);
+           if ( CORBA::is_nil( aNode ) ) {
+             QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));    
              return;
            }
-           node->Coords(myX, myY);
-           myX += NODE_DX;
-           myY += NODE_DY;
-           aMain->addComputeNode(SUPERV::CNode::_narrow(node));
+
+           SUPERV::INode_var aDummyEndNode;
+           addNode( aNode, aDummyEndNode, myX, myY );
+           b = true; // at least one node was added
          }
        }
       }
-      if (!b) {
-       QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NONODE_TOADD"));
+      if ( !b ) {
+       QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
       }
     }
   }
 }
 
 void SUPERVGUI_Service::addFactoryNode() {
-  SUPERVGUI_Main* aMain = Supervision.getMain();
+  SUIT_Desktop* aDesktop = SUIT_Session::session()->activeApplication()->desktop();
+  CAM_Application* anApp = ( CAM_Application* )(SUIT_Session::session()->activeApplication());
+  if ( !anApp ) return;
+
+  SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
+  if ( !aSupMod ) {
+    MESSAGE("NULL Supervision module!");
+    return;
+  }
+
+  SUPERVGUI_Main* aMain = aSupMod->getMain();
   if (aMain==0) {
-    QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+    QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+  } else if (!aMain->isEditable()) {
+    QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));     
   } else {
     CORBA::Object_ptr obj  = naming->Resolve("/Kernel/ModulCatalog");
     SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
     *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
     if (CORBA::is_nil(*aModuleCatalog)) {
-      QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
+      QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
     } else {
       QListViewItem*        item;
       bool                  b = false;
@@ -349,28 +452,40 @@ void SUPERVGUI_Service::addFactoryNode() {
        if (item->isSelected()) {
          const char* service   = item->text(0).latin1();
          const char* interface = item->parent()->text(0).latin1();
-         const char* component = item->parent()->parent()->text(0).latin1();
-         SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(component);
-         if (myComponent==NULL) {
-           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
-         } else {
-           const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
-           b  = true;
-           
-           SUPERV_FNode node = aMain->getDataflow()->FNode(component, interface, *myService);
-           if (CORBA::is_nil(node)) {
-             QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));   
-             return;
+         //const char* component = anApp->moduleName(item->parent()->parent()->text(0).latin1());
+         if ( aSupMod->getInterfaceNameMap().contains(item->parent()->text(0)) ) {
+           const char* component = aSupMod->getInterfaceNameMap().find(item->parent()->text(0)).data();
+
+           SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(component);
+           if (myComponent==NULL) {
+             QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
+           } 
+           else {
+             const SALOME_ModuleCatalog::Service* myService = myComponent->GetService(interface, service);
+             SUPERV_CNode aNode;
+             if ( myService->TypeOfNode == 0 ) { // ComputeNode
+               aNode = aMain->getDataflow()->CNode(*myService);
+               if (CORBA::is_nil( aNode ) ) {
+                 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
+                 return;
+               }
+             } 
+             else { // Factory Node
+               aNode = aMain->getDataflow()->FNode(component, interface, *myService);
+               if ( CORBA::is_nil( aNode ) ) {
+                 QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
+                 return;
+               }
+             }
+             SUPERV::INode_var aDummyEndNode;
+             addNode( aNode, aDummyEndNode, myX, myY );
+             b = true;
            }
-           node->Coords(myX, myY);
-           myX += NODE_DX;
-           myY += NODE_DY;
-           aMain->addComputeNode(SUPERV::CNode::_narrow(node));
          }
        }
       }
-      if (!b) {
-       QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NONODE_TOADD"));
+      if ( !b ) {
+       QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
       }
     }
   }
@@ -378,67 +493,73 @@ void SUPERVGUI_Service::addFactoryNode() {
 
 
 void SUPERVGUI_Service::addInlineNode() {
-  SUPERVGUI_Main* aMain = Supervision.getMain();
+  SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
+  if ( !aSupMod ) {
+    MESSAGE("NULL Supervision module!");
+    return;
+  }
+
+  SUPERVGUI_Main* aMain = aSupMod->getMain();
   if (aMain==0) {
-    QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
-  } else {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+  } 
+  else if (!aMain->isEditable()) {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));      
+  } 
+  else {
     int aSel = myTypeCombo->currentItem();
     switch (aSel) {
     case 0: // Computation
-      if (myScriptPane->isDefined()) { 
-       SUPERV_INode aNode = aMain->getDataflow()->INode(myScriptPane->getFuncName().latin1(), 
-                                                        (myScriptPane->getFunction()).in());
+      {        
+       SUPERV_CNode aNode = 
+         aMain->getDataflow()->INode(myScriptPane->getFuncName().isEmpty() ? "" : myScriptPane->getFuncName().latin1(), 
+                                     (myScriptPane->getFunction()).in());
        if (CORBA::is_nil(aNode)) {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aNode->Coords(myX, myY);
-       myX += NODE_DX;
-       myY += NODE_DY;
-       aMain->addComputeNode(SUPERV::CNode::_narrow(aNode));
+       SUPERV::INode_var aDummyEndNode;
+       addNode( aNode, aDummyEndNode, myX, myY );
       }
       break;
       
     case 1: // Switch
-      if (myScriptPane->isDefined()) {
+      {
        SUPERV_INode aEndNode;
-       SUPERV_SNode aStartNode = aMain->getDataflow()->SNode(myScriptPane->getFuncName().latin1(),
-                                                             (myScriptPane->getFunction()).in(),
-                                                             aEndNode);
+       SUPERV_CNode aStartNode = 
+         aMain->getDataflow()->SNode(myScriptPane->getFuncName().isEmpty() ? "" : myScriptPane->getFuncName().latin1(),
+                                     (myScriptPane->getFunction()).in(),
+                                     aEndNode);
        if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aStartNode->Coords(myX, myY);
-       aEndNode->Coords(myX + LABEL_WIDTH*2, myY);
-       myX += NODE_DX;
-       myY += NODE_DY;
-       aMain->addControlNode(SUPERV::CNode::_narrow(aStartNode), SUPERV::CNode::_narrow(aEndNode), true);
+       addNode( aStartNode, aEndNode, myX, myY );
       }
       break;
       
     case 2: // Loop
       {
        SUPERV_INode aEndNode;
-       SUPERV_LNode aStartNode = aMain->getDataflow()->LNode(myInitPane->getFuncName().latin1(), (myInitPane->getFunction()).in(),
-                                                             myMorePane->getFuncName().latin1(), (myMorePane->getFunction()).in(),
-                                                             myNextPane->getFuncName().latin1(), (myNextPane->getFunction()).in(),
-                                                             aEndNode);
+       SUPERV_CNode aStartNode = 
+         aMain->getDataflow()->LNode(myInitPane->getFuncName().isEmpty() ? "" : myInitPane->getFuncName().latin1(), 
+                                     (myInitPane->getFunction()).in(),
+                                     myMorePane->getFuncName().isEmpty() ? "" : myMorePane->getFuncName().latin1(), 
+                                     (myMorePane->getFunction()).in(),
+                                     myNextPane->getFuncName().isEmpty() ? "" : myNextPane->getFuncName().latin1(), 
+                                     (myNextPane->getFunction()).in(),
+                                     aEndNode);
        if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aStartNode->Coords(myX, myY);
-       aEndNode->Coords(myX + LABEL_WIDTH*2, myY);
-       myX += NODE_DX;
-       myY += NODE_DY;
-       aMain->addControlNode(SUPERV::CNode::_narrow(aStartNode), SUPERV::CNode::_narrow(aEndNode), true);
+       addNode( aStartNode, aEndNode, myX, myY );
       }
       break;
       
     case 3: // GoTo
       {
-       SUPERV_GNode aGotoNode;
+       SUPERV_CNode aGotoNode;
        if (myScriptPane->isDefined()) 
          aGotoNode = aMain->getDataflow()->GNode(myScriptPane->getFuncName().latin1(), 
                                                  (myScriptPane->getFunction()).in(), "");
@@ -448,17 +569,97 @@ void SUPERVGUI_Service::addInlineNode() {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aGotoNode->Coords(myX, myY);
-       myX += NODE_DX;
-       myY += NODE_DY;
-       aMain->addGOTONode(SUPERV::GNode::_narrow(aGotoNode));
+       SUPERV::INode_var aDummyEndNode;
+       addNode( aGotoNode, aDummyEndNode, myX, myY );
       }
       break;
     }
   }
 }
 
+void SUPERVGUI_Service::addMacroNode() {
+  SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
+  if ( !aSupMod ) {
+    MESSAGE("NULL Supervision module!");
+    return;
+  }
+
+  SUPERVGUI_Main* aMain = aSupMod->getMain();
+  if (aMain==0) {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+  } 
+  else if (!aMain->isEditable()) {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));      
+  } 
+  else {
+    if ( myMFile ) {
+      SUPERV_CNode aNode;
+      if (aMain->getDataflow()->IsStreamGraph()) {
+       SUPERV_StreamGraph aSGraph = aMain->getDataflow()->ToStreamGraph();
+       if (!SUPERV_isNull(aSGraph)) 
+         aNode = aSGraph->StreamMNode(myMFile->name().latin1());
+       // TMP: while stream macro nodes doesn't impemented 
+       if (CORBA::is_nil(aNode)) {
+         aNode = aSGraph->MNode(myMFile->name().latin1());
+       }
+      }
+      else 
+       aNode = aMain->getDataflow()->MNode(myMFile->name().latin1());
+      if (CORBA::is_nil(aNode)) {
+       QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));         
+       return;
+      }
+
+      SUPERV::INode_var aDummyEndNode;
+      addNode( aNode, aDummyEndNode, myX, myY );
+    }
+    else {
+      QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("WARNING"), tr("MSG_NONODE_TOADD"));
+    }
+  }
+}
+
+void SUPERVGUI_Service::loadGraph() {
+       if ( getenv( "ENABLE_MACRO_NODE" ) == NULL )
+       // error! if ENABLE_MACRO_NODE is set - we should NOT get here by any means..
+       {
+               //MESSAGE("Error: ENABLE_MACRO_NODE is not set, but loadGraph() was called!");
+               return;
+       }
+
+  QString aFileName = SUIT_FileDlg::getFileName(SUIT_Session::session()->activeApplication()->desktop(),
+                                               "",
+                                               "*.xml",
+                                               tr("MSG_GRAPH_INSERT"),
+                                               true);
+  if (aFileName.isEmpty()) return;
+
+  myMacroPane->clear();
+
+  myMFile = new QFile(aFileName);
+  if (!myMFile->open(IO_ReadOnly)) {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), 
+                        tr("MSG_CANT_LOADSCRIPT"));
+    delete myMFile; myMFile = 0;
+    return;
+  }
+
+  QTextStream* aStream = new QTextStream(myMFile);
+  if (aStream->atEnd()) {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), 
+                        tr("MSG_EMTY_FILE"));
+    delete aStream;
+    myMFile->close();
+    delete myMFile; myMFile = 0;
+    return;
+  }
 
+  // read graph info
+  // temporary display only file name
+  QFileInfo anInfo(*myMFile);
+  QListViewItem* anItem = new QListViewItem(myMacroPane, anInfo.baseName());
+  anItem->setSelectable(true);
+}
 
 void SUPERVGUI_Service::typeNodeSelected(int theRow) {
   if (theRow == 2)
@@ -477,9 +678,16 @@ void SUPERVGUI_Service::choose() {
     
 
 void SUPERVGUI_Service::showEvent(QShowEvent* theEvent) {
-  SUPERVGUI_Main* aMain = Supervision.getMain();
+  SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
+  if ( !aSupMod ) {
+    MESSAGE("NULL Supervision module!");
+    return;
+  }
+
+  SUPERVGUI_Main* aMain = aSupMod->getMain();
   if (aMain && (!aMain->isArrayShown())) {
-    aMain->getGraph()->viewportToContents(0, 0, myX, myY);
+    aMain->getArrayView()->viewportToContents(0, 0, myX, myY);
+    //aMain->getGraph()->viewportToContents(0, 0, myX, myY);
   }
   QDialog::showEvent(theEvent);
 }
@@ -494,173 +702,271 @@ void SUPERVGUI_Service::tabChanged(QWidget* theWidget) {
 //*****************************************************
 //  Pane for Python script editing
 //*****************************************************
-SUPERVGUI_PythonEditPane::SUPERVGUI_PythonEditPane(QWidget* theParent) 
-  : QFrame(theParent),
-    myIStream(0)
+SUPERVGUI_PythonEditPane::SUPERVGUI_PythonEditPane( QWidget* theParent, const bool isNodeCreation, int& theX, int& theY ) 
+  : myIsWithLibrary( isNodeCreation ), 
+    QFrame( theParent ),
+    myX( theX ), myY( theY )
 {
-  QGridLayout* aEditLayout = new QGridLayout(this, 2, 4);
+  QGridLayout* aEditLayout = new QGridLayout( this, 2, 8, 0, 6 );
 
   // First row
+  if ( myIsWithLibrary ) {
+    QPushButton* aLibBtn = new QPushButton(tr("BUT_LIBRARY"), this);
+    connect(aLibBtn, SIGNAL(clicked()), this, SLOT(library()));
+    aEditLayout->addMultiCellWidget( aLibBtn, 0, 0, 1, 2 );
+  }
+
   QPushButton* aLoadBtn = new QPushButton(tr("BUT_LOAD"), this);
   connect(aLoadBtn, SIGNAL(clicked()), this, SLOT(loadFile()));
   
-  aEditLayout->addWidget(aLoadBtn, 0, 2);
+  aEditLayout->addMultiCellWidget( aLoadBtn, 0, 0, 3, 4 );
 
-  myNextBtn = new QPushButton(tr("BUT_NEXT"), this);
-  myNextBtn->setEnabled(false);
-  connect(myNextBtn, SIGNAL(clicked()), this, SLOT(readFunction()));
+  myFunctionsCombo = new QComboBox( this );
+  connect( myFunctionsCombo, SIGNAL( activated( int ) ), this, SLOT( readFunction( int ) ) );
   
-  aEditLayout->addWidget(myNextBtn, 0, 3);
+  aEditLayout->addMultiCellWidget( myFunctionsCombo, 0, 0, 5, 7 );
   
   //Second row
   myText = new QTextEdit(this);
-  myText->setWordWrap(QTextEdit::FixedColumnWidth);
-  myText->setWrapColumnOrWidth(80);
+  myText->setTextFormat( Qt::PlainText ); // NOT rich text, so text() returns plain text
+  myText->setWordWrap( QTextEdit::FixedColumnWidth );
+  myText->setWrapColumnOrWidth( 80 );
+  connect( myText, SIGNAL( returnPressed() ), this, SLOT( autoIndentLine() ) );
 
-  aEditLayout->addMultiCellWidget(myText, 1, 1, 0, 3);
+  aEditLayout->addMultiCellWidget( myText, 1, 1, 0, 7 );
+  //aEditLayout->setColStretch( 3, 1 ); // to allow myFunctionsCombo be larger when needed
+}
+
+/**
+ * Return a text between "def" and "("
+ * "def" must begin with position 0, which means that only global function definitions are possible
+ */ 
+QString getFunctionName( const QString& aLine ) {
+  int aDefPos = aLine.find("def");
+  if ( aDefPos == 0 ) { // only global function definitions!
+    int aStart = aLine.find(" ", aDefPos);
+    int aEnd = aLine.find("(", aStart);
+    QString aName = aLine.mid(aStart, (aEnd-aStart));
+    return aName.stripWhiteSpace();
+  }
+  return QString();
 }
    
+/**
+ * Searches for text beginning with "def" and ending with any meanful character at 
+ * beginning of line.  Starts searching with current position of given stream.
+ * Fills the myPyFunctions with strings corresponding to found fucntions.
+ */
+void SUPERVGUI_PythonEditPane::initPyFunctions( QTextStream& theStream ) {
+
+  if ( theStream.atEnd() )
+    return;
+
+  QString aPyFunction;
+  QString aLine = theStream.readLine(); 
+
+  while ( !theStream.atEnd() ) { // not EOF
+
+    // asv : 23.11.04 : fix for PAL6870 : skip empty lines in the beginning or  between functions
+    //       find("def)==0 -> analizing only global function definitions which start with 0 indentation
+    while ( !aLine.isNull() && aLine.find( "def" ) != 0 ) 
+      aLine = theStream.readLine();
+    
+    if ( !aLine.isNull() && aLine.find("def") == 0 ) { 
+      myFunctionsCombo->insertItem( getFunctionName( aLine ) ); // aLine now == function name 
+
+      aPyFunction += aLine;
+      aPyFunction += '\n'; 
+
+      // read function body
+      aLine = theStream.readLine();
+      // asv : 23.11.04 : added "|| aLine.isEmpty()" - fix for PAL6870. readLine() returns an empty
+      //       string for "\n" string, it trails \n caracter.  but we accept such lines..
+      // asv : 22.12.04 : aLine[0].isSpace() || aLine[0]=='#' -> line must begin with space or tab
+      //       (a normal code with indentation) or comment sign.
+      while ( !aLine.isNull() && ( aLine.isEmpty() || aLine[0].isSpace() || aLine[0] == '#' ) ) {
+       aPyFunction += aLine;
+       aPyFunction += '\n'; 
+       aLine = theStream.readLine();
+      }
+
+      myPyFunctions << aPyFunction;
+      aPyFunction.setLength( 0 );
+    }
+  }
+}
 
 /**
  * Load existing Python script
  */
 void SUPERVGUI_PythonEditPane::loadFile() {
-  QString aFileName = QAD_FileDlg::getFileName(QAD_Application::getDesktop(),
-                                              "",
-                                              "*.py",
-                                              tr("TIT_LOADSCRIPT"),
-                                              true);
+  QString aFileName = SUIT_FileDlg::getFileName(SUIT_Session::session()->activeApplication()->desktop(),
+                                               "",
+                                               "*.py",
+                                               tr("TIT_LOADSCRIPT"),
+                                               true);
   if (aFileName.isEmpty()) return;
 
-  myFile = new QFile(aFileName);
-  if (!myFile->open(IO_ReadOnly)) {
-    QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), 
+  QFile aFile( aFileName );
+  if (!aFile.open(IO_ReadOnly)) {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), 
                         tr("MSG_CANT_LOADSCRIPT"));
     return;
   }
-  myIStream = new QTextStream(myFile);
 
-  if (myIStream->atEnd()) {
-    QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), 
-                        tr("MSG_EMTY_FILE"));
-    myNextBtn->setEnabled(false);
-    delete myIStream;
-    myIStream = 0;
-    myFile->close();
-    delete myFile;
+  myPyFunctions.clear();
+  myFunctionsCombo->clear();
+  myText->clear();
+
+  QTextStream aFileReader(&aFile);
+  if ( aFileReader.atEnd() ) {
+    QMessageBox::warning(SUIT_Session::session()->activeApplication()->desktop(), tr("ERROR"), tr("MSG_EMTY_FILE"));
+    aFile.close();
     return;
   }
-  myNextBtn->setEnabled(true);
-  readFunction();
+
+  initPyFunctions( aFileReader );
+
+  if ( myPyFunctions.size() )
+    readFunction( 0 );
 }
   
-
 /**
  * Finds and Reads a function from current position in the opened file
+ * asv : Comment above is old! Present model: just take an already read string = PyFunction
+ * from the list which is filled in loadFile().
  */
-void SUPERVGUI_PythonEditPane::readFunction() {
-  if (!myIStream) return;
-
-  while (!myIStream->atEnd()) {
-    QString aLine = myIStream->readLine();
-    if (aLine.isNull()) return;
-
-    // find first function
-    int aDefPos = aLine.find("def");
-    if (aDefPos == 0) { // only not a class members
-      myText->clear();
-      // find name
-      /*int aStart = aLine.find(" ", aDefPos);
-      int aEnd = aLine.find("(", aStart);
-      QString aName = aLine.mid(aStart, (aEnd-aStart));
-      aName = aName.stripWhiteSpace();
-      myNameEdt->setText(aName);*/
-      
-      // find input params
-      /*aStart = aEnd+1;
-      aEnd = aLine.find(")", aStart);
-      QString aParams = aLine.mid(aStart, (aEnd-aStart));
-      aParams = aParams.stripWhiteSpace();
-      myParamEdt->setText(aParams);*/
-
-      myText->append(aLine);
-      // read body
-      QString aBodyLine = myIStream->readLine();
-      while ((!aBodyLine.isNull()) && aBodyLine[0].isSpace()) {
-       myText->append(aBodyLine);
-       aBodyLine = myIStream->readLine();
-      }
-      return;
-    }
-  }
-  QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), 
-                        tr("MSG_NOMORE_FUNCTIONS"));
-  delete myIStream;
-  myIStream = 0;
-  myNextBtn->setEnabled(false);
-  myFile->close();
-  delete myFile;
+void SUPERVGUI_PythonEditPane::readFunction( int i ) {
+  myText->clear();
+  if ( i != -1 && myPyFunctions.size() && myPyFunctions.size() > i )
+    myText->append( myPyFunctions[ i ] );
+
+  // asv : 30.11.04 : 2.7 - Inline node function editor improvement
+  // 2.7.1 - set focus to editor widget on editor window opening
+  // 2.7.2 - scroll to the beginning of function on editor window opening
+  myText->setFocus();
+  myText->ensureVisible( 0,0 );
 }
 
-
+/**
+ * Returns the text after "def" and before "(" -- first defined function name
+ */
 QString SUPERVGUI_PythonEditPane::getFuncName() {
-  QString aName("");
   for (int i=0; i < myText->paragraphs(); i++) {
-    QString aLine = myText->text(i);
-    int aDefPos = aLine.find("def");
-    if (aDefPos == 0) {
-      int aStart = aLine.find(" ", aDefPos);
-      int aEnd = aLine.find("(", aStart);
-      QString aName = aLine.mid(aStart, (aEnd-aStart));
-      return aName.stripWhiteSpace();
-    }
+    QString aName = getFunctionName( myText->text(i) );
+    if ( !aName.isEmpty() )
+      return aName;
   }
-  return aName;
+  return QString();
 }
 
-
+/**
+ * Returns the contents of the myText widget without trailing spacing 
+ */
 SUPERV_Strings SUPERVGUI_PythonEditPane::getFunction() {
   SUPERV_Strings aStrings = new SUPERV::ListOfStrings();
   aStrings->length(myText->paragraphs());
   for (int i=0; i < myText->paragraphs(); i++) {
-    aStrings[i] = CORBA::string_dup(myText->text(i).latin1());
+    QString aLine = myText->text(i);
+    // asv : 30.11.04 - why do we have to remove trailing spaces??  
+    // it's user's responsibility to enter correct Python code, we don't do anything with it.
+    // if (..) -- initial, while(..) -- my improvement, but also commented out -- needless.
+    //if (!aLine.right(1).compare(" ")) // replaced with the line below -- loop
+    //while (aLine.at(aLine.length()-1).isSpace()) // remove trailing spaces
+    //  aLine = aLine.remove(aLine.length()-1,1);
+    aStrings[i] = CORBA::string_dup(aLine.latin1());
   }
   return aStrings._retn();
 }
 
 
 void SUPERVGUI_PythonEditPane::setFunction(SUPERV_Strings theStr) {
-  int aLen = theStr->length();
-  for (int i=0; i < aLen; i++)
+  myText->clear();
+  for ( int i=0, aLen = theStr->length(); i < aLen; i++ )
     myText->append(QString(theStr[i]));
+
+  // asv : 30.11.04 : 2.7 - Inline node function editor improvement
+  // 2.7.1 - set focus to editor widget on editor window opening
+  // 2.7.2 - scroll to the beginning of function on editor window opening
+  myText->setFocus();
+  myText->ensureVisible( 0,0 );
 }
 
+/**
+ * Automatic indentation rule: if a previous line ended with 
+ * ':', then add N additional spaces in the current line.  If no ':' found, then 
+ * the same amount of spaces as in the previous line is added. Connected to 
+ * "returnPressed" signal of myText text edit.
+*/
+void SUPERVGUI_PythonEditPane::autoIndentLine() {
+  const int N = 4; // width of indentation "tab"
+  if ( myText && myText->paragraphs() ) {
+
+    // get current cursor position and previous line (the one to be analized) 
+    int pos, para, i;
+    QString spacesStr;
+    myText->getCursorPosition( &para, &pos ); // pos==0, beginning of line
+    if ( myText->paragraphLength(para-1) > 0 ) { // mkr : IPAL9817
+      QString line = myText->text( para-1 ); // previous paragraph line
+
+      // construct a string containing all leading space characters of previous line (tabs, etc.)
+      i = -1;
+      while ( line[++i].isSpace() ) // append all isSpace() characters at beginning of line to spacesStr
+       spacesStr += line[i];
+      
+      // if ':' was found -- add more spaces to spacesStr
+      line = line.stripWhiteSpace();
+      if ( line[ line.length()-1 ] == ':' ) {
+       i = 0;
+       while ( i++ < N ) 
+         spacesStr += ' ';
+      }
+    }
 
+    // ok, append spacesStr at the beginning of the current line = make indentation
+    myText->insertAt( spacesStr, para, pos );
+    myText->setCursorPosition( para, pos+spacesStr.length() );
+  }
+}
+
+/**
+ * Create a node by loading it from an external XML library file
+ * This slot opens a dialog box which then "lives" by itself..
+ */
+void SUPERVGUI_PythonEditPane::library() {
+  // if CanImport() returns false, it displays an error message box, so there is no need to
+  // display such message here ("library file not found", etc.).
+  if ( SUPERVGUI_Library::getLibrary()->CanImport() ) {
+    SUPERVGUI_LibDlg* aDlg = new SUPERVGUI_LibDlg( this, myX, myY );
+    aDlg->exec();
+  }
+}
 
 /*!
  * Edit Python dialog
  */
-SUPERVGUI_EditPythonDlg::SUPERVGUI_EditPythonDlg(bool isLoop)
-  :QDialog(QAD_Application::getDesktop(), 0, true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu)
+SUPERVGUI_EditPythonDlg::SUPERVGUI_EditPythonDlg( bool isLoop )
+  :QDialog(SUIT_Session::session()->activeApplication()->desktop(), 0, true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu) 
 {
   setSizeGripEnabled( true );
   setCaption(tr("TIT_FUNC_PYTHON"));
   resize( 500, 250 );
   QVBoxLayout* aMainLayout = new QVBoxLayout(this, 7, 4);
+  int a,b; // dummies for PythonEditPane, not used, since library = false and myX, myY are not used in PythonEditPane
   if (isLoop) {
     QTabWidget* aLoopTabPane = new QTabWidget(this);
-    myInitPane = new SUPERVGUI_PythonEditPane(this); 
+    myInitPane = new SUPERVGUI_PythonEditPane( this, false, a, b ); // library == false, since no creation of a node is needed here
     aLoopTabPane->addTab(myInitPane, "Init");
     
-    myMorePane = new SUPERVGUI_PythonEditPane(this);
+    myMorePane = new SUPERVGUI_PythonEditPane( this, false, a, b );
     aLoopTabPane->addTab(myMorePane, "More");
     
-    myNextPane = new SUPERVGUI_PythonEditPane(this);
+    myNextPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
     aLoopTabPane->addTab(myNextPane, "Next");
 
     aMainLayout->addWidget(aLoopTabPane);    
   } else {
-    myEditPane = new SUPERVGUI_PythonEditPane(this);
+    myEditPane = new SUPERVGUI_PythonEditPane( this, false, a, b );
     aMainLayout->addWidget(myEditPane);
   }
   QGroupBox* aBtnBox = new QGroupBox( this );
@@ -671,7 +977,7 @@ SUPERVGUI_EditPythonDlg::SUPERVGUI_EditPythonDlg(bool isLoop)
   aBtnLayout->setSpacing( 6 ); aBtnLayout->setMargin( 11 );
   
   QPushButton* aOKBtn = new QPushButton( tr( "BUT_OK" ), aBtnBox );
-  connect( aOKBtn, SIGNAL( clicked() ), this, SLOT( accept() ) );
+  connect( aOKBtn, SIGNAL( clicked() ), this, SLOT( clickOnOk() ) );
   aBtnLayout->addWidget( aOKBtn );
 
   aBtnLayout->addStretch();
@@ -682,3 +988,61 @@ SUPERVGUI_EditPythonDlg::SUPERVGUI_EditPythonDlg(bool isLoop)
 
   aMainLayout->addWidget(aBtnBox);
 }
+
+// mkr : IPAL9817 : to avoid a SIGSEGV when INode_Impl::SetPyFunction(...)
+//                  will call with null python function name
+void SUPERVGUI_EditPythonDlg::clickOnOk()
+{
+  if ( getFuncName().isEmpty() )
+    QMessageBox::warning( SUIT_Session::session()->activeApplication()->desktop(), tr( "ERROR" ), tr( "MSG_INCORRECT_INDENT" ) );
+  else  
+    accept();
+}
+
+/**
+ * Do the following actions for newly created Engine's CNode:
+ * 1. Create a presentation for it (CanvasNode)
+ * 2. Place the CanvasNode to the current top-left corner or the current viewport
+ * 3. Increment the coordinates of the next CanvasNode (new nodes are "cascaded" when several of them are created at once)
+ * PS theEndNode is passed only for Loop and Switch nodes (EndLoop and EndSwitch)
+ */ 
+void SUPERVGUI_Service::addNode( SUPERV::CNode_var theNode, SUPERV::INode_var theEndNode, int& theX, int& theY )  {
+  SUPERVGUI* aSupMod = SUPERVGUI::Supervision();
+  if ( !aSupMod ) {
+    MESSAGE("NULL Supervision module!");
+    return;
+  }
+  
+  SUPERVGUI_Main* aMain = aSupMod->getMain();
+
+  if ( !CORBA::is_nil( theNode ) && aMain ) {
+    
+    aMain->Editing(); // PAL6170: GUI->Engine: setting "Editing" flag, why here? -> PAL7960
+
+    int cx, cy;   //to appear a new node in the top-left corner of the current viewport
+
+    //2.8 point of improvements: Adding node to graph window with taking into account zoom factor
+    QWMatrix aWM = aMain->getCanvasView()->worldMatrix();
+    aMain->getCanvasView()->viewportToContents(theX, theY, cx, cy);
+
+    //2.8 point of improvements:
+    cx = (int)((double)cx/aWM.m11());
+    cy = (int)((double)cy/aWM.m22());
+    theNode->Coords(cx, cy);
+    if ( !CORBA::is_nil( theEndNode ) )
+      theEndNode->Coords(cx + LABEL_WIDTH*2, cy);
+    theX += (int)(NODE_DX*aWM.m11());
+    theY += (int)(NODE_DY*aWM.m22());
+
+    if ( theNode->IsGOTO() )
+      aMain->addGOTONode( theNode );
+    else if ( theNode->IsMacro() )
+      aMain->addMacroNode( theNode );
+    else if ( theNode->IsLoop() || theNode->IsSwitch() )
+      aMain->addControlNode( theNode, SUPERV::CNode::_narrow( theEndNode ), true );
+    else
+      aMain->addComputeNode( theNode );
+    aSupMod->nullifyInitialVF();
+  }
+}
+