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

Private GIT Repository
modified pattern to use only QMap
[blast.git] / AbstractBoxItem.cpp
1 #include "AbstractBoxItem.h"
2
3 #include "Parameters.h"
4
5 #include "Dispatcher.h"
6 #include "InterfaceItem.h"
7 #include "ConnectionItem.h"
8
9 #include "AbstractBlock.h"
10 #include "GroupScene.h"
11 #include "GroupItem.h"
12 #include "AbstractInterface.h"
13 #include "ConnectedInterface.h"
14
15
16 AbstractBoxItem::  AbstractBoxItem(AbstractBlock *_refBlock, Dispatcher *_dispatcher, Parameters *_params, QGraphicsItem *parent) : QGraphicsItem(parent) {
17   dispatcher = _dispatcher;
18   params = _params;
19   refBlock = _refBlock;  
20   QFontMetrics fmId(params->defaultBlockFont);
21   nameWidth = fmId.width(refBlock->getName());
22   nameHeight = fmId.height();
23   nameMargin = 5;
24   ifaceMargin = 10;
25
26   // the six following values will be override in subclass constructors
27   minimumBoxWidth = 0;
28   minimumBoxHeight = 0;
29   boxWidth = 0;
30   boxHeight = 0;
31   totalWidth = 0;
32   totalHeight = 0;
33
34   originPoint = QPointF(0.0,0.0);
35
36   selected = false;
37   currentInterface = NULL;
38   rstClkVisible = false;
39   wishboneVisible = false;
40
41   setAcceptHoverEvents(true);
42
43   // NOTE : initInterfaces() is only called in subclasses
44 }
45
46 AbstractBoxItem::AbstractBoxItem(Dispatcher *_dispatcher, Parameters *_params, QGraphicsItem* parent) : QGraphicsItem(parent) {
47   dispatcher = _dispatcher;
48   params = _params;
49   refBlock = NULL;
50   nameWidth = 0;
51   nameHeight = 0;
52   nameMargin = 10;
53   ifaceMargin = 10;
54
55   // the six following values will be override in subclass constructors
56   minimumBoxWidth = 0;
57   minimumBoxHeight = 0;
58   boxWidth = 0;
59   boxHeight = 0;
60   totalWidth = 0;
61   totalHeight = 0;
62
63   originPoint = QPointF(0.0,0.0);
64
65   selected = false;
66   currentInterface = NULL;
67   rstClkVisible = false;
68   wishboneVisible = false;
69   
70   setAcceptHoverEvents(true);
71
72   // NOTE : initInterfaces() is only called in subclasses
73 }
74
75 AbstractBoxItem::~AbstractBoxItem() {
76   foreach(InterfaceItem* inter, interfaces) {
77     delete inter;
78   }
79   interfaces.clear();
80 }
81
82 bool AbstractBoxItem::isBoxItem() {
83   return false;
84 }
85
86 bool AbstractBoxItem::isGroupItem() {
87   return false;
88 }
89
90 bool AbstractBoxItem::isSourceItem() {
91   return false;
92 }
93
94 void AbstractBoxItem::setRstClkVisible(bool b) { 
95   rstClkVisible = b;
96   foreach(InterfaceItem* ifaceItem, interfaces) {
97     if ((ifaceItem->refInter->getPurpose() == AbstractInterface::Clock) ||
98         (ifaceItem->refInter->getPurpose() == AbstractInterface::Reset) ) {
99       ifaceItem->visible = b;
100     }
101   }
102   resetInterfaceItemsPosition();
103   updateGeometry(InterfaceMove);
104   update();
105   getScene()->updateConnectionItemsShape();
106   (getScene()->getGroupItem())->updateShape();
107   
108 }
109
110 void AbstractBoxItem::setWishboneVisible(bool b) { 
111   wishboneVisible = b;
112   foreach(InterfaceItem* ifaceItem, interfaces) {
113     if (ifaceItem->refInter->getPurpose() == AbstractInterface::Wishbone) {
114       ifaceItem->visible = b;
115     }
116   }
117   resetInterfaceItemsPosition();
118   updateGeometry(InterfaceMove);
119   update();
120   getScene()->updateConnectionItemsShape();
121   (getScene()->getGroupItem())->updateShape();
122 }
123
124 void AbstractBoxItem::setRefBlock(AbstractBlock* _refBlock) {
125   refBlock = _refBlock;
126   QFontMetrics fmId(params->defaultBlockFont);
127   nameWidth = fmId.width(refBlock->getName());
128   nameHeight = fmId.height();
129 }
130
131 void AbstractBoxItem::initInterfaceItems() {
132   /* TO DO : creating all needed InterfaceItem, with by default, input at west and output at east */
133   int orientation = Parameters::West;
134
135   foreach(AbstractInterface *inter, refBlock->getInterfaces()){
136    
137     /* NB: does not create InterfaceItem for control interfaces.
138     */
139     if (inter->getPurpose() != AbstractInterface::Control) {
140       InterfaceItem *item;
141       if(inter->getDirection() == AbstractInterface::Input){
142         orientation = Parameters::West;
143       } else if(inter->getDirection() == AbstractInterface::Output){
144         orientation = Parameters::East;
145       } else if(inter->getDirection() == AbstractInterface::InOut){
146         orientation = Parameters::North;
147       }
148       item = new InterfaceItem(0.0 , orientation, (ConnectedInterface *)inter, this, params);
149       interfaces.append(item);        
150     }
151   }
152 }
153
154 InterfaceItem* AbstractBoxItem::searchInterfaceItemByName(QString name) {
155   foreach(InterfaceItem *inter, interfaces){
156     if(inter->getName() == name)
157       return inter;
158   }
159   return NULL;
160 }
161
162 InterfaceItem* AbstractBoxItem::searchInterfaceItemByRef(ConnectedInterface *ref) {
163   foreach(InterfaceItem *inter, interfaces){
164     if(inter->refInter == ref) {
165       return inter;
166     }
167   }
168   return NULL;
169 }
170
171 void AbstractBoxItem::addInterfaceItem(InterfaceItem *i, bool resetPosition) {
172   interfaces.append(i);
173   if (resetPosition) resetInterfaceItemsPosition();
174   updateGeometry(InterfaceMove);
175   update();
176 }
177
178 void AbstractBoxItem::removeInterfaceItem(InterfaceItem *i) {
179   // NB : removing from model is done in dispatcher
180   interfaces.removeAll(i);
181   delete i;
182
183   //resetInterfacesPosition();
184   updateGeometry(InterfaceMove);
185   update();
186 }
187
188
189 void AbstractBoxItem::resetInterfaceItemsPosition() {
190
191   int nbNorth=0, nbSouth=0, nbEast=0, nbWest=0;
192   double cntNorth=1.0,cntSouth=1.0,cntEast=1.0,cntWest=1.0;
193   double positionRatio = 1.0;
194
195
196   foreach(InterfaceItem* inter, interfaces) {
197     // only data interfaces and if needed time and reset
198     if(inter->visible) {
199       if(inter->getOrientation() == Parameters::North){
200         nbNorth++;
201       } else if(inter->getOrientation() == Parameters::South){
202         nbSouth++;
203       } else if(inter->getOrientation() == Parameters::East){
204         nbEast++;
205       } else if(inter->getOrientation() == Parameters::West){
206         nbWest++;
207       }
208     }
209   }
210
211   foreach(InterfaceItem* inter, interfaces) {
212
213     if(inter->visible){
214
215       if(inter->getOrientation() == Parameters::North){
216         positionRatio = cntNorth/(double)(nbNorth+1);
217         cntNorth += 1.0;
218       } else if(inter->getOrientation() == Parameters::South){
219         positionRatio = cntSouth/(double)(nbSouth+1);
220         cntSouth += 1.0;
221       } else if(inter->getOrientation() == Parameters::East){
222         positionRatio = cntEast/(double)(nbEast+1);
223         cntEast += 1.0;
224       } else if(inter->getOrientation() == Parameters::West){
225         positionRatio = cntWest/(double)(nbWest+1);
226         cntWest += 1.0;
227       }
228       inter->setPositionRatio(positionRatio);
229       inter->updatePosition();
230     }
231   }
232 }
233
234 void AbstractBoxItem::moveInterfaceItemTo(QPointF pos) {
235   double positionRatio;
236   if(currentInterface->getOrientation() == Parameters::North || currentInterface->getOrientation() == Parameters::South){
237     if(pos.x() < 0){
238       positionRatio = 0;
239       if(pos.y() > 0 && pos.y() < boxHeight){
240         currentInterface->setOrientation(Parameters::West);
241       }
242     } else if(pos.x() > boxWidth){
243       positionRatio = 1;
244       if(pos.y() > 0 && pos.y() < boxHeight){
245         currentInterface->setOrientation(Parameters::East);
246       }
247     } else {
248       positionRatio = ((double) pos.x())/boxWidth;
249     }
250   } else {
251
252     if(pos.y() < 0){
253       positionRatio = 0;
254       if(pos.x() > 0 && pos.x() < boxWidth){
255         currentInterface->setOrientation(Parameters::North);
256       }
257     } else if(pos.y() > boxHeight){
258       positionRatio = 1;
259       if(pos.x() > 0 && pos.x() < boxWidth){
260         currentInterface->setOrientation(Parameters::South);
261       }
262     } else {
263       positionRatio = ((double) pos.y())/boxHeight;
264     }
265   }
266   currentInterface->setPositionRatio(positionRatio);
267   currentInterface->updatePosition();
268 }
269
270 QRectF AbstractBoxItem::boundingRect() const {
271   // returns a QRectF that contains the block (i.e the main rectangle, interfaces, title, ...)
272   QPointF p = originPoint;
273   QSizeF s(totalWidth,totalHeight);
274   return QRectF(p,s);
275 }
276
277 QRectF AbstractBoxItem::boundingRectInScene() {
278   /* returns a QRectF in scene coordinates, that contains the block plus
279      a margin of size arrowWidth+arrowLineLength
280   */
281   int marginConn = params->arrowLineLength+params->arrowWidth;  
282   
283   QPointF posBox = scenePos();
284   posBox.setX(posBox.x()+originPoint.x()-marginConn);
285   posBox.setY(posBox.y()+originPoint.y()-marginConn);
286   
287   QSizeF sizeBox(totalWidth+2*marginConn,totalHeight+2*marginConn);     
288   
289   return QRectF(posBox,sizeBox);
290 }
291
292
293 /* isInterface() : return true if there are some interfaces
294    with the given orientation (N,S,E,O)
295 */
296 bool AbstractBoxItem::isInterfaces(int orientation) const {
297   foreach(InterfaceItem* inter, interfaces) {
298     if (inter->getOrientation() == orientation) return true;
299   }
300   return false;
301 }
302
303 int AbstractBoxItem::nbInterfacesByOrientation(int orientation) {
304   int nb = 0;
305   foreach(InterfaceItem* inter, interfaces) {
306     if ((inter->visible) && (inter->getOrientation() == orientation)) nb++;
307   }
308   return nb;
309 }
310
311 void AbstractBoxItem::updateInterfaceAndConnectionItems() {
312
313   // update all interfaces positions
314   foreach(InterfaceItem *item, interfaces){
315     item->updatePosition();
316   }
317   // NB: dunno the utility of this test !!
318   if (getScene() != NULL) {
319     // update all connections from/to this block
320     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
321       if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
322         item->setPath();
323       }
324     }
325   }
326 }
327
328 void AbstractBoxItem::setDimension(int x, int y) {
329   boxWidth = x;
330   boxHeight = y;
331 }
332
333 InterfaceItem* AbstractBoxItem::getInterfaceItemFromCursor(qreal x, qreal y) {
334
335   foreach(InterfaceItem* inter, interfaces) {
336     if(x > inter->boundingRect().x() && x < (inter->boundingRect().x() + inter->boundingRect().width())){
337       if(y > inter->boundingRect().y() && y < (inter->boundingRect().y() + inter->boundingRect().height())){
338         return inter;
339       }
340     }
341   }
342   /* TO DO : check each interfaces if it contains x,y. If yes, return that interface */
343   return NULL;
344 }