1 #include "ConnectionItem.h"
3 #include "Dispatcher.h"
4 #include "Parameters.h"
5 #include "AbstractBoxItem.h"
6 #include "ConnectedInterface.h"
7 #include "InterfaceItem.h"
8 #include "AbstractBlock.h"
10 //int ConnectionItem::counter = 0;
12 ConnectionItem::ConnectionItem(InterfaceItem* _iface1,
13 InterfaceItem* _iface2,
14 Dispatcher* _dispatcher,
16 QGraphicsItem *_parent) : QGraphicsItem(_parent) {
19 dispatcher = _dispatcher;
22 ConnectedInterface* ref1 = _iface1->refInter;
23 ConnectedInterface* ref2 = _iface2->refInter;
25 case 1 : ref1 is group interface, and ref2 block interface of a block within the group
26 case 2 : the opposite of case 1
27 case 3 : ref1 and ref2 are block interface of blocks that are both within the same parent group.
29 if (ref1->getOwner() == ref2->getOwner()->getParent()) {
31 if (ref1->getDirection() == AbstractInterface::Input) {
32 fromInterfaceItem = _iface1;
33 toInterfaceItem = _iface2;
35 else if (ref1->getDirection() == AbstractInterface::InOut) {
36 fromInterfaceItem = _iface1;
37 toInterfaceItem = _iface2;
39 else if (ref1->getDirection() == AbstractInterface::Output) {
40 toInterfaceItem = _iface1;
41 fromInterfaceItem = _iface2;
44 else if (ref1->getOwner()->getParent() == ref2->getOwner()) {
46 if (ref1->getDirection() == AbstractInterface::Input) {
47 fromInterfaceItem = _iface2;
48 toInterfaceItem = _iface1;
50 else if (ref1->getDirection() == AbstractInterface::InOut) {
51 fromInterfaceItem = _iface2;
52 toInterfaceItem = _iface1;
54 else if (ref1->getDirection() == AbstractInterface::Output) {
55 toInterfaceItem = _iface2;
56 fromInterfaceItem = _iface1;
59 // NB : this case is in fact similar to the previous. Kept here for clarity
60 else if (ref1->getOwner()->getParent() == ref2->getOwner()->getParent()) {
62 if (ref1->getDirection() == AbstractInterface::Input) {
63 fromInterfaceItem = _iface2;
64 toInterfaceItem = _iface1;
66 else if (ref1->getDirection() == AbstractInterface::InOut) {
67 fromInterfaceItem = _iface2;
68 toInterfaceItem = _iface1;
70 else if (ref1->getDirection() == AbstractInterface::Output) {
71 toInterfaceItem = _iface2;
72 fromInterfaceItem = _iface1;
75 // adding this to interface items
76 fromInterfaceItem->addConnectionItem(this);
77 toInterfaceItem->addConnectionItem(this);
80 marginConn = params->arrowLineLength+params->arrowWidth;
82 setFlag(ItemIsSelectable);
83 setAcceptHoverEvents(true);
84 setFlag(ItemSendsGeometryChanges);
85 setCursor(Qt::PointingHandCursor);
92 ConnectionItem::ConnectionItem(const ConnectionItem ©) {
93 pointFrom = copy.pointFrom;
94 pointTo = copy.pointTo;
95 interPoint1 = copy.interPoint1;
96 interPoint2 = copy.interPoint2;
97 interPoint3 = copy.interPoint3;
98 interPoint4 = copy.interPoint4;
101 ConnectionItem::~ConnectionItem() {
104 ConnectionItem::ConnectionItem() {
107 QPainterPath ConnectionItem::shape() const {
111 QRectF ConnectionItem::boundingRect() const {
115 if(pointFrom.x() < pointTo.x()){
116 start.setX(pointFrom.x()-20);
117 end.setX(pointTo.x()+20);
119 start.setX(pointTo.x()-20);
120 end.setX(pointFrom.x()+20);
122 if(pointFrom.y() < pointTo.y()){
123 start.setY(pointFrom.y()-20);
124 end.setY(pointTo.y()+20);
126 start.setY(pointTo.y()-20);
127 end.setY(pointFrom.y()+20);
129 return QRectF(start, end);
132 void ConnectionItem::paint(QPainter *painter,
133 const QStyleOptionGraphicsItem *option,
136 painter->setPen(Qt::blue);
138 painter->setPen(Qt::red);
141 painter->drawPath(pathPaint);
144 void ConnectionItem::addInterPoint(QPointF point) {
148 void ConnectionItem::setPathes() {
150 prepareGeometryChange();
152 pointFrom = fromInterfaceItem->getEndPointInGroup();
153 pointTo = toInterfaceItem->getEndPointInGroup();
156 oriFrom = fromInterfaceItem->getOrientation();
157 oriTo = toInterfaceItem->getOrientation();
159 /* NB: if src or dest is onwed by a GroupItem the orientation
160 must be changed as it is a block.
162 if(fromInterfaceItem->owner->isGroupItem()){
163 switch(fromInterfaceItem->getOrientation()){
164 case Parameters::North :
165 oriFrom = Parameters::South;
167 case Parameters::South :
168 oriFrom = Parameters::North;
170 case Parameters::East :
171 oriFrom = Parameters::West;
173 case Parameters::West :
174 oriFrom = Parameters::East;
178 if(toInterfaceItem->owner->isGroupItem()){
179 switch(toInterfaceItem->getOrientation()){
180 case Parameters::North :
181 oriTo = Parameters::South;
183 case Parameters::South :
184 oriTo = Parameters::North;
186 case Parameters::East :
187 oriTo = Parameters::West;
189 case Parameters::West :
190 oriTo = Parameters::East;
197 if(oriFrom == Parameters::South) {
199 // FROM SOUTH TO SOUTH
200 if(oriTo == Parameters::South) {
201 computeElle(oriFrom);
203 // FROM SOUTH TO NORTH
204 else if(oriTo == Parameters::North) {
205 gap1 = pointTo.y() - pointFrom.y();
206 if (gap1 > 2*marginConn) {
207 computeStaircase(oriFrom);
210 computeEsse(oriFrom);
213 // FROM SOUTH TO EAST OR WEST
214 else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
216 gap1 = pointTo.x() - pointFrom.x();
217 if (oriTo == Parameters::West) gap1 = -gap1;
218 gap2 = pointTo.y() - pointFrom.y();
222 computeHookSmallEnd(oriFrom,oriTo);
225 computeOpenRect(oriFrom,oriTo);
230 computeCorner(oriFrom);
233 computeHookSmallStart(oriFrom,oriTo);
238 else if(oriFrom == Parameters::North) {
240 // FROM NORTH TO SOUTH
241 if(oriTo == Parameters::South) {
242 gap1 = pointFrom.y() - pointTo.y();
243 if (gap1 > 2*marginConn) {
244 computeStaircase(oriFrom);
247 computeEsse(oriFrom);
250 // FROM NORTH TO NORTH
251 else if(oriTo == Parameters::North) {
252 computeElle(oriFrom);
254 // FROM NORTH TO EAST OR WEST
255 else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
257 gap1 = pointTo.x() - pointFrom.x();
258 if (oriTo == Parameters::West) gap1 = -gap1;
259 gap2 = pointFrom.y() - pointTo.y();
263 computeHookSmallEnd(oriFrom,oriTo);
266 computeOpenRect(oriFrom,oriTo);
271 computeCorner(oriFrom);
274 computeHookSmallStart(oriFrom,oriTo);
279 else if(oriFrom == Parameters::East) {
280 // FROM EAST TO NORTH OR SOUTH
281 if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
283 gap1 = pointFrom.x() - pointTo.x();
284 gap2 = pointFrom.y() - pointTo.y();
285 if (oriTo == Parameters::North) gap2 = -gap2;
289 computeHookSmallStart(oriFrom,oriTo);
292 computeOpenRect(oriFrom,oriTo);
297 computeCorner(oriFrom);
300 computeHookSmallEnd(oriFrom,oriTo);
304 else if(oriTo == Parameters::East) {
305 computeElle(oriFrom);
307 else if (oriTo == Parameters::West) {
308 gap1 = pointTo.x() - pointFrom.x();
309 if (gap1 > 2*marginConn) {
310 computeStaircase(oriFrom);
313 computeEsse(oriFrom);
317 else if (oriFrom == Parameters::West) {
319 // FROM WEST TO NORTH OR SOUTH
320 if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
322 gap1 = pointTo.x() - pointFrom.x();
323 gap2 = pointFrom.y() - pointTo.y();
324 if (oriTo == Parameters::North) gap2 = -gap2;
328 computeHookSmallStart(oriFrom,oriTo);
331 computeOpenRect(oriFrom,oriTo);
336 computeCorner(oriFrom);
339 computeHookSmallEnd(oriFrom,oriTo);
343 else if(oriTo == Parameters::East) {
344 gap1 = pointFrom.x() - pointTo.x();
345 if (gap1 > 2*marginConn) {
346 computeStaircase(oriFrom);
349 computeEsse(oriFrom);
352 else if (oriTo == Parameters::West) {
353 computeElle(oriFrom);
358 pathShape = pps.createStroke(pathPaint);
362 void ConnectionItem::computeEsse(int orientationFrom) {
364 //cout << "drawing an esse" << endl;
365 pathPaint = QPainterPath(pointFrom);
367 double gap = marginConn;
368 if ((orientationFrom == Parameters::North)||(orientationFrom == Parameters::West)) gap = -gap;
371 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
372 // must draw a complete esse
373 p = QPointF(pointFrom.x()+gap,pointFrom.y());
375 interPoints.append(p);
376 p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
378 interPoints.append(p);
379 p = QPointF(pointTo.x()-gap,(pointFrom.y()+pointTo.y())/2.0);
381 interPoints.append(p);
382 p = QPointF(pointTo.x()-gap,pointTo.y());
384 interPoints.append(p);
385 pathPaint.lineTo(pointTo);
387 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
389 // must draw a complete esse
390 p = QPointF(pointFrom.x(),pointFrom.y()+gap);
392 interPoints.append(p);
393 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
395 interPoints.append(p);
396 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()-gap);
398 interPoints.append(p);
399 p = QPointF(pointTo.x(), pointTo.y()-gap);
401 interPoints.append(p);
402 pathPaint.lineTo(pointTo);
406 void ConnectionItem::computeStaircase(int orientationFrom) {
408 pathPaint = QPainterPath(pointFrom);
412 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
413 if (pointFrom.y() == pointTo.y()) {
414 //cout << "drawing straight line" << endl;
415 pathPaint.lineTo(pointTo);
418 //cout << "drawing a staircase" << endl;
419 // sufficient place to draw a simple staircase
420 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
422 interPoints.append(p);
423 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
425 interPoints.append(p);
426 pathPaint.lineTo(pointTo);
429 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
430 if (pointFrom.x() == pointTo.x()) {
431 //cout << "drawing straight line" << endl;
432 pathPaint.lineTo(pointTo);
435 //cout << "drawing a staircase" << endl;
436 // sufficient place to draw a simple staircase
437 p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
439 interPoints.append(p);
440 p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
442 interPoints.append(p);
443 pathPaint.lineTo(pointTo);
450 A Corner has the following shape :
455 void ConnectionItem::computeCorner(int orientationFrom) {
457 pathPaint = QPainterPath(pointFrom);
460 //cout << "drawing a corner" << endl;
462 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
463 p = QPointF(pointTo.x(),pointFrom.y());
465 interPoints.append(p);
466 pathPaint.lineTo(pointTo);
468 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
469 p = QPointF(pointFrom.x(),pointTo.y());
471 interPoints.append(p);
472 pathPaint.lineTo(pointTo);
478 A OpenRect has the following shape :
483 void ConnectionItem::computeOpenRect(int orientationFrom, int orientationTo) {
484 pathPaint = QPainterPath(pointFrom);
487 double gap1 = marginConn;
488 double gap2 = marginConn;
489 //cout << "drawing an OpenRect" << endl;
491 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
492 if (orientationFrom == Parameters::West) {
495 if (orientationTo == Parameters::North) {
498 p = QPointF(pointFrom.x()+gap1,pointFrom.y());
500 interPoints.append(p);
501 p = QPointF(pointFrom.x()+gap1,pointTo.y()+gap2);
503 interPoints.append(p);
504 p = QPointF(pointTo.x(),pointTo.y()+gap2);
506 interPoints.append(p);
507 pathPaint.lineTo(pointTo);
510 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
511 if (orientationFrom == Parameters::North) {
514 if (orientationTo == Parameters::West) {
517 p = QPointF(pointFrom.x(),pointFrom.y()+gap1);
519 interPoints.append(p);
520 p = QPointF(pointTo.x()+gap2,pointFrom.y()+gap1);
522 interPoints.append(p);
523 p = QPointF(pointTo.x()+gap2,pointTo.y());
525 interPoints.append(p);
526 pathPaint.lineTo(pointTo);
530 /* drawHookSmallEnd():
532 A Hook has the following shape :
536 Its end has always a size of marginConn
538 void ConnectionItem::computeHookSmallEnd(int orientationFrom, int orientationTo) {
539 pathPaint = QPainterPath(pointFrom);
542 double gap = marginConn;
543 //cout << "drawing a Hook with small end" << endl;
545 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
547 if (orientationTo == Parameters::North) gap = -gap;
549 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
551 interPoints.append(p);
552 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()+gap);
554 interPoints.append(p);
555 p = QPointF(pointTo.x(),pointTo.y()+gap);
557 interPoints.append(p);
558 pathPaint.lineTo(pointTo);
561 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
563 if (orientationTo == Parameters::West) gap = -gap;
565 p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
567 interPoints.append(p);
568 p = QPointF(pointTo.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
570 interPoints.append(p);
571 p = QPointF(pointTo.x()+gap,pointTo.y());
573 interPoints.append(p);
574 pathPaint.lineTo(pointTo);
578 /* drawHookSmallStart():
580 A Hook has the following shape :
584 Its start has always a size of marginConn
586 void ConnectionItem::computeHookSmallStart(int orientationFrom, int orientationTo) {
587 pathPaint = QPainterPath(pointFrom);
590 double gap = marginConn;
591 //cout << "drawing a Hook with small start" << endl;
593 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
595 if (orientationFrom == Parameters::West) gap = -gap;
597 p = QPointF(pointFrom.x()+gap,pointFrom.y());
599 interPoints.append(p);
600 p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
602 interPoints.append(p);
603 p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
605 interPoints.append(p);
606 pathPaint.lineTo(pointTo);
608 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
610 if (orientationFrom == Parameters::North) gap = -gap;
612 p = QPointF(pointFrom.x(),pointFrom.y()+gap);
614 interPoints.append(p);
615 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
617 interPoints.append(p);
618 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
620 interPoints.append(p);
621 pathPaint.lineTo(pointTo);
627 An Elle has the following shape :
632 void ConnectionItem::computeElle(int orientationFrom) {
634 pathPaint = QPainterPath(pointFrom);
639 switch(orientationFrom){
640 case Parameters::North :
641 if(pointFrom.y() < pointTo.y()) {
642 y = pointFrom.y()-marginConn;
645 y = pointTo.y()-marginConn;
647 p = QPointF(pointFrom.x(),y);
649 interPoints.append(p);
650 p = QPointF(pointTo.x(),y);
652 interPoints.append(p);
653 pathPaint.lineTo(pointTo);
655 case Parameters::South :
656 if(pointFrom.y() > pointTo.y()) {
657 y = pointFrom.y()+marginConn;
660 y = pointTo.y()+marginConn;
662 p = QPointF(pointFrom.x(),y);
664 interPoints.append(p);
665 p = QPointF(pointTo.x(),y);
667 interPoints.append(p);
668 pathPaint.lineTo(pointTo);
670 case Parameters::West :
671 if(pointFrom.x() < pointTo.x()) {
672 x = pointFrom.x()-marginConn;
675 x = pointTo.x()-marginConn;
677 p = QPointF(x, pointFrom.y());
679 interPoints.append(p);
680 p = QPointF(x, pointTo.y());
682 interPoints.append(p);
683 pathPaint.lineTo(pointTo);
685 case Parameters::East :
686 if(pointFrom.x() > pointTo.x()) {
687 x = pointFrom.x()+marginConn;
690 x = pointTo.x()+marginConn;
692 p = QPointF(x, pointFrom.y());
694 interPoints.append(p);
695 p = QPointF(x, pointTo.y());
697 interPoints.append(p);
698 pathPaint.lineTo(pointTo);
703 void ConnectionItem::setSelected(bool selected) {
704 this->selected = selected;
712 void ConnectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
713 QGraphicsItem::mousePressEvent(event);
714 setZValue(zValue()+100);
715 setSelected(!selected);
716 update(boundingRect());
719 void ConnectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
720 QGraphicsItem::mouseReleaseEvent(event);
721 setZValue(zValue()-100);
724 void ConnectionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
725 QGraphicsItem::mouseMoveEvent(event);
728 void ConnectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
730 QAction* removeAction = menu.addAction("Remove");
731 QAction * selectedAction= menu.exec(event->screenPos());
733 if(selectedAction == removeAction){
734 dispatcher->removeConnection(this);
735 dispatcher->removeUselessGroupInterfaces();
739 void ConnectionItem::prepareChange() {
740 prepareGeometryChange();
743 QDataStream &operator <<(QDataStream &out, ConnectionItem &c) {
744 out.setVersion(QDataStream::Qt_4_8);
747 QDataStream toWrite(&connData, QIODevice::WriteOnly);
750 toWrite << c.getFromInterfaceItem()->getId();
751 toWrite << c.getToInterfaceItem()->getId();
758 QDataStream &operator >>(QDataStream &in, ConnectionItem &c) {
759 in.setVersion(QDataStream::Qt_4_8);