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);
88 if (fromInterfaceItem->refInter->getPurpose() == AbstractInterface::Data) {
99 ConnectionItem::ConnectionItem(const ConnectionItem ©) {
100 pointFrom = copy.pointFrom;
101 pointTo = copy.pointTo;
102 interPoint1 = copy.interPoint1;
103 interPoint2 = copy.interPoint2;
104 interPoint3 = copy.interPoint3;
105 interPoint4 = copy.interPoint4;
108 ConnectionItem::~ConnectionItem() {
111 ConnectionItem::ConnectionItem() {
114 QPainterPath ConnectionItem::shape() const {
118 QRectF ConnectionItem::boundingRect() const {
122 if(pointFrom.x() < pointTo.x()){
123 start.setX(pointFrom.x()-20);
124 end.setX(pointTo.x()+20);
126 start.setX(pointTo.x()-20);
127 end.setX(pointFrom.x()+20);
129 if(pointFrom.y() < pointTo.y()){
130 start.setY(pointFrom.y()-20);
131 end.setY(pointTo.y()+20);
133 start.setY(pointTo.y()-20);
134 end.setY(pointFrom.y()+20);
136 return QRectF(start, end);
139 void ConnectionItem::paint(QPainter *painter,
140 const QStyleOptionGraphicsItem *option,
143 if (!visible) return;
145 painter->setPen(Qt::blue);
147 painter->setPen(Qt::red);
150 painter->drawPath(pathPaint);
153 void ConnectionItem::addInterPoint(QPointF point) {
157 void ConnectionItem::setPath() {
159 // signals to the scene that this connection is going to change of shape.
160 prepareGeometryChange();
162 pointFrom = fromInterfaceItem->getEndPointInGroup();
163 pointTo = toInterfaceItem->getEndPointInGroup();
166 oriFrom = fromInterfaceItem->getOrientation();
167 oriTo = toInterfaceItem->getOrientation();
169 /* NB: if src or dest is onwed by a GroupItem the orientation
170 must be changed as it is a block.
172 if(fromInterfaceItem->owner->isGroupItem()){
173 switch(fromInterfaceItem->getOrientation()){
174 case Parameters::North :
175 oriFrom = Parameters::South;
177 case Parameters::South :
178 oriFrom = Parameters::North;
180 case Parameters::East :
181 oriFrom = Parameters::West;
183 case Parameters::West :
184 oriFrom = Parameters::East;
188 if(toInterfaceItem->owner->isGroupItem()){
189 switch(toInterfaceItem->getOrientation()){
190 case Parameters::North :
191 oriTo = Parameters::South;
193 case Parameters::South :
194 oriTo = Parameters::North;
196 case Parameters::East :
197 oriTo = Parameters::West;
199 case Parameters::West :
200 oriTo = Parameters::East;
207 if(oriFrom == Parameters::South) {
209 // FROM SOUTH TO SOUTH
210 if(oriTo == Parameters::South) {
211 computeElle(oriFrom);
213 // FROM SOUTH TO NORTH
214 else if(oriTo == Parameters::North) {
215 gap1 = pointTo.y() - pointFrom.y();
216 if (gap1 > 2*marginConn) {
217 computeStaircase(oriFrom);
220 computeEsse(oriFrom);
223 // FROM SOUTH TO EAST OR WEST
224 else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
226 gap1 = pointTo.x() - pointFrom.x();
227 if (oriTo == Parameters::West) gap1 = -gap1;
228 gap2 = pointTo.y() - pointFrom.y();
232 computeHookSmallEnd(oriFrom,oriTo);
235 computeOpenRect(oriFrom,oriTo);
240 computeCorner(oriFrom);
243 computeHookSmallStart(oriFrom,oriTo);
248 else if(oriFrom == Parameters::North) {
250 // FROM NORTH TO SOUTH
251 if(oriTo == Parameters::South) {
252 gap1 = pointFrom.y() - pointTo.y();
253 if (gap1 > 2*marginConn) {
254 computeStaircase(oriFrom);
257 computeEsse(oriFrom);
260 // FROM NORTH TO NORTH
261 else if(oriTo == Parameters::North) {
262 computeElle(oriFrom);
264 // FROM NORTH TO EAST OR WEST
265 else if ((oriTo == Parameters::East) || (oriTo == Parameters::West)){
267 gap1 = pointTo.x() - pointFrom.x();
268 if (oriTo == Parameters::West) gap1 = -gap1;
269 gap2 = pointFrom.y() - pointTo.y();
273 computeHookSmallEnd(oriFrom,oriTo);
276 computeOpenRect(oriFrom,oriTo);
281 computeCorner(oriFrom);
284 computeHookSmallStart(oriFrom,oriTo);
289 else if(oriFrom == Parameters::East) {
290 // FROM EAST TO NORTH OR SOUTH
291 if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
293 gap1 = pointFrom.x() - pointTo.x();
294 gap2 = pointFrom.y() - pointTo.y();
295 if (oriTo == Parameters::North) gap2 = -gap2;
299 computeHookSmallStart(oriFrom,oriTo);
302 computeOpenRect(oriFrom,oriTo);
307 computeCorner(oriFrom);
310 computeHookSmallEnd(oriFrom,oriTo);
314 else if(oriTo == Parameters::East) {
315 computeElle(oriFrom);
317 else if (oriTo == Parameters::West) {
318 gap1 = pointTo.x() - pointFrom.x();
319 if (gap1 > 2*marginConn) {
320 computeStaircase(oriFrom);
323 computeEsse(oriFrom);
327 else if (oriFrom == Parameters::West) {
329 // FROM WEST TO NORTH OR SOUTH
330 if ((oriTo == Parameters::South) || (oriTo == Parameters::North)){
332 gap1 = pointTo.x() - pointFrom.x();
333 gap2 = pointFrom.y() - pointTo.y();
334 if (oriTo == Parameters::North) gap2 = -gap2;
338 computeHookSmallStart(oriFrom,oriTo);
341 computeOpenRect(oriFrom,oriTo);
346 computeCorner(oriFrom);
349 computeHookSmallEnd(oriFrom,oriTo);
353 else if(oriTo == Parameters::East) {
354 gap1 = pointFrom.x() - pointTo.x();
355 if (gap1 > 2*marginConn) {
356 computeStaircase(oriFrom);
359 computeEsse(oriFrom);
362 else if (oriTo == Parameters::West) {
363 computeElle(oriFrom);
368 pathShape = pps.createStroke(pathPaint);
372 void ConnectionItem::computeEsse(int orientationFrom) {
374 //cout << "drawing an esse" << endl;
375 pathPaint = QPainterPath(pointFrom);
377 double gap = marginConn;
378 if ((orientationFrom == Parameters::North)||(orientationFrom == Parameters::West)) gap = -gap;
381 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
382 // must draw a complete esse
383 p = QPointF(pointFrom.x()+gap,pointFrom.y());
385 interPoints.append(p);
386 p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
388 interPoints.append(p);
389 p = QPointF(pointTo.x()-gap,(pointFrom.y()+pointTo.y())/2.0);
391 interPoints.append(p);
392 p = QPointF(pointTo.x()-gap,pointTo.y());
394 interPoints.append(p);
395 pathPaint.lineTo(pointTo);
397 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
399 // must draw a complete esse
400 p = QPointF(pointFrom.x(),pointFrom.y()+gap);
402 interPoints.append(p);
403 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
405 interPoints.append(p);
406 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()-gap);
408 interPoints.append(p);
409 p = QPointF(pointTo.x(), pointTo.y()-gap);
411 interPoints.append(p);
412 pathPaint.lineTo(pointTo);
416 void ConnectionItem::computeStaircase(int orientationFrom) {
418 pathPaint = QPainterPath(pointFrom);
422 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
423 if (pointFrom.y() == pointTo.y()) {
424 //cout << "drawing straight line" << endl;
425 pathPaint.lineTo(pointTo);
428 //cout << "drawing a staircase" << endl;
429 // sufficient place to draw a simple staircase
430 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
432 interPoints.append(p);
433 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
435 interPoints.append(p);
436 pathPaint.lineTo(pointTo);
439 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
440 if (pointFrom.x() == pointTo.x()) {
441 //cout << "drawing straight line" << endl;
442 pathPaint.lineTo(pointTo);
445 //cout << "drawing a staircase" << endl;
446 // sufficient place to draw a simple staircase
447 p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
449 interPoints.append(p);
450 p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
452 interPoints.append(p);
453 pathPaint.lineTo(pointTo);
460 A Corner has the following shape :
465 void ConnectionItem::computeCorner(int orientationFrom) {
467 pathPaint = QPainterPath(pointFrom);
470 //cout << "drawing a corner" << endl;
472 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
473 p = QPointF(pointTo.x(),pointFrom.y());
475 interPoints.append(p);
476 pathPaint.lineTo(pointTo);
478 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
479 p = QPointF(pointFrom.x(),pointTo.y());
481 interPoints.append(p);
482 pathPaint.lineTo(pointTo);
488 A OpenRect has the following shape :
493 void ConnectionItem::computeOpenRect(int orientationFrom, int orientationTo) {
494 pathPaint = QPainterPath(pointFrom);
497 double gap1 = marginConn;
498 double gap2 = marginConn;
499 //cout << "drawing an OpenRect" << endl;
501 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
502 if (orientationFrom == Parameters::West) {
505 if (orientationTo == Parameters::North) {
508 p = QPointF(pointFrom.x()+gap1,pointFrom.y());
510 interPoints.append(p);
511 p = QPointF(pointFrom.x()+gap1,pointTo.y()+gap2);
513 interPoints.append(p);
514 p = QPointF(pointTo.x(),pointTo.y()+gap2);
516 interPoints.append(p);
517 pathPaint.lineTo(pointTo);
520 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
521 if (orientationFrom == Parameters::North) {
524 if (orientationTo == Parameters::West) {
527 p = QPointF(pointFrom.x(),pointFrom.y()+gap1);
529 interPoints.append(p);
530 p = QPointF(pointTo.x()+gap2,pointFrom.y()+gap1);
532 interPoints.append(p);
533 p = QPointF(pointTo.x()+gap2,pointTo.y());
535 interPoints.append(p);
536 pathPaint.lineTo(pointTo);
540 /* drawHookSmallEnd():
542 A Hook has the following shape :
546 Its end has always a size of marginConn
548 void ConnectionItem::computeHookSmallEnd(int orientationFrom, int orientationTo) {
549 pathPaint = QPainterPath(pointFrom);
552 double gap = marginConn;
553 //cout << "drawing a Hook with small end" << endl;
555 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
557 if (orientationTo == Parameters::North) gap = -gap;
559 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y());
561 interPoints.append(p);
562 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y()+gap);
564 interPoints.append(p);
565 p = QPointF(pointTo.x(),pointTo.y()+gap);
567 interPoints.append(p);
568 pathPaint.lineTo(pointTo);
571 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
573 if (orientationTo == Parameters::West) gap = -gap;
575 p = QPointF(pointFrom.x(),(pointFrom.y()+pointTo.y())/2.0);
577 interPoints.append(p);
578 p = QPointF(pointTo.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
580 interPoints.append(p);
581 p = QPointF(pointTo.x()+gap,pointTo.y());
583 interPoints.append(p);
584 pathPaint.lineTo(pointTo);
588 /* drawHookSmallStart():
590 A Hook has the following shape :
594 Its start has always a size of marginConn
596 void ConnectionItem::computeHookSmallStart(int orientationFrom, int orientationTo) {
597 pathPaint = QPainterPath(pointFrom);
600 double gap = marginConn;
601 //cout << "drawing a Hook with small start" << endl;
603 if ((orientationFrom == Parameters::East)||(orientationFrom == Parameters::West)) {
605 if (orientationFrom == Parameters::West) gap = -gap;
607 p = QPointF(pointFrom.x()+gap,pointFrom.y());
609 interPoints.append(p);
610 p = QPointF(pointFrom.x()+gap,(pointFrom.y()+pointTo.y())/2.0);
612 interPoints.append(p);
613 p = QPointF(pointTo.x(),(pointFrom.y()+pointTo.y())/2.0);
615 interPoints.append(p);
616 pathPaint.lineTo(pointTo);
618 else if ((orientationFrom == Parameters::South)||(orientationFrom == Parameters::North)) {
620 if (orientationFrom == Parameters::North) gap = -gap;
622 p = QPointF(pointFrom.x(),pointFrom.y()+gap);
624 interPoints.append(p);
625 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointFrom.y()+gap);
627 interPoints.append(p);
628 p = QPointF((pointFrom.x()+pointTo.x())/2.0,pointTo.y());
630 interPoints.append(p);
631 pathPaint.lineTo(pointTo);
637 An Elle has the following shape :
642 void ConnectionItem::computeElle(int orientationFrom) {
644 pathPaint = QPainterPath(pointFrom);
649 switch(orientationFrom){
650 case Parameters::North :
651 if(pointFrom.y() < pointTo.y()) {
652 y = pointFrom.y()-marginConn;
655 y = pointTo.y()-marginConn;
657 p = QPointF(pointFrom.x(),y);
659 interPoints.append(p);
660 p = QPointF(pointTo.x(),y);
662 interPoints.append(p);
663 pathPaint.lineTo(pointTo);
665 case Parameters::South :
666 if(pointFrom.y() > pointTo.y()) {
667 y = pointFrom.y()+marginConn;
670 y = pointTo.y()+marginConn;
672 p = QPointF(pointFrom.x(),y);
674 interPoints.append(p);
675 p = QPointF(pointTo.x(),y);
677 interPoints.append(p);
678 pathPaint.lineTo(pointTo);
680 case Parameters::West :
681 if(pointFrom.x() < pointTo.x()) {
682 x = pointFrom.x()-marginConn;
685 x = pointTo.x()-marginConn;
687 p = QPointF(x, pointFrom.y());
689 interPoints.append(p);
690 p = QPointF(x, pointTo.y());
692 interPoints.append(p);
693 pathPaint.lineTo(pointTo);
695 case Parameters::East :
696 if(pointFrom.x() > pointTo.x()) {
697 x = pointFrom.x()+marginConn;
700 x = pointTo.x()+marginConn;
702 p = QPointF(x, pointFrom.y());
704 interPoints.append(p);
705 p = QPointF(x, pointTo.y());
707 interPoints.append(p);
708 pathPaint.lineTo(pointTo);
713 void ConnectionItem::setSelected(bool selected) {
714 this->selected = selected;
722 void ConnectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
723 QGraphicsItem::mousePressEvent(event);
724 setZValue(zValue()+100);
725 setSelected(!selected);
726 update(boundingRect());
729 void ConnectionItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
730 QGraphicsItem::mouseReleaseEvent(event);
731 setZValue(zValue()-100);
734 void ConnectionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
735 QGraphicsItem::mouseMoveEvent(event);
738 void ConnectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
739 /* have to check if the connection can be removed.
740 If the from or to InterfaceItem is owned by a group item, and this item
741 is both connected to and from, thus it is impossible to remove this connection
743 bool canRemove = true;
744 InterfaceItem* groupIfaceItem = NULL;
745 if (fromInterfaceItem->getOwner()->isGroupItem()) {
746 groupIfaceItem = fromInterfaceItem;
748 else if (toInterfaceItem->getOwner()->isGroupItem()) {
749 groupIfaceItem = toInterfaceItem;
752 if (groupIfaceItem != NULL) {
753 ConnectedInterface* ref = groupIfaceItem->refInter;
754 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
761 QAction* titleAction = menu.addAction("Connection operations");
762 titleAction->setEnabled(false);
764 QAction* removeAction = menu.addAction("Remove");
765 QAction * selectedAction= menu.exec(event->screenPos());
767 if(selectedAction == removeAction){
768 dispatcher->removeConnection(this);
773 void ConnectionItem::prepareChange() {
774 prepareGeometryChange();
777 QDataStream &operator <<(QDataStream &out, ConnectionItem &c) {
778 out.setVersion(QDataStream::Qt_4_8);
781 QDataStream toWrite(&connData, QIODevice::WriteOnly);
784 toWrite << c.getFromInterfaceItem()->getId();
785 toWrite << c.getToInterfaceItem()->getId();
792 QDataStream &operator >>(QDataStream &in, ConnectionItem &c) {
793 in.setVersion(QDataStream::Qt_4_8);