]> SALOME platform Git repositories - modules/superv.git/blob - src/SUPERVGUI/SUPERVGUI_Library.cxx
Salome HOME
0972fd5716b4019cc134d351325349950a2e9490
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Library.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SUPERVGUI_Library.cxx
25 //  Author : Alexander SLADKOV
26 //  Module : SUPERV
27
28
29 #include "SUPERVGUI_Library.h"
30
31 #include "QAD_MessageBox.h"
32 #include "QAD_Application.h"
33
34 #include <qlistbox.h>
35 #include <qlayout.h>
36 #include <qgroupbox.h>
37 #include <qpushbutton.h>
38 #include <qdom.h>
39 #include <qfile.h>
40
41 using namespace std;
42
43 #define LIBFILE "/.salome/InLineLibrary.xml" // $HOME+LIBFILE
44 #define DOCTYPE "InLineNodesLibrary"         // XML DocType
45 #define ROOT_ELEMENT "inlinenodeslibrary"    // XML Element and Attribute tags (many)
46 #define NODE_ELEMENT "INode"
47 #define PORT_ELEMENT "Port"
48 #define ES_PORT_ELEMENT "ESPort"
49 #define PORT_INPUT_ATT "IsInput"
50 #define PORT_NAME_ATT "Name"
51 #define PORT_TYPE_ATT "Type"
52
53 #define FUNC_NAME_ATT "PyFuncName"           // XML attributes and elements
54 #define FUNC_ELEMENT "PyFunc"                // for Python functions defined
55 #define FUNC_INIT_NAME_ATT "InitFuncName"    // in different types of InLine nodes
56 #define FUNC_INIT_ELEMENT "InitPyFunc"
57 #define FUNC_MORE_NAME_ATT "MoreFuncName"
58 #define FUNC_MORE_ELEMENT "MorePyFunc"
59 #define FUNC_NEXT_NAME_ATT "NextFuncName"
60 #define FUNC_NEXT_ELEMENT "NextPyFunc"
61 #define FUNC_EL_NAME_ATT "ELFuncName"        // EndLoop
62 #define FUNC_EL_ELEMENT "ELPyFunc"
63 #define FUNC_ES_NAME_ATT "ESFuncName"        // EndSwitch
64 #define FUNC_ES_ELEMENT "ESPyFunc"
65
66
67 SUPERVGUI_Library* SUPERVGUI_Library::myLibrary = 0;
68
69 /**
70  * Inline nodes library.  constructor. 
71  */
72 SUPERVGUI_Library::SUPERVGUI_Library() {
73 }
74
75 /**
76  * Returns the XML file name used as InLine nodes repository
77  */
78 const char* SUPERVGUI_Library::GetLibraryFileName() const {
79   string aFileName = getenv( "HOME" );
80   aFileName += LIBFILE;
81   return aFileName.c_str();
82 }
83
84 /**
85  * Creates a new library file, truncates the length to zero, writes an empty 
86  * XML stub to it.  If fails - displays an error message box and returns false
87  */
88 bool SUPERVGUI_Library::createLibFile() const {
89   QFile libFile( GetLibraryFileName() );
90   try {
91     if ( libFile.open( IO_WriteOnly | IO_Truncate ) ) { 
92       QDomDocument doc( DOCTYPE ); // create a simple XML stub
93       doc.appendChild( doc.createElement( ROOT_ELEMENT ) ); // IMPORTANT: do not delete this root element
94       QTextStream stream( &libFile );
95       stream << doc.toString();
96       libFile.close();
97       return true;
98     }
99     else {
100       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB1" ), tr( "OK" ) );
101       return false; // error opening library file for writing
102     }
103   }
104   catch ( ... ) {
105     QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_IO" ), tr( "OK" ) );
106   }
107   return false;
108 }
109
110 /**
111  * Save Function Name as attribute of given DomElement, and Function strings as its children with CDATASection
112  * saveStrings() is called to save 'main' Py function of a node, and Init(), More(), Next() for Loop node
113  */
114 void saveStrings( QDomDocument doc, QDomElement element, const char* theNameAtt, const char* theFuncName, 
115                   const char* theFuncElem, SUPERV::ListOfStrings_var pyFunc ) {
116   QString pyFuncName( theFuncName );
117   element.setAttribute( theNameAtt, pyFuncName );  // store Py function name
118   
119   // store Py functions as children of 'element'.
120   for ( int i = 0, n = pyFunc->length(); i < n; i++ ) {
121     QString pyFuncStr( pyFunc[i] );
122     QDomCDATASection aCDATA = doc.createCDATASection( pyFuncStr );
123     QDomElement funcElement = doc.createElement( theFuncElem );
124     element.appendChild( funcElement );
125     funcElement.appendChild( aCDATA );
126   }
127 }
128
129 /**
130  * Export an InLine node to Library 
131  */
132 bool SUPERVGUI_Library::Export( SUPERV::INode_var theNode ) const {
133   if ( CORBA::is_nil( theNode ) ) {
134     QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_NIL_NODE" ), tr( "OK" ) );
135     return false; // null node
136   }
137
138   // open existing library file or create a new one and set some empty XML content
139   QFile libFile( GetLibraryFileName() );
140   if ( !libFile.exists() ) { // new library
141     if ( !createLibFile() )
142       return false; // error opening library file for writing.  MB was already displayed
143   }
144
145   // create the main XML document object
146   QString docName( DOCTYPE ) ;
147   QDomDocument doc( docName );
148   bool xmlOk = doc.setContent( &libFile );
149   if ( xmlOk )      
150     xmlOk = ( doc.elementsByTagName( ROOT_ELEMENT ).length() == 1 ); // find "root" element
151   QDomNode rootElement;
152   if ( xmlOk ) {
153     rootElement = doc.elementsByTagName( ROOT_ELEMENT ).item( 0 );
154     xmlOk = ( !rootElement.isNull() );
155   }
156   if ( !xmlOk ) {
157     const int toRecreate = QAD_MessageBox::error2( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), 
158                                                   tr( "MSG_ERROR_LIB_IS_RECREATE" ), tr( "BUT_YES" ), tr( "BUT_NO" ), 1, 0, 0 );
159     if ( toRecreate ) { // user selected to recreate a bad XML file
160       libFile.close(); // in case it was opened by doc.setContent()
161       if ( !createLibFile() )
162         return false; // error opening library file for writing.  MB was already displayed
163       
164       // library file was successfully recreated. now re-set content, init rooElement. No checking - it MUST be OK.
165       libFile.setName( GetLibraryFileName() ); // IMPORTANT: re-read the file
166       doc.setContent( &libFile );
167       rootElement = doc.elementsByTagName( ROOT_ELEMENT ).item( 0 );
168     }
169     else // user chose not to recreate a bad library file
170       return false; // library file is corrupt (bad XML structure), don't recreate
171   }
172   
173   // if theNode is EndSwitch or EndLoop -> first export Switch or Loop node
174   if ( theNode->IsEndLoop() || theNode->IsEndSwitch() ) {
175     SUPERV::GNode_var aTmpNode = SUPERV::GNode::_narrow( theNode );
176     theNode = aTmpNode->Coupled();
177     if ( CORBA::is_nil( theNode ) ) {
178       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_NIL_COUPLED" ), tr( "OK" ) );
179       return false; // null coupled node
180     }
181   }
182
183   // create element under main document
184   QDomElement element = doc.createElement( NODE_ELEMENT ) ;
185   rootElement.appendChild( element );
186   
187   // save the 'main' Py function of the node
188   saveStrings( doc, element, FUNC_NAME_ATT, theNode->PyFuncName(), FUNC_ELEMENT, theNode->PyFunction() );
189
190   // create DOM elements for ports
191   SUPERV::ListOfPorts_var aPorts = theNode->Ports();
192   for ( int i = 0, n = aPorts->length(); i < n; i++) {
193     if ( !CORBA::is_nil( aPorts[i] ) && !aPorts[i]->IsGate() ) {
194       QDomElement portElement = doc.createElement( PORT_ELEMENT );
195       portElement.setAttribute( PORT_INPUT_ATT, aPorts[i]->IsInput() );
196       portElement.setAttribute( PORT_NAME_ATT, aPorts[i]->Name() );
197       portElement.setAttribute( PORT_TYPE_ATT, aPorts[i]->Type() );
198       element.appendChild( portElement );
199     }
200   }
201
202   // if the node is Loop -> additionally export Init(), More(), Next() and EndLoop's function
203   if ( theNode->IsLoop() ) {
204     SUPERV::LNode_var aLoopNode = SUPERV::LNode::_narrow( theNode );
205     if ( CORBA::is_nil( aLoopNode ) ) {
206       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_LOOP" ), tr( "OK" ) );
207       return false;
208     } 
209     SUPERV::INode_var aEndLoopNode = aLoopNode->Coupled();
210     if ( CORBA::is_nil( aEndLoopNode ) ) {
211       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_LOOP" ), tr( "OK" ) );
212       return false;
213     } 
214     // save init, more, next, end-loop functions of the Loop node
215     saveStrings( doc, element, FUNC_INIT_NAME_ATT, aLoopNode->PyInitName(), FUNC_INIT_ELEMENT, aLoopNode->PyInit() );
216     saveStrings( doc, element, FUNC_MORE_NAME_ATT, aLoopNode->PyMoreName(), FUNC_MORE_ELEMENT, aLoopNode->PyMore() );
217     saveStrings( doc, element, FUNC_NEXT_NAME_ATT, aLoopNode->PyNextName(), FUNC_NEXT_ELEMENT, aLoopNode->PyNext() );
218     saveStrings( doc, element, FUNC_EL_NAME_ATT, aEndLoopNode->PyFuncName(), FUNC_EL_ELEMENT, aEndLoopNode->PyFunction() );
219   }
220
221   // if the node is Switch -> additionally export EndSwitch's function and ports 
222   if ( theNode->IsSwitch() ) {
223     SUPERV::SNode_var aSwitchNode = SUPERV::SNode::_narrow( theNode );
224     if ( CORBA::is_nil( aSwitchNode ) ) {
225       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_SWITCH" ), tr( "OK" ) );
226       return false;
227     } 
228     SUPERV::INode_var aEndSwitchNode = aSwitchNode->Coupled();
229     if ( CORBA::is_nil( aEndSwitchNode ) ) {
230       QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_BAD_SWITCH" ), tr( "OK" ) );
231       return false;
232     } 
233     // save EndSwitch function
234     saveStrings( doc, element, FUNC_ES_NAME_ATT, aEndSwitchNode->PyFuncName(), FUNC_ES_ELEMENT, aEndSwitchNode->PyFunction() );
235
236     // save ports of EndSwitch
237     SUPERV::ListOfPorts_var aESPorts = aEndSwitchNode->Ports();
238     for ( int i = 0, n = aESPorts->length(); i < n; i++) {
239       if ( !CORBA::is_nil( aESPorts[i] ) && !aESPorts[i]->IsGate() ) {
240         QDomElement portElement = doc.createElement( ES_PORT_ELEMENT );
241         portElement.setAttribute( PORT_INPUT_ATT, aESPorts[i]->IsInput() );
242         portElement.setAttribute( PORT_NAME_ATT, aESPorts[i]->Name() );
243         portElement.setAttribute( PORT_TYPE_ATT, aESPorts[i]->Type() );
244         element.appendChild( portElement );
245       }
246     }
247   } // end of IsSwitch() 
248
249   // OK, done with file export.  write the document to the file
250   libFile.close(); // it seems that QDomDocument opens the file when doing 
251                    // setContent() and does not close it
252   if ( libFile.open( IO_WriteOnly ) ) { // IO_WriteOnly truncates the file!
253     QTextStream stream( &libFile );
254     stream << doc.toString();
255     libFile.close();
256     return true;
257   }
258   else {  // error opening library file for final writing
259     QAD_MessageBox::error1( (QWidget*)QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_ERROR_LIB_WRITE" ), tr( "OK" ) );
260   }
261   return false;
262 }
263
264 /**
265  * Import an InLine node from Library into the dataflow  
266  */
267 SUPERV::CNode_var SUPERVGUI_Library::Import( SUPERV::Graph_var theDataflow, const int theLibIndex ) const {
268   SUPERV::CNode_var aNode;
269
270   return aNode;
271 }
272
273
274
275
276 /**
277  * Inline nodes library management dialog.  constructor. 
278  */
279 SUPERVGUI_LibDlg::SUPERVGUI_LibDlg( QWidget* parent, int& theX, int& theY )
280   :QDialog( parent, "SUPERVGUI_LibDlg", true, WStyle_Customize | WStyle_NormalBorder | WStyle_Title | WStyle_SysMenu),
281    myX( theX ), myY( theY )
282 {
283   setSizeGripEnabled( true );
284   setCaption(tr("TIT_FUNC_PYTHON"));
285   resize( 350, 400 );
286   QGridLayout* aMainLayout = new QGridLayout( this, 4, 4, 11, 6 );
287
288   myLB = new QListBox( this );
289
290   QPushButton* anAddBtn = new QPushButton( tr("TIT_ADDFNODE"), this );
291   connect( anAddBtn, SIGNAL( clicked() ), this, SLOT( add() ) );
292   QPushButton* aRemBtn = new QPushButton( tr("BUT_REMOVE"), this );
293   connect( aRemBtn, SIGNAL( clicked() ), this, SLOT( remove() ) );
294
295   aMainLayout->addMultiCellWidget( myLB, 0, 2, 0, 2 );
296   aMainLayout->addWidget( anAddBtn, 0, 3  );
297   aMainLayout->addWidget( aRemBtn, 1, 3 );
298
299   QGroupBox* aBtnBox = new QGroupBox( 0, Qt::Vertical, this );
300   aBtnBox->layout()->setSpacing( 0 ); aBtnBox->layout()->setMargin( 0 );
301   QHBoxLayout* aBtnLayout = new QHBoxLayout( aBtnBox->layout() );
302   aBtnLayout->setAlignment( Qt::AlignTop );
303   aBtnLayout->setSpacing( 6 ); aBtnLayout->setMargin( 11 );
304
305   QPushButton* aCloseBtn = new QPushButton( tr("BUT_CLOSE"), aBtnBox );
306   connect( aCloseBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
307   aBtnLayout->addStretch();
308   aBtnLayout->addWidget( aCloseBtn );
309   aBtnLayout->addStretch();
310
311   aMainLayout->addMultiCellWidget( aBtnBox, 3, 3, 0, 3 );
312   aMainLayout->setRowStretch( 2, 1 );
313 }
314
315 /**
316  * Inline nodes library management dialog.  destructor. 
317  */
318 SUPERVGUI_LibDlg::~SUPERVGUI_LibDlg() {}
319
320 /**
321  * Called when user presses "Add" button.  Add a selected node from library to graph
322  */
323 void SUPERVGUI_LibDlg::add() {
324 }
325
326 /**
327  * Called when user presses "Remove" button.  Remove a selected node from library
328  */
329 void SUPERVGUI_LibDlg::remove() {
330 }
331
332