Salome HOME
Add functionality for Table view based on QCanvas.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI_GraphNode.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  CEA/DEN, EDF R&D
4 //
5 //
6 //
7 //  File   : SUPERVGUI_ComputeNode.cxx
8 //  Author : Vitaly SMETANNIKOV
9 //  Module : SUPERV
10
11 using namespace std;
12 #include "SUPERVGUI_GraphNode.h"
13 #include "SUPERVGUI_Graph.h"
14 #include "SUPERVGUI_Main.h"
15
16
17 SUPERVGUI_GraphNode::SUPERVGUI_GraphNode(QWidget* theParent, SUPERVGUI_Main* theMain, SUPERV_CNode theNode)
18   :SUPERVGUI_Node(theParent, theMain, theNode),
19    MouseX(MouseNo),
20    MouseY(MouseNo)
21 {
22   //disconnect(myTitle, 0, this, 0);
23   myTitle = new SUPERVGUI_Label(this, LABEL_WIDTH, LABEL_HEIGHT, name(), QLabel::AlignLeft);
24   myTitle->hide();
25   connect(myTitle, SIGNAL(MousePress(QMouseEvent*)), this, SLOT(mouseTitlePress(QMouseEvent*)));
26   connect(myTitle, SIGNAL(MouseMove (QMouseEvent*)), this, SLOT(mouseTitleMove(QMouseEvent*)));
27   connect(myTitle, SIGNAL(MouseRelease(QMouseEvent*)), this, SLOT(mouseTitleRelease(QMouseEvent*)));
28
29   myPortsBox = new QVBox(0);  
30   myPortsBox->setSpacing(3);
31   myValuesBox = new QWidget(myPortsBox);
32   myPortLayout = new QGridLayout(myValuesBox, 0, 2, 0, 1);
33
34   SUPERV_StreamPorts aStreamPorts = myNode->StreamPorts();
35   int  aStreamNb = aStreamPorts->length();
36   if (aStreamNb) {
37     myStreamBox = new QFrame(myPortsBox);
38     myStreamBox->setPaletteForegroundColor(red.dark());
39     myStreamBox->setPaletteBackgroundColor(paletteBackgroundColor());
40     myStreamBox->setFrameStyle( QFrame::Box | QFrame::Plain );
41     myStreamBox->setLineWidth(1);
42     myStreamLayout = new QGridLayout(myStreamBox, 0, 2, 2, 3);
43   } else {
44     myStreamBox = 0;
45     myStreamLayout = 0;
46   }
47   myGatesBox = new QFrame(myPortsBox);
48   myGatesBox->setFrameStyle( QFrame::Panel | QFrame::Raised );
49   myGatesBox->setLineWidth(2);
50   //  myGatesBox->setPaletteBackgroundColor(backgroundColor().dark(105));
51   myGatesBox->setPaletteBackgroundColor(green.light(170));
52   myGatesLayout = new QGridLayout(myGatesBox, 0, 2);
53   myGatesLayout->setMargin(3);
54   
55   myTimer = new QTimer(this);
56   connect(myTimer, SIGNAL(timeout()), this, SLOT(movingNode(/*QMouseEvent* e*/)));
57   myStopFlag = true;
58
59   myX = -1;
60   myY = -1;
61   myDifX = 0;
62   myDifY = 0;
63   myFirstDifX = 0;
64   myFirstDifY = 0;
65
66   myPIcount = 0;
67   myPOcount = 0;
68   SUPERV_Ports       ports = myNode->Ports();
69   int                n     = ports->length();
70  
71   for (int i=0; i<n; i++) {
72     if (ports[i]->IsInput()) {
73       if (getComputingNode()->IsEndSwitch()) {
74         if (ports[i]->IsGate())
75           myGatesLayout->addWidget(new SUPERVGUI_PortInESNode(myGatesBox, myMain, ports[i].in()), 
76                                   0, 0);
77         else {
78           myPortLayout->addWidget(new SUPERVGUI_PortInESNode(myValuesBox, myMain, ports[i].in()), 
79                                   myPIcount, 0);
80           myPIcount++;
81         }
82       } else {
83         if (ports[i]->IsGate())
84           myGatesLayout->addWidget(new SUPERVGUI_PortIn(myGatesBox, myMain, ports[i].in()), 
85                                    0, 0);
86         else {
87           myPortLayout->addWidget(new SUPERVGUI_PortIn(myValuesBox, myMain, ports[i].in()), 
88                                   myPIcount, 0);
89           myPIcount++;
90         }
91       }
92     } else {
93       if (ports[i]->IsGate())
94         myGatesLayout->addWidget(new SUPERVGUI_PortOut(myGatesBox, myMain, ports[i].in()), 
95                                  0, 1, Qt::AlignRight);
96       else {
97         myPortLayout->addWidget(new SUPERVGUI_PortOut(myValuesBox, myMain, ports[i].in()), 
98                                 myPOcount, 1, Qt::AlignRight);
99         myPOcount++;
100       }
101     }
102   }
103   myStrPIcount = 0;
104   myStrPOcount = 0;
105   for (int i=0; i < aStreamNb; i++) {
106     if (aStreamPorts[i]->IsInput()) {
107       myStreamLayout->addWidget(new SUPERVGUI_StreamPortIn(myStreamBox, myMain, aStreamPorts[i].in()), 
108                               myStrPIcount, 0);
109       myStrPIcount++;
110     } else {
111       myStreamLayout->addWidget(new SUPERVGUI_StreamPortOut(myStreamBox, myMain, aStreamPorts[i].in()), 
112                               myStrPOcount, 1, Qt::AlignRight);
113       myStrPOcount++;
114     }
115   }
116 }
117
118
119
120 SUPERVGUI_GraphNode::~SUPERVGUI_GraphNode() {
121 }
122
123 void SUPERVGUI_GraphNode::mouseTitlePress(QMouseEvent* e) {
124   if (!myMain->getGraph()->isAnyLinkCreating()) {
125     if (e->button() == RightButton) {
126       MouseLeft       = 0;
127       showPopup(e);
128     } else {
129       MouseLeft       = 1;
130       SUPERVGUI_Graph* sv = myMain->getGraph();
131       MouseX          = sv->childX(this) - e->globalX();
132       MouseY          = sv->childY(this) - e->globalY();
133     }
134   }
135 }
136
137 void SUPERVGUI_GraphNode::mouseTitleMove(QMouseEvent* e) {
138     Trace("SUPERVGUI_Node::moveAgain")
139     SUPERVGUI_Graph* sv = myMain->getGraph();
140
141     if ((MouseX == MouseNo) && (MouseY == MouseNo)) {
142         MouseX    = sv->childX(this) - e->globalX();
143         MouseY    = sv->childY(this) - e->globalY();
144         MouseLeft = (e->state() == RightButton? 0: 1);
145     };
146
147     if (MouseLeft == 1) {
148
149       int x = e->globalX()+MouseX;
150       int y = e->globalY()+MouseY;
151       x = x<0? 0: x;
152       y = y<0? 0: y;
153
154         if (x > myMain->getGraph()->horizontalScrollBar()->value()
155             + myMain->getGraph()->viewport()->width() - width()/2
156             ||
157             y > myMain->getGraph()->verticalScrollBar()->value()
158             + myMain->getGraph()->viewport()->height() - height()/2 
159             ||
160             x < myMain->getGraph()->horizontalScrollBar()->value()
161             ||
162             y < myMain->getGraph()->verticalScrollBar()->value()){
163           if (!myTimer->isActive()) {
164             myX = x;
165             myY = y;
166             myDifX = x - myNode->X();
167             myDifY = y - myNode->Y();
168             myFirstDifX = myDifX;
169             myFirstDifY = myDifY;
170           }
171
172           StartTimer();
173           myStopFlag = false;
174
175           if (x - myNode->X() > 15 && abs(myDifX) < abs(myDifY)) {
176             if (x > myMain->getGraph()->horizontalScrollBar()->value()
177                 + myMain->getGraph()->viewport()->width() - width()/2)
178               myDifX = 5; // or another positive number
179             else {
180               //not out of the right boundary
181               sv->moveChild(this, x, myNode->Y()); //new X and old Y
182               myNode->Coords(x, myNode->Y());
183               myX = x;
184             }
185           }
186
187           if (x - myNode->X() < -15 && abs(myDifX) < abs(myDifY)) {
188             if(x < myMain->getGraph()->horizontalScrollBar()->value())
189               myDifX = -5; //or another negative number
190             else {
191               //not out of the left boundary
192               sv->moveChild(this, x, myNode->Y()); //new X and old Y
193               myNode->Coords(x, myNode->Y());
194               myX = x;
195             }
196           }
197
198           if (y - myNode->Y() > 15 && abs(myDifX) > abs(myDifY)) {
199             if (y > myMain->getGraph()->verticalScrollBar()->value() 
200                 + myMain->getGraph()->viewport()->height() - height()/2)
201               myDifY = 5; //or another positive number
202             else {
203               //not out of the lower boundary
204               sv->moveChild(this, myNode->X(), y); //old X and new Y
205               myNode->Coords(myNode->X(), y);
206               myY = y;
207             }
208           }
209
210           if (y - myNode->Y() < -15 && abs(myDifX) > abs(myDifY)) {
211             if (y < myMain->getGraph()->verticalScrollBar()->value())
212               myDifY = -5; //or another negative number
213             else {
214               //not out of the upper boundary
215               sv->moveChild(this, myNode->X(), y); //old X and new Y
216               myNode->Coords(myNode->X(), y);
217               myY = y;
218             }
219           }
220
221         } 
222         else { 
223           if ((myDifX*(x - myNode->X()) < 0 || myDifY*(y - myNode->Y()) < 0)) {
224             StopTimer();
225             myStopFlag = true;
226           }
227           //for mouse moving to boundaries from outside space (chack then node must be move)
228           int xp1, yp1, xp2, yp2;
229           xp1 = myMain->getGraph()->horizontalScrollBar()->value();
230           xp2 = myMain->getGraph()->horizontalScrollBar()->value() +
231             myMain->getGraph()->viewport()->width();
232           yp1 = myMain->getGraph()->verticalScrollBar()->value();
233           yp2 = myMain->getGraph()->verticalScrollBar()->value() +
234             myMain->getGraph()->viewport()->height();
235           if (x >= xp1
236               && x <= xp1+myMain->getGraph()->viewport()->visibleRect().width() 
237               && y >= yp1 
238               && y <= yp1+myMain->getGraph()->viewport()->visibleRect().height()) {
239             sv->moveChild(this, x, y);
240             myNode->Coords(x, y);
241           }
242           
243         }
244     }
245 }
246
247 void SUPERVGUI_GraphNode::mouseTitleRelease(QMouseEvent* e) {
248   StopTimer();
249   myStopFlag = true;
250 }
251
252 void SUPERVGUI_GraphNode::movingNode() {
253   SUPERVGUI_Graph* sv = myMain->getGraph();
254
255   myX = myX<0 ? 0: myX;
256   myY = myY<0 ? 0: myY;
257
258   if (myDifX > 0)
259     myX = myX + 5;
260   if (myDifX < 0)
261     myX = myX - 5;
262   if (myDifY > 0)
263     myY = myY + 5;
264   if (myDifY < 0)
265     myY = myY - 5;
266
267   myMain->getGraph()->ResizeGraph(this, myX, myY);
268   myMain->getGraph()->scrollBy( myX - myNode->X(), myY - myNode->Y() );
269   sv->moveChild(this, myX, myY);
270   myNode->Coords(myX, myY);
271 }
272
273 void SUPERVGUI_GraphNode::StartTimer() {
274     Trace("SUPERVGUI_Main::StartTimer")
275     if (!myTimer->isActive()) {
276       myTimer->start(170);
277     };
278 }
279
280 void SUPERVGUI_GraphNode::StopTimer() {
281     Trace("SUPERVGUI_Main::StopTimer")
282     if (myTimer->isActive()) {
283       myTimer->stop();
284     };
285 }
286
287 void SUPERVGUI_GraphNode::deleteLinks() {
288   QObjectList* aList = queryList("SUPERVGUI_Port");
289   SUPERVGUI_Port* aPort;
290   QObjectListIt aIt(*aList);
291   while ((aPort=(SUPERVGUI_Port*)aIt.current()) != 0) {
292     ++aIt;
293     aPort->deleteLinks();
294   }
295   delete aList;
296 }
297
298
299 void SUPERVGUI_GraphNode::sync() {
300   SUPERVGUI_Node::sync();
301
302   SUPERVGUI_Port* pi;
303   QObjectList* ihmList = queryList("SUPERVGUI_Port");
304   QObjectListIt i(*ihmList);
305   while ((pi=(SUPERVGUI_Port*)i.current()) != 0) {
306     ++i;
307     pi->sync();
308   }
309   delete ihmList;
310     
311   //check: is creation of link is complete
312   if (myMain->getGraph()->isAnyLinkCreating()) {
313     //not creation complete
314     myPopup->setItemEnabled(myDeleteItem, false);
315   }
316   else {
317     //creation complete
318     myPopup->setItemEnabled(myDeleteItem, true);
319   }
320 }
321
322
323 /**
324  * Creates presentation of links to In ports
325  * If toCheckExisting = false the links will be created without checking
326  * of their existing in Graph
327  * If toCheckExisting = true the existing of links will be checked before creation
328  */
329 void SUPERVGUI_GraphNode::updateLinksPrs(bool toCheckExisting) {
330     
331   SUPERVGUI_Graph* aGraph= myMain->getGraph();
332   //Find PortInESNode
333   SUPERVGUI_PortInESNode* piES;
334   QObjectList* ihmListES = queryList("SUPERVGUI_PortInESNode");
335   QObjectListIt iES(*ihmListES);
336   if (iES.count()) {
337     while ((piES=(SUPERVGUI_PortInESNode*)iES.current()) != 0) {
338       ++iES;
339       if (piES->getPort()->IsLinked()) {
340         SUPERV_Links aLinks = piES->getPort()->Links();
341         for (int j=0; j<aLinks->length(); j++) {
342           if (toCheckExisting) {
343             if (aGraph->isLinkPrsExists(aLinks[j]))
344               continue;
345           }
346           aGraph->createLinkPrs(aLinks[j]);
347         }
348       }
349     }
350   }
351   else {
352     SUPERVGUI_PortIn* pi;
353     QObjectList* ihmList = queryList("SUPERVGUI_PortIn");
354     QObjectListIt i(*ihmList);
355     while ((pi=(SUPERVGUI_PortIn*)i.current()) != 0) {
356       ++i;
357       if (pi->getPort()->IsLinked()) {
358         SUPERV_Link aLink = pi->getPort()->Link();
359         if (toCheckExisting) {
360           if (aGraph->isLinkPrsExists(aLink))
361             continue;
362         }
363         aGraph->createLinkPrs(aLink);
364       }
365     }
366     delete ihmList;
367   }
368
369   delete ihmListES;
370 }
371
372
373 void SUPERVGUI_GraphNode::setNodeName(QString theName) {
374   SUPERVGUI_Node::setNodeName(theName);
375   myTitle->setText(name());
376 }
377
378
379 void SUPERVGUI_GraphNode::deletePort(SUPERVGUI_Port* thePort) {
380   if (thePort->isA("SUPERVGUI_PortIn") || thePort->isA("SUPERVGUI_PortInESNode")) {
381     myPIcount--;
382   }
383   else {
384     myPOcount--;
385   }
386   thePort->deleteLinks();
387   
388   thePort->getPort()->destroy();
389
390   thePort->close(true);
391
392   updatePorts();
393   updateShape();
394 }
395
396
397 void SUPERVGUI_GraphNode::addInputPort() {
398   SUPERV_Port aPort = createInPort();
399   if (aPort == NULL) return;
400
401   if (getNodeType() == SUPERV::EndSwitchNode) {
402     SUPERVGUI_PortInESNode* aPortPrs = new SUPERVGUI_PortInESNode(myValuesBox, myMain, aPort.in());    
403     myPortLayout->addWidget(aPortPrs, myPIcount, 0);
404
405     if (myPortsBox->isVisible()) {
406       aPortPrs->show();
407     }
408   }
409   else {
410     SUPERVGUI_PortIn* aPortPrs = new SUPERVGUI_PortIn(myValuesBox, myMain, aPort.in());
411     myPortLayout->addWidget(aPortPrs, myPIcount, 0);
412
413     if (myPortsBox->isVisible()) {
414       aPortPrs->show();
415     }
416   }
417
418   myPIcount++;
419   updatePorts();
420   updateShape();
421 }
422
423
424 void SUPERVGUI_GraphNode::addOutputPort() {
425   SUPERV_Port aPort = createOutPort();
426   if (aPort == NULL) return;
427
428   SUPERVGUI_PortOut* aPortPrs = new SUPERVGUI_PortOut(myValuesBox, myMain, aPort.in());
429   myPortLayout->addWidget(aPortPrs, myPOcount, 1, Qt::AlignRight);
430   myPOcount++;
431   if (myPortsBox->isVisible()) {
432     aPortPrs->show();
433   }
434   updatePorts();
435   updateShape();
436 }
437
438
439 void SUPERVGUI_GraphNode::updatePorts() {
440   bool isAdded = false;
441   SUPERV_Ports aPorts = getEngine()->Ports();
442   int n = aPorts->length();
443   SUPERVGUI_Port* aPortPrs;
444   bool aIsVisible = myPortsBox->isVisible();
445   for (int i=0; i < n; i++) {
446     QString aName(aPorts[i]->Name());
447     aName += (aPorts[i]->IsInput())? "Input":"Output";
448     aPortPrs = (SUPERVGUI_Port*) child(aName, "SUPERVGUI_Port");
449     if (aPortPrs == NULL) {
450       if (aPorts[i]->IsInput()) {
451         SUPERVGUI_PortIn* aPortIn;
452         if (aPorts[i]->IsGate()) {
453           aPortIn = new SUPERVGUI_PortIn(myGatesBox, myMain, aPorts[i].in());
454           myGatesLayout->addWidget(aPortIn, myPIcount, 0);
455         } else {
456           aPortIn = new SUPERVGUI_PortIn(myValuesBox, myMain, aPorts[i].in());
457           myPortLayout->addWidget(aPortIn, myPIcount, 0);
458           myPIcount++;
459         }
460         if (aIsVisible) aPortIn->show();
461         isAdded = true;
462       } else {
463         SUPERVGUI_PortOut* aPortOut;
464         if (aPorts[i]->IsGate()) {
465           aPortOut = new SUPERVGUI_PortOut(myGatesBox, myMain, aPorts[i].in());
466           myGatesLayout->addWidget(aPortOut, myPOcount, 1, Qt::AlignRight);
467         } else {
468           aPortOut = new SUPERVGUI_PortOut(myValuesBox, myMain, aPorts[i].in());
469           myPortLayout->addWidget(aPortOut, myPOcount, 1, Qt::AlignRight);
470           myPOcount++;
471         }
472         if (aIsVisible) aPortOut->show();
473         isAdded = true;
474       }
475     }
476   }
477   
478   QObjectList* aShownPortsList = queryList("SUPERVGUI_Port");
479   QObjectListIt aLI(*aShownPortsList);
480   SUPERVGUI_Port* aVisPort;
481
482
483   while ((aVisPort=(SUPERVGUI_Port*)aLI.current()) != 0) {  
484     ++aLI;
485     QString aNameVisible(aVisPort->getPort()->Name());
486     
487     bool aIsExists = false;
488     for (int i=0; i < n; i++) {
489       QString aName(aPorts[i]->Name());
490       if (aName == aNameVisible)
491           aIsExists = true;
492     }
493   
494     if (!aIsExists) { //we have a visible object, which has no engine entity
495       aVisPort->close(true);
496     }
497   }
498 }
499
500
501 /**
502  * Returns coordinates of connection point in content coordinates
503  */
504 QPoint SUPERVGUI_GraphNode::getInConnectPnt() {
505   return QPoint(pos().x(), 
506                 pos().y() + (height()/2));
507 }
508 QPoint SUPERVGUI_GraphNode::getOutConnectPnt() {
509   return QPoint(pos().x() + width(),
510                 pos().y() + (height()/2));
511 }