Salome HOME
A new popup menu item and new slot are added to the class to display "Edit Ports...
[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 "SUPERVGUI_ManagePortsDlg.h"
18 #include "SALOMEGUI_NameDlg.h"
19 #include "SUPERVGUI_Information.h"
20 /*
21 #include "SUPERVGUI_CanvasControlNode.h"
22
23 #include <qtooltip.h>
24 */
25
26 SUPERVGUI_CanvasNode::SUPERVGUI_CanvasNode(QObject* theParent, SUPERVGUI_Main* theMain, SUPERV_CNode theNode):
27     QObject(theParent),
28     myMain(theMain),
29     myNode(theNode),
30     myPrs(0),
31     myDestroyed(false),
32     warning(true),
33     step(true),
34     trace(true),
35     verbose(true),
36     myBrowseDlg(0)
37 {
38   Trace("SUPERVGUI_CanvasNode::SUPERVGUI_CanvasNode");
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 }
79
80 SUPERVGUI_CanvasNode::~SUPERVGUI_CanvasNode()
81 {
82   isIgnore = true;
83   if (myPrs) delete myPrs;
84 }
85
86 void SUPERVGUI_CanvasNode::setDestroyed()
87 {
88   myDestroyed = true;
89   getPrs()->hide();
90 }
91
92 SUPERVGUI_CanvasNodePrs* SUPERVGUI_CanvasNode::getPrs() const
93 {
94   if (myPrs == 0) {
95     ((SUPERVGUI_CanvasNode*)this)->myPrs = createPrs();
96   }
97   return myPrs;
98 }
99
100 SUPERVGUI_CanvasNodePrs* SUPERVGUI_CanvasNode::createPrs() const
101 {
102   return new SUPERVGUI_CanvasNodePrs(myMain->getCanvas(), (SUPERVGUI_CanvasNode*)this);
103 }
104
105 void SUPERVGUI_CanvasNode::createPort(SUPERV::Port_ptr thePort) const
106 {
107   SUPERVGUI_CanvasPort* aPort = 0;
108   if (thePort->IsInput())
109     aPort = new SUPERVGUI_CanvasPortIn((SUPERVGUI_CanvasNode*)this, myMain, thePort);
110   else
111     aPort = new SUPERVGUI_CanvasPortOut((SUPERVGUI_CanvasNode*)this, myMain, thePort);
112
113   if (aPort) {
114     connect(aPort, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
115     if (!isIgnore) getPrs()->updatePorts();
116   }
117 }
118
119 void SUPERVGUI_CanvasNode::createStreamPort(SUPERV::StreamPort_ptr thePort) const
120 {
121   SUPERVGUI_CanvasPort* aPort = 0;
122   if (thePort->IsInput())
123     aPort = new SUPERVGUI_CanvasStreamPortIn((SUPERVGUI_CanvasNode*)this, myMain, thePort);
124   else
125     aPort = new SUPERVGUI_CanvasStreamPortOut((SUPERVGUI_CanvasNode*)this, myMain, thePort);
126
127   if (aPort) {
128     connect(aPort, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroyed(QObject*)));
129     if (!isIgnore) getPrs()->updatePorts();
130   }
131 }
132
133 void SUPERVGUI_CanvasNode::onDestroyed(QObject* theObject)
134 {
135   if (!isIgnore) {
136     removeChild(theObject); // signal is sent before removing the object
137     getPrs()->updatePorts();
138   }
139 }
140
141 QPopupMenu* SUPERVGUI_CanvasNode::getPopupMenu(QWidget* theParent) 
142 {
143   QPopupMenu* popup = new QPopupMenu(theParent);
144   if (myMain->getDataflow()->IsExecuting()) {
145     popup->insertItem((myNode->IsSuspended()?tr("MSG_RESUME"):tr("MSG_SUSPEND")),
146                       this, SLOT(suspendResume()));
147     popup->insertItem(tr("MSG_KILL"), this, SLOT(kill()));
148   }
149   else {
150     if (myMain->isEditable() && getNodeType() != SUPERV::EndLoopNode
151                              && getNodeType() != SUPERV::EndSwitchNode) {
152       popup->insertItem(tr("MSG_RENAME"), this, SLOT(rename()));
153       popup->insertItem(tr("MSG_DELETE"), this, SLOT(remove()));
154       popup->insertSeparator();
155     }
156     popup->insertItem(tr("MSG_BROWSE"), this, SLOT(browse()));
157
158     if (getNodeType() != SUPERV::EndLoopNode && 
159         getNodeType() != SUPERV::EndSwitchNode)
160       popup->insertItem(tr("MSG_CHANGE_INFO"), this, SLOT(changeInformation()));
161
162     if (myMain->isEditable() && getNodeType() != SUPERV::FactoryNode
163                              && getNodeType() != SUPERV::ComputingNode
164                              && getNodeType() != SUPERV::EndLoopNode
165                              && getNodeType() != SUPERV::MacroNode) {
166       QPopupMenu* addPortMenu = new QPopupMenu(theParent);
167       addPortMenu->insertItem( tr( "MNU_INPUT" ), this, SLOT(addInputPort()));
168       if (getNodeType() != SUPERV::LoopNode)
169         addPortMenu->insertItem( tr( "MNU_OUTPUT" ), this, SLOT(addOutputPort()));
170       
171       popup->insertSeparator();
172       if ((getNodeType() != SUPERV::EndSwitchNode))
173         popup->insertItem( tr( "MNU_EDIT_FUNC" ), this, SLOT(editFunction()));
174       popup->insertItem( tr( "MNU_ADD_PORT" ), addPortMenu);
175       popup->insertItem( tr( "MNU_MANAGE_PORTS" ), this, SLOT(managePorts()));
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   //MESSAGE("===> SUPERVGUI_CanvasNode::merge() " << myNode->Name());
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   //MESSAGE("===> SUPERVGUI_CanvasNode::sync() " << myNode->Name() << ", state " << myNode->State());
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 QStringList SUPERVGUI_CanvasNode::getPortsNamesIN(SUPERV_INode theNode, bool theInputPorts)
490 {
491   QStringList aPNList;
492   if (!SUPERV_isNull(theNode)) {
493     SUPERV_Ports aPorts = theNode->Ports();
494     for (int i=0; i<aPorts->length(); i++) {
495       if (theInputPorts) {
496         if (aPorts[i]->IsInput()) aPNList.append(QString(aPorts[i]->Name()));
497       }
498       else 
499         if (!aPorts[i]->IsInput()) aPNList.append(QString(aPorts[i]->Name()));
500     }
501   }
502   return aPNList;
503 }
504
505 SUPERV_Port SUPERVGUI_CanvasNode::createInPort() 
506 {
507   SUPERV_INode aNode = getInlineNode();
508   if (SUPERV_isNull(aNode)) {
509     MESSAGE("SUPERVGUI_CanvasNode::createInPort: Node is wrong type");
510     return NULL;
511   }
512   SUPERVGUI_PortParamsDlg* aDlg = new SUPERVGUI_PortParamsDlg(getPortsNamesIN(aNode,true));
513   if (aDlg->exec()) {
514     SUPERV_Port aPort = aNode->InPort(aDlg->getName().latin1(),
515                                       aDlg->getType().latin1());    
516     delete aDlg;
517     return aPort;
518   }
519   delete aDlg;
520   return NULL;
521 }
522
523 SUPERV_Port SUPERVGUI_CanvasNode::createOutPort() 
524 {
525   SUPERV_INode aNode = getInlineNode();
526   if (SUPERV_isNull(aNode)) {
527     MESSAGE("SUPERVGUI_CanvasNode::createOutPort: Node is wrong type");
528     return NULL;
529   }
530   
531   SUPERVGUI_PortParamsDlg* aDlg = new SUPERVGUI_PortParamsDlg(getPortsNamesIN(aNode,false));
532   if (aDlg->exec()) {
533     SUPERV_Port aPort = aNode->OutPort(aDlg->getName().latin1(),
534                                        aDlg->getType().latin1());
535     delete aDlg;
536     return aPort;
537   }
538   delete aDlg;
539   return NULL;
540 }
541
542 void SUPERVGUI_CanvasNode::addInputPort() {
543   SUPERV_Port aPort = createInPort();
544   if (aPort == NULL) return;
545
546   createPort(aPort.in());
547 }
548
549
550 void SUPERVGUI_CanvasNode::addOutputPort() {
551   SUPERV_Port aPort = createOutPort();
552   if (aPort == NULL) return;
553
554   createPort(aPort.in());
555 }
556
557
558 void SUPERVGUI_CanvasNode::editFunction() 
559 {
560   if (getNodeType() == SUPERV::LoopNode) {
561     SUPERVGUI_EditPythonDlg* aDlg = new SUPERVGUI_EditPythonDlg(true);
562     SUPERV_LNode aLNode = getLoopNode();
563     aDlg->setInitFunction(aLNode->PyInit());
564     aDlg->setMoreFunction(aLNode->PyMore());
565     aDlg->setNextFunction(aLNode->PyNext());
566     if (aDlg->exec()) {
567       aLNode->SetPyInit(aDlg->getInitFuncName().latin1(), (aDlg->getInitFunction()).in());
568       aLNode->SetPyMore(aDlg->getMoreFuncName().latin1(), (aDlg->getMoreFunction()).in());
569       aLNode->SetPyNext(aDlg->getNextFuncName().latin1(), (aDlg->getNextFunction()).in());
570     }
571     delete aDlg;
572   } 
573   else {
574     SUPERVGUI_EditPythonDlg* aDlg = new SUPERVGUI_EditPythonDlg();
575     SUPERV_INode aINode = getInlineNode();
576     aDlg->setFunction(aINode->PyFunction());
577     if (aDlg->exec()) {
578       aINode->SetPyFunction(aDlg->getFuncName().latin1(), (aDlg->getFunction()).in());
579     }
580     delete aDlg;
581   }
582 }
583
584 /** 
585  * Called on "Edit ports" popup menu command. See SUPERVGUI_ManagePortsDlg.h
586  * for detailed description of the functionality
587  */
588 void SUPERVGUI_CanvasNode::managePorts() {
589   SUPERVGUI_ManagePortsDlg* aDlg = new SUPERVGUI_ManagePortsDlg( this );
590   aDlg->exec();
591   delete aDlg;
592 }