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::setPath() {
150 // signals to the scene that this connection is going to change of shape.
151 prepareGeometryChange();
153 pointFrom = fromInterfaceItem->getEndPointInGroup();
154 pointTo = toInterfaceItem->getEndPointInGroup();
157 oriFrom = fromInterfaceItem->getOrientation();
158 oriTo = toInterfaceItem->getOrientation();
160 /* NB: if src or dest is onwed by a GroupItem the orientation
161 must be changed as it is a block.
163 if(fromInterfaceItem->owner->isGroupItem()){
164 switch(fromInterfaceItem->getOrientation()){
165 case Parameters::North :
166 oriFrom = Parameters::South;
168 case Parameters::South :
169 oriFrom = Parameters::North;
171 case Parameters::East :
172 oriFrom = Parameters::West;
174 case Parameters::West :
175 oriFrom = Parameters::East;
179 if(toInterfaceItem->owner->isGroupItem()){
180 switch(toInterfaceItem->getOrientation()){
181 case Parameters::North :
182 oriTo = Parameters::South;
184 case Parameters::South :
185 oriTo = Parameters::North;
187 case Parameters::East :
188 oriTo = Parameters::West;
190 case Parameters::West :
191 oriTo = Parameters::East;
198 if(oriFrom == Parameters::South) {
200 // FROM SOUTH TO SOUTH
201 if(oriTo == Parameters::South) {
202 computeElle(oriFrom);
204 // FROM SOUTH TO NORTH
205 else if(oriTo == Parameters::North) {
206 gap1 = pointTo.y() - pointFrom.y();
207 if (gap1 > 2*marginConn) {
208 computeStaircase(oriFrom);
211 computeEsse(oriFrom);
214 // FROM SOUTH TO EAST OR WEST
215 else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
217 gap1 = pointTo.x() - pointFrom.x();
218 if (oriTo == Parameters::West) gap1 = -gap1;
219 gap2 = pointTo.y() - pointFrom.y();
223 computeHookSmallEnd(oriFrom,oriTo);
226 computeOpenRect(oriFrom,oriTo);
231 computeCorner(oriFrom);
234 computeHookSmallStart(oriFrom,oriTo);
239 else if(oriFrom == Parameters::North) {
241 // FROM NORTH TO SOUTH
242 if(oriTo == Parameters::South) {
243 gap1 = pointFrom.y() - pointTo.y();
244 if (gap1 > 2*marginConn) {
245 computeStaircase(oriFrom);
248 computeEsse(oriFrom);
251 // FROM NORTH TO NORTH
252 else if(oriTo == Parameters::North) {
253 computeElle(oriFrom);
255 // FROM NORTH TO EAST OR WEST
256 else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
258 gap1 = pointTo.x() - pointFrom.x();
259 if (oriTo == Parameters::West) gap1 = -gap1;
260 gap2 = pointFrom.y() - pointTo.y();
264 computeHookSmallEnd(oriFrom,oriTo);
267 computeOpenRect(oriFrom,oriTo);
272 computeCorner(oriFrom);
275 computeHookSmallStart(oriFrom,oriTo);
280 else if(oriFrom == Parameters::East) {
281 // FROM EAST TO NORTH OR SOUTH
282 if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
284 gap1 = pointFrom.x() - pointTo.x();
285 gap2 = pointFrom.y() - pointTo.y();
286 if (oriTo == Parameters::North) gap2 = -gap2;
290 computeHookSmallStart(oriFrom,oriTo);
293 computeOpenRect(oriFrom,oriTo);
298 computeCorner(oriFrom);
301 computeHookSmallEnd(oriFrom,oriTo);
305 else if(oriTo == Parameters::East) {
306 computeElle(oriFrom);
308 else if (oriTo == Parameters::West) {
309 gap1 = pointTo.x() - pointFrom.x();
310 if (gap1 > 2*marginConn) {
311 computeStaircase(oriFrom);
314 computeEsse(oriFrom);
318 else if (oriFrom == Parameters::West) {
320 // FROM WEST TO NORTH OR SOUTH
321 if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
323 gap1 = pointTo.x() - pointFrom.x();
324 gap2 = pointFrom.y() - pointTo.y();
325 if (oriTo == Parameters::North) gap2 = -gap2;
329 computeHookSmallStart(oriFrom,oriTo);
332 computeOpenRect(oriFrom,oriTo);
337 computeCorner(oriFrom);
340 computeHookSmallEnd(oriFrom,oriTo);
344 else if(oriTo == Parameters::East) {
345 gap1 = pointFrom.x() - pointTo.x();
346 if (gap1 > 2*marginConn) {
347 computeStaircase(oriFrom);
350 computeEsse(oriFrom);
353 else if (oriTo == Parameters::West) {
354 computeElle(oriFrom);
359 pathShape = pps.createStroke(pathPaint);
363 void ConnectionItem::computeEsse(int orientationFrom) {
365 //cout << "drawing an esse" << endl;
366 pathPaint = QPainterPath(pointFrom);
368 double gap = marginConn;
369 if ((orientationFrom == Parameters::North)||(orientationFrom == Parameters::West)) gap = -gap;
372 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
373 // must draw a complete esse
374 p = QPointF(pointFrom.x()+gap,pointFrom.y());
376 interPoints.append(p);
377 p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
379 interPoints.append(p);
380 p = QPointF(pointTo.x()-gap,(pointFrom.y()+pointTo.y())/2.0);
382 interPoints.append(p);
383 p = QPointF(pointTo.x()-gap,pointTo.y());
385 interPoints.append(p);
386 pathPaint.lineTo(pointTo);
388 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
390 // must draw a complete esse
391 p = QPointF(pointFrom.x(),pointFrom.y()+gap);
393 interPoints.append(p);
394 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
396 interPoints.append(p);
397 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()-gap);
399 interPoints.append(p);
400 p = QPointF(pointTo.x(), pointTo.y()-gap);
402 interPoints.append(p);
403 pathPaint.lineTo(pointTo);
407 void ConnectionItem::computeStaircase(int orientationFrom) {
409 pathPaint = QPainterPath(pointFrom);
413 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
414 if (pointFrom.y() == pointTo.y()) {
415 //cout << "drawing straight line" << endl;
416 pathPaint.lineTo(pointTo);
419 //cout << "drawing a staircase" << endl;
420 // sufficient place to draw a simple staircase
421 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
423 interPoints.append(p);
424 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
426 interPoints.append(p);
427 pathPaint.lineTo(pointTo);
430 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
431 if (pointFrom.x() == pointTo.x()) {
432 //cout << "drawing straight line" << endl;
433 pathPaint.lineTo(pointTo);
436 //cout << "drawing a staircase" << endl;
437 // sufficient place to draw a simple staircase
438 p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
440 interPoints.append(p);
441 p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
443 interPoints.append(p);
444 pathPaint.lineTo(pointTo);
451 A Corner has the following shape :
456 void ConnectionItem::computeCorner(int orientationFrom) {
458 pathPaint = QPainterPath(pointFrom);
461 //cout << "drawing a corner" << endl;
463 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
464 p = QPointF(pointTo.x(),pointFrom.y());
466 interPoints.append(p);
467 pathPaint.lineTo(pointTo);
469 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
470 p = QPointF(pointFrom.x(),pointTo.y());
472 interPoints.append(p);
473 pathPaint.lineTo(pointTo);
479 A OpenRect has the following shape :
484 void ConnectionItem::computeOpenRect(int orientationFrom, int orientationTo) {
485 pathPaint = QPainterPath(pointFrom);
488 double gap1 = marginConn;
489 double gap2 = marginConn;
490 //cout << "drawing an OpenRect" << endl;
492 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
493 if (orientationFrom == Parameters::West) {
496 if (orientationTo == Parameters::North) {
499 p = QPointF(pointFrom.x()+gap1,pointFrom.y());
501 interPoints.append(p);
502 p = QPointF(pointFrom.x()+gap1,pointTo.y()+gap2);
504 interPoints.append(p);
505 p = QPointF(pointTo.x(),pointTo.y()+gap2);
507 interPoints.append(p);
508 pathPaint.lineTo(pointTo);
511 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
512 if (orientationFrom == Parameters::North) {
515 if (orientationTo == Parameters::West) {
518 p = QPointF(pointFrom.x(),pointFrom.y()+gap1);
520 interPoints.append(p);
521 p = QPointF(pointTo.x()+gap2,pointFrom.y()+gap1);
523 interPoints.append(p);
524 p = QPointF(pointTo.x()+gap2,pointTo.y());
526 interPoints.append(p);
527 pathPaint.lineTo(pointTo);
531 /* drawHookSmallEnd():
533 A Hook has the following shape :
537 Its end has always a size of marginConn
539 void ConnectionItem::computeHookSmallEnd(int orientationFrom, int orientationTo) {
540 pathPaint = QPainterPath(pointFrom);
543 double gap = marginConn;
544 //cout << "drawing a Hook with small end" << endl;
546 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
548 if (orientationTo == Parameters::North) gap = -gap;
550 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
552 interPoints.append(p);
553 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()+gap);
555 interPoints.append(p);
556 p = QPointF(pointTo.x(),pointTo.y()+gap);
558 interPoints.append(p);
559 pathPaint.lineTo(pointTo);
562 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
564 if (orientationTo == Parameters::West) gap = -gap;
566 p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
568 interPoints.append(p);
569 p = QPointF(pointTo.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
571 interPoints.append(p);
572 p = QPointF(pointTo.x()+gap,pointTo.y());
574 interPoints.append(p);
575 pathPaint.lineTo(pointTo);
579 /* drawHookSmallStart():
581 A Hook has the following shape :
585 Its start has always a size of marginConn
587 void ConnectionItem::computeHookSmallStart(int orientationFrom, int orientationTo) {
588 pathPaint = QPainterPath(pointFrom);
591 double gap = marginConn;
592 //cout << "drawing a Hook with small start" << endl;
594 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
596 if (orientationFrom == Parameters::West) gap = -gap;
598 p = QPointF(pointFrom.x()+gap,pointFrom.y());
600 interPoints.append(p);
601 p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
603 interPoints.append(p);
604 p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
606 interPoints.append(p);
607 pathPaint.lineTo(pointTo);
609 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
611 if (orientationFrom == Parameters::North) gap = -gap;
613 p = QPointF(pointFrom.x(),pointFrom.y()+gap);
615 interPoints.append(p);
616 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
618 interPoints.append(p);
619 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
621 interPoints.append(p);
622 pathPaint.lineTo(pointTo);
628 An Elle has the following shape :
633 void ConnectionItem::computeElle(int orientationFrom) {
635 pathPaint = QPainterPath(pointFrom);
640 switch(orientationFrom){
641 case Parameters::North :
642 if(pointFrom.y() < pointTo.y()) {
643 y = pointFrom.y()-marginConn;
646 y = pointTo.y()-marginConn;
648 p = QPointF(pointFrom.x(),y);
650 interPoints.append(p);
651 p = QPointF(pointTo.x(),y);
653 interPoints.append(p);
654 pathPaint.lineTo(pointTo);
656 case Parameters::South :
657 if(pointFrom.y() > pointTo.y()) {
658 y = pointFrom.y()+marginConn;
661 y = pointTo.y()+marginConn;
663 p = QPointF(pointFrom.x(),y);
665 interPoints.append(p);
666 p = QPointF(pointTo.x(),y);
668 interPoints.append(p);
669 pathPaint.lineTo(pointTo);
671 case Parameters::West :
672 if(pointFrom.x() < pointTo.x()) {
673 x = pointFrom.x()-marginConn;
676 x = pointTo.x()-marginConn;
678 p = QPointF(x, pointFrom.y());
680 interPoints.append(p);
681 p = QPointF(x, pointTo.y());
683 interPoints.append(p);
684 pathPaint.lineTo(pointTo);
686 case Parameters::East :
687 if(pointFrom.x() > pointTo.x()) {
688 x = pointFrom.x()+marginConn;
691 x = pointTo.x()+marginConn;
693 p = QPointF(x, pointFrom.y());
695 interPoints.append(p);
696 p = QPointF(x, pointTo.y());
698 interPoints.append(p);
699 pathPaint.lineTo(pointTo);
704 void ConnectionItem::setSelected(bool selected) {
705 this->selected = selected;
713 void ConnectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
714 QGraphicsItem::mousePressEvent(event);
715 setZValue(zValue()+100);
716 setSelected(!selected);
717 update(boundingRect());
720 void ConnectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
721 QGraphicsItem::mouseReleaseEvent(event);
722 setZValue(zValue()-100);
725 void ConnectionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
726 QGraphicsItem::mouseMoveEvent(event);
729 void ConnectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
730 /* have to check if the connection can be removed.
731 If the from or to InterfaceItem is owned by a group item, and this item
732 is both connected to and from, thus it is impossible to remove this connection
734 bool canRemove = true;
735 InterfaceItem* groupIfaceItem = NULL;
736 if (fromInterfaceItem->getOwner()->isGroupItem()) {
737 groupIfaceItem = fromInterfaceItem;
739 else if (toInterfaceItem->getOwner()->isGroupItem()) {
740 groupIfaceItem = toInterfaceItem;
743 if (groupIfaceItem != NULL) {
744 ConnectedInterface* ref = groupIfaceItem->refInter;
745 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
752 QAction* titleAction = menu.addAction("Connection operations");
753 titleAction->setEnabled(false);
755 QAction* removeAction = menu.addAction("Remove");
756 QAction * selectedAction= menu.exec(event->screenPos());
758 if(selectedAction == removeAction){
759 dispatcher->removeConnection(this);
764 void ConnectionItem::prepareChange() {
765 prepareGeometryChange();
768 QDataStream &operator <<(QDataStream &out, ConnectionItem &c) {
769 out.setVersion(QDataStream::Qt_4_8);
772 QDataStream toWrite(&connData, QIODevice::WriteOnly);
775 toWrite << c.getFromInterfaceItem()->getId();
776 toWrite << c.getToInterfaceItem()->getId();
783 QDataStream &operator >>(QDataStream &in, ConnectionItem &c) {
784 in.setVersion(QDataStream::Qt_4_8);