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));
89 else if(refInter->getLevel() == AbstractInterface::Basic) {
90 painter->setPen(QPen(Qt::darkCyan,1));
92 else if(refInter->getLevel() == AbstractInterface::Top) {
93 painter->setPen(QPen(Qt::black,1));
96 painter->translate(originPoint);
99 case Parameters::North:
100 painter->rotate(-90);
102 case Parameters::West:
103 painter->rotate(180);
105 case Parameters::South:
111 if(refInter->getDirection() == AbstractInterface::Input) {
112 painter->drawPath(params->inArrow);
114 else if(refInter->getDirection() == AbstractInterface::Output) {
115 painter->drawPath(params->outArrow);
116 } else if(refInter->getDirection() == AbstractInterface::InOut) {
117 painter->drawPath(params->inArrow);
118 painter->drawPath(params->outArrow);
123 // reset to normal if at west
124 if(orientation == Parameters::West){
125 painter->rotate(180);
128 painter->setFont(params->defaultIfaceFont);
130 QFontMetrics fm = painter->fontMetrics();
131 int w = nameWidth + owner->getIfaceMargin();
134 if(orientation == Parameters::West){
136 if(owner->isGroupItem()){
137 painter->drawText(-(w+params->arrowWidth+params->arrowLineLength),-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
139 else if(owner->isBoxItem()){
140 painter->drawText(0,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
145 if(owner->isGroupItem()) {
146 painter->drawText(params->arrowWidth+params->arrowLineLength,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
148 else if(owner->isBoxItem()) {
149 painter->drawText(-w,-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
157 QPointF InterfaceItem::getEndPointInGroup() {
160 if (owner->isGroupItem()) {
164 double x = owner->x() + originPoint.x();
165 double y = owner->y() + originPoint.y();
167 case Parameters::East:
168 x += params->arrowWidth+params->arrowLineLength;
170 case Parameters::North:
171 y -= params->arrowWidth+params->arrowLineLength;
173 case Parameters::West:
174 x -= params->arrowWidth+params->arrowLineLength;
176 case Parameters::South:
177 y += params->arrowWidth+params->arrowLineLength;
183 //cout << "iface end point in group item: " << p.x() << "," << p.y() << endl;
187 void InterfaceItem::setOriginPoint() {
189 case Parameters::East:
190 originPoint = QPointF(owner->getWidth(),position);
192 case Parameters::North:
193 originPoint = QPointF(position,0);
195 case Parameters::West:
196 originPoint = QPointF(0,position);
198 case Parameters::South:
199 originPoint = QPointF(position,owner->getHeight());
204 QString InterfaceItem::getStrOrientation() {
207 case Parameters::North :
208 str = QString("north");
210 case Parameters::South :
211 str = QString("south");
213 case Parameters::East :
214 str = QString("east");
216 case Parameters::West :
217 str = QString("west");
224 int InterfaceItem::getIntOrientation(QString str) {
225 if(str == "west") return Parameters::West;
226 if(str == "east") return Parameters::East;
227 if(str == "south") return Parameters::South;
228 if(str == "north") return Parameters::North;
234 - modify all necessary attributes in the model to create a connection
235 between current InterfaceItem and iface. Note that the source and destination
236 are deduced from the direction (In, Out) and the type of the owner (funcitonal, group)
238 CAUTION: No security checks are done. This method must be called only if canConnectWith has been called and returned true.
240 NOTE : conditions so that this InterfaceItem can be connected with inter.
241 (i.e. current one can connect to inter OR inter can connect to current)
243 Here are all the possible combinations, depending on the type of the
244 block/item and direction of the interface, which are :
245 GI/GB : a GroupItem referencing a GroupBlock (single solution for GI)
246 BI/FB : a BlockItem referencing a FunctionalBlock
247 BI/GB : a BlockItem referencing a GroupBlock
250 - Input can connect with BI/FB or BI/GB Input
251 - Output can connect with BI/FB or BI/GB Output
254 - Input can connect with:
258 - Output can connect with:
264 - Input can connect with:
268 - Output can connect with:
273 And whatever the case an InOut can only connect with an InOut
275 - the IG does not allow the connect a GI/GB interface to an
276 interface of another GI/GB, thus the case is not considered above.
277 - BI/FB and BI/GB are the same.
278 - the cases where direction are the same only occur when
279 the 2 items are of different type (GI and BI)
280 - the cases where directions are different only occur when
281 the 2 are of both BlockItem
284 bool InterfaceItem::connectWith(InterfaceItem *iface) {
285 ConnectedInterface* interThis = refInter; // the reference of this
286 ConnectedInterface* interOther = iface->refInter; // the reference of the other
287 ConnectedInterface* src = NULL, *dest = NULL;
289 if(interThis->getDirection() == AbstractInterface::InOut && interOther->getDirection() == AbstractInterface::InOut){
290 /* NOTE: InOut interfaces have both directions and thus are
291 connected from inter1 to inter2 AND inter2 to inter1
292 Another effect is that a InOut can be connected to/from a single
295 if((interThis->getConnectedFrom() == NULL) && (interOther->getConnectedFrom() == NULL)) {
297 interOther->connectFrom(interThis);
298 interOther->getConnectedTo().append(interThis);
299 interThis->connectFrom(interOther);
300 interThis->getConnectedTo().append(interOther);
302 cout << "connecting 2 InOut"<< endl;
307 else if (interThis->getDirection() == interOther->getDirection()) {
309 // cannot connect GI to GI or 2 BI of the same direction.
310 if ((getOwner()->isGroupItem()) && (iface->getOwner()->isGroupItem())) return false;
311 if ((getOwner()->isBoxItem()) && (iface->getOwner()->isBoxItem())) return false;
313 if (interThis->getDirection() == AbstractInterface::Input) { // both are inputs
314 cout << "connecting GI to BI" << endl;
315 if(getOwner()->isGroupItem()) {
324 else { // both are outputs
325 cout << "connecting BO to GO" << endl;
326 if(getOwner()->isGroupItem()){
337 if ((getOwner()->isGroupItem()) || (iface->getOwner()->isGroupItem())) return false;
339 cout << "connecting BO to BI" << endl;
340 if(interOther->getDirection() == AbstractInterface::Output) {
350 if(dest != NULL && src != NULL){
351 // cannot overrive existing connectionFrom
352 if(dest->getConnectedFrom() == NULL) {
353 dest->connectFrom(src);
354 src->connectTo(dest);
364 void InterfaceItem::unconnectTo(InterfaceItem *iface)
366 if(iface->refInter->getConnectedFrom() == refInter){
367 iface->refInter->connectFrom(NULL);
369 if(iface->refInter->getConnectedTo().contains(refInter)){
370 cout << "abnormal case while removing iface conn from " << qPrintable(refInter->getName()) << " to " << qPrintable(iface->refInter->getName()) << endl;
371 iface->refInter->removeConnectedTo(refInter);
373 if(refInter->getConnectedFrom() == iface->refInter) {
374 cout << "abnormal case while removing iface conn from " << qPrintable(refInter->getName()) << " to " << qPrintable(iface->refInter->getName()) << endl;
375 refInter->connectFrom(NULL);
377 if(refInter->getConnectedTo().contains(iface->refInter)){
378 refInter->removeConnectedTo(iface->refInter);
382 void InterfaceItem::updatePosition()
384 if(orientation == Parameters::North || orientation == Parameters::South){
385 position = positionRatio * owner->getWidth();
387 position = positionRatio * owner->getHeight();
392 void InterfaceItem::addConnectionItem(ConnectionItem* item) {
393 connections.append(item);
396 void InterfaceItem::removeConnectionItem(ConnectionItem* item) {
397 connections.removeOne(item);
400 QDataStream &operator <<(QDataStream &out, InterfaceItem *i) {
403 out.setVersion(QDataStream::Qt_5);
405 QByteArray interfaceData;
406 QDataStream toWrite(&interfaceData, QIODevice::WriteOnly);
408 toWrite << i->getId();
409 toWrite << i->getName();
410 toWrite << i->getPositionRatio();
411 toWrite << i->getOrientation();
413 foreach(QGraphicsItem* item, i->params->getCurrentScene()->items()){
414 if(item->data(0) == "connection"){
415 ConnectionItem *conn = dynamic_cast<ConnectionItem*>(item);
416 if(conn->getFromInterfaceItem() == i || conn->getToInterfaceItem() == i){
417 toWrite << conn->getId();
418 cout << "id connection : " << conn->getId() << endl;
422 out << interfaceData;
427 QDataStream &operator >>(QDataStream &in, InterfaceItem &i) {
430 in.setVersion(QDataStream::Qt_5);
433 double positionRatio;
443 i.setPositionRatio(positionRatio);
444 i.setOrientation(orientation);