Salome HOME
Bug fix: don't set "Loading" state for MacroNodes in InitialState() function (called...
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Service.cxx
index 230e55161527c12c0705d969a5becc797ac941eb..6213aa42ed97c30cc6dc590b4cafcdb612a3eab1 100644 (file)
@@ -1,11 +1,31 @@
-using namespace std;
-//  File      : SUPERVGUI_Service.cxx
-//  Created   : 7 / 11 / 2001
-//  Author    : Francis KLOSS
-//  Project   : SALOME
-//  Module    : SUPERVGUI
-//  Copyright : CEA
+//  SUPERV SUPERVGUI : GUI for Supervisor component
+//
+//  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
+//
+//
+//
+//  File   : SUPERVGUI_Service.cxx
+//  Author : Francis KLOSS
+//  Module : SUPERV
 
+using namespace std;
 #include "SUPERVGUI_Service.h"
 #include "SUPERVGUI_Main.h"
 #include "SUPERVGUI.h"
@@ -15,6 +35,7 @@ using namespace std;
 #include "SALOME_NamingService.hxx"
 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
 #include <qlayout.h>
+#include <qhbox.h>
 #include <qtextstream.h>
 
 
@@ -74,7 +95,7 @@ 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)
+    naming(ns), myMFile(0)
 {
   setSizeGripEnabled( true );
   setCaption(tr("TIT_SERVICES"));
@@ -107,14 +128,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())); //!!
+//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"));
@@ -130,14 +153,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);
@@ -172,6 +194,44 @@ 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
@@ -191,6 +251,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");
@@ -207,7 +284,7 @@ void SUPERVGUI_Service::initialise() {
   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()) {
@@ -241,14 +318,34 @@ void SUPERVGUI_Service::initialise() {
        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);
        }
       }
@@ -260,18 +357,22 @@ void SUPERVGUI_Service::initialise() {
 
 SUPERVGUI_Service::~SUPERVGUI_Service() {
     Trace("SUPERVGUI_Service::~SUPERVGUI_Service")
+      if (myMFile) delete myMFile;
 }
 
 void SUPERVGUI_Service::addComputeNode() {
+  QAD_Desktop* aDesktop = QAD_Application::getDesktop();
   SUPERVGUI_Main* aMain = Supervision.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;
@@ -282,19 +383,22 @@ 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);
+         SALOME_ModuleCatalog::Acomponent_ptr myComponent = (*aModuleCatalog)->GetComponent(aDesktop->getComponentName(component));
          if (myComponent==NULL) {
-           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CHOOSE_SERVICE"));
+           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"));   
+             QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));    
              return;
            }
-           node->Coords(myX, myY);
+           //to appear a new node in the top-left corner of the current viewport
+           int cx, cy;
+           aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+           node->Coords(cx, cy);
            myX += NODE_DX;
            myY += NODE_DY;
            aMain->addComputeNode(SUPERV::CNode::_narrow(node));
@@ -302,22 +406,25 @@ void SUPERVGUI_Service::addComputeNode() {
        }
       }
       if (!b) {
-       QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NONODE_TOADD"));
+       QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
       }
     }
   }
 }
 
 void SUPERVGUI_Service::addFactoryNode() {
+  QAD_Desktop* aDesktop = QAD_Application::getDesktop();
   SUPERVGUI_Main* aMain = Supervision.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;
@@ -327,28 +434,58 @@ 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();
+         const char* component = aDesktop->getComponentName(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"));
+           QMessageBox::warning(aDesktop, 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;
+           MESSAGE ( " myService->TypeOfNode == " << myService->TypeOfNode ) 
+
+           int cx, cy;
+           if ( myService->TypeOfNode == 0 ) { // ComputeNode
+             SUPERV_CNode node = aMain->getDataflow()->CNode(*myService);
+             if (CORBA::is_nil(node)) {
+               QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));          
+               return;
+             }
+             //to appear a new node in the top-left corner of the current viewport
+             aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+             node->Coords(cx, cy);
+             myX += NODE_DX;
+             myY += NODE_DY;
+             aMain->addComputeNode(SUPERV::CNode::_narrow(node));
+           } else { // Factory Node
+             SUPERV_FNode node = aMain->getDataflow()->FNode(component, interface, *myService);
+             if (CORBA::is_nil(node)) {
+               QMessageBox::warning(aDesktop, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));          
+               return;
+             }
+             //to appear a new node in the top-left corner of the current viewport
+             aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+             node->Coords(cx, cy);
+             myX += NODE_DX;
+             myY += NODE_DY;
+             aMain->addComputeNode(SUPERV::CNode::_narrow(node));
+             
            }
-           node->Coords(myX, myY);
-           myX += NODE_DX;
-           myY += NODE_DY;
-           aMain->addComputeNode(SUPERV::CNode::_narrow(node));
-         }
+
+//         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;
+//         }
+//         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"));
+       QMessageBox::warning(aDesktop, tr("WARNING"), tr("MSG_NONODE_TOADD"));
       }
     }
   }
@@ -359,8 +496,11 @@ void SUPERVGUI_Service::addInlineNode() {
   SUPERVGUI_Main* aMain = Supervision.getMain();
   if (aMain==0) {
     QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+  } else if (!aMain->isEditable()) {
+    QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
   } else {
     int aSel = myTypeCombo->currentItem();
+    int cx, cy;
     switch (aSel) {
     case 0: // Computation
       if (myScriptPane->isDefined()) { 
@@ -370,7 +510,9 @@ void SUPERVGUI_Service::addInlineNode() {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aNode->Coords(myX, myY);
+       //to appear a new node in the top-left corner of the current viewport
+       aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+       aNode->Coords(cx, cy);
        myX += NODE_DX;
        myY += NODE_DY;
        aMain->addComputeNode(SUPERV::CNode::_narrow(aNode));
@@ -387,11 +529,13 @@ void SUPERVGUI_Service::addInlineNode() {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aStartNode->Coords(myX, myY);
-       aEndNode->Coords(myX + LABEL_WIDTH*2, myY);
+       //to appear a new node in the top-left corner of the current viewport
+       aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+       aStartNode->Coords(cx, cy);
+       aEndNode->Coords(cx + LABEL_WIDTH*2, cy);
        myX += NODE_DX;
        myY += NODE_DY;
-       aMain->addControlNode(SUPERV::CNode::_narrow(aStartNode), SUPERV::CNode::_narrow(aEndNode));
+       aMain->addControlNode(SUPERV::CNode::_narrow(aStartNode), SUPERV::CNode::_narrow(aEndNode), true);
       }
       break;
       
@@ -406,11 +550,13 @@ void SUPERVGUI_Service::addInlineNode() {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aStartNode->Coords(myX, myY);
-       aEndNode->Coords(myX + LABEL_WIDTH*2, myY);
+       //to appear a new node in the top-left corner of the current viewport
+       aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+       aStartNode->Coords(cx, cy);
+       aEndNode->Coords(cx + LABEL_WIDTH*2, cy);
        myX += NODE_DX;
        myY += NODE_DY;
-       aMain->addControlNode(SUPERV::CNode::_narrow(aStartNode), SUPERV::CNode::_narrow(aEndNode));
+       aMain->addControlNode(SUPERV::CNode::_narrow(aStartNode), SUPERV::CNode::_narrow(aEndNode), true);
       }
       break;
       
@@ -426,7 +572,9 @@ void SUPERVGUI_Service::addInlineNode() {
          QMessageBox::warning(0, tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));       
          return;
        }
-       aGotoNode->Coords(myX, myY);
+       //to appear a new node in the top-left corner of the current viewport
+       aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+       aGotoNode->Coords(cx, cy);
        myX += NODE_DX;
        myY += NODE_DY;
        aMain->addGOTONode(SUPERV::GNode::_narrow(aGotoNode));
@@ -436,7 +584,85 @@ void SUPERVGUI_Service::addInlineNode() {
   }
 }
 
+void SUPERVGUI_Service::addMacroNode() {
+  SUPERVGUI_Main* aMain = Supervision.getMain();
+  if (aMain==0) {
+    QMessageBox::warning(QAD_Application::getDesktop(), tr("WARNING"), tr("MSG_NO_SUPERVISION_WINDOW"));
+  } else if (!aMain->isEditable()) {
+    QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));        
+  } else {
+    if (myMFile) {
+      SUPERV_Graph 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;
+      }
+      //to appear a new node in the top-left corner of the current viewport
+      int cx, cy;
+      aMain->getCanvasView()->viewportToContents(myX, myY, cx, cy);
+      aNode->Coords(cx, cy);
+      myX += NODE_DX;
+      myY += NODE_DY;
+      aMain->addMacroNode(SUPERV::CNode::_narrow(aNode));
+    }
+    else {
+      QMessageBox::warning(QAD_Application::getDesktop(), 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 = QAD_FileDlg::getFileName(QAD_Application::getDesktop(),
+                                              "",
+                                              "*.xml",
+                                              tr("MSG_GRAPH_INSERT"),
+                                              true);
+  if (aFileName.isEmpty()) return;
+
+  myMacroPane->clear();
 
+  myMFile = new QFile(aFileName);
+  if (!myMFile->open(IO_ReadOnly)) {
+    QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), 
+                        tr("MSG_CANT_LOADSCRIPT"));
+    delete myMFile; myMFile = 0;
+    return;
+  }
+
+  QTextStream* aStream = new QTextStream(myMFile);
+  if (aStream->atEnd()) {
+    QMessageBox::warning(QAD_Application::getDesktop(), 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)
@@ -457,7 +683,8 @@ void SUPERVGUI_Service::choose() {
 void SUPERVGUI_Service::showEvent(QShowEvent* theEvent) {
   SUPERVGUI_Main* aMain = Supervision.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);
 }
@@ -473,8 +700,7 @@ void SUPERVGUI_Service::tabChanged(QWidget* theWidget) {
 //  Pane for Python script editing
 //*****************************************************
 SUPERVGUI_PythonEditPane::SUPERVGUI_PythonEditPane(QWidget* theParent) 
-  : QFrame(theParent),
-    myIStream(0)
+  : QFrame(theParent)
 {
   QGridLayout* aEditLayout = new QGridLayout(this, 2, 4);
 
@@ -498,6 +724,45 @@ SUPERVGUI_PythonEditPane::SUPERVGUI_PythonEditPane(QWidget* theParent)
   aEditLayout->addMultiCellWidget(myText, 1, 1, 0, 3);
 }
    
+/**
+ * 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 ) { 
+      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..
+      while ( !aLine.isNull() && ( aLine.isEmpty() || aLine[0].isSpace() ) ) {
+       aPyFunction += aLine;
+       aPyFunction += '\n'; 
+       aLine = theStream.readLine();
+      }
+
+      myPyFunctions << aPyFunction;
+      aPyFunction.setLength( 0 );
+    }
+  }
+}
 
 /**
  * Load existing Python script
@@ -510,77 +775,50 @@ void SUPERVGUI_PythonEditPane::loadFile() {
                                               true);
   if (aFileName.isEmpty()) return;
 
-  myFile = new QFile(aFileName);
-  if (!myFile->open(IO_ReadOnly)) {
+  QFile aFile( aFileName );
+  if (!aFile.open(IO_ReadOnly)) {
     QMessageBox::warning(QAD_Application::getDesktop(), 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();
+  myPyIndex = -1;
+  myNextBtn->setEnabled( false );
+  myText->clear();
+
+  QTextStream aFileReader(&aFile);
+  if ( aFileReader.atEnd() ) {
+    QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_EMTY_FILE"));
+    aFile.close();
     return;
   }
-  myNextBtn->setEnabled(true);
-  readFunction();
+
+  initPyFunctions( aFileReader );
+
+  if ( myPyFunctions.size() ) {
+    myNextBtn->setEnabled( true );
+    myPyIndex = 0;
+    readFunction();
+  }
 }
   
-
 /**
  * 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;
+  myText->clear();
+  if ( myPyIndex != -1 && myPyFunctions.size() && myPyFunctions.size() > myPyIndex )
+    myText->append( myPyFunctions[ myPyIndex++ ] );
+  if ( myPyFunctions.size() <= myPyIndex ) // last index was reached
+    myNextBtn->setEnabled( false );
 }
 
-
+/**
+ * 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++) {
@@ -596,12 +834,21 @@ QString SUPERVGUI_PythonEditPane::getFuncName() {
   return aName;
 }
 
-
+/**
+ * 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();
 }
@@ -611,6 +858,12 @@ void SUPERVGUI_PythonEditPane::setFunction(SUPERV_Strings theStr) {
   int aLen = theStr->length();
   for (int i=0; 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 );
 }