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