Salome HOME
Merge with OCC_development_01
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_CanvasNode.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  OPEN CASCADE
4 //
5 //  File   : SUPERVGUI_CanvasNode.cxx
6 //  Author : Natalia KOPNOVA
7 //  Module : SUPERV
8
9 using namespace std;
10 #include "SUPERVGUI_CanvasNode.h"
11 #include "SUPERVGUI_CanvasNodePrs.h"
12 #include "SUPERVGUI_CanvasPort.h"
13 #include "SUPERVGUI_Main.h"
14 #include "SUPERVGUI_Python.h"
15 #include "SUPERVGUI.h"
16 #include "SUPERVGUI_BrowseNodeDlg.h"
17 #include "SALOMEGUI_NameDlg.h"
18 #include "SUPERVGUI_Information.h"
19 /*
20 #include "SUPERVGUI_CanvasControlNode.h"
21
22 #include <qtooltip.h>
23 */
24
25 SUPERVGUI_CanvasNode::SUPERVGUI_CanvasNode(QObject* theParent, SUPERVGUI_Main* theMain, SUPERV_CNode theNode):
26     QObject(theParent),
27     myMain(theMain),
28     myNode(theNode),
29     myPrs(0),
30     myDestroyed(false),
31     warning(true),
32     step(true),
33     trace(true),
34     verbose(true),
35     myBrowseDlg(0)
36 {
37   Trace("SUPERVGUI_CanvasNode::SUPERVGUI_CanvasNode");
38
39   setName(myNode->Name());
40
41   QString aComment(myNode->Comment());
42   QString aNewComment = aComment;
43   if (getNodeType() == SUPERV::FactoryNode) {
44     aNewComment = QString(myNode->Service()->ServiceName) +
45       QString(tr("COMMENT_FROM")) +
46       QString(getFactoryNode()->GetComponentName());
47   }
48   else if (myNode->IsMacro()) {
49     aNewComment = tr("COMMENT_MNODE");
50   }
51   else {
52     aNewComment = tr("COMMENT_CNODE");
53   }
54   if (aComment.isEmpty()) {
55     myNode->SetComment(aNewComment.latin1());
56   }
57
58   myLabelText = aNewComment;
59
60   // create node ports
61   isIgnore = true;
62   //cout << "     get port list... " ;
63   SUPERV_Ports aPortList = myNode->Ports();
64   //cout << aPortList->length() << endl;
65   for (int i = 0; i < aPortList->length(); i++) {
66     createPort(aPortList[i].in());
67   }
68
69   //cout << "     get stream port list... " ;
70   SUPERV_StreamPorts aStreamPortList = myNode->StreamPorts();
71   //cout << aStreamPortList->length() << endl;
72   for (int i = 0; i < aStreamPortList->length(); i++) {
73     createStreamPort(aStreamPortList[i].in());
74   }
75
76   isIgnore = false;
77 }
78
79 SUPERVGUI_CanvasNode::~SUPERVGUI_CanvasNode()
80 {
81   isIgnore = true;
82   if (myPrs) delete myPrs;
83 }
84
85 void SUPERVGUI_CanvasNode::setDestroyed()
86 {
87   myDestroyed = true;
88   getPrs()->hide();
89 }
90
91 SUPERVGUI_CanvasNodePrs* SUPERVGUI_CanvasNode::getPrs() const
92 {
93   if (myPrs == 0) {
94     ((SUPERVGUI_CanvasNode*)this)->myPrs = createPrs();
95   }
96   return myPrs;
97 }
98
99 SUPERVGUI_CanvasNodePrs* SUPERVGUI_CanvasNode::createPrs() const
100 {
101   return new SUPERVGUI_CanvasNodePrs(myMain->getCanvas(), (SUPERVGUI_CanvasNode*)this);
102 }
103
104 void SUPERVGUI_CanvasNode::createPort(SUPERV::Port_ptr thePort) const
105 {
106   SUPERVGUI_CanvasPort* aPort = 0;
107   if (thePort->IsInput())
108     aPort = new SUPERVGUI_CanvasPortIn((SUPERVGUI_CanvasNode*)this, myMain, thePort);
109   else
110     aPort = new SUPERVGUI_CanvasPortOut((SUPERVGUI_CanvasNode*)this, myMain, thePort);
111
112   if (aPort) {
113     connect(aPort, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
114     if (!isIgnore) getPrs()->updatePorts();
115   }
116 }
117
118 void SUPERVGUI_CanvasNode::createStreamPort(SUPERV::StreamPort_ptr thePort) const
119 {
120   SUPERVGUI_CanvasPort* aPort = 0;
121   if (thePort->IsInput())
122     aPort = new SUPERVGUI_CanvasStreamPortIn((SUPERVGUI_CanvasNode*)this, myMain, thePort);
123   else
124     aPort = new SUPERVGUI_CanvasStreamPortOut((SUPERVGUI_CanvasNode*)this, myMain, thePort);
125
126   if (aPort) {
127     connect(aPort, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
128     if (!isIgnore) getPrs()->updatePorts();
129   }
130 }
131
132 void SUPERVGUI_CanvasNode::onDestroyed(QObject* theObject)
133 {
134   if (!isIgnore) {
135     removeChild(theObject); // signal is sent before removing the object
136     getPrs()->updatePorts();
137   }
138 }
139
140 QPopupMenu* SUPERVGUI_CanvasNode::getPopupMenu(QWidget* theParent) 
141 {
142   QPopupMenu* popup = new QPopupMenu(theParent);
143   if (myMain->getDataflow()->IsExecuting()) {
144     popup->insertItem((myNode->IsSuspended()?tr("MSG_RESUME"):tr("MSG_SUSPEND")),
145                       this, SLOT(suspendResume()));
146     popup->insertItem(tr("MSG_KILL"), this, SLOT(kill()));
147   }
148   else {
149     if (myMain->isEditable() && getNodeType() != SUPERV::EndLoopNode
150                              && getNodeType() != SUPERV::EndSwitchNode) {
151       popup->insertItem(tr("MSG_RENAME"), this, SLOT(rename()));
152       popup->insertItem(tr("MSG_DELETE"), this, SLOT(remove()));
153       popup->insertSeparator();
154     }
155     popup->insertItem(tr("MSG_BROWSE"), this, SLOT(browse()));
156
157     if (getNodeType() != SUPERV::EndLoopNode && 
158         getNodeType() != SUPERV::EndSwitchNode)
159       popup->insertItem(tr("MSG_CHANGE_INFO"), this, SLOT(changeInformation()));
160
161     if (myMain->isEditable() && getNodeType() != SUPERV::FactoryNode
162                              && getNodeType() != SUPERV::ComputingNode
163                              && getNodeType() != SUPERV::EndLoopNode
164                              && getNodeType() != SUPERV::MacroNode) {
165       QPopupMenu* addPortMenu = new QPopupMenu(theParent);
166       addPortMenu->insertItem("Input", this, SLOT(addInputPort()));
167       if (getNodeType() != SUPERV::LoopNode)
168         addPortMenu->insertItem("Output", this, SLOT(addOutputPort()));
169       
170       popup->insertSeparator();
171       if ((getNodeType() != SUPERV::EndSwitchNode))
172         popup->insertItem("Edit Function", this, SLOT(editFunction()));
173       popup->insertItem("Add Port", addPortMenu);
174     }
175   }
176
177   return popup;
178 }
179
180 void SUPERVGUI_CanvasNode::show() 
181 {
182   getPrs()->show();
183 }
184
185 void SUPERVGUI_CanvasNode::showAll() 
186 {
187   getPrs()->showAll();
188 }
189
190 void SUPERVGUI_CanvasNode::hideAll() 
191 {
192   getPrs()->hideAll();
193 }
194
195 void SUPERVGUI_CanvasNode::switchLabel()
196 {
197   getPrs()->setLabelVisible(!getPrs()->isLabelVisible());
198 }
199
200 void SUPERVGUI_CanvasNode::switchPorts()
201 {
202   getPrs()->setPortVisible(!getPrs()->isPortVisible());
203 }
204
205 void SUPERVGUI_CanvasNode::move(int x, int y)
206 {
207   //  myNode->Coords(x, y); //  <<<- done inside Prs to reflect item movement by mouse press
208   if (x > GRAPH_MAX) x = (int) getPrs()->x();
209   if (y > GRAPH_MAX) y = (int) getPrs()->y();
210   getPrs()->move(x, y);
211 }
212
213 void SUPERVGUI_CanvasNode::merge() 
214 {
215   //MESSAGE("===> SUPERVGUI_CanvasNode::merge() " << myNode->Name());
216   // synchronize port list
217   bool update = false;
218   isIgnore = true;
219   SUPERVGUI_CanvasPort* aPort;
220   QObjectList* aPortList = queryList("SUPERVGUI_CanvasPort");
221   //cout << "     get port list... " ;
222   SUPERV_Ports aPorts = myNode->Ports();
223   //cout << aPorts->length() << endl;
224   for (int i = 0; i < aPorts->length(); i++) {
225     aPort = (SUPERVGUI_CanvasPort*) 
226       child(myMain->getCanvas()->getPortName(aPorts[i].in()), "SUPERVGUI_CanvasPort");
227     if (aPort) {
228   //cout << "     update port " << aPort->name() << endl;
229       aPortList->removeRef(aPort);
230       aPort->update();
231     }
232     else {
233   //cout << "     create port " << myMain->getCanvas()->getPortName(aPorts[i].in()) << endl;
234       createPort(aPorts[i].in());
235       update = true;
236     }
237   }
238
239   //cout << "     get stream port list... " ;
240   SUPERV_StreamPorts aStreamPorts = myNode->StreamPorts();
241   //cout << aStreamPorts->length() << endl;
242   for (int i = 0; i < aStreamPorts->length(); i++) {
243     aPort = (SUPERVGUI_CanvasPort*) 
244       child(myMain->getCanvas()->getPortName(aStreamPorts[i].in()), "SUPERVGUI_CanvasPort");
245     if (aPort) {
246   //cout << "     update stream port " << aPort->name() << endl;
247       aPortList->removeRef(aPort);
248       aPort->update();
249     }
250     else {
251   //cout << "     create stream port " << myMain->getCanvas()->getPortName(aStreamPorts[i].in()) << endl;
252       createPort(aStreamPorts[i].in());
253       update = true;
254     }
255   }
256
257   //cout << "     remove inexistant " << endl;
258   QObjectListIt it(*aPortList);
259   while ((aPort=(SUPERVGUI_CanvasPort*)it.current()) != 0) {
260     ++it;
261     aPortList->removeRef(aPort);
262     delete aPort;
263     update = true;
264   }
265   delete aPortList;
266   isIgnore = false;
267   if (update) getPrs()->updatePorts();
268
269   sync(); // update node state also
270 }
271
272 void SUPERVGUI_CanvasNode::sync() 
273 {
274   //MESSAGE("===> SUPERVGUI_CanvasNode::sync() " << myNode->Name() << ", state " << myNode->State());
275
276   const bool isExecuting = myMain->getDataflow()->IsExecuting();
277   //if myNode is a MacroNode then set it state to state of its subgraph
278   if ( myNode->IsMacro() && isExecuting ) {
279     // get SubGraph from MacroNode
280     SUPERV_Graph aMacro = SUPERV::Graph::_narrow(myNode);
281     if (!SUPERV_isNull(aMacro)) {
282       SUPERV_Graph aGraph;
283       if (aMacro->IsStreamMacro())
284         aGraph = aMacro->StreamObjRef();
285       else
286         aGraph = aMacro->FlowObjRef();
287       if (!SUPERV_isNull(aGraph)) {
288         if (aGraph->State() != SUPERV::UndefinedState && aGraph->State() != SUPERV::NoState)
289           getPrs()->setState(aGraph->State());
290         else 
291           getPrs()->setState(myNode->State());
292       }
293     }
294   }
295   else {
296     SUPERV::GraphState aState = myNode->State();
297
298     // asv : 18.11.04 : fix for 6170 : after execution is finished, nodes' status must be reset.
299     if ( !isExecuting && myMain->IsGUIEventLoopFinished() && (aState == SUPERV::DoneState || 
300          aState == SUPERV::KillState || aState == SUPERV::StopState ) )
301         aState = SUPERV::EditingState;
302     getPrs()->setState(aState);
303   }
304   
305   // update child ports
306   const QObjectList* list = children();
307   if (list) {
308     QObjectListIt it(*list);
309     while (QObject* obj = it.current()) {
310       ++it;
311       if (obj->inherits("SUPERVGUI_CanvasPort")) {
312         ((SUPERVGUI_CanvasPort*)obj)->sync();
313       }
314     }
315   }
316 }
317
318 void SUPERVGUI_CanvasNode::syncOnEvent(SUPERV::GraphState theStateFromEvent) 
319 {
320   getPrs()->setState(theStateFromEvent);
321 }
322
323 bool SUPERVGUI_CanvasNode::setNodeName(QString aName) 
324 {
325   bool result = myNode->SetName(aName.latin1());
326   if (result) {
327     setName(myNode->Name());
328     getPrs()->updateInfo();
329     // TODO: update name of all the links to this node
330   } 
331   else {
332     QMessageBox::warning( QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_CANT_RENAMENODE" ) );
333   }
334   return result;
335 }
336
337 void SUPERVGUI_CanvasNode::rename()
338 {
339   QString aName = SALOMEGUI_NameDlg::getName(QAD_Application::getDesktop(), myNode->Name());
340   if (!aName.isEmpty()) {
341     setNodeName(aName);
342   }
343 }
344
345 void SUPERVGUI_CanvasNode::remove() {
346   Trace("SUPERVGUI_CanvasNode::remove");
347   SUPERVGUI_Canvas* aCanvas = myMain->getCanvas();
348   setDestroyed();
349   myNode->destroy();
350   delete this;
351   aCanvas->update();
352 }
353
354 void SUPERVGUI_CanvasNode::suspendResume() {
355   Trace("SUPERVGUI_CanvasNode::suspendResume");
356   int n = queryList("SUPERVGUI_CanvasNode")->count(); 
357   if (myNode->IsSuspended()) {
358     if (!((n==1)? myMain->getDataflow()->Resume() : myNode->Resume())) {
359       QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_RESUMENODE"));
360     }
361     else {
362       sync();
363       myMain->getMyThread()->startThread(tr("MSG_NODE_RESUMED1")+myNode->Name()+tr("MSG_NODE_RESUMED2"));
364     }
365   } else {
366     if (!((n==1)? myMain->getDataflow()->Suspend() : myNode->Suspend())) {
367       QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_SUSPENDNODE"));
368     } else {
369       syncOnEvent(SUPERV::SuspendReadyState);
370       myMain->getMyThread()->stopThread(tr("MSG_NODE_SUSPENDED1")+myNode->Name()+tr("MSG_NODE_SUSPENDED2"));
371     }
372   }
373 }
374
375 void SUPERVGUI_CanvasNode::kill() {
376   Trace("SUPERVGUI_CanvasNode::kill");
377   int n = queryList("SUPERVGUI_CanvasNode")->count(); 
378   if (!((n==1)? myMain->getDataflow()->Kill() : myNode->Kill())) {
379     QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_KILLNODE"));
380   } else {
381     syncOnEvent(SUPERV_Kill);
382     myMain->getMyThread()->stopThread(tr("MSG_NODE_KILLED1")+myNode->Name()+tr("MSG_NODE_KILLED2"));
383   }
384 }
385
386 void SUPERVGUI_CanvasNode::stopRestart() {
387   Trace("SUPERVGUI_CanvasNode::stopRestart");
388   
389   int n = queryList("SUPERVGUI_CanvasNode")->count(); 
390   if ((myNode->State() == SUPERV_Stop) || (myNode->State() == SUPERV_Kill)) {
391     if (!((n==1)? myMain->getDataflow()->Run() : myNode->ReStart())) {
392       QMessageBox::warning(QAD_Application::getDesktop(),  tr("ERROR"), tr("MSG_CANT_RESTARTNODE"));
393     }
394   } else {
395     if (!((n==1)? myMain->getDataflow()->Stop() : myNode->Stop())) {
396       QMessageBox::warning(QAD_Application::getDesktop(),  tr("ERROR"), tr("MSG_CANT_STOPNODE"));
397     }
398   }
399 }
400
401 void SUPERVGUI_CanvasNode::changeInformation() {
402   SUPERVGUI_Information* aDlg = new SUPERVGUI_Information(myNode, !myMain->isEditable());
403   if (aDlg->exec()) {
404     QString aName = myNode->Name();
405     if (!aName.isEmpty() && myMain->isEditable())
406       setNodeName(aName);
407   }
408   delete aDlg;
409 }
410
411 void SUPERVGUI_CanvasNode::configure() 
412 {
413   Trace("SUPERVGUI_CanvasNode::configure");
414   QMessageBox::warning(QAD_Application::getDesktop(),  tr("ERROR"), tr("MSG_NOT_IMPLEMENTED")); // kloss : a faire : lancer l'ihm DATA
415 }
416
417 void SUPERVGUI_CanvasNode::showPython() 
418 {
419   Trace("SUPERVGUI_CanvasNode::showPython");
420   SUPERVGUI_Python cp(myMain->getStudy()->get_PyInterp(), !myMain->isEditable());
421   cp.exec();
422 }
423
424 bool SUPERVGUI_CanvasNode::isWarning() 
425 {
426   Trace("SUPERVGUI_CanvasNode::isWarning");
427   return(warning);
428 }
429
430 bool SUPERVGUI_CanvasNode::isStep() 
431 {
432   Trace("SUPERVGUI_CanvasNode::isStep");
433   return(step);
434 }
435
436 bool SUPERVGUI_CanvasNode::isTrace() 
437 {
438   Trace("SUPERVGUI_CanvasNode::isTrace");
439   return(trace);
440 }
441
442 bool SUPERVGUI_CanvasNode::isVerbose() 
443 {
444   Trace("SUPERVGUI_CanvasNode::isVerbose");
445   return(verbose);
446 }
447
448 void SUPERVGUI_CanvasNode::setWarning(bool b) 
449 {
450   Trace("SUPERVGUI_CanvasNode::setWarning");
451   warning = b;
452 }
453
454 void SUPERVGUI_CanvasNode::setStep(bool b) 
455 {
456   Trace("SUPERVGUI_CanvasNode::setStep");
457   step = b;
458 }
459
460 void SUPERVGUI_CanvasNode::setTrace(bool b) 
461 {
462   Trace("SUPERVGUI_CanvasNode::setTrace");
463   trace = b;
464 }
465
466 void SUPERVGUI_CanvasNode::setVerbose(bool b) 
467 {
468   Trace("SUPERVGUI_CanvasNode::setVerbose");
469   verbose = b;
470 }
471
472
473 void SUPERVGUI_CanvasNode::browse() 
474 {
475   if (!myBrowseDlg) {
476     myBrowseDlg = new SUPERVGUI_BrowseNodeDlg(this);
477     myBrowseDlg->installEventFilter(this);
478   }
479   if (!myBrowseDlg->isVisible())
480     myBrowseDlg->show();
481   else {
482     myBrowseDlg->raise();
483     myBrowseDlg->setActiveWindow();
484     myBrowseDlg->setFocus();
485   }
486 }
487
488 bool SUPERVGUI_CanvasNode::eventFilter( QObject* o, QEvent* e )
489 {
490   if (o == myBrowseDlg && e->type() == QEvent::Close)
491     myBrowseDlg = 0;
492
493   return QObject::eventFilter(o, e);
494 }
495
496 QStringList SUPERVGUI_CanvasNode::getPortsNamesIN(SUPERV_INode theNode, bool theInputPorts)
497 {
498   QStringList aPNList;
499   if (!SUPERV_isNull(theNode)) {
500     SUPERV_Ports aPorts = theNode->Ports();
501     for (int i=0; i<aPorts->length(); i++) {
502       if (theInputPorts) {
503         if (aPorts[i]->IsInput()) aPNList.append(QString(aPorts[i]->Name()));
504       }
505       else 
506         if (!aPorts[i]->IsInput()) aPNList.append(QString(aPorts[i]->Name()));
507     }
508   }
509   return aPNList;
510 }
511
512 SUPERV_Port SUPERVGUI_CanvasNode::createInPort() 
513 {
514   SUPERV_INode aNode = getInlineNode();
515   if (SUPERV_isNull(aNode)) {
516     MESSAGE("SUPERVGUI_CanvasNode::createInPort: Node is wrong type");
517     return NULL;
518   }
519   SUPERVGUI_PortParamsDlg* aDlg = new SUPERVGUI_PortParamsDlg(getPortsNamesIN(aNode,true));
520   if (aDlg->exec()) {
521     SUPERV_Port aPort = aNode->InPort(aDlg->getName().latin1(),
522                                       aDlg->getType().latin1());    
523     delete aDlg;
524     return aPort;
525   }
526   delete aDlg;
527   return NULL;
528 }
529
530 SUPERV_Port SUPERVGUI_CanvasNode::createOutPort() 
531 {
532   SUPERV_INode aNode = getInlineNode();
533   if (SUPERV_isNull(aNode)) {
534     MESSAGE("SUPERVGUI_CanvasNode::createOutPort: Node is wrong type");
535     return NULL;
536   }
537   
538   SUPERVGUI_PortParamsDlg* aDlg = new SUPERVGUI_PortParamsDlg(getPortsNamesIN(aNode,false));
539   if (aDlg->exec()) {
540     SUPERV_Port aPort = aNode->OutPort(aDlg->getName().latin1(),
541                                        aDlg->getType().latin1());
542     delete aDlg;
543     return aPort;
544   }
545   delete aDlg;
546   return NULL;
547 }
548
549 void SUPERVGUI_CanvasNode::addInputPort() {
550   SUPERV_Port aPort = createInPort();
551   if (aPort == NULL) return;
552
553   createPort(aPort.in());
554 }
555
556
557 void SUPERVGUI_CanvasNode::addOutputPort() {
558   SUPERV_Port aPort = createOutPort();
559   if (aPort == NULL) return;
560
561   createPort(aPort.in());
562 }
563
564
565 void SUPERVGUI_CanvasNode::editFunction() 
566 {
567   if (getNodeType() == SUPERV::LoopNode) {
568     SUPERVGUI_EditPythonDlg* aDlg = new SUPERVGUI_EditPythonDlg(true);
569     SUPERV_LNode aLNode = getLoopNode();
570     aDlg->setInitFunction(aLNode->PyInit());
571     aDlg->setMoreFunction(aLNode->PyMore());
572     aDlg->setNextFunction(aLNode->PyNext());
573     if (aDlg->exec()) {
574       aLNode->SetPyInit(aDlg->getInitFuncName().latin1(), (aDlg->getInitFunction()).in());
575       aLNode->SetPyMore(aDlg->getMoreFuncName().latin1(), (aDlg->getMoreFunction()).in());
576       aLNode->SetPyNext(aDlg->getNextFuncName().latin1(), (aDlg->getNextFunction()).in());
577     }
578     delete aDlg;
579   } 
580   else {
581     SUPERVGUI_EditPythonDlg* aDlg = new SUPERVGUI_EditPythonDlg();
582     SUPERV_INode aINode = getInlineNode();
583     aDlg->setFunction(aINode->PyFunction());
584     if (aDlg->exec()) {
585       aINode->SetPyFunction(aDlg->getFuncName().latin1(), (aDlg->getFunction()).in());
586     }
587     delete aDlg;
588   }
589 }