Salome HOME
A constructor and destructor added.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_Clipboard.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_Clipboard.cxx
25 //  Author : Alexander SLADKOV
26 //  Module : SUPERV
27
28
29 #include "SUPERVGUI_Clipboard.h"
30 #include "SUPERVGUI_CanvasNode.h"
31 #include "SUPERVGUI.h"
32
33
34 SUPERVGUI_Clipboard* SUPERVGUI_Clipboard::myCB = 0;
35
36
37 /**
38  * Compute the next valid name for a Python function (add "_N" if a function with given name already exists)
39  */
40 QString getNewName( QStringList& allNames, const QString& oldName ) {
41   QString newName;
42   int id = 1; //increment index
43   newName = oldName + QString("_") + QString::number( id );
44   while ( allNames.contains( newName ) )
45     newName = oldName + QString("_") + QString::number( ++id );
46   
47   return newName;
48 }
49
50 /**
51  * Replaces origName string with newName string in all lines of theFunc
52  * origName must be preceeded by space and end by space or '('.
53  */
54 bool replaceName( SUPERV::ListOfStrings_var& theFunc, const QString& origName, const QString& newName ) {
55   for ( int i = 0, n = theFunc->length(); i < n; i++ ) {
56     QString aLine( theFunc[i] );
57     int index = aLine.find( origName, 0 ); // find FIRST occurance of origName in aLine
58     while ( index >= 0 ) {
59       bool preceedingCharOk = ( index==0 || ( index > 0 && aLine[index-1].isSpace() ) );
60       const int ll = aLine.length();
61       const int ol = origName.length();
62       const int ni = index + ol;
63       bool nextCharOk = ( ll==ni || ( ll>ni && ( aLine[ni].isSpace() || aLine[ni]=='(' ) ) );
64       if ( preceedingCharOk && nextCharOk ) {
65         aLine = aLine.replace( index, origName.length(), newName );
66         theFunc[i] = aLine.latin1();
67       }
68       index = aLine.find( origName, index+newName.length() ); // find NEXT occurance of origName in aLine
69     }
70   }
71 }
72
73 /**
74  * "Copies" all ports from fromNode to toNode: creates the sames ports in toNode in fact
75  */
76 void copyPorts( const SUPERV::CNode_var& fromNode, const SUPERV::INode_var& toNode ) {
77   if ( CORBA::is_nil( fromNode ) || CORBA::is_nil( toNode ) )
78     return;
79   SUPERV::ListOfPorts_var aPList = fromNode->Ports();
80   QString aName, aType;
81   for (int i = 0; i < aPList->length(); i++) {
82     aName = aPList[i].in()->Name();
83     aType = aPList[i].in()->Type();
84     if ( aPList[i].in()->IsInput() )
85       toNode->InPort( aName.latin1(), aType.latin1() );
86     else
87       toNode->OutPort( aName.latin1(), aType.latin1() );
88   }
89 }
90
91 /**
92  * Constructor
93  */
94 SUPERVGUI_Clipboard::SUPERVGUI_Clipboard( QObject* parent ) 
95 : QObject( parent ) {
96 }
97
98 /**
99  * Destructor
100  */
101 SUPERVGUI_Clipboard::~SUPERVGUI_Clipboard() {
102 }
103
104 /**
105  * Called on Paste Node command.  Inserts a new node to the dataflow equal to the copied node.
106  * For InLine nodes the Python function name is changed ("_N" added).
107  */
108 void SUPERVGUI_Clipboard::pasteNode() {
109   Trace("SUPERVGUI_Main::pasteNode");
110   SUPERV::CNode_var aNode = getCopyNode();
111   if ( !CORBA::is_nil( aNode ) ) {
112
113     //collect all python functions names of allready exist InLine nodes 
114     //in QStringList for automatic change of function's name on Paste of InLine node
115     QStringList aFuncNames;
116     SUPERV::Graph_var dataflow = Supervision.getMain()->getDataflow();
117     SUPERV::ListOfNodes_var nodes = dataflow->Nodes();
118     //InLine nodes
119     for(int i = 0; i < nodes->INodes.length(); i++)
120       aFuncNames.append(nodes->INodes[i]->PyFuncName());
121     //Loop nodes
122     for(int i = 0; i < nodes->LNodes.length(); i++) {
123       aFuncNames.append(nodes->LNodes[i]->PyInitName());
124       aFuncNames.append(nodes->LNodes[i]->PyMoreName());
125       aFuncNames.append(nodes->LNodes[i]->PyNextName());
126     }
127     //Switch nodes
128     for(int i = 0; i < nodes->SNodes.length(); i++)
129       aFuncNames.append(nodes->SNodes[i]->PyFuncName());
130     //GOTO nodes
131     for(int i = 0; i < nodes->GNodes.length(); i++)
132       aFuncNames.append(nodes->GNodes[i]->PyFuncName());
133
134     int id, fid;
135     QString aOriginalName;
136
137     // automatic change of function_name and function_strings ( +"_N" )
138     QString aFName, aInitFName, aMoreFName, aNextFName;
139     SUPERV::ListOfStrings_var aFunc, aInitFunc, aMoreFunc, aNextFunc;    
140
141     const int aKind = aNode->Kind();
142
143     if ( aKind == SUPERV::InLineNode || aKind == SUPERV::GOTONode || aKind == SUPERV::SwitchNode ) {
144       // "fix" Main function_name and Main function_strings
145       aOriginalName = SUPERV::INode::_narrow(aNode)->PyFuncName();
146       if ( !aOriginalName.isEmpty() ) {
147         aFName = getNewName( aFuncNames, aOriginalName );
148         aFunc = SUPERV::INode::_narrow(aNode)->PyFunction();
149         replaceName( aFunc, aOriginalName, aFName );
150       }
151     }
152     else if (aNode->Kind() == SUPERV::LoopNode) {
153
154       // "fix" Init function_name and Init function_strings
155       aOriginalName = SUPERV::LNode::_narrow(aNode)->PyInitName();
156       if (!aOriginalName.isEmpty()) {
157         aInitFName = getNewName( aFuncNames, aOriginalName );
158         aInitFunc = SUPERV::LNode::_narrow(aNode)->PyInit();
159         replaceName( aInitFunc, aOriginalName, aInitFName );
160       }
161
162       // "fix" More function_name and More function_strings
163       aOriginalName = SUPERV::LNode::_narrow(aNode)->PyMoreName();
164       if (!aOriginalName.isEmpty()) {
165         aMoreFName = getNewName( aFuncNames, aOriginalName );
166         aMoreFunc = SUPERV::LNode::_narrow(aNode)->PyMore();
167         replaceName( aMoreFunc, aOriginalName, aMoreFName );
168       }
169
170       // "fix" Next function_name and Next function_strings
171       aOriginalName = SUPERV::LNode::_narrow(aNode)->PyNextName();
172       if (!aOriginalName.isEmpty()) {
173         aNextFName = getNewName( aFuncNames, aOriginalName );
174         aNextFunc = SUPERV::LNode::_narrow(aNode)->PyNext();
175         replaceName( aNextFunc, aOriginalName, aNextFName );
176       }
177     }
178     
179     int cx, cy;
180     //2.8 point of improvements: Adding node to graph window with taking into account zoom factor
181     SUPERVGUI_CanvasView* aCanvasView = Supervision.getMain()->getCanvasView();
182     QWMatrix aWM = aCanvasView->worldMatrix();
183     switch (aNode->Kind()) {
184     case SUPERV::FactoryNode : 
185       {
186         SUPERV::FNode_var aFNode = dataflow->FNode( SUPERV::FNode::_narrow(aNode)->GetComponentName(),
187                                                SUPERV::FNode::_narrow(aNode)->GetInterfaceName(),
188                                                *SUPERV::FNode::_narrow(aNode)->Service() );
189         if (CORBA::is_nil(aFNode)) {
190           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
191           return;
192         }
193
194         SUPERV::INode_var aDummyEndNode;
195         Supervision.getBrowser()->addNode(SUPERV::CNode::_narrow(aFNode), aDummyEndNode, myXCopyNode, myYCopyNode);
196       }
197       break;
198     case SUPERV::ComputingNode : 
199       {
200         SUPERV::CNode_var aCNode = dataflow->CNode(*SUPERV::CNode::_narrow(aNode)->Service());
201         if (CORBA::is_nil(aCNode)) {
202           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
203           return;
204         }
205         
206         SUPERV::INode_var aDummyEndNode;
207         Supervision.getBrowser()->addNode(aCNode, aDummyEndNode, myXCopyNode, myYCopyNode);
208       }
209       break;
210     case SUPERV::InLineNode : 
211       {
212         SUPERV::INode_var aINode = dataflow->INode( aFName, aFunc );
213
214         if (CORBA::is_nil(aINode)) {
215           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
216           return;
217         }
218         copyPorts( aNode, aINode );
219
220         SUPERV::INode_var aDummyEndNode;
221         Supervision.getBrowser()->addNode(SUPERV::CNode::_narrow(aINode), aDummyEndNode, myXCopyNode, myYCopyNode);
222       }
223       break;
224     case SUPERV::LoopNode :
225       {
226         SUPERV::INode_var aEndNode;
227         SUPERV::LNode_var aStartNode = dataflow->LNode(aInitFName, aInitFunc, aMoreFName, aMoreFunc, aNextFName, aNextFunc, aEndNode);
228         if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
229           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
230           return;
231         }
232         copyPorts( aNode, SUPERV::INode::_narrow( aStartNode ) );
233
234         Supervision.getBrowser()->addNode(SUPERV::CNode::_narrow(aStartNode), aEndNode, myXCopyNode, myYCopyNode);
235       }
236       break;
237     case SUPERV::SwitchNode :
238       {
239         SUPERV::INode_var aEndNode;
240         SUPERV::SNode_var aStartNode = dataflow->SNode(aFName, aFunc, aEndNode);
241         if (CORBA::is_nil(aStartNode) || CORBA::is_nil(aEndNode)) {
242           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
243           return;
244         }
245         copyPorts( aNode, SUPERV::INode::_narrow( aStartNode ) );
246         SUPERV::INode_var aNodeEnd = SUPERV::SNode::_narrow(aNode)->Coupled();
247         copyPorts( SUPERV::CNode::_narrow( aNodeEnd ), aEndNode );
248
249         Supervision.getBrowser()->addNode(SUPERV::CNode::_narrow(aStartNode), aEndNode, myXCopyNode, myYCopyNode);
250       }
251       break;
252     case SUPERV::GOTONode :
253       {
254         SUPERV::GNode_var aGNode = dataflow->GNode(aFName, aFunc, "");
255         if (CORBA::is_nil(aGNode)) {
256           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
257           return;
258         }
259         copyPorts( aNode, SUPERV::INode::_narrow( aGNode ) );
260
261         SUPERV::INode_var aDummyEndNode;
262         Supervision.getBrowser()->addNode(SUPERV::CNode::_narrow(aGNode), aDummyEndNode, myXCopyNode, myYCopyNode);
263       }
264       break;
265     case SUPERV::MacroNode :
266       {
267         /* to implement in the future */
268         /*
269         //get SubGraph from MacroNode
270         SUPERV::Graph_var aMacro = SUPERV::Graph::_narrow(aNode);
271         SUPERV::Graph_var aGraph;
272         if (aMacro->IsStreamMacro())
273           aGraph = aMacro->StreamObjRef();
274         else
275           aGraph = aMacro->FlowObjRef();
276         SUPERV::Graph_var aMacroNode = dataflow->GraphMNode(aGraph);
277         
278         if (CORBA::is_nil(aMacroNode)) {
279           QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_CREATE_NODE"));
280           return;
281         }
282
283         SUPERV::INode_var aDummyEndNode;
284         Supervision.getBrowser()->addNode(SUPERV::CNode::_narrow(aMacroNode), aDummyEndNode, myXCopyNode, myYCopyNode);
285         */
286       }
287       break;
288     }
289   }
290 }
291
292
293 /** 
294  * Called from CanvasNode on "Paste port" command of popup menu
295  */
296 void SUPERVGUI_Clipboard::pastePort( SUPERVGUI_CanvasNode* node )
297 {
298   SUPERV::Port_var aPort = getCopyPort();
299   if ( !CORBA::is_nil(aPort) ) {
300     SUPERV::INode_var aNode = node->getInlineNode();
301     if (!CORBA::is_nil(aNode)) {
302       QString aName = aPort->Name();
303       QString aType = aPort->Type();
304       SUPERV::Port_var aPastePort;
305       if (aPort->IsInput()) {
306         //check if port with such name is alredy exists
307         QStringList aNames = node->getPortsNamesIN(aNode, true);
308         if (aNames.contains(aName))
309           QMessageBox::warning( QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_PORT_EXIST") );
310         else
311           aPastePort = aNode->InPort(aName.latin1(), aType.latin1());
312       }
313       else {
314         //check if port with such name is already exists
315         QStringList aNames = node->getPortsNamesIN(aNode, false);
316         if (aNames.contains(aName))
317           QMessageBox::warning( QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_PORT_EXIST") );
318         else
319           aPastePort = aNode->OutPort(aName.latin1(), aType.latin1());
320       }
321       if ( !CORBA::is_nil(aPastePort) )
322         node->createPort( aPastePort.in() );
323     }
324   }
325 }