]> AND Private Git Repository - blast.git/blob - InterfaceItem.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
0e87a1934d67e8fc30b604466cad3ca2fe7cf4f5
[blast.git] / InterfaceItem.cpp
1 #include "InterfaceItem.h"
2
3 #include "Parameters.h"
4 #include "GroupInterface.h"
5 #include "FunctionalInterface.h"
6 #include "BoxItem.h"
7
8 int InterfaceItem::counter = 0;
9
10 InterfaceItem::InterfaceItem(double _position,
11                              int _orientation,
12                              ConnectedInterface *_refInter,
13                              AbstractBoxItem* _owner,
14                              Parameters* _params){
15   positionRatio = _position;
16   orientation = _orientation;
17   refInter = _refInter;
18
19   // CAUTION : the owner must add explicitely this item to its interface, calling addInterface()
20   owner = _owner;
21   params = _params;
22   selected = false;  
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) {
28     visible = true;
29   }
30   else {
31     visible = false;
32   }
33
34   this->id = InterfaceItem::counter++;
35
36   updatePosition();
37 }
38
39
40 InterfaceItem::InterfaceItem(){
41   this->id = counter++;
42 }
43
44 QString InterfaceItem::getName() {
45   return refInter->getName();
46 }
47
48 /* boundingRect() : give the bounding rect in the blockitem coord. system */
49 QRectF InterfaceItem::boundingRect() const {
50
51   QPointF pointHG;
52   QSizeF s;
53
54   switch(orientation){
55   case Parameters::East :
56     pointHG = QPointF(originPoint.x(),originPoint.y()-(params->arrowHeight/2.0));
57     s = QSizeF(params->arrowWidth+params->arrowLineLength, params->arrowHeight);
58     break;
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);
62     break;
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);
66     break;
67   case Parameters::South :
68     pointHG = QPointF(originPoint.x()-(params->arrowHeight/2.0),originPoint.y());
69     s = QSizeF(params->arrowHeight, params->arrowWidth+params->arrowLineLength);
70     break;
71   default :
72     pointHG = QPointF();
73     s = QSizeF();
74     break;
75   }  
76
77   return QRectF(pointHG,s);
78 }
79
80 void InterfaceItem::paint(QPainter *painter) {
81
82   if(visible) {
83
84     painter->save();
85
86     if(selected) {
87       painter->setPen(QPen(Qt::red,2));
88     }
89     else if(refInter->getLevel() == AbstractInterface::Basic) {
90       painter->setPen(QPen(Qt::darkCyan,1));
91     }
92     else if(refInter->getLevel() == AbstractInterface::Top) {
93       painter->setPen(QPen(Qt::black,1));
94     }
95
96     painter->translate(originPoint);
97
98     switch(orientation) {
99     case Parameters::North:
100       painter->rotate(-90);
101       break;
102     case Parameters::West:
103       painter->rotate(180);
104       break;
105     case Parameters::South:
106       painter->rotate(90);
107       break;
108     }
109
110     // draw arrows
111     if(refInter->getDirection() == AbstractInterface::Input) {
112       painter->drawPath(params->inArrow);
113     }
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);
119     }
120
121     // draw names
122
123     // reset to normal if at west
124     if(orientation == Parameters::West){
125       painter->rotate(180);
126     }
127
128     painter->setFont(params->defaultIfaceFont);
129
130     QFontMetrics fm = painter->fontMetrics();
131     int w = nameWidth + owner->getIfaceMargin();
132     int h = nameHeight;
133
134     if(orientation == Parameters::West){
135
136       if(owner->isGroupItem()){
137         painter->drawText(-(w+params->arrowWidth+params->arrowLineLength),-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
138       }
139       else if(owner->isBoxItem()){
140         painter->drawText(0,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
141       }
142     }
143     else  {
144
145       if(owner->isGroupItem()) {
146         painter->drawText(params->arrowWidth+params->arrowLineLength,-h/2,w,h,Qt::AlignRight | Qt::TextWordWrap, refInter->getName());
147       }
148       else if(owner->isBoxItem()) {
149         painter->drawText(-w,-h/2,w,h,Qt::AlignLeft | Qt::TextWordWrap, refInter->getName());
150       }
151     }    
152
153     painter->restore();
154   }
155 }
156
157 QPointF InterfaceItem::getEndPointInGroup() {
158   QPointF p;
159
160   if (owner->isGroupItem()) {
161     p = originPoint;
162   }
163   else {
164     double x = owner->x() + originPoint.x();
165     double y = owner->y() + originPoint.y();
166     switch(orientation){
167     case Parameters::East:
168       x += params->arrowWidth+params->arrowLineLength;
169       break;
170     case Parameters::North:
171       y -= params->arrowWidth+params->arrowLineLength;
172       break;
173     case Parameters::West:
174       x -= params->arrowWidth+params->arrowLineLength;
175       break;
176     case Parameters::South:
177       y += params->arrowWidth+params->arrowLineLength;
178       break;
179     }
180     p = QPointF(x,y);
181   }
182
183   //cout << "iface end point in group item: " << p.x() << "," << p.y() << endl;
184   return p;
185 }
186
187 void InterfaceItem::setOriginPoint() {
188   switch(orientation){
189   case Parameters::East:
190     originPoint = QPointF(owner->getWidth(),position);
191     break;
192   case Parameters::North:
193     originPoint = QPointF(position,0);
194     break;
195   case Parameters::West:
196     originPoint = QPointF(0,position);
197     break;
198   case Parameters::South:
199     originPoint = QPointF(position,owner->getHeight());
200     break;
201   }
202 }
203
204 QString InterfaceItem::getStrOrientation() {
205   QString str = NULL;
206   switch(orientation){
207   case Parameters::North :
208     str = QString("north");
209     break;
210   case Parameters::South :
211     str = QString("south");
212     break;
213   case Parameters::East :
214     str = QString("east");
215     break;
216   case Parameters::West :
217     str = QString("west");
218     break;
219   }
220
221   return str;
222 }
223
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;
229   return -1;
230 }
231
232
233 /* connectWith() :
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)
237
238   CAUTION: No security checks are done. This method must be called only if canConnectWith has been called and returned true.
239
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)
242
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
248
249      For GI/GB:
250      - Input can connect with BI/FB or BI/GB Input
251      - Output can connect with BI/FB or BI/GB Output
252
253      For BI/FB:
254      - Input can connect with:
255          GI/GB Input
256          BI/FB Output
257          BI/GB Output
258      - Output can connect with:
259          GI/GB Output
260          BI/FB Input
261          BI/GB Input
262
263      For BI/GB:
264      - Input can connect with:
265          GI/GB Input
266          BI/FB Output
267          BI/GB Output
268      - Output can connect with:
269          GI/GB Output
270          BI/FB Input
271          BI/GB Input
272
273     And whatever the case an InOut can only connect with an InOut
274     We note that:
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
282
283 */
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;
288
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
293        InOut.
294     */
295     if((interThis->getConnectedFrom() == NULL) && (interOther->getConnectedFrom() == NULL)) {
296
297       interOther->connectFrom(interThis);
298       interOther->getConnectedTo().append(interThis);
299       interThis->connectFrom(interOther);
300       interThis->getConnectedTo().append(interOther);
301
302       cout << "connecting 2 InOut"<< endl;
303       return true;
304     }
305     return false;
306   }
307   else if (interThis->getDirection() == interOther->getDirection()) {
308
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;
312
313     if (interThis->getDirection() == AbstractInterface::Input) { // both are inputs
314       cout << "connecting GI to BI" << endl;
315       if(getOwner()->isGroupItem()) {
316         src = interThis;
317         dest = interOther;
318       }
319       else {
320         src = interOther;
321         dest = interThis;
322       }
323     }
324     else { // both are outputs
325       cout << "connecting BO to GO" << endl;
326       if(getOwner()->isGroupItem()){
327         src = interOther;
328         dest = interThis;
329       }
330       else {
331         src = interThis;
332         dest = interOther;
333       }
334     }
335   }
336   else {
337     if ((getOwner()->isGroupItem()) || (iface->getOwner()->isGroupItem())) return false;
338
339     cout << "connecting BO to BI" << endl;
340     if(interOther->getDirection() == AbstractInterface::Output) {
341       src = interOther;
342       dest = interThis;
343     }
344     else {
345       src = interThis;
346       dest = interOther;
347     }
348   }
349
350   if(dest != NULL && src != NULL){
351     // cannot overrive existing connectionFrom
352     if(dest->getConnectedFrom() == NULL) {
353       dest->connectFrom(src);
354       src->connectTo(dest);
355       return true;
356     }
357     else {
358       return false;
359     }
360   }
361   return false;
362 }
363
364 void InterfaceItem::unconnectTo(InterfaceItem *iface)
365 {
366   if(iface->refInter->getConnectedFrom() == refInter){
367     iface->refInter->connectFrom(NULL);
368   }
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);
372   }
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);
376   }
377   if(refInter->getConnectedTo().contains(iface->refInter)){
378     refInter->removeConnectedTo(iface->refInter);
379   }
380 }
381
382 void InterfaceItem::updatePosition()
383 {
384   if(orientation == Parameters::North || orientation == Parameters::South){
385     position = positionRatio * owner->getWidth();
386   } else {
387     position = positionRatio * owner->getHeight();
388   }
389   setOriginPoint();
390 }
391
392 void InterfaceItem::addConnectionItem(ConnectionItem* item) {
393   connections.append(item);
394 }
395
396 void InterfaceItem::removeConnectionItem(ConnectionItem* item) {
397   connections.removeOne(item);
398 }
399
400 QDataStream &operator <<(QDataStream &out, InterfaceItem *i) {
401
402 #ifdef DEBUG_INCLFUN
403   out.setVersion(QDataStream::Qt_5);
404
405   QByteArray interfaceData;
406   QDataStream toWrite(&interfaceData, QIODevice::WriteOnly);
407
408   toWrite << i->getId();
409   toWrite << i->getName();
410   toWrite << i->getPositionRatio();
411   toWrite << i->getOrientation();
412
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;
419       }
420     }
421   }
422   out << interfaceData;
423 #endif
424   return out;
425 }
426
427 QDataStream &operator >>(QDataStream &in, InterfaceItem &i) {
428
429 #ifdef DEBUG_INCLFUN
430   in.setVersion(QDataStream::Qt_5);
431
432   int id, orientation;
433   double positionRatio;
434   QString name;
435
436   in >> id;
437   in >> name;
438   in >> positionRatio;
439   in >> orientation;
440
441   i.setId(id);
442   i.setName(name);
443   i.setPositionRatio(positionRatio);
444   i.setOrientation(orientation);
445   i.updatePosition();
446 #endif
447   return in;
448 }