Salome HOME
Import and Export of InLine nodes to Library (external file) is implemented. This...
authorasv <asv@opencascade.com>
Tue, 28 Dec 2004 07:01:10 +0000 (07:01 +0000)
committerasv <asv@opencascade.com>
Tue, 28 Dec 2004 07:01:10 +0000 (07:01 +0000)
src/SUPERVGUI/SUPERVGUI_Library.cxx
src/SUPERVGUI/SUPERVGUI_Library.h

index 0972fd5716b4019cc134d351325349950a2e9490..f42463b100ae6587ba849eb32805b581496603eb 100644 (file)
@@ -27,6 +27,8 @@
 
 
 #include "SUPERVGUI_Library.h"
+#include "SUPERVGUI_Main.h"
+#include "SUPERVGUI.h"
 
 #include "QAD_MessageBox.h"
 #include "QAD_Application.h"
@@ -35,7 +37,6 @@
 #include <qlayout.h>
 #include <qgroupbox.h>
 #include <qpushbutton.h>
-#include <qdom.h>
 #include <qfile.h>
 
 using namespace std;
@@ -44,6 +45,8 @@ using namespace std;
 #define DOCTYPE "InLineNodesLibrary"         // XML DocType
 #define ROOT_ELEMENT "inlinenodeslibrary"    // XML Element and Attribute tags (many)
 #define NODE_ELEMENT "INode"
+#define NODE_NAME_ATT "Name"
+#define NODE_KIND_ATT "Kind"
 #define PORT_ELEMENT "Port"
 #define ES_PORT_ELEMENT "ESPort"
 #define PORT_INPUT_ATT "IsInput"
@@ -92,7 +95,7 @@ bool SUPERVGUI_Library::createLibFile() const {
       QDomDocument doc( DOCTYPE ); // create a simple XML stub
       doc.appendChild( doc.createElement( ROOT_ELEMENT ) ); // IMPORTANT: do not delete this root element
       QTextStream stream( &libFile );
-      stream << doc.toString();
+      doc.save( stream, 0 );
       libFile.close();
       return true;
     }
@@ -130,147 +133,420 @@ void saveStrings( QDomDocument doc, QDomElement element, const char* theNameAtt,
  * Export an InLine node to Library 
  */
 bool SUPERVGUI_Library::Export( SUPERV::INode_var theNode ) const {
-  if ( CORBA::is_nil( theNode ) ) {
-    QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_NIL_NODE" ), tr( "OK" ) );
-    return false; // null node
-  }
-
-  // open existing library file or create a new one and set some empty XML content
-  QFile libFile( GetLibraryFileName() );
-  if ( !libFile.exists() ) { // new library
-    if ( !createLibFile() )
-      return false; // error opening library file for writing.  MB was already displayed
-  }
+  try {
+    if ( CORBA::is_nil( theNode ) ) {
+      QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_NIL_NODE" ), tr( "OK" ) );
+      return false; // null node
+    }
 
-  // create the main XML document object
-  QString docName( DOCTYPE ) ;
-  QDomDocument doc( docName );
-  bool xmlOk = doc.setContent( &libFile );
-  if ( xmlOk )      
-    xmlOk = ( doc.elementsByTagName( ROOT_ELEMENT ).length() == 1 ); // find "root" element
-  QDomNode rootElement;
-  if ( xmlOk ) {
-    rootElement = doc.elementsByTagName( ROOT_ELEMENT ).item( 0 );
-    xmlOk = ( !rootElement.isNull() );
-  }
-  if ( !xmlOk ) {
-    const int toRecreate = QAD_MessageBox::error2( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), 
-                                                 tr( "MSG_ERROR_LIB_IS_RECREATE" ), tr( "BUT_YES" ), tr( "BUT_NO" ), 1, 0, 0 );
-    if ( toRecreate ) { // user selected to recreate a bad XML file
-      libFile.close(); // in case it was opened by doc.setContent()
+    // open existing library file or create a new one and set some empty XML content
+    QFile libFile( GetLibraryFileName() );
+    if ( !libFile.exists() ) { // new library
       if ( !createLibFile() )
        return false; // error opening library file for writing.  MB was already displayed
-      
-      // library file was successfully recreated. now re-set content, init rooElement. No checking - it MUST be OK.
-      libFile.setName( GetLibraryFileName() ); // IMPORTANT: re-read the file
-      doc.setContent( &libFile );
+    }
+
+    // create the main XML document object
+    QString docName( DOCTYPE ) ;
+    QDomDocument doc( docName );
+    bool xmlOk = doc.setContent( &libFile );
+    if ( xmlOk )      
+      xmlOk = ( doc.elementsByTagName( ROOT_ELEMENT ).length() == 1 ); // find "root" element
+    QDomNode rootElement;
+    if ( xmlOk ) {
       rootElement = doc.elementsByTagName( ROOT_ELEMENT ).item( 0 );
+      xmlOk = ( !rootElement.isNull() );
+    }
+    if ( !xmlOk ) {
+      const int toRecreate = QAD_MessageBox::error2( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), 
+                                                   tr( "MSG_ERROR_LIB_IS_RECREATE" ), tr( "BUT_YES" ), tr( "BUT_NO" ), 1, 0, 0 );
+      if ( toRecreate ) { // user selected to recreate a bad XML file
+       libFile.close(); // in case it was opened by doc.setContent()
+       if ( !createLibFile() )
+         return false; // error opening library file for writing.  MB was already displayed
+       
+       // library file was successfully recreated. now re-set content, init rooElement. No checking - it MUST be OK.
+       libFile.setName( GetLibraryFileName() ); // IMPORTANT: re-read the file
+       doc.setContent( &libFile ); // no checking of setContent() and find root element is done, since we are sure
+       rootElement = doc.elementsByTagName( ROOT_ELEMENT ).item( 0 ); // that in newly created file everything is OK
+      }
+      else // user chose not to recreate a bad library file
+       return false; // library file is corrupt (bad XML structure), don't recreate
     }
-    else // user chose not to recreate a bad library file
-      return false; // library file is corrupt (bad XML structure), don't recreate
-  }
   
-  // if theNode is EndSwitch or EndLoop -> first export Switch or Loop node
-  if ( theNode->IsEndLoop() || theNode->IsEndSwitch() ) {
-    SUPERV::GNode_var aTmpNode = SUPERV::GNode::_narrow( theNode );
-    theNode = aTmpNode->Coupled();
-    if ( CORBA::is_nil( theNode ) ) {
-      QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_NIL_COUPLED" ), tr( "OK" ) );
-      return false; // null coupled node
+    // if theNode is EndSwitch or EndLoop -> first export Switch or Loop node
+    if ( theNode->IsEndLoop() || theNode->IsEndSwitch() ) {
+      SUPERV::GNode_var aTmpNode = SUPERV::GNode::_narrow( theNode );
+      theNode = aTmpNode->Coupled();
+      if ( CORBA::is_nil( theNode ) ) {
+       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_NIL_COUPLED" ), tr( "OK" ) );
+       return false; // null coupled node
+      }
     }
-  }
 
-  // create element under main document
-  QDomElement element = doc.createElement( NODE_ELEMENT ) ;
-  rootElement.appendChild( element );
-  
-  // save the 'main' Py function of the node
-  saveStrings( doc, element, FUNC_NAME_ATT, theNode->PyFuncName(), FUNC_ELEMENT, theNode->PyFunction() );
-
-  // create DOM elements for ports
-  SUPERV::ListOfPorts_var aPorts = theNode->Ports();
-  for ( int i = 0, n = aPorts->length(); i < n; i++) {
-    if ( !CORBA::is_nil( aPorts[i] ) && !aPorts[i]->IsGate() ) {
-      QDomElement portElement = doc.createElement( PORT_ELEMENT );
-      portElement.setAttribute( PORT_INPUT_ATT, aPorts[i]->IsInput() );
-      portElement.setAttribute( PORT_NAME_ATT, aPorts[i]->Name() );
-      portElement.setAttribute( PORT_TYPE_ATT, aPorts[i]->Type() );
-      element.appendChild( portElement );
+    // create element under main document
+    QDomElement element = doc.createElement( NODE_ELEMENT ) ;
+    rootElement.appendChild( element );
+
+    // save node's name and kind
+    element.setAttribute( NODE_NAME_ATT, theNode->Name() );
+    element.setAttribute( NODE_KIND_ATT, theNode->Kind() );
+    // save the 'main' Py function of the node
+    saveStrings( doc, element, FUNC_NAME_ATT, theNode->PyFuncName(), FUNC_ELEMENT, theNode->PyFunction() );
+
+    // create DOM elements for ports
+    SUPERV::ListOfPorts_var aPorts = theNode->Ports();
+    for ( int i = 0, n = aPorts->length(); i < n; i++) {
+      if ( !CORBA::is_nil( aPorts[i] ) && !aPorts[i]->IsGate() ) {
+       QDomElement portElement = doc.createElement( PORT_ELEMENT );
+       portElement.setAttribute( PORT_INPUT_ATT, aPorts[i]->IsInput() );
+       portElement.setAttribute( PORT_NAME_ATT, aPorts[i]->Name() );
+       portElement.setAttribute( PORT_TYPE_ATT, aPorts[i]->Type() );
+       element.appendChild( portElement );
+      }
     }
-  }
 
-  // if the node is Loop -> additionally export Init(), More(), Next() and EndLoop's function
-  if ( theNode->IsLoop() ) {
-    SUPERV::LNode_var aLoopNode = SUPERV::LNode::_narrow( theNode );
-    if ( CORBA::is_nil( aLoopNode ) ) {
-      QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_LOOP" ), tr( "OK" ) );
-      return false;
-    } 
-    SUPERV::INode_var aEndLoopNode = aLoopNode->Coupled();
-    if ( CORBA::is_nil( aEndLoopNode ) ) {
-      QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_LOOP" ), tr( "OK" ) );
+    // if the node is Loop -> additionally export Init(), More(), Next() and EndLoop's function
+    if ( theNode->IsLoop() ) {
+      SUPERV::LNode_var aLoopNode = SUPERV::LNode::_narrow( theNode );
+      if ( CORBA::is_nil( aLoopNode ) ) {
+       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_LOOP" ), tr( "OK" ) );
+       return false;
+      } 
+      SUPERV::INode_var aEndLoopNode = aLoopNode->Coupled();
+      if ( CORBA::is_nil( aEndLoopNode ) ) {
+       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_LOOP" ), tr( "OK" ) );
+       return false;
+      } 
+      // save init, more, next, end-loop functions of the Loop node
+      saveStrings( doc, element, FUNC_INIT_NAME_ATT, aLoopNode->PyInitName(), FUNC_INIT_ELEMENT, aLoopNode->PyInit() );
+      saveStrings( doc, element, FUNC_MORE_NAME_ATT, aLoopNode->PyMoreName(), FUNC_MORE_ELEMENT, aLoopNode->PyMore() );
+      saveStrings( doc, element, FUNC_NEXT_NAME_ATT, aLoopNode->PyNextName(), FUNC_NEXT_ELEMENT, aLoopNode->PyNext() );
+      saveStrings( doc, element, FUNC_EL_NAME_ATT, aEndLoopNode->PyFuncName(), FUNC_EL_ELEMENT, aEndLoopNode->PyFunction() );
+    }
+
+    // if the node is Switch -> additionally export EndSwitch's function and ports 
+    if ( theNode->IsSwitch() ) {
+      SUPERV::SNode_var aSwitchNode = SUPERV::SNode::_narrow( theNode );
+      if ( CORBA::is_nil( aSwitchNode ) ) {
+       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_SWITCH" ), tr( "OK" ) );
+       return false;
+      } 
+      SUPERV::INode_var aEndSwitchNode = aSwitchNode->Coupled();
+      if ( CORBA::is_nil( aEndSwitchNode ) ) {
+        QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_SWITCH" ), tr( "OK" ) );
+        return false;
+      } 
+      // save EndSwitch function
+      saveStrings( doc, element, FUNC_ES_NAME_ATT, aEndSwitchNode->PyFuncName(), FUNC_ES_ELEMENT, aEndSwitchNode->PyFunction() );
+
+      // save ports of EndSwitch
+      SUPERV::ListOfPorts_var aESPorts = aEndSwitchNode->Ports();
+      for ( int i = 0, n = aESPorts->length(); i < n; i++) {
+       if ( !CORBA::is_nil( aESPorts[i] ) && !aESPorts[i]->IsGate() ) {
+         QDomElement portElement = doc.createElement( ES_PORT_ELEMENT );
+         portElement.setAttribute( PORT_INPUT_ATT, aESPorts[i]->IsInput() );
+         portElement.setAttribute( PORT_NAME_ATT, aESPorts[i]->Name() );
+         portElement.setAttribute( PORT_TYPE_ATT, aESPorts[i]->Type() );
+         element.appendChild( portElement );
+       }
+      }
+    } // end of IsSwitch() 
+
+    // OK, done with file export.  write the document to the file
+    libFile.close(); // it seems that QDomDocument opens the file when doing 
+                     // setContent() and does not close it
+    if ( libFile.open( IO_WriteOnly ) ) { // IO_WriteOnly truncates the file!
+      QTextStream stream( &libFile );
+      doc.save( stream, 0 );
+      libFile.close();
+      return true;
+    }
+    else {  // error opening library file for final writing
+      QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_WRITE" ), tr( "OK" ) );
       return false;
-    } 
-    // save init, more, next, end-loop functions of the Loop node
-    saveStrings( doc, element, FUNC_INIT_NAME_ATT, aLoopNode->PyInitName(), FUNC_INIT_ELEMENT, aLoopNode->PyInit() );
-    saveStrings( doc, element, FUNC_MORE_NAME_ATT, aLoopNode->PyMoreName(), FUNC_MORE_ELEMENT, aLoopNode->PyMore() );
-    saveStrings( doc, element, FUNC_NEXT_NAME_ATT, aLoopNode->PyNextName(), FUNC_NEXT_ELEMENT, aLoopNode->PyNext() );
-    saveStrings( doc, element, FUNC_EL_NAME_ATT, aEndLoopNode->PyFuncName(), FUNC_EL_ELEMENT, aEndLoopNode->PyFunction() );
+    }
+  } // try
+  catch ( ... ) {
   }
 
-  // if the node is Switch -> additionally export EndSwitch's function and ports 
-  if ( theNode->IsSwitch() ) {
-    SUPERV::SNode_var aSwitchNode = SUPERV::SNode::_narrow( theNode );
-    if ( CORBA::is_nil( aSwitchNode ) ) {
-      QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_SWITCH" ), tr( "OK" ) );
-      return false;
-    } 
-    SUPERV::INode_var aEndSwitchNode = aSwitchNode->Coupled();
-    if ( CORBA::is_nil( aEndSwitchNode ) ) {
-      QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_SWITCH" ), tr( "OK" ) );
-      return false;
-    } 
-    // save EndSwitch function
-    saveStrings( doc, element, FUNC_ES_NAME_ATT, aEndSwitchNode->PyFuncName(), FUNC_ES_ELEMENT, aEndSwitchNode->PyFunction() );
-
-    // save ports of EndSwitch
-    SUPERV::ListOfPorts_var aESPorts = aEndSwitchNode->Ports();
-    for ( int i = 0, n = aESPorts->length(); i < n; i++) {
-      if ( !CORBA::is_nil( aESPorts[i] ) && !aESPorts[i]->IsGate() ) {
-       QDomElement portElement = doc.createElement( ES_PORT_ELEMENT );
-       portElement.setAttribute( PORT_INPUT_ATT, aESPorts[i]->IsInput() );
-       portElement.setAttribute( PORT_NAME_ATT, aESPorts[i]->Name() );
-       portElement.setAttribute( PORT_TYPE_ATT, aESPorts[i]->Type() );
-       element.appendChild( portElement );
+  // should get here only in case of exception
+  QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_EXPORT_EXCEPTION" ), tr( "OK" ) );
+  return false;
+}
+
+/**
+ * Returns in out parameters Py function name and Py function body
+ */
+void getStrings( QDomElement element, const char* pyFuncName, QString& thePyFuncName, 
+               const char* theFuncElem, SUPERV::ListOfStrings_var& pyFunc ) {
+  QDomNamedNodeMap aNodeAtt = element.attributes();
+  if ( !aNodeAtt.namedItem( pyFuncName ).isNull() ) { // if pyFuncName is found - fill pyFunc.
+    thePyFuncName = aNodeAtt.namedItem( pyFuncName ).nodeValue();
+
+    // every 'theFuncElem' element has a CDATA child - one line
+    // iterate through all of them twice: 1) to count the number of these items (number of strings)
+    // 2) to fill pyFunc out-parameter
+    int nStrings( 0 );
+    QDomNode n = element.firstChild();
+    while ( !n.isNull() ) {
+      if ( n.isElement() && n.nodeName() == theFuncElem && n.firstChild().isCDATASection() )
+       nStrings++;
+      n = n.nextSibling();
+    }
+  
+    pyFunc->length( nStrings );
+  
+    int i( 0 );
+    n = element.firstChild();
+    while ( !n.isNull() ) {
+      if ( n.isElement() && n.nodeName() == theFuncElem && n.firstChild().isCDATASection() ) {
+       QDomCDATASection aCDATA = n.firstChild().toCDATASection();
+       pyFunc[i++] = aCDATA.nodeValue();
       }
+      n = n.nextSibling();
     }
-  } // end of IsSwitch() 
-
-  // OK, done with file export.  write the document to the file
-  libFile.close(); // it seems that QDomDocument opens the file when doing 
-                   // setContent() and does not close it
-  if ( libFile.open( IO_WriteOnly ) ) { // IO_WriteOnly truncates the file!
-    QTextStream stream( &libFile );
-    stream << doc.toString();
-    libFile.close();
-    return true;
+  } // if ( pyFuncName )
+}
+/**
+ * Adds ports stored in Dom node to the CNode
+ */
+void addPorts( SUPERV::INode_var theINode, QDomElement element, const char* portElement ) {
+  QDomNodeList aPorts = element.elementsByTagName( portElement );
+  for ( int i = 0, n = aPorts.length(); i < n; i++ ) {
+    QDomNode aPort = aPorts.item( i );
+    QDomNamedNodeMap anAtt = aPort.attributes();
+    bool isInput = ( anAtt.namedItem( PORT_INPUT_ATT ).nodeValue() == "1" );
+    QString portName = anAtt.namedItem( PORT_NAME_ATT ).nodeValue();
+    QString portType = anAtt.namedItem( PORT_TYPE_ATT ).nodeValue();
+    if ( isInput )
+      theINode->InPort( portName.latin1(), portType.latin1() );
+    else
+      theINode->OutPort( portName.latin1(), portType.latin1() );
   }
-  else {  // error opening library file for final writing
-    QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_WRITE" ), tr( "OK" ) );
+}
+
+/**
+ * Import an InLine node from Library into the dataflow  
+ */
+bool SUPERVGUI_Library::Import( SUPERV::Graph_var theDataflow,  SUPERV::INode_var& theNode, 
+                               SUPERV::INode_var& theEndNode, const int i ) const {
+  try {
+    QDomNodeList aNodes;
+    QDomDocument doc;
+    if ( getNodes( doc, aNodes ) ) { // xml is ok
+      if ( i >=0 && i < aNodes.length() ) { // index is ok
+       // 1. retrieve the node with given index 
+       QDomElement aNode = aNodes.item( i ).toElement();
+       // 2. create an Engines node
+       QDomNamedNodeMap aNodeAtt = aNode.attributes();
+       const int aKind = aNodeAtt.namedItem( NODE_KIND_ATT ).nodeValue().toInt();
+       QString aNodeName = aNodeAtt.namedItem( NODE_NAME_ATT ).nodeValue();
+       switch ( aKind ) {
+       case SUPERV::InLineNode : // PyFunction
+       case SUPERV::GOTONode :
+         {
+           // get all the Python function
+           QString aPyFuncName;
+           SUPERV::ListOfStrings_var aPyFunc = new SUPERV::ListOfStrings();
+           getStrings( aNode, FUNC_NAME_ATT, aPyFuncName, FUNC_ELEMENT, aPyFunc );
+
+           // create the corresponding Engines node 
+           SUPERV::INode_var aINode;
+           if ( aKind == SUPERV::InLineNode ) 
+             aINode = theDataflow->INode( aPyFuncName.latin1(), aPyFunc );
+           else
+             aINode = theDataflow->GNode( aPyFuncName.latin1(), aPyFunc, "" );
+           
+           aINode->SetName( aNodeName.latin1() ); // try to set the same name of node (might be changed by CNode::SetName)
+           addPorts( aINode, aNode, PORT_ELEMENT ); // add stored ports
+
+           theNode = aINode; // init out-parameter
+           return true;
+         }
+       case SUPERV::LoopNode : // PyInit, PyNext, PyMore, PyEndLoopFunction
+         {
+           // get all required Python function
+           QString aInitName, aMoreName, aNextName, aELName;
+           SUPERV::ListOfStrings_var aInitFunc = new SUPERV::ListOfStrings(),
+           aMoreFunc = new SUPERV::ListOfStrings(),
+           aNextFunc = new SUPERV::ListOfStrings(),
+           aELFunc   = new SUPERV::ListOfStrings();
+           getStrings( aNode, FUNC_INIT_NAME_ATT, aInitName, FUNC_INIT_ELEMENT, aInitFunc );
+           getStrings( aNode, FUNC_MORE_NAME_ATT, aMoreName, FUNC_MORE_ELEMENT, aMoreFunc );
+           getStrings( aNode, FUNC_NEXT_NAME_ATT, aNextName, FUNC_NEXT_ELEMENT, aNextFunc );
+           getStrings( aNode, FUNC_EL_NAME_ATT,   aELName, FUNC_EL_ELEMENT,     aELFunc );
+
+           // create Engines Loop node 
+           SUPERV::INode_var aELNode;
+           SUPERV::INode_var aINode = theDataflow->LNode( aInitName.latin1(), aInitFunc,
+                                                         aMoreName.latin1(), aMoreFunc,
+                                                         aNextName.latin1(), aNextFunc, aELNode );
+           // EndLoop node may have or may NOT have pyFunc. set it if it was stored.
+           if ( !aELName.isEmpty() )
+             aELNode->SetPyFunction( aELName.latin1(), aELFunc );
+           
+           aINode->SetName( aNodeName.latin1() );// try to set the same name of node (might be changed by CNode::SetName)
+           addPorts( aINode, aNode, PORT_ELEMENT ); // add stored ports
+         
+           theNode = aINode;  // init out-parameters
+           theEndNode = aELNode;
+           return true;
+         }
+       case SUPERV::SwitchNode : // PyFunction, PyESFunction, ESPorts
+         {
+           // get all required Python function
+           QString aPyFuncName, aESPyFuncName;
+           SUPERV::ListOfStrings_var aPyFunc = new SUPERV::ListOfStrings(),
+           aESPyFunc = new SUPERV::ListOfStrings();
+           getStrings( aNode, FUNC_NAME_ATT,    aPyFuncName,   FUNC_ELEMENT,    aPyFunc );
+           getStrings( aNode, FUNC_ES_NAME_ATT, aESPyFuncName, FUNC_ES_ELEMENT, aESPyFunc );
+
+           // create Engines Switch node 
+           SUPERV::INode_var aESNode;
+           SUPERV::INode_var aINode = theDataflow->SNode( aPyFuncName.latin1(), aPyFunc, aESNode );
+           
+           // EndSwitch node may have or may NOT have pyFunc
+           if ( !aESPyFuncName.isEmpty() )
+             aESNode->SetPyFunction( aESPyFuncName.latin1(), aESPyFunc );
+
+           aINode->SetName( aNodeName.latin1() );// try to set the same name of node (might be changed by CNode::SetName)
+           addPorts( aINode, aNode, PORT_ELEMENT ); // add stored ports
+           addPorts( aESNode, aNode, ES_PORT_ELEMENT ); // add stores ports of EndSwitch
+
+           theNode = aINode;  // init out-parameters
+           theEndNode = aESNode;
+           return true;
+         }
+       default: // wrong kind of node error
+         QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_IMPORT_BAD_KIND_OF_NODE" ), tr( "OK" ) );
+         return false;
+       } // switch ( kind_of_node )
+      } // if ( index >= 0...)
+      else {
+       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_IMPORT_BAD_INDEX" ), tr( "OK" ) );
+      }
+    } // if ( getNodes() )
+    else {
+      return false; // no MB, getNodes() in case of errors displays MB itself
+    }
+  } // try
+  catch ( ... ) {
   }
+
+  // Normally we get here ONLY if an exception occured.  All other paths of execution must return before.
+  // But - who knows, maybe we can get here by some other means.. anyway, it's an error and we report it here
+  QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_IMPORT_EXCEPTION" ), tr( "OK" ) );
   return false;
 }
 
 /**
- * Import an InLine node from Library into the dataflow  
+ * Returns list of NODE_ELEMENT-s and error result (false) if failed (also displays MB)
  */
-SUPERV::CNode_var SUPERVGUI_Library::Import( SUPERV::Graph_var theDataflow, const int theLibIndex ) const {
-  SUPERV::CNode_var aNode;
+bool SUPERVGUI_Library::getNodes( QDomDocument& doc, QDomNodeList& theNodes ) const {
+  QFile libFile( GetLibraryFileName() );  // open existing library file
+  if ( !libFile.exists() ) { 
+    QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_IMPORT_LIB_NO_XML" ), tr( "OK" ) );
+    return false;
+  }
+
+  // create the main XML document object
+  QString docName( DOCTYPE ) ;
+  doc = QDomDocument( docName );
+  bool xmlOk = doc.setContent( &libFile );
+  // check XML for validity: 1) find root element with predefined name 2) check xml doctype
+  if ( xmlOk )    
+    xmlOk = ( doc.doctype().name() ==  DOCTYPE && doc.elementsByTagName( ROOT_ELEMENT ).length() == 1 ); 
+  if ( !xmlOk ) {
+    QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_IMPORT_LIB_BAD_XML" ), tr( "OK" ) );
+    return false;
+  }
 
-  return aNode;
+  theNodes = doc.elementsByTagName( NODE_ELEMENT );
+  return true;
 }
 
+/**
+ * Remove an InLine node with given index from Library
+ */
+bool SUPERVGUI_Library::Remove( const int i ) const {
+  QDomNodeList aNodes;
+  QDomDocument doc;
+  if ( getNodes( doc, aNodes ) && doc.elementsByTagName( ROOT_ELEMENT ).length() == 1 ) { // xml is ok
+    if ( i >=0 && i < aNodes.length() ) {
+      // 1. remove the child element (node) from Dom Document
+      QDomElement root = doc.elementsByTagName( ROOT_ELEMENT ).item( 0 ).toElement();
+      root.removeChild( aNodes.item( i ) );
+      // 2. write the modified document to the file
+      QFile libFile( GetLibraryFileName() );
+      if ( libFile.open( IO_WriteOnly | IO_Truncate ) ) { 
+       QTextStream stream( &libFile );
+       doc.save( stream, 0 );
+       libFile.close();
+       return true;
+      }
+    }
+  }
+  return false;
+}
 
+/**
+ * Returns a string descriptor of KindOfNode enumeration
+ */
+QString getKindStr( const QString& theKind ) {
+  switch ( theKind.toInt() ) {
+  case SUPERV::InLineNode : return "InLine";
+  case SUPERV::LoopNode :   return "Loop";
+  case SUPERV::SwitchNode : return "Switch";
+  case SUPERV::GOTONode :   return "GOTO";
+  case SUPERV::FactoryNode : 
+  case SUPERV::DataFlowGraph : 
+  case SUPERV::ComputingNode : 
+  case SUPERV::EndLoopNode : 
+  case SUPERV::EndSwitchNode :
+  case SUPERV::DataStreamGraph : 
+  case SUPERV::MacroNode : 
+  case SUPERV::UnknownNode : 
+  default:
+    ;
+  }
+  return "INCORRECT kind";
+}
+
+/**
+ * returns a list of node names currently stored in the library.  Indexes of the nodes in
+ * this list can be used for futher calls to Import(.., index)
+ */
+SUPERV::ListOfStrings SUPERVGUI_Library::GetLibraryNodesNames() const {
+  SUPERV::ListOfStrings aNodesNames;
+  aNodesNames.length( 0 );
+  
+  QDomNodeList aNodes;
+  QDomDocument doc;
+  if ( !getNodes( doc, aNodes ) )
+    return aNodesNames;
+
+  const int n = aNodes.length();
+  aNodesNames.length( n );
+  QDomNode aNode;
+  for ( int i = 0; i < n; i++ ) {
+    QString aNodeName( "" );
+    aNode = aNodes.item( i );
+    if ( !aNode.isNull() ) {
+      QDomNode aNameAtt = aNode.attributes().namedItem( NODE_NAME_ATT );
+      QDomNode aTypeAtt = aNode.attributes().namedItem( NODE_KIND_ATT );
+      if ( !aNameAtt.isNull() && !aTypeAtt.isNull() ) {
+       aNodeName = QString( "%1 ( %2 )" ).arg( aNameAtt.toAttr().value() ).arg( 
+                   getKindStr( aTypeAtt.toAttr().value() ) ); 
+      }
+    }
+    // if NodeName attribute was not found or some error (NULL node), 
+    // then an empty string is added for that index in the list
+    aNodesNames[i] = aNodeName.latin1();
+  }
+
+  return aNodesNames;
+}
 
 
 /**
@@ -310,6 +586,8 @@ SUPERVGUI_LibDlg::SUPERVGUI_LibDlg( QWidget* parent, int& theX, int& theY )
 
   aMainLayout->addMultiCellWidget( aBtnBox, 3, 3, 0, 3 );
   aMainLayout->setRowStretch( 2, 1 );
+
+  initList();
 }
 
 /**
@@ -321,12 +599,38 @@ SUPERVGUI_LibDlg::~SUPERVGUI_LibDlg() {}
  * Called when user presses "Add" button.  Add a selected node from library to graph
  */
 void SUPERVGUI_LibDlg::add() {
+  const int i = myLB->currentItem();
+  if ( i >= 0 && i < myLB->count() ) {
+    SUPERV::Graph_var aDataflow = Supervision.getMain()->getDataflow();
+    SUPERV::INode_var aNode, aEndNode;
+    if ( SUPERVGUI_Library::getLibrary()->Import( aDataflow, aNode, aEndNode, i ) ) {
+      SUPERVGUI_Service::addNode( SUPERV::CNode::_narrow( aNode ), aEndNode, myX, myY );
+      Supervision.getMain()->sync();
+    }
+    else { // all errors must be reported to user in Import(), MB shown, etc..
+    }      // so we don't need to report errors if Import() returned false.
+  }
 }
 
 /**
  * Called when user presses "Remove" button.  Remove a selected node from library
  */
 void SUPERVGUI_LibDlg::remove() {
+  const int i = myLB->currentItem();
+  if ( i >= 0 && i < myLB->count() ) {
+    SUPERVGUI_Library::getLibrary()->Remove( i );
+    initList(); // re-initialize the list to reflect the changes
+  } 
 }
 
+/**
+ * Fills the list with names of nodes currently stored in the library.  Indexes in the list
+ * can be used for calls to Library::Import()
+ */
+void SUPERVGUI_LibDlg::initList() {
+  myLB->clear();
+  SUPERV::ListOfStrings aNodesNames = SUPERVGUI_Library::getLibrary()->GetLibraryNodesNames();
+  for ( int i = 0, n = aNodesNames.length(); i < n; i++ )
+    myLB->insertItem( (const char*)aNodesNames[i] );
+}
 
index 840e0be6c425d625d4ad50f9e676532e3626eb1f..4999b7b9cdb03e23c6ad3c5f4bf1468d8305b39f 100644 (file)
@@ -29,6 +29,7 @@
 #define SUPERVGUI_Library_H
 
 #include <qdialog.h>
+#include <qdom.h>
 
 #include "utilities.h"
 #include "SALOME_LifeCycleCORBA.hxx"
@@ -63,13 +64,24 @@ public:
   bool Export( SUPERV::INode_var theNode ) const;
 
   // Import an InLine node from Library into the dataflow  
-  SUPERV::CNode_var Import( SUPERV::Graph_var theDataflow, const int theLibIndex ) const; 
+  bool Import( SUPERV::Graph_var theDataflow, SUPERV::INode_var& theNode, 
+              SUPERV::INode_var& theEndNode, const int theLibIndex ) const; 
+
+  // Remove an InLine node with given index from Library
+  bool Remove( const int i ) const;
+
+  // returns a list of node names currently stored in the library.  Indexes of the nodes in
+  // this list can be used for futher calls to Import(.., index)
+  SUPERV::ListOfStrings GetLibraryNodesNames() const;
 
 private:
   static SUPERVGUI_Library* myLibrary;
 
   bool createLibFile() const; // returns false on file creation error (also displays MB)
 
+  // returns list of NODE_ELEMENT-s and error result (false) if failed (also displays MB)
+  bool getNodes( QDomDocument& theDoc, QDomNodeList& theNodes ) const; 
+
 };
 
 /**
@@ -83,6 +95,8 @@ public:
   SUPERVGUI_LibDlg( QWidget* parent, int& theX, int& theY );
   ~SUPERVGUI_LibDlg();
 
+  void initList();
+
 private slots:
   void add(); // add selected node from library to graph
   void remove(); // remove selected node from library