#include "SUPERVGUI_Library.h"
+#include "SUPERVGUI_Main.h"
+#include "SUPERVGUI.h"
#include "QAD_MessageBox.h"
#include "QAD_Application.h"
#include <qlayout.h>
#include <qgroupbox.h>
#include <qpushbutton.h>
-#include <qdom.h>
#include <qfile.h>
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"
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;
}
* 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;
+}
/**
aMainLayout->addMultiCellWidget( aBtnBox, 3, 3, 0, 3 );
aMainLayout->setRowStretch( 2, 1 );
+
+ initList();
}
/**
* 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] );
+}