]> AND Private Git Repository - blast.git/blob - ConnectionItem.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
c3a7ada6d0fc2d1b1d15f4ec9e35accfa828c2dc
[blast.git] / ConnectionItem.cpp
1 #include "ConnectionItem.h"
2
3 #include "Dispatcher.h"
4 #include "Parameters.h"
5 #include "AbstractBoxItem.h"
6 #include "ConnectedInterface.h"
7 #include "InterfaceItem.h"
8 #include "AbstractBlock.h"
9
10 //int ConnectionItem::counter = 0;
11
12 ConnectionItem::ConnectionItem(InterfaceItem* _iface1,
13                                InterfaceItem* _iface2,
14                                Dispatcher* _dispatcher,
15                                Parameters* _params) : QGraphicsItem() {
16
17
18   dispatcher = _dispatcher;
19   params = _params;
20
21   ConnectedInterface* ref1 = _iface1->refInter;
22   ConnectedInterface* ref2 = _iface2->refInter;
23   /* ref. note in .h
24      case 1 : ref1 is group interface, and ref2 block interface of a block within the group
25      case 2 : the opposite of case 1
26      case 3 : ref1 and ref2 are block interface of blocks that are both within the same parent group.
27      case 4 : ref1 is source interface and ref2 interface of top group
28      case 5 : the opposite of case 4
29    */
30   if (ref1->getOwner() == ref2->getOwner()->getParent()) {
31
32     if (ref1->getDirection() == AbstractInterface::Input) {
33       fromInterfaceItem = _iface1;
34       toInterfaceItem = _iface2;
35     }
36     else if (ref1->getDirection() == AbstractInterface::InOut) {
37       fromInterfaceItem = _iface1;
38       toInterfaceItem = _iface2;
39     }
40     else if (ref1->getDirection() == AbstractInterface::Output) {
41       toInterfaceItem = _iface1;
42       fromInterfaceItem = _iface2;
43     }
44   }
45   else if (ref1->getOwner()->getParent() == ref2->getOwner()) {
46
47     if (ref1->getDirection() == AbstractInterface::Input) {
48       fromInterfaceItem = _iface2;
49       toInterfaceItem = _iface1;
50     }
51     else if (ref1->getDirection() == AbstractInterface::InOut) {
52       fromInterfaceItem = _iface2;
53       toInterfaceItem = _iface1;
54     }
55     else if (ref1->getDirection() == AbstractInterface::Output) {
56       toInterfaceItem = _iface2;
57       fromInterfaceItem = _iface1;
58     }
59   }
60   // NB : this case is in fact similar to the previous. Kept here for clarity
61   else if (ref1->getOwner()->getParent() == ref2->getOwner()->getParent()) {
62
63     if (ref1->getDirection() == AbstractInterface::Input) {
64       fromInterfaceItem = _iface2;
65       toInterfaceItem = _iface1;
66     }
67     else if (ref1->getDirection() == AbstractInterface::InOut) {
68       fromInterfaceItem = _iface2;
69       toInterfaceItem = _iface1;
70     }
71     else if (ref1->getDirection() == AbstractInterface::Output) {
72       toInterfaceItem = _iface2;
73       fromInterfaceItem = _iface1;
74     }
75   }
76   else if ((ref1->getOwner()->isStimuliBlock()) && (ref2->getOwner()->isTopGroupBlock())) {    
77     fromInterfaceItem = _iface1;    
78     toInterfaceItem = _iface2;
79   }
80   else if ((ref2->getOwner()->isStimuliBlock()) && (ref1->getOwner()->isTopGroupBlock())) {    
81     fromInterfaceItem = _iface2;    
82     toInterfaceItem = _iface1;
83   }
84   // adding this to interface items
85   fromInterfaceItem->addConnectionItem(this);
86   toInterfaceItem->addConnectionItem(this);
87
88   selected = false;
89   marginConn = params->arrowLineLength+params->arrowWidth;
90
91   setFlag(ItemIsSelectable);
92   setAcceptHoverEvents(true);
93   setFlag(ItemSendsGeometryChanges);
94   setCursor(Qt::PointingHandCursor);
95   setZValue(200);
96   
97   if (fromInterfaceItem->refInter->getPurpose() == AbstractInterface::Data) {
98     visible = true;
99   }
100   else {
101     visible = false;
102   }
103
104   setPath();
105 }
106
107
108 ConnectionItem::ConnectionItem(const ConnectionItem &copy) {
109   pointFrom = copy.pointFrom;
110   pointTo = copy.pointTo;
111   interPoint1 = copy.interPoint1;
112   interPoint2 = copy.interPoint2;
113   interPoint3 = copy.interPoint3;
114   interPoint4 = copy.interPoint4;
115 }
116
117 ConnectionItem::~ConnectionItem() {
118 }
119
120 ConnectionItem::ConnectionItem() {
121 }
122
123 QPainterPath ConnectionItem::shape() const {
124   return pathShape;
125 }
126
127 QRectF ConnectionItem::boundingRect() const {
128
129   QPointF start, end;
130
131   if(pointFrom.x() < pointTo.x()){
132     start.setX(pointFrom.x()-20);
133     end.setX(pointTo.x()+20);
134   } else {
135     start.setX(pointTo.x()-20);
136     end.setX(pointFrom.x()+20);
137   }
138   if(pointFrom.y() < pointTo.y()){
139     start.setY(pointFrom.y()-20);
140     end.setY(pointTo.y()+20);
141   } else {
142     start.setY(pointTo.y()-20);
143     end.setY(pointFrom.y()+20);
144   }
145   return QRectF(start, end);
146 }
147
148 void ConnectionItem::paint(QPainter *painter,
149                            const QStyleOptionGraphicsItem *option,
150                            QWidget *widget) {
151
152   if (!visible) return;
153   
154   painter->setPen(Qt::blue);
155   if(selected){
156     painter->setPen(Qt::red);
157   }
158
159   painter->drawPath(pathPaint);
160 }
161
162 void ConnectionItem::addInterPoint(QPointF point) {
163
164 }
165
166 void ConnectionItem::setPath() {
167
168   // signals to the scene that this connection is going to change of shape.
169   prepareGeometryChange();
170
171   bool withinGroup = false;
172   /* NB: four cases
173      1: from group input iface to box input iface
174      2: from output box iface to group output iface
175      3: from output box iface to input box iface
176      4: from source output iface to input group iface
177    
178     For cases 1 & 2, the position of group iface is given by getStartPosition
179     For all other cases, the iface from and to position is given by getEndPosition
180    */
181   if ((fromInterfaceItem->getOwner()->isGroupItem()) && (toInterfaceItem->getOwner()->isBoxItem())) {
182     pointFrom = fromInterfaceItem->getStartPosition();
183     pointTo = toInterfaceItem->getEndPosition();
184     withinGroup = true;
185   }
186   else if ((toInterfaceItem->getOwner()->isGroupItem()) && (fromInterfaceItem->getOwner()->isBoxItem())) {
187     pointFrom = fromInterfaceItem->getEndPosition();
188     pointTo = toInterfaceItem->getStartPosition();
189     withinGroup = true;
190   }
191   else {
192     pointFrom = fromInterfaceItem->getEndPosition();
193     pointTo = toInterfaceItem->getEndPosition();
194   }
195
196   int oriFrom, oriTo;
197   oriFrom = fromInterfaceItem->getOrientation();
198   oriTo = toInterfaceItem->getOrientation();
199
200 /* NB: if src or dest is onwed by a GroupItem the orientation
201    must be changed as it is a block.
202  */
203   if (withinGroup) {
204     if(fromInterfaceItem->owner->isGroupItem()){
205       switch(fromInterfaceItem->getOrientation()){
206       case Parameters::North :
207         oriFrom = Parameters::South;
208         break;
209       case Parameters::South :
210         oriFrom = Parameters::North;
211         break;
212       case Parameters::East :
213         oriFrom = Parameters::West;
214         break;
215       case Parameters::West :
216         oriFrom = Parameters::East;
217         break;
218       }
219     }
220     else if(toInterfaceItem->owner->isGroupItem()){
221       switch(toInterfaceItem->getOrientation()){
222       case Parameters::North :
223         oriTo = Parameters::South;
224         break;
225       case Parameters::South :
226         oriTo = Parameters::North;
227         break;
228       case Parameters::East :
229         oriTo = Parameters::West;
230         break;
231       case Parameters::West :
232         oriTo = Parameters::East;
233         break;
234       }
235     }
236   }
237   double gap1 = 0.0;
238   double gap2 = 0.0;
239
240   if(oriFrom == Parameters::South) {
241
242     // FROM SOUTH TO SOUTH
243     if(oriTo == Parameters::South) {
244       computeElle(oriFrom);
245     }
246     // FROM SOUTH TO NORTH
247     else if(oriTo == Parameters::North) {
248       gap1 = pointTo.y() - pointFrom.y();
249       if (gap1 > 2*marginConn) {
250         computeStaircase(oriFrom);
251       }
252       else {
253         computeEsse(oriFrom);
254       }
255     }
256     // FROM SOUTH TO EAST OR WEST
257     else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
258
259       gap1 = pointTo.x() - pointFrom.x();
260       if (oriTo == Parameters::West) gap1 = -gap1;
261       gap2 = pointTo.y() - pointFrom.y();
262
263       if (gap1 > 0.0) {
264         if (gap2 > 0.0) {
265           computeHookSmallEnd(oriFrom,oriTo);
266         }
267         else {
268           computeOpenRect(oriFrom,oriTo);
269         }
270       }
271       else {
272         if (gap2 >= 0.0) {
273           computeCorner(oriFrom);
274         }
275         else {
276           computeHookSmallStart(oriFrom,oriTo);
277         }
278       }
279     }
280   }
281   else if(oriFrom == Parameters::North) {
282
283     // FROM NORTH TO SOUTH
284     if(oriTo == Parameters::South) {
285       gap1 = pointFrom.y() - pointTo.y();
286       if (gap1 > 2*marginConn) {
287         computeStaircase(oriFrom);
288       }
289       else {
290         computeEsse(oriFrom);
291       }
292     }
293     // FROM NORTH TO NORTH
294     else if(oriTo == Parameters::North) {
295       computeElle(oriFrom);
296     }
297     // FROM NORTH TO EAST OR WEST
298     else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
299
300       gap1 = pointTo.x() - pointFrom.x();
301       if (oriTo == Parameters::West) gap1 = -gap1;
302       gap2 = pointFrom.y() - pointTo.y();
303
304       if (gap1 > 0.0) {
305         if (gap2 > 0.0) {
306           computeHookSmallEnd(oriFrom,oriTo);
307         }
308         else {
309           computeOpenRect(oriFrom,oriTo);
310         }
311       }
312       else {
313         if (gap2 >= 0.0) {
314           computeCorner(oriFrom);
315         }
316         else {
317           computeHookSmallStart(oriFrom,oriTo);
318         }
319       }
320     }
321   }
322   else if(oriFrom == Parameters::East) {
323     // FROM EAST TO NORTH OR SOUTH
324     if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
325
326       gap1 = pointFrom.x() - pointTo.x();
327       gap2 = pointFrom.y() - pointTo.y();
328       if (oriTo == Parameters::North) gap2 = -gap2;
329
330       if (gap1 > 0.0) {
331         if (gap2 > 0.0) {
332           computeHookSmallStart(oriFrom,oriTo);
333         }
334         else {
335           computeOpenRect(oriFrom,oriTo);
336         }
337       }
338       else {
339         if (gap2 >= 0.0) {
340           computeCorner(oriFrom);
341         }
342         else {
343           computeHookSmallEnd(oriFrom,oriTo);
344         }
345       }
346     }
347     else if(oriTo == Parameters::East) {
348       computeElle(oriFrom);
349     }
350     else if (oriTo == Parameters::West) {
351       gap1 = pointTo.x() - pointFrom.x();
352       if (gap1 > 2*marginConn) {
353         computeStaircase(oriFrom);
354       }
355       else {
356         computeEsse(oriFrom);
357       }
358     }
359   }
360   else if (oriFrom == Parameters::West) {
361
362     // FROM WEST TO NORTH OR SOUTH
363     if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
364
365       gap1 = pointTo.x() - pointFrom.x();
366       gap2 = pointFrom.y() - pointTo.y();
367       if (oriTo == Parameters::North) gap2 = -gap2;
368
369       if (gap1 > 0.0) {
370         if (gap2 > 0.0) {
371           computeHookSmallStart(oriFrom,oriTo);
372         }
373         else {
374           computeOpenRect(oriFrom,oriTo);
375         }
376       }
377       else {
378         if (gap2 >= 0.0) {
379           computeCorner(oriFrom);
380         }
381         else {
382           computeHookSmallEnd(oriFrom,oriTo);
383         }
384       }
385     }
386     else if(oriTo == Parameters::East) {
387       gap1 = pointFrom.x() - pointTo.x();
388       if (gap1 > 2*marginConn) {
389         computeStaircase(oriFrom);
390       }
391       else {
392         computeEsse(oriFrom);
393       }
394     }
395     else if (oriTo == Parameters::West) {
396       computeElle(oriFrom);
397     }
398   }
399
400   //pps.setWidth(5);
401   //pathShape = pps.createStroke(pathPaint);
402 }
403
404
405 void ConnectionItem::computeEsse(int orientationFrom) {
406
407   //cout << "drawing an esse" << endl;
408   pathPaint = QPainterPath(pointFrom);
409   QPainterPath s;
410   interPoints.clear();
411   double gap = marginConn;  
412   
413   if ((orientationFrom == Parameters::North)||(orientationFrom == Parameters::West)) gap = -gap;
414   QPointF p(0.0,0.0);
415
416   if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
417         
418     // must draw a complete esse
419     p = QPointF(pointFrom.x()+gap,pointFrom.y());    
420     s.moveTo(p);
421     pathPaint.lineTo(p);
422     interPoints.append(p);
423     p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
424     pathPaint.lineTo(p);
425     s.lineTo(p);
426     interPoints.append(p);
427     p = QPointF(pointTo.x()-gap,(pointFrom.y()+pointTo.y())/2.0);
428     pathPaint.lineTo(p);
429     s.lineTo(p);
430     interPoints.append(p);
431     p = QPointF(pointTo.x()-gap,pointTo.y());
432     pathPaint.lineTo(p);
433     s.lineTo(p);
434     interPoints.append(p);
435     pathPaint.lineTo(pointTo);
436   }
437   else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
438
439     // must draw a complete esse
440     p = QPointF(pointFrom.x(),pointFrom.y()+gap);    
441     pathPaint.lineTo(p);
442     s.moveTo(p);
443     interPoints.append(p);
444     p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
445     pathPaint.lineTo(p);
446     s.lineTo(p);
447     interPoints.append(p);
448     p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()-gap);
449     pathPaint.lineTo(p);
450     s.lineTo(p);
451     interPoints.append(p);
452     p = QPointF(pointTo.x(), pointTo.y()-gap);
453     pathPaint.lineTo(p);
454     s.lineTo(p);
455     interPoints.append(p);
456     pathPaint.lineTo(pointTo);
457   }
458   pps.setWidth(5);
459   pathShape = pps.createStroke(s);
460 }
461
462 void ConnectionItem::computeStaircase(int orientationFrom) {
463
464   pathPaint = QPainterPath(pointFrom);
465   QPainterPath s;
466   double gap = marginConn;
467   interPoints.clear();  
468   QPointF p(0.0,0.0);
469
470   if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
471     
472     if (orientationFrom == Parameters::West) gap = -gap;
473     p = QPointF(pointFrom.x()+gap,pointFrom.y());    
474     s.moveTo(p);
475     
476     if (pointFrom.y() == pointTo.y()) {
477       //cout << "drawing straight line" << endl;
478       pathPaint.lineTo(pointTo);
479       
480     }
481     else  {
482       //cout << "drawing a staircase" << endl;
483       // sufficient place to draw a simple staircase
484       p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
485       pathPaint.lineTo(p);
486       s.lineTo(p);   
487       interPoints.append(p);
488       p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
489       pathPaint.lineTo(p);
490       s.lineTo(p);   
491       interPoints.append(p);
492       pathPaint.lineTo(pointTo);
493     }
494     p = QPointF(pointTo.x()-gap,pointTo.y());    
495     s.lineTo(p);   
496   }
497   else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
498     
499     if (orientationFrom == Parameters::North) gap = -gap;
500     
501     p = QPointF(pointFrom.x(),pointFrom.y()+gap);    
502     s.moveTo(p);
503     
504     if (pointFrom.x() == pointTo.x()) {
505       //cout << "drawing straight line" << endl;
506       pathPaint.lineTo(pointTo);      
507     }
508     else {
509       //cout << "drawing a staircase" << endl;
510       // sufficient place to draw a simple staircase
511       p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
512       pathPaint.lineTo(p);
513       s.lineTo(p);   
514       interPoints.append(p);
515       p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
516       pathPaint.lineTo(p);
517       s.lineTo(p);   
518       interPoints.append(p);
519       pathPaint.lineTo(pointTo);
520     }
521     p = QPointF(pointTo.x(),pointTo.y()-gap);    
522     s.lineTo(p);   
523   }
524   pps.setWidth(5);
525   pathShape = pps.createStroke(s);
526 }
527
528 /* drawCorner():
529
530   A Corner has the following shape :
531   |
532   |__
533
534 */
535 void ConnectionItem::computeCorner(int orientationFrom) {
536
537   pathPaint = QPainterPath(pointFrom);
538   interPoints.clear();
539   QPointF p(0.0,0.0);
540   QPainterPath s;
541   double gap = marginConn;
542   
543   //cout << "drawing a corner" << endl;
544
545   if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
546     if (orientationFrom == Parameters::West) gap = -gap;
547     p = QPointF(pointFrom.x()+gap,pointFrom.y());    
548     s.moveTo(p);
549     p = QPointF(pointTo.x(),pointFrom.y());
550     pathPaint.lineTo(p);
551     s.lineTo(p);   
552     interPoints.append(p);
553     pathPaint.lineTo(pointTo);
554     p = QPointF(pointTo.x(),pointTo.y()-gap);    
555     s.lineTo(p);   
556   }
557   else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
558     if (orientationFrom == Parameters::North) gap = -gap;
559     p = QPointF(pointFrom.x(),pointFrom.y()+gap);    
560     s.moveTo(p);
561     p = QPointF(pointFrom.x(),pointTo.y());
562     pathPaint.lineTo(p);
563     s.lineTo(p);
564     interPoints.append(p);
565     pathPaint.lineTo(pointTo);
566     p = QPointF(pointTo.x()-gap,pointTo.y());    
567     s.lineTo(p);   
568   }
569   pps.setWidth(5);
570   pathShape = pps.createStroke(s);
571 }
572
573 /* drawOpenRect():
574
575   A OpenRect has the following shape :
576   __
577   |
578   |_|
579   
580   Its beginning and end have always a size of marginConn
581 */
582 void ConnectionItem::computeOpenRect(int orientationFrom, int orientationTo) {
583   pathPaint = QPainterPath(pointFrom);
584   interPoints.clear();
585   QPointF p(0.0,0.0);
586   double gap1 = marginConn;
587   double gap2 = marginConn;
588   QPainterPath s;  
589   //cout << "drawing an OpenRect" << endl;
590
591   if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
592     if (orientationFrom == Parameters::West) {
593       gap1 = -gap1;
594     }
595     if (orientationTo == Parameters::North) {
596       gap2 = -gap2;
597     }
598     p = QPointF(pointFrom.x()+gap1,pointFrom.y());
599     pathPaint.lineTo(p);
600     s.moveTo(p);
601     interPoints.append(p);
602     p = QPointF(pointFrom.x()+gap1,pointTo.y()+gap2);
603     pathPaint.lineTo(p);
604     s.lineTo(p);   
605     interPoints.append(p);
606     p = QPointF(pointTo.x(),pointTo.y()+gap2);
607     pathPaint.lineTo(p);
608     s.lineTo(p);   
609     interPoints.append(p);
610     pathPaint.lineTo(pointTo);
611
612   }
613   else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
614     if (orientationFrom == Parameters::North) {
615       gap1 = -gap1;
616     }
617     if (orientationTo == Parameters::West) {
618       gap2 = -gap2;
619     }
620     p = QPointF(pointFrom.x(),pointFrom.y()+gap1);
621     pathPaint.lineTo(p);
622     s.moveTo(p);
623     interPoints.append(p);
624     p = QPointF(pointTo.x()+gap2,pointFrom.y()+gap1);
625     pathPaint.lineTo(p);
626     s.lineTo(p);
627     interPoints.append(p);
628     p = QPointF(pointTo.x()+gap2,pointTo.y());
629     pathPaint.lineTo(p);
630     s.lineTo(p);
631     interPoints.append(p);
632     pathPaint.lineTo(pointTo);
633   }
634   pps.setWidth(5);
635   pathShape = pps.createStroke(s);
636 }
637
638
639 /* drawHookSmallEnd():
640
641   A Hook has the following shape :
642   _
643    |
644    |_|
645    Its end has always a size of marginConn
646 */
647 void ConnectionItem::computeHookSmallEnd(int orientationFrom, int orientationTo) {
648   pathPaint = QPainterPath(pointFrom);
649   interPoints.clear();
650   QPointF p(0.0,0.0);  
651   QPainterPath s;
652   double gap2 = marginConn;
653   double gap1 = marginConn;
654   //cout << "drawing a Hook with small end" << endl;
655
656   if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
657
658     if (orientationFrom == Parameters::West) gap1 = -gap1;
659     if (orientationTo == Parameters::North) gap2 = -gap2;
660
661     p = QPointF(pointFrom.x()+gap1,pointFrom.y());
662     s.moveTo(p);
663     p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
664     pathPaint.lineTo(p);
665     s.lineTo(p);
666     interPoints.append(p);
667     p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()+gap2);
668     pathPaint.lineTo(p);
669     s.lineTo(p);
670     interPoints.append(p);
671     p = QPointF(pointTo.x(),pointTo.y()+gap2);
672     pathPaint.lineTo(p);
673     s.lineTo(p);
674     interPoints.append(p);
675     pathPaint.lineTo(pointTo);
676
677   }
678   else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
679
680     if (orientationFrom == Parameters::North) gap1 = -gap1;
681     if (orientationTo == Parameters::West) gap2 = -gap2;
682     
683     p = QPointF(pointFrom.x(),pointFrom.y()+gap1);
684     s.moveTo(p);
685     p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
686     pathPaint.lineTo(p);
687     s.lineTo(p);
688     interPoints.append(p);
689     p = QPointF(pointTo.x()+gap2,(pointFrom.y()+pointTo.y())/2.0);
690     pathPaint.lineTo(p);
691     s.lineTo(p);
692     interPoints.append(p);
693     p = QPointF(pointTo.x()+gap2,pointTo.y());
694     pathPaint.lineTo(p);
695     s.lineTo(p);
696     interPoints.append(p);
697     pathPaint.lineTo(pointTo);
698   }
699   pps.setWidth(5);
700   pathShape = pps.createStroke(s);
701 }
702
703 /* drawHookSmallStart():
704
705   A Hook has the following shape :
706   _
707    |
708    |_|
709    Its start has always a size of marginConn
710 */
711 void ConnectionItem::computeHookSmallStart(int orientationFrom, int orientationTo) {
712   pathPaint = QPainterPath(pointFrom);
713   interPoints.clear();
714   QPointF p(0.0,0.0);
715   QPainterPath s;
716   double gap1 = marginConn;
717   double gap2 = marginConn;
718   //cout << "drawing a Hook with small start" << endl;
719
720   if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
721
722     if (orientationFrom == Parameters::West) gap1 = -gap1;
723     if (orientationTo == Parameters::North) gap2 = -gap2;
724
725     p = QPointF(pointFrom.x()+gap1,pointFrom.y());
726     s.moveTo(p);
727     pathPaint.lineTo(p);
728     interPoints.append(p);
729     p = QPointF(pointFrom.x()+gap1,(pointFrom.y()+pointTo.y())/2.0);
730     pathPaint.lineTo(p);
731     s.lineTo(p);
732     interPoints.append(p);
733     p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
734     pathPaint.lineTo(p);
735     s.lineTo(p);
736     interPoints.append(p);
737     pathPaint.lineTo(pointTo);
738     p = QPointF(pointTo.x(),pointFrom.y()+gap2);
739     s.lineTo(p);
740   }
741   else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
742
743     if (orientationFrom == Parameters::North) gap1 = -gap1;
744     if (orientationTo == Parameters::West) gap2 = -gap2;
745
746     p = QPointF(pointFrom.x(),pointFrom.y()+gap1);
747     s.moveTo(p);
748     pathPaint.lineTo(p);
749     interPoints.append(p);
750     p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap1);
751     pathPaint.lineTo(p);
752     s.lineTo(p);
753     interPoints.append(p);
754     p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
755     pathPaint.lineTo(p);
756     s.lineTo(p);
757     interPoints.append(p);
758     pathPaint.lineTo(pointTo);
759     p = QPointF(pointTo.x()+gap2,pointFrom.y());
760     s.lineTo(p);
761   }
762   pps.setWidth(5);
763   pathShape = pps.createStroke(s);
764 }
765
766 /* drawElle():
767
768   An Elle has the following shape :
769   |
770   |_|
771
772 */
773 void ConnectionItem::computeElle(int orientationFrom) {
774
775   pathPaint = QPainterPath(pointFrom);
776   interPoints.clear();
777   QPointF p(0.0,0.0);
778   QPainterPath s;
779   double gap = marginConn;  
780   
781   double x;
782   double y;
783   if ((orientationFrom == Parameters::North) || (orientationFrom == Parameters::South)) {
784     double diffPos = pointFrom.y() - pointTo.y();
785     if (orientationFrom == Parameters::North) {
786       gap = -gap;
787       diffPos = -diffPos;
788     }
789     p = QPointF(pointFrom.x(),pointFrom.y()+gap);
790     s.moveTo(p);
791     if (diffPos >= 0.0) {      
792       pathPaint.lineTo(p);
793       interPoints.append(p);
794       p = QPointF(pointTo.x(),pointFrom.y()+gap);
795       pathPaint.lineTo(p);
796       s.lineTo(p);
797       interPoints.append(p);
798       pathPaint.lineTo(pointTo);
799       p = QPointF(pointTo.x(),pointTo.y()+gap);
800       s.lineTo(p);
801     }
802     else {
803       p = QPointF(pointFrom.x(),pointTo.y()+gap);
804       pathPaint.lineTo(p);
805       s.lineTo(p);
806       interPoints.append(p);
807       p = QPointF(pointTo.x(),pointTo.y()+gap);
808       pathPaint.lineTo(p);
809       s.lineTo(p);
810       interPoints.append(p);
811       pathPaint.lineTo(pointTo);
812     }    
813   }
814   else if ((orientationFrom == Parameters::West) || (orientationFrom == Parameters::East)) {
815     double diffPos = pointFrom.x() - pointTo.x();
816     if (orientationFrom == Parameters::West) {
817       gap = -gap;
818       diffPos = -diffPos;
819     }
820     p = QPointF(pointFrom.x()+gap,pointFrom.y());
821     s.moveTo(p);
822     if (diffPos >= 0.0) {      
823       pathPaint.lineTo(p);
824       interPoints.append(p);
825       p = QPointF(pointTo.x()+gap,pointFrom.y());
826       pathPaint.lineTo(p);
827       s.lineTo(p);
828       interPoints.append(p);
829       pathPaint.lineTo(pointTo);
830       p = QPointF(pointTo.x()+gap,pointTo.y());
831       s.lineTo(p);
832     }
833     else {
834       p = QPointF(pointFrom.x()+gap,pointTo.y());
835       pathPaint.lineTo(p);
836       s.lineTo(p);
837       interPoints.append(p);
838       p = QPointF(pointTo.x()+gap,pointTo.y());
839       pathPaint.lineTo(p);
840       s.lineTo(p);
841       interPoints.append(p);
842       pathPaint.lineTo(pointTo);
843     }
844   }
845   
846   pps.setWidth(5);
847   pathShape = pps.createStroke(s);
848 }
849
850 void ConnectionItem::setSelected(bool selected) {
851   this->selected = selected;
852   if(selected){
853     setZValue(201);
854   } else {
855     setZValue(200);
856   }
857 }
858
859 void ConnectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
860   QGraphicsItem::mousePressEvent(event);
861   setZValue(zValue()+100);  
862   setSelected(!selected);
863   update(boundingRect());
864 }
865
866 void ConnectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
867   QGraphicsItem::mouseReleaseEvent(event);
868   setZValue(zValue()-100);
869 }
870
871 void ConnectionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
872   QGraphicsItem::mouseMoveEvent(event);
873 }
874
875 void ConnectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
876   /* have to check if the connection can be removed.
877      If the from or to InterfaceItem is owned by a group item, and this item
878      is both connected to and from, thus it is impossible to remove this connection
879      because there would be a  group interface alone and not connected and this situation is not allowed.
880
881      Nevertheless, there are 2 exceptions :
882         - a from group interface is connected to more than one input interface
883         - the connection is between a source block outside the top group and the top group
884    */
885   bool canRemove = true;
886
887   if (fromInterfaceItem->getOwner()->isGroupItem()) {
888     ConnectedInterface* ref = fromInterfaceItem->refInter;
889     if ((ref->isConnectedFrom()) && (ref->getConnectedTo().length() == 1)) {
890       canRemove = false;
891     }
892   }
893   else if ((toInterfaceItem->getOwner()->isGroupItem()) && (! toInterfaceItem->getOwner()->getRefBlock()->isTopGroupBlock())) {
894     ConnectedInterface* ref = toInterfaceItem->refInter;
895     if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
896       canRemove = false;
897     }
898   }
899
900   if (canRemove) {
901     QMenu menu;
902     QAction* titleAction = menu.addAction("Connection operations");
903     titleAction->setEnabled(false);
904     menu.addSeparator();
905     QAction* removeAction = menu.addAction("Remove");
906     QAction * selectedAction= menu.exec(event->screenPos());
907
908     if(selectedAction == removeAction){
909       dispatcher->removeConnection(Dispatcher::Design, this);
910     }
911   }
912 }
913
914 void ConnectionItem::prepareChange() {
915   prepareGeometryChange();
916 }
917
918 QDataStream &operator <<(QDataStream &out, ConnectionItem &c) {
919   out.setVersion(QDataStream::Qt_4_8);
920
921   QByteArray connData;
922   QDataStream toWrite(&connData, QIODevice::WriteOnly);
923
924   toWrite << c.id;
925   toWrite << c.getFromInterfaceItem()->getId();
926   toWrite << c.getToInterfaceItem()->getId();
927
928   out << connData;
929
930   return out;
931 }
932
933 QDataStream &operator >>(QDataStream &in, ConnectionItem &c) {
934   in.setVersion(QDataStream::Qt_4_8);
935
936   return in;
937 }