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