1 #include "InterfaceItem.h"
3 #include "Parameters.h"
4 #include "GroupInterface.h"
5 #include "FunctionalInterface.h"
8 int InterfaceItem::counter = 0;
10 InterfaceItem::InterfaceItem(double _position,
12 ConnectedInterface *_refInter,
13 AbstractBoxItem* _owner,
15 positionRatio = _position;
16 orientation = _orientation;
19 // CAUTION : the owner must add explicitely this item to its interface, calling addInterface()
23 QFontMetrics fmName(params->defaultIfaceFont);
24 nameWidth = fmName.width(refInter->getName());
25 nameHeight = fmName.height();
26 // by default, only data interface are visible
27 if (refInter->getPurpose() == AbstractInterface::Data) {
34 this->id = InterfaceItem::counter++;
40 InterfaceItem::InterfaceItem(){
44 QString InterfaceItem::getName() {
45 return refInter->getName();
48 /* boundingRect() : give the bounding rect in the blockitem coord. system */
49 QRectF InterfaceItem::boundingRect() const {
55 case Parameters::East :
56 pointHG = QPointF(originPoint.x(),originPoint.y()-(params->arrowHeight/2.0));
57 s = QSizeF(params->arrowWidth+params->arrowLineLength, params->arrowHeight);
59 case Parameters::North :
60 pointHG = QPointF(originPoint.x()-(params->arrowHeight/2.0),originPoint.y()-params->arrowWidth-params->arrowLineLength);
61 s = QSizeF(params->arrowHeight,params->arrowWidth+params->arrowLineLength);
63 case Parameters::West :
64 pointHG = QPointF(originPoint.x()-params->arrowLineLength-params->arrowWidth,originPoint.y()-(params->arrowHeight/2.0));
65 s = QSizeF(params->arrowWidth+params->arrowLineLength, params->arrowHeight);
67 case Parameters::South :
68 pointHG = QPointF(originPoint.x()-(params->arrowHeight/2.0),originPoint.y());
69 s = QSizeF(params->arrowHeight, params->arrowWidth+params->arrowLineLength);
77 return QRectF(pointHG,s);
80 void InterfaceItem::paint(QPainter *painter) {
87 painter->setPen(QPen(Qt::red,2));
90 painter->setPen(QPen(Qt::black,1));
93 painter->translate(originPoint);
96 case Parameters::North:
99 case Parameters::West:
100 painter->rotate(180);
102 case Parameters::South:
108 if(refInter->getDirection() == AbstractInterface::Input) {
109 painter->drawPath(params->inArrow);
111 else if(refInter->getDirection() == AbstractInterface::Output) {
112 painter->drawPath(params->outArrow);
113 } else if(refInter->getDirection() == AbstractInterface::InOut) {
114 painter->drawPath(params->inArrow);
115 painter->drawPath(params->outArrow);
120 // reset to normal if at west
121 if(orientation == Parameters::West){
122 painter->rotate(180);
125 painter->setFont(params->defaultIfaceFont);
127 QFontMetrics fm = painter->fontMetrics();
128 int w = nameWidth + owner->getIfaceMargin();
131 if(orientation == Parameters::West){
133 if(owner->isGroupItem()){
134 painter->drawText(-(w+params->arrowWidth+params->arrowLineLength),-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
136 else if(owner->isBoxItem()){
137 painter->drawText(0,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
142 if(owner->isGroupItem()) {
143 painter->drawText(params->arrowWidth+params->arrowLineLength,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
145 else if(owner->isBoxItem()) {
146 painter->drawText(-w,-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
154 QPointF InterfaceItem::getEndPointInGroup() {
157 if (owner->isGroupItem()) {
161 double x = owner->x() + originPoint.x();
162 double y = owner->y() + originPoint.y();
164 case Parameters::East:
165 x += params->arrowWidth+params->arrowLineLength;
167 case Parameters::North:
168 y -= params->arrowWidth+params->arrowLineLength;
170 case Parameters::West:
171 x -= params->arrowWidth+params->arrowLineLength;
173 case Parameters::South:
174 y += params->arrowWidth+params->arrowLineLength;
180 //cout << "iface end point in group item: " << p.x() << "," << p.y() << endl;
184 void InterfaceItem::setOriginPoint() {
186 case Parameters::East:
187 originPoint = QPointF(owner->getWidth(),position);
189 case Parameters::North:
190 originPoint = QPointF(position,0);
192 case Parameters::West:
193 originPoint = QPointF(0,position);
195 case Parameters::South:
196 originPoint = QPointF(position,owner->getHeight());
201 QString InterfaceItem::getStrOrientation() {
204 case Parameters::North :
205 str = QString("north");
207 case Parameters::South :
208 str = QString("south");
210 case Parameters::East :
211 str = QString("east");
213 case Parameters::West :
214 str = QString("west");
221 int InterfaceItem::getIntOrientation(QString str) {
222 if(str == "west") return Parameters::West;
223 if(str == "east") return Parameters::East;
224 if(str == "south") return Parameters::South;
225 if(str == "north") return Parameters::North;
231 - modify all necessary attributes in the model to create a connection
232 between current InterfaceItem and iface. Note that the source and destination
233 are deduced from the direction (In, Out) and the type of the owner (funcitonal, group)
235 CAUTION: No security checks are done. This method must be called only if canConnectWith has been called and returned true.
237 NOTE : conditions so that this InterfaceItem can be connected with inter.
238 (i.e. current one can connect to inter OR inter can connect to current)
240 Here are all the possible combinations, depending on the type of the
241 block/item and direction of the interface, which are :
242 GI/GB : a GroupItem referencing a GroupBlock (single solution for GI)
243 BI/FB : a BlockItem referencing a FunctionalBlock
244 BI/GB : a BlockItem referencing a GroupBlock
247 - Input can connect with BI/FB or BI/GB Input
248 - Output can connect with BI/FB or BI/GB Output
251 - Input can connect with:
255 - Output can connect with:
261 - Input can connect with:
265 - Output can connect with:
270 And whatever the case an InOut can only connect with an InOut
272 - the IG does not allow the connect a GI/GB interface to an
273 interface of another GI/GB, thus the case is not considered above.
274 - BI/FB and BI/GB are the same.
275 - the cases where direction are the same only occur when
276 the 2 items are of different type (GI and BI)
277 - the cases where directions are different only occur when
278 the 2 are of both BlockItem
281 bool InterfaceItem::connectWith(InterfaceItem *iface) {
282 ConnectedInterface* interThis = refInter; // the reference of this
283 ConnectedInterface* interOther = iface->refInter; // the reference of the other
284 ConnectedInterface* src = NULL, *dest = NULL;
286 if(interThis->getDirection() == AbstractInterface::InOut && interOther->getDirection() == AbstractInterface::InOut){
287 /* NOTE: InOut interfaces have both directions and thus are
288 connected from inter1 to inter2 AND inter2 to inter1
289 Another effect is that a InOut can be connected to/from a single
292 if((interThis->getConnectedFrom() == NULL) && (interOther->getConnectedFrom() == NULL)) {
294 interOther->connectFrom(interThis);
295 interOther->getConnectedTo().append(interThis);
296 interThis->connectFrom(interOther);
297 interThis->getConnectedTo().append(interOther);
299 cout << "connecting 2 InOut"<< endl;
304 else if (interThis->getDirection() == interOther->getDirection()) {
306 // cannot connect GI to GI or 2 BI of the same direction.
307 if ((getOwner()->isGroupItem()) && (iface->getOwner()->isGroupItem())) return false;
308 if ((getOwner()->isBoxItem()) && (iface->getOwner()->isBoxItem())) return false;
310 if (interThis->getDirection() == AbstractInterface::Input) { // both are inputs
311 cout << "connecting GI to BI" << endl;
312 if(getOwner()->isGroupItem()) {
321 else { // both are outputs
322 cout << "connecting BO to GO" << endl;
323 if(getOwner()->isGroupItem()){
334 if ((getOwner()->isGroupItem()) || (iface->getOwner()->isGroupItem())) return false;
336 cout << "connecting BO to BI" << endl;
337 if(interOther->getDirection() == AbstractInterface::Output) {
347 if(dest != NULL && src != NULL){
348 // cannot overrive existing connectionFrom
349 if(dest->getConnectedFrom() == NULL) {
350 dest->connectFrom(src);
351 src->connectTo(dest);
361 void InterfaceItem::unconnectTo(InterfaceItem *iface)
363 if(iface->refInter->getConnectedFrom() == refInter){
364 iface->refInter->connectFrom(NULL);
366 if(iface->refInter->getConnectedTo().contains(refInter)){
367 cout << "abnormal case while removing iface conn from " << qPrintable(refInter->getName()) << " to " << qPrintable(iface->refInter->getName()) << endl;
368 iface->refInter->removeConnectedTo(refInter);
370 if(refInter->getConnectedFrom() == iface->refInter) {
371 cout << "abnormal case while removing iface conn from " << qPrintable(refInter->getName()) << " to " << qPrintable(iface->refInter->getName()) << endl;
372 refInter->connectFrom(NULL);
374 if(refInter->getConnectedTo().contains(iface->refInter)){
375 refInter->removeConnectedTo(iface->refInter);
379 void InterfaceItem::updatePosition()
381 if(orientation == Parameters::North || orientation == Parameters::South){
382 position = positionRatio * owner->getWidth();
384 position = positionRatio * owner->getHeight();
389 void InterfaceItem::addConnectionItem(ConnectionItem* item) {
390 connections.append(item);
393 void InterfaceItem::removeConnectionItem(ConnectionItem* item) {
394 connections.removeOne(item);
397 QDataStream &operator <<(QDataStream &out, InterfaceItem *i) {
400 out.setVersion(QDataStream::Qt_5);
402 QByteArray interfaceData;
403 QDataStream toWrite(&interfaceData, QIODevice::WriteOnly);
405 toWrite << i->getId();
406 toWrite << i->getName();
407 toWrite << i->getPositionRatio();
408 toWrite << i->getOrientation();
410 foreach(QGraphicsItem* item, i->params->getCurrentScene()->items()){
411 if(item->data(0) == "connection"){
412 ConnectionItem *conn = dynamic_cast<ConnectionItem*>(item);
413 if(conn->getFromInterfaceItem() == i || conn->getToInterfaceItem() == i){
414 toWrite << conn->getId();
415 cout << "id connection : " << conn->getId() << endl;
419 out << interfaceData;
424 QDataStream &operator >>(QDataStream &in, InterfaceItem &i) {
427 in.setVersion(QDataStream::Qt_5);
430 double positionRatio;
440 i.setPositionRatio(positionRatio);
441 i.setOrientation(orientation);