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

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