Salome HOME
273f161e23e90f68ea200e91d5eaa7545b930e42
[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   //if myNode is a MacroNode then set it state to state of its subgraph
277   if (myNode->IsMacro() && myMain->getDataflow()->IsExecuting()) {
278     // get SubGraph from MacroNode
279     SUPERV_Graph aMacro = SUPERV::Graph::_narrow(myNode);
280     if (!SUPERV_isNull(aMacro)) {
281       SUPERV_Graph aGraph;
282       if (aMacro->IsStreamMacro())
283         aGraph = aMacro->StreamObjRef();
284       else
285         aGraph = aMacro->FlowObjRef();
286       if (!SUPERV_isNull(aGraph)) {
287         if (aGraph->State() != SUPERV::UndefinedState && aGraph->State() != SUPERV::NoState)
288           getPrs()->setState(aGraph->State());
289         else 
290           getPrs()->setState(myNode->State());
291       }
292     }
293   }
294   else 
295     getPrs()->setState(myNode->State());
296   
297   // update child ports
298   const QObjectList* list = children();
299   if (list) {
300     QObjectListIt it(*list);
301     while (QObject* obj = it.current()) {
302       ++it;
303       if (obj->inherits("SUPERVGUI_CanvasPort")) {
304         ((SUPERVGUI_CanvasPort*)obj)->sync();
305       }
306     }
307   }
308 }
309
310 void SUPERVGUI_CanvasNode::syncOnEvent(SUPERV::GraphState theStateFromEvent) 
311 {
312   getPrs()->setState(theStateFromEvent);
313 }
314
315 bool SUPERVGUI_CanvasNode::setNodeName(QString aName) 
316 {
317   bool result = myNode->SetName(aName.latin1());
318   if (result) {
319     setName(myNode->Name());
320     getPrs()->updateInfo();
321     // TODO: update name of all the links to this node
322   } 
323   else {
324     QMessageBox::warning( QAD_Application::getDesktop(), tr( "ERROR" ), tr( "MSG_CANT_RENAMENODE" ) );
325   }
326   return result;
327 }
328
329 void SUPERVGUI_CanvasNode::rename()
330 {
331   QString aName = SALOMEGUI_NameDlg::getName(QAD_Application::getDesktop(), myNode->Name());
332   if (!aName.isEmpty()) {
333     setNodeName(aName);
334   }
335 }
336
337 void SUPERVGUI_CanvasNode::remove() {
338   Trace("SUPERVGUI_CanvasNode::remove");
339   SUPERVGUI_Canvas* aCanvas = myMain->getCanvas();
340   setDestroyed();
341   myNode->destroy();
342   delete this;
343   aCanvas->update();
344 }
345
346 void SUPERVGUI_CanvasNode::suspendResume() {
347   Trace("SUPERVGUI_CanvasNode::suspendResume");
348   int n = queryList("SUPERVGUI_CanvasNode")->count(); 
349   if (myNode->IsSuspended()) {
350     if (!((n==1)? myMain->getDataflow()->Resume() : myNode->Resume())) {
351       QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_RESUMENODE"));
352     }
353     else {
354       sync();
355       myMain->getMyThread()->startThread(tr("MSG_NODE_RESUMED1")+myNode->Name()+tr("MSG_NODE_RESUMED2"));
356     }
357   } else {
358     if (!((n==1)? myMain->getDataflow()->Suspend() : myNode->Suspend())) {
359       QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_SUSPENDNODE"));
360     } else {
361       syncOnEvent(SUPERV::SuspendReadyState);
362       myMain->getMyThread()->stopThread(tr("MSG_NODE_SUSPENDED1")+myNode->Name()+tr("MSG_NODE_SUSPENDED2"));
363     }
364   }
365 }
366
367 void SUPERVGUI_CanvasNode::kill() {
368   Trace("SUPERVGUI_CanvasNode::kill");
369   int n = queryList("SUPERVGUI_CanvasNode")->count(); 
370   if (!((n==1)? myMain->getDataflow()->Kill() : myNode->Kill())) {
371     QMessageBox::warning(QAD_Application::getDesktop(), tr("ERROR"), tr("MSG_CANT_KILLNODE"));
372   } else {
373     syncOnEvent(SUPERV_Kill);
374     myMain->getMyThread()->stopThread(tr("MSG_NODE_KILLED1")+myNode->Name()+tr("MSG_NODE_KILLED2"));
375   }
376 }
377
378 void SUPERVGUI_CanvasNode::stopRestart() {
379   Trace("SUPERVGUI_CanvasNode::stopRestart");
380   
381   int n = queryList("SUPERVGUI_CanvasNode")->count(); 
382   if ((myNode->State() == SUPERV_Stop) || (myNode->State() == SUPERV_Kill)) {
383     if (!((n==1)? myMain->getDataflow()->Run() : myNode->ReStart())) {
384       QMessageBox::warning(QAD_Application::getDesktop(),  tr("ERROR"), tr("MSG_CANT_RESTARTNODE"));
385     }
386   } else {
387     if (!((n==1)? myMain->getDataflow()->Stop() : myNode->Stop())) {
388       QMessageBox::warning(QAD_Application::getDesktop(),  tr("ERROR"), tr("MSG_CANT_STOPNODE"));
389     }
390   }
391 }
392
393 void SUPERVGUI_CanvasNode::changeInformation() {
394   SUPERVGUI_Information* aDlg = new SUPERVGUI_Information(myNode, !myMain->isEditable());
395   if (aDlg->exec()) {
396     QString aName = myNode->Name();
397     if (!aName.isEmpty() && myMain->isEditable())
398       setNodeName(aName);
399   }
400   delete aDlg;
401 }
402
403 void SUPERVGUI_CanvasNode::configure() 
404 {
405   Trace("SUPERVGUI_CanvasNode::configure");
406   QMessageBox::warning(QAD_Application::getDesktop(),  tr("ERROR"), tr("MSG_NOT_IMPLEMENTED")); // kloss : a faire : lancer l'ihm DATA
407 }
408
409 void SUPERVGUI_CanvasNode::showPython() 
410 {
411   Trace("SUPERVGUI_CanvasNode::showPython");
412   SUPERVGUI_Python cp(myMain->getStudy()->get_PyInterp(), !myMain->isEditable());
413   cp.exec();
414 }
415
416 bool SUPERVGUI_CanvasNode::isWarning() 
417 {
418   Trace("SUPERVGUI_CanvasNode::isWarning");
419   return(warning);
420 }
421
422 bool SUPERVGUI_CanvasNode::isStep() 
423 {
424   Trace("SUPERVGUI_CanvasNode::isStep");
425   return(step);
426 }
427
428 bool SUPERVGUI_CanvasNode::isTrace() 
429 {
430   Trace("SUPERVGUI_CanvasNode::isTrace");
431   return(trace);
432 }
433
434 bool SUPERVGUI_CanvasNode::isVerbose() 
435 {
436   Trace("SUPERVGUI_CanvasNode::isVerbose");
437   return(verbose);
438 }
439
440 void SUPERVGUI_CanvasNode::setWarning(bool b) 
441 {
442   Trace("SUPERVGUI_CanvasNode::setWarning");
443   warning = b;
444 }
445
446 void SUPERVGUI_CanvasNode::setStep(bool b) 
447 {
448   Trace("SUPERVGUI_CanvasNode::setStep");
449   step = b;
450 }
451
452 void SUPERVGUI_CanvasNode::setTrace(bool b) 
453 {
454   Trace("SUPERVGUI_CanvasNode::setTrace");
455   trace = b;
456 }
457
458 void SUPERVGUI_CanvasNode::setVerbose(bool b) 
459 {
460   Trace("SUPERVGUI_CanvasNode::setVerbose");
461   verbose = b;
462 }
463
464
465 void SUPERVGUI_CanvasNode::browse() 
466 {
467   if (!myBrowseDlg) {
468     myBrowseDlg = new SUPERVGUI_BrowseNodeDlg(this);
469     myBrowseDlg->installEventFilter(this);
470   }
471   if (!myBrowseDlg->isVisible())
472     myBrowseDlg->show();
473   else {
474     myBrowseDlg->raise();
475     myBrowseDlg->setActiveWindow();
476     myBrowseDlg->setFocus();
477   }
478 }
479
480 bool SUPERVGUI_CanvasNode::eventFilter( QObject* o, QEvent* e )
481 {
482   if (o == myBrowseDlg && e->type() == QEvent::Close)
483     myBrowseDlg = 0;
484   return QObject::eventFilter(o, e);
485 }
486
487 QStringList SUPERVGUI_CanvasNode::getPortsNamesIN(SUPERV_INode theNode, bool theInputPorts)
488 {
489   QStringList aPNList;
490   if (!SUPERV_isNull(theNode)) {
491     SUPERV_Ports aPorts = theNode->Ports();
492     for (int i=0; i<aPorts->length(); i++) {
493       if (theInputPorts) {
494         if (aPorts[i]->IsInput()) aPNList.append(QString(aPorts[i]->Name()));
495       }
496       else 
497         if (!aPorts[i]->IsInput()) aPNList.append(QString(aPorts[i]->Name()));
498     }
499   }
500   return aPNList;
501 }
502
503 SUPERV_Port SUPERVGUI_CanvasNode::createInPort() 
504 {
505   SUPERV_INode aNode = getInlineNode();
506   if (SUPERV_isNull(aNode)) {
507     MESSAGE("SUPERVGUI_CanvasNode::createInPort: Node is wrong type");
508     return NULL;
509   }
510   SUPERVGUI_PortParamsDlg* aDlg = new SUPERVGUI_PortParamsDlg(getPortsNamesIN(aNode,true));
511   if (aDlg->exec()) {
512     SUPERV_Port aPort = aNode->InPort(aDlg->getName().latin1(),
513                                       aDlg->getType().latin1());    
514     delete aDlg;
515     return aPort;
516   }
517   delete aDlg;
518   return NULL;
519 }
520
521 SUPERV_Port SUPERVGUI_CanvasNode::createOutPort() 
522 {
523   SUPERV_INode aNode = getInlineNode();
524   if (SUPERV_isNull(aNode)) {
525     MESSAGE("SUPERVGUI_CanvasNode::createOutPort: Node is wrong type");
526     return NULL;
527   }
528   
529   SUPERVGUI_PortParamsDlg* aDlg = new SUPERVGUI_PortParamsDlg(getPortsNamesIN(aNode,false));
530   if (aDlg->exec()) {
531     SUPERV_Port aPort = aNode->OutPort(aDlg->getName().latin1(),
532                                        aDlg->getType().latin1());
533     delete aDlg;
534     return aPort;
535   }
536   delete aDlg;
537   return NULL;
538 }
539
540 void SUPERVGUI_CanvasNode::addInputPort() {
541   SUPERV_Port aPort = createInPort();
542   if (aPort == NULL) return;
543
544   createPort(aPort.in());
545 }
546
547
548 void SUPERVGUI_CanvasNode::addOutputPort() {
549   SUPERV_Port aPort = createOutPort();
550   if (aPort == NULL) return;
551
552   createPort(aPort.in());
553 }
554
555
556 void SUPERVGUI_CanvasNode::editFunction() 
557 {
558   if (getNodeType() == SUPERV::LoopNode) {
559     SUPERVGUI_EditPythonDlg* aDlg = new SUPERVGUI_EditPythonDlg(true);
560     SUPERV_LNode aLNode = getLoopNode();
561     aDlg->setInitFunction(aLNode->PyInit());
562     aDlg->setMoreFunction(aLNode->PyMore());
563     aDlg->setNextFunction(aLNode->PyNext());
564     if (aDlg->exec()) {
565       aLNode->SetPyInit(aDlg->getInitFuncName().latin1(), (aDlg->getInitFunction()).in());
566       aLNode->SetPyMore(aDlg->getMoreFuncName().latin1(), (aDlg->getMoreFunction()).in());
567       aLNode->SetPyNext(aDlg->getNextFuncName().latin1(), (aDlg->getNextFunction()).in());
568     }
569     delete aDlg;
570   } 
571   else {
572     SUPERVGUI_EditPythonDlg* aDlg = new SUPERVGUI_EditPythonDlg();
573     SUPERV_INode aINode = getInlineNode();
574     aDlg->setFunction(aINode->PyFunction());
575     if (aDlg->exec()) {
576       aINode->SetPyFunction(aDlg->getFuncName().latin1(), (aDlg->getFunction()).in());
577     }
578     delete aDlg;
579   }
580 }