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

Private GIT Repository
finished testbench generation
[blast.git] / BoxItem.cpp
1 #include "BoxItem.h"
2 #include "GroupScene.h"
3 #include "ConnectionItem.h"
4 #include "InterfaceItem.h"
5 #include "GroupItem.h"
6 #include "Parameters.h"
7 #include "Exception.h"
8 #include "Dispatcher.h"
9 #include "FunctionalBlock.h"
10 #include "FunctionalInterface.h"
11 #include "ReferenceInterface.h"
12 #include "ReferenceBlock.h"
13 #include "ParametersWindow.h"
14 #include "BlockParameter.h"
15 #include "Graph.h"
16
17
18 BoxItem::BoxItem(AbstractBlock *_refBlock,
19                      Dispatcher *_dispatcher,
20                      Parameters *_params, GroupItem *parent, int _lock, SpanType _span, Position _position) throw(Exception) : AbstractBoxItem( _refBlock, _dispatcher, _params, _lock, parent) {
21
22   /*  NOTE :
23      _refBlock : mandatory a FunctionalBlock or a GroupBlock
24   */
25   if (_refBlock->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));  
26
27   span = _span;
28   position = _position;
29
30   childGroupItem = NULL;
31   //boxWidth = params->defaultBlockWidth;
32   //boxHeight = params->defaultBlockHeight;
33   currentBorder = NoBorder;
34   selected = false;
35
36   setZValue(100);
37   QGraphicsItem::GraphicsItemFlags flags = QGraphicsItem::ItemIsSelectable;
38   if (!isPositionLock()) {
39     flags |= QGraphicsItem::ItemIsMovable;
40     cout << "item " << qPrintable(refBlock->getName()) << "is movable" << endl;
41   }
42   if (!isDimensionLock()) {
43     flags |= QGraphicsItem::ItemSendsGeometryChanges;
44     cout << "item " << qPrintable(refBlock->getName()) << "is resizable" << endl;
45   }
46   setFlags(flags);
47
48   bool freeBorder[4]; // 0 = east, 1 = north, 2 = west, 3 = south
49   Parameters::Direction dirs[4];
50   for(int i=0;i<4;i++) {
51     freeBorder[i] = true;
52   }
53   dirs[0] = Parameters::East;
54   dirs[1] = Parameters::North;
55   dirs[2] = Parameters::West;
56   dirs[3] = Parameters::South;
57
58
59   if (position == Top) {
60     freeBorder[1] = false;
61   }
62   if (position == Bottom) {
63     freeBorder[3] = false;
64   }
65   if (position == Left) {
66     freeBorder[2] = false;
67   }
68   if (position == Right) {
69     freeBorder[0] = false;
70   }
71   if (span == HSpan) {
72     freeBorder[2] = false;
73     freeBorder[0] = false;
74   }
75   if (span == VSpan) {
76     freeBorder[1] = false;
77     freeBorder[3] = false;
78   }
79   Parameters::Direction dIn = Parameters::West;
80   Parameters::Direction dOut = Parameters::East;
81   Parameters::Direction dBi = Parameters::South;
82   if (freeBorder[2] == false) {
83     int i=3;
84     while (freeBorder[i] == false) {
85       i = (i+1)%4;
86     }
87     dIn = dirs[i];
88   }
89   if (freeBorder[0] == false) {
90     int i=1;
91     while (freeBorder[i] == false) {
92       i = (i+1)%4;
93     }
94     dOut = dirs[i];
95   }
96   if (freeBorder[3] == false) {
97     int i=0;
98     while (freeBorder[i] == false) {
99       i = (i+1)%4;
100     }
101     dBi = dirs[i];
102   }
103
104   createInterfaceItems(dIn,dOut,dBi);
105   updateGeometry(Creation);
106
107   // position the item
108   int groupWidth = getScene()->getGroupItem()->getWidth();
109   int groupHeight = getScene()->getGroupItem()->getHeight();
110   double xx = 0.0,yy = 0.0;
111   if ((position == BoxItem::Left) || (position == BoxItem::TopLeft) || (position == BoxItem::BottomLeft)) {
112     xx = 0;
113     if ((span == VSpan) || (position == BoxItem::TopLeft)) {
114       yy = 0;
115     }
116     else if (position == BoxItem::BottomLeft) {
117       yy = groupHeight-totalHeight;
118     }
119     else {
120       yy = (groupHeight-totalHeight)/2.0;
121     }
122   }
123   else if ((position == BoxItem::Right) || (position == BoxItem::TopRight) || (position == BoxItem::BottomRight)) {
124     xx = groupWidth-totalWidth;
125     if (xx < 0) xx = 0;
126     if ((span == VSpan) || (position == BoxItem::TopRight)) {
127       yy = 0;
128     }
129     else if (position == BoxItem::BottomRight) {
130       yy = groupHeight-totalHeight;
131     }
132     else {
133       yy = (groupHeight-totalHeight)/2.0;
134     }
135   }
136   else if ((position == BoxItem::Top) || (position == BoxItem::TopLeft) || (position == BoxItem::TopRight)) {
137     yy = 0;
138     if ((span == HSpan) || (position == BoxItem::TopLeft)) {
139       xx = 0;
140     }
141     else if (position == BoxItem::TopRight) {
142       xx = groupWidth-totalWidth;
143     }
144     else {
145       xx = (groupWidth-totalWidth)/2.0;
146     }    
147   }
148   else if ((position == BoxItem::Bottom) || (position == BoxItem::BottomLeft) || (position == BoxItem::BottomRight)) {
149     yy = groupHeight-totalHeight;
150     if ((span == HSpan) || (position == BoxItem::BottomLeft)) {
151       xx = 0;
152     }
153     else if (position == BoxItem::BottomRight) {
154       xx = groupWidth-totalWidth;
155     }
156     else {
157       xx = (groupWidth-totalWidth)/2.0;
158     }    
159   }
160   else {
161     int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
162     xx = (groupWidth-totalWidth)/2.0;
163     if (xx < marginConn) xx = marginConn;
164     yy = (groupHeight-totalHeight)/2.0;
165     if (yy < marginConn) yy = marginConn;
166   }
167   cout << "setting raw pos to " << xx << "," << yy << endl;
168   QPointF initPos(xx,yy);
169   initPos = initPos-originPoint;
170   setPos(initPos);
171   cout << "total size of block: " << totalWidth << "," << totalHeight << endl;
172   cout << "pos in group: " << x() << "," << y() << endl;
173 }
174
175 BoxItem::BoxItem(Dispatcher *_dispatcher, Parameters *_params, GroupItem *parent, int _lock, SpanType _span, Position _position) throw(Exception) : AbstractBoxItem(_dispatcher, _params, _lock, parent) {
176
177   span = _span;
178   position = _position;
179
180   refBlock = NULL;
181   childGroupItem = NULL;
182   currentBorder = NoBorder;
183   selected = false;
184
185   setZValue(100);
186   QGraphicsItem::GraphicsItemFlags flags = QGraphicsItem::ItemIsSelectable;
187   if (!isPositionLock()) {
188     flags |= QGraphicsItem::ItemIsMovable;
189   }
190   if (!isDimensionLock()) {
191     flags |= QGraphicsItem::ItemSendsGeometryChanges;
192   }
193   setFlags(flags);
194
195   boxWidth = params->defaultBlockWidth;
196   boxHeight = params->defaultBlockHeight;
197   //initInterfaces();
198   //updateGeometry(InterfaceMove);
199   //resetInterfacesPosition();
200   //QPointF initPos = QPointF(0.0,0.0) - originPoint;
201   //setPos(initPos);
202   //cout << "total size of block: " << totalWidth << "," << totalHeight << endl;
203   //cout << "pos in group: " << x() << "," << y() << endl;
204 }
205
206 BoxItem::~BoxItem() {
207 }
208
209 void BoxItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
210
211   if (!visible) return;
212
213   QPen pen(Qt::black, 3);
214   if(selected)
215     pen.setColor(Qt::red);
216
217   painter->setPen(pen);
218   painter->setBrush(Qt::yellow);
219
220   painter->drawRect(0,0,boxWidth, boxHeight);
221   painter->drawText(0,0,boxWidth, boxHeight,Qt::AlignCenter | Qt::TextWordWrap,QString(refBlock->getName()));
222   foreach(InterfaceItem *inter, interfaces) {
223     inter->paint(painter);
224   }
225 }
226
227 void BoxItem::moveTo(QPointF dest) {
228   setPos(dest);
229   currentPosition = dest;
230 }
231
232 bool BoxItem::isBoxItem() {
233   return true;
234 }
235
236 void BoxItem::updateMinimumSize() {
237
238   int maxSouth = 0;
239   int maxNorth = 0;
240   int maxEast = 0;
241   int maxWest = 0;
242   int nbSouth = nbInterfacesByOrientation(Parameters::South);
243   int nbNorth = nbInterfacesByOrientation(Parameters::North);
244   int nbMaxSN = nbNorth;
245   if (nbSouth > nbNorth) nbMaxSN = nbSouth;
246   int nbEast = nbInterfacesByOrientation(Parameters::East);
247   int nbWest = nbInterfacesByOrientation(Parameters::West);
248   int nbMaxEW = nbEast;
249   if (nbWest > nbEast) {
250     nbMaxEW = nbWest;
251   }
252
253   int ifaceWidth = 0;
254   int ifaceHeight = 0;
255
256   foreach(InterfaceItem* iface, interfaces) {
257
258     if (iface->visible) {
259       ifaceWidth = iface->getNameWidth();
260       ifaceHeight = iface->getNameHeight();
261       if (iface->getOrientation() == Parameters::South) {
262         if (ifaceWidth > maxSouth) maxSouth = ifaceWidth;
263       }
264       else if (iface->getOrientation() == Parameters::North) {
265         if (ifaceWidth > maxNorth) maxNorth = ifaceWidth;
266       }
267       else if (iface->getOrientation() == Parameters::East) {
268         if (ifaceWidth > maxEast) maxEast = ifaceWidth;
269       }
270       else if (iface->getOrientation() == Parameters::West) {
271         if (ifaceWidth > maxWest) maxWest = ifaceWidth;
272       }
273     }
274   }
275
276   /* NB: the width layout is the following
277      ifaceMargin | maxWest | nameMargin | name | nameMargin | maxEast | ifaceMargin
278    */
279   minimumBoxWidth = maxWest+maxEast+nameWidth+2*(ifaceMargin+nameMargin);
280   // if the minimum is not sufficent taking into account N/S interfaces
281   if (minimumBoxWidth < (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1))) {
282     minimumBoxWidth = (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1));
283   }
284   minimumBoxHeight = maxNorth+maxSouth+3*ifaceMargin;
285   if (minimumBoxHeight < (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1))) {
286     minimumBoxHeight = (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1));
287   }
288 }
289
290
291 /* updateGeometry() :
292
293  */
294 bool BoxItem::updateGeometry(ChangeType type) {
295
296   currentPosition = pos();
297   //cout << "current pos of block: " << currentPosition.x() << "," << currentPosition.y() << endl;
298   QPointF oldOrigin = originPoint;
299   QSize oldSize(totalWidth,totalHeight);
300   bool boxSizeChanged = false;
301
302   // whatever the change, the minimum size may have changed
303   updateMinimumSize();
304
305   int groupWidth = getScene()->getGroupItem()->getWidth();
306   int groupHeight = getScene()->getGroupItem()->getHeight();
307
308   cout << "minimum box size is " << minimumBoxWidth << "x" << minimumBoxHeight << endl;
309   cout << "group size is " << groupWidth << "x" << groupHeight << endl;
310
311   if (type == Creation) {
312
313     boxSizeChanged = true;
314     boxWidth = minimumBoxWidth;
315     boxHeight = minimumBoxHeight;
316     /* reset and update interfaces positions
317      * in case of spanning, the interface are positionned
318      * only on free borders.
319      */
320     resetInterfaceItemsPosition();
321     /* must test if the GroupItem must be resized */
322     if ((span == HSpan) && (boxWidth < groupWidth)) {
323       boxWidth = groupWidth; // no interfaces in east/west (done in constructor)
324     }
325     else if ((span == VSpan) && (boxHeight < groupHeight)) {
326       boxHeight = groupHeight;
327     }
328   }
329   else if (type == Resize) {
330     // resize implies to move interfaces and to update connections
331     boxSizeChanged = true;
332     updateInterfaceAndConnectionItems();
333   }
334   else if (type == InterfaceMove) {
335     // if an interface moves, it may change the box size
336     if (boxWidth < minimumBoxWidth) {
337       boxWidth = minimumBoxWidth;
338       boxSizeChanged = true;
339       updateInterfaceAndConnectionItems();
340     }
341     if (boxHeight < minimumBoxHeight) {
342       boxHeight = minimumBoxHeight;
343       boxSizeChanged = true;
344       updateInterfaceAndConnectionItems();
345     }
346   }
347
348   // update total size
349   double x = 0.0;
350   double y = 0.0;
351
352   totalWidth = boxWidth;
353   totalHeight = boxHeight;
354
355   if(isInterfaces(Parameters::East)){
356     totalWidth += params->arrowWidth+params->arrowLineLength;
357   }
358   if(isInterfaces(Parameters::West)){
359     totalWidth += params->arrowWidth+params->arrowLineLength;
360     x -= params->arrowWidth+params->arrowLineLength;
361   }
362   if(isInterfaces(Parameters::South)){
363     totalHeight += params->arrowWidth+params->arrowLineLength;
364   }
365   if(isInterfaces(Parameters::North)){
366     totalHeight += params->arrowWidth+params->arrowLineLength;
367     y -= params->arrowWidth+params->arrowLineLength;
368   }
369   QSizeF newSize(totalWidth,totalHeight);
370   originPoint.setX(x);
371   originPoint.setY(y);
372   cout << "change orig pos of " << qPrintable(refBlock->getName()) << "to " << x << "," << y << endl;
373   cout << "box size is " << boxWidth << "x" << boxHeight << endl;
374   cout << "total size is " << totalWidth << "x" << totalHeight << endl;
375
376   if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
377     prepareGeometryChange();
378     return true;
379   }
380   return false;
381 }
382
383 void BoxItem::nameChanged() {
384   
385   QFontMetrics fmId(params->defaultBlockFont);
386   nameWidth = fmId.width(refBlock->getName());
387   nameHeight = fmId.height();
388   
389   if (updateGeometry(InterfaceMove)) {
390     //cout << "must recompute group item geometry" << endl;
391     (getScene()->getGroupItem())->updateShape();
392   }
393   // force the update in case of size has not changed
394   update();
395 }
396
397 void BoxItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
398
399   if(params->editState == Parameters::EditBlockMove) {
400
401     if (isPositionLock()) return;
402     QPointF absPos = currentPosition + originPoint;
403     int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
404     int gapX = event->scenePos().x() - cursorPosition.x();
405     int gapY = event->scenePos().y() - cursorPosition.y();
406     // update cursor position
407     cursorPosition = event->scenePos();
408
409     //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
410     //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
411
412     if ((position == Left) || (position == Right)) {
413       gapX = 0;
414     }
415     else if ((gapX < 0) && (absPos.x() == marginConn)) {
416       gapX = 0;
417     }
418     else if (absPos.x()+gapX < marginConn) {
419       gapX = marginConn-absPos.x();
420     }
421     if ((position == Top) || (position == Bottom)) {
422       gapY = 0;
423     }
424     else if ((gapY < 0) && (absPos.y() == marginConn)) {
425       gapY = 0;
426     }
427     else if (absPos.y()+gapY < marginConn) {
428       gapY = marginConn-absPos.y();
429     }
430     //cout << "gap: " << gapX << "," << gapY << endl;
431     if ((gapX != 0) || (gapY != 0)) {
432       QPointF gap(gapX,gapY);
433       currentPosition = currentPosition+gap;
434       setPos(currentPosition);
435       // update all connections from/to this block
436       foreach(ConnectionItem *item, getScene()->getConnectionItems()){
437         if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
438           item->setPath();
439         }
440       }
441       // udpate the groupitem
442       (getScene()->getGroupItem())->updateShape();
443     }
444   }
445   else if(params->editState == Parameters::EditBlockResize) {
446
447     if (isDimensionLock()) return;
448     int gapX = event->scenePos().x() - cursorPosition.x();
449     int gapY = event->scenePos().y() - cursorPosition.y();
450     //cout << "gap: " << gapX << "," << gapY << endl;
451     switch(currentBorder){
452     case BorderEast: {    
453       if(boxWidth+gapX > minimumBoxWidth){
454         boxWidth += gapX;
455       }
456       break;
457     }
458     case BorderSouth: {      
459       if(boxHeight+gapY > minimumBoxHeight){
460         boxHeight += gapY;
461       }
462       break;
463     }
464     case CornerSouthEast: {
465       if(boxWidth+gapX > minimumBoxWidth){
466         boxWidth += gapX;
467       }
468       if(boxHeight+gapY > minimumBoxHeight){
469         boxHeight += gapY;
470       }
471       break;
472     }
473     case Title:
474       cout << "abnormal case while resizing block" << endl;
475       break;
476     case BorderWest:
477       cout << "abnormal case while resizing block" << endl;
478       break;
479     case BorderNorth:
480       cout << "abnormal case while resizing block" << endl;
481       break;
482     case NoBorder:
483       cout << "abnormal case while resizing block" << endl;
484       break;
485     }
486     // recompute the geometry of the block and possibly the group item
487     if (updateGeometry(Resize)) {
488       (getScene()->getGroupItem())->updateShape();
489     }
490
491     cursorPosition = event->scenePos();   
492   }
493   else if(params->editState == Parameters::EditInterfaceMove) {
494     prepareGeometryChange();
495     moveInterfaceItemTo(event->pos());
496     // recompute the geometry of the block
497     if (updateGeometry(InterfaceMove)) {
498       //cout << "must recompute group item geometry" << endl;
499       (getScene()->getGroupItem())->updateShape();
500     }
501     // update connection from/to the selected interface
502     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
503       if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
504         item->setPath();
505       }
506     }    
507   }
508 }
509
510 void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
511
512   QPointF pos = event->pos();
513   qreal x = pos.x();
514   qreal y = pos.y();
515
516   //QGraphicsItem::mousePressEvent(event);
517
518   if(event->button() == Qt::RightButton) return;
519
520   int mode = getScene()->getEditionMode();
521
522   dispatcher->setCurrentGroupWidget(Dispatcher::Design, getScene()->getGroupWidget());
523
524   if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
525     InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
526     if (inter != NULL) {
527
528       if (params->editState == Parameters::EditNoOperation) {
529         getScene()->setSelectedInterface(1,inter);
530         params->setEditState(Parameters::EditStartConnection);
531       }
532       else if (params->editState == Parameters::EditStartConnection) {
533         if (inter == getScene()->getSelectedInterface(1)) {
534           params->setEditState(Parameters::EditAbortConnection);
535         }
536         else {
537           getScene()->setSelectedInterface(2,inter);
538           params->setEditState(Parameters::EditCloseConnection);
539         }
540       }
541     }
542   }
543   else if (mode == GroupScene::ItemEdition) {
544     //setZValue(zValue()+100);
545     if (params->cursorState == Parameters::CursorOnInterface) {
546       InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
547       if (inter != NULL) {
548         if (inter == currentInterface) {
549            params->setEditState(Parameters::EditInterfaceDeselect);
550         }
551         else {
552           setFlag(ItemIsMovable, false);
553           currentInterface = inter;
554           params->setEditState(Parameters::EditInterfaceMove);
555         }
556       }
557     }
558     else if (params->cursorState == Parameters::CursorInBlock) {
559       selected = !selected;
560       params->setEditState(Parameters::EditBlockMove);
561       cursorPosition = event->scenePos();
562       //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
563       update();
564     }
565     else if (params->cursorState == Parameters::CursorOnBorder) {
566       if (isDimensionLock()) {
567         if ((position == Bottom)||(position == Right)) {
568           event->ignore();
569         }
570       }
571       else {
572         setFlag(ItemIsMovable, false);
573         cursorPosition = event->scenePos();
574         params->setEditState(Parameters::EditBlockResize);
575       }
576     }
577   }
578 }
579
580 void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
581
582   //setZValue(zValue()-100);
583
584   int mode = getScene()->getEditionMode();
585
586   if (mode == GroupScene::AddConnection) {
587
588     if (params->editState == Parameters::EditStartConnection) {
589       InterfaceItem* iface = getScene()->getSelectedInterface(1);
590       iface->selected = true;
591       update(iface->boundingRect());
592     }
593     else if (params->editState == Parameters::EditAbortConnection) {
594       InterfaceItem* iface = getScene()->getSelectedInterface(1);
595       iface->selected = false;
596       update(iface->boundingRect());
597       getScene()->setSelectedInterface(1,NULL);
598       params->setEditState(Parameters::EditNoOperation);
599     }
600     else if (params->editState == Parameters::EditCloseConnection) {
601       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
602       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
603       bool ok = dispatcher->createConnection(Dispatcher::Design, iface1,iface2);
604       if (ok) {
605         iface1->selected = false;
606         update(iface1->boundingRect());
607         iface2->selected = false;
608         update(iface2->boundingRect());        
609         getScene()->setSelectedInterface(1,NULL);
610         getScene()->setSelectedInterface(2,NULL);
611         params->setEditState(Parameters::EditNoOperation);
612       }
613       else {
614         //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok);
615         getScene()->setSelectedInterface(2,NULL);
616         params->setEditState(Parameters::EditStartConnection);
617       }
618     }
619   }
620   else if (mode == GroupScene::ItemEdition) {
621     currentInterface = NULL;
622     params->editState = Parameters::EditNoOperation;
623     setFlag(ItemIsMovable);
624   }
625
626   QGraphicsItem::mouseReleaseEvent(event);
627 }
628
629 void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
630
631   QPointF evPos = event->pos();
632   qreal x = evPos.x();
633   qreal y = evPos.y();
634   currentBorder = NoBorder;
635   int mode = getScene()->getEditionMode();
636
637   if (mode == GroupScene::AddConnection) {
638     InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
639     if (iface != NULL) {
640       params->cursorState = Parameters::CursorOnInterface;
641       setCursor(Qt::PointingHandCursor);
642     }
643     else {
644       params->cursorState = Parameters::CursorNowhere;
645       setCursor(Qt::ArrowCursor);
646     }
647   }
648   else if (mode == GroupScene::ItemEdition) {
649     int marginE = 5;
650     int marginS = 5;
651
652     InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
653     if (iface != NULL) {
654       params->cursorState = Parameters::CursorOnInterface;
655       setCursor(Qt::PointingHandCursor);
656     }
657     else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
658
659       params->cursorState = Parameters::CursorOnBorder;
660
661       if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
662         currentBorder = CornerSouthEast;
663         setCursor(Qt::SizeFDiagCursor);
664       }
665       else {
666         currentBorder = BorderEast;
667         setCursor(Qt::SizeHorCursor);
668       }
669     }
670     else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
671
672       params->cursorState = Parameters::CursorOnBorder;
673
674       if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
675         currentBorder = CornerSouthEast;
676         setCursor(Qt::SizeFDiagCursor);
677       }
678       else {
679         currentBorder = BorderSouth;
680         setCursor(Qt::SizeVerCursor);
681       }
682     }
683     else {
684       if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
685         params->cursorState = Parameters::CursorInBlock;
686         setCursor(Qt::OpenHandCursor);
687       }
688       else {
689         params->cursorState = Parameters::CursorNowhere;
690         setCursor(Qt::ArrowCursor);
691       }
692     }
693   }
694   if (params->cursorState == Parameters::CursorOnBorder) {
695     if (isDimensionLock()) {
696       if ((position == Bottom)||(position == Right)) {
697         event->setPos(evPos+pos());
698         getScene()->getGroupItem()->hoverMoveEvent(event);
699       }
700     }
701   }
702 }
703
704
705 void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {  
706   
707   QMenu menu;
708   QAction* titleAction = NULL;
709   QAction* removeAction = NULL;
710   QAction* duplicateAction = NULL;
711   QAction* renameAction = NULL;
712   QAction* connectToGroup = NULL;  
713   QAction* showProperties = NULL;
714   QAction* cloneInterface = NULL;
715   QAction* openWindow = NULL;
716   QAction* showRstClkIface = NULL;
717   QAction* showWishboneIface = NULL;
718   QAction* showParameters = NULL;
719   QAction* showPatterns = NULL;
720   QAction* showModifier = NULL;
721   QAction* removeModifier = NULL;
722   QAction* generateVHDL = NULL;
723
724   InterfaceItem* ifaceItem = getInterfaceItemFromCursor(event->pos().x(), event->pos().y());
725   // menu for interface
726   if( ifaceItem != NULL){
727
728     titleAction = menu.addAction("Interface operations");
729     titleAction->setEnabled(false);
730     menu.addSeparator();
731
732
733     showProperties = menu.addAction("Show properties");
734     renameAction = menu.addAction("Rename");
735
736     ConnectedInterface* iface = ifaceItem->refInter;
737     ConnectedInterface* ifaceGroup = NULL;
738     bool canRemove = true;
739
740     if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) {
741         connectToGroup = menu.addAction("Connect to group input");
742     }
743     else if ((iface->getDirection() == AbstractInterface::Output) && (iface->getConnectionToParentGroup() == NULL)) {
744       connectToGroup = menu.addAction("Connect to group output");
745     }
746     else if (iface->getConnectionFromParentGroup() != NULL) {
747       ifaceGroup = iface->getConnectionFromParentGroup();     
748       if (ifaceGroup->isConnectedFrom()) {        
749         canRemove = false;
750       }
751     }
752     else if (iface->getConnectionToParentGroup() != NULL) {
753       ifaceGroup = iface->getConnectionToParentGroup();      
754       if (ifaceGroup->isConnectedTo()) {
755         canRemove = false;
756       }
757     }
758
759     if (iface->isFunctionalInterface()) {
760       FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter);
761       ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference());
762       if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){
763         cloneInterface = menu.addAction("Duplicate");
764         if ((canRemove) && (fi->getInterfaceMultiplicity() > 1)) {
765           removeAction = menu.addAction("Remove");
766         }
767       }      
768     }
769     if (iface->getAssociatedIface() != NULL) {
770       if (iface->getDirection() == AbstractInterface::Output) {
771         showPatterns = menu.addAction("Show output pattern");
772       }
773       else if (iface->getDirection() == AbstractInterface::Input) {
774         showPatterns = menu.addAction("Show input pattern");
775       }
776     }    
777
778     if (iface->getAssociatedIface() != NULL) {
779       ConnectedInterface* assoIface = AI_TO_CON(iface->getAssociatedIface());
780       if (assoIface->getInputModifier() != NULL) {
781         removeModifier = menu.addAction("Remove input modifier");
782       }
783       if (assoIface->getInputModifier() != NULL) {
784         showModifier = menu.addAction("Show input modifier parameters");
785       }
786     }
787
788   }
789   // menu for blocks (group or func)
790   else {
791     titleAction = menu.addAction("Block operations");
792     titleAction->setEnabled(false);
793     menu.addSeparator();
794
795     if (refBlock->nbParameters() > 0) {
796       showParameters = menu.addAction("Show parameters");
797     }
798     renameAction = menu.addAction("Rename");
799
800     if(refBlock->isGroupBlock()){
801       openWindow = menu.addAction("Open/show group window");
802     }
803     else {
804       duplicateAction = menu.addAction("Duplicate");
805       showRstClkIface = menu.addAction("Show reset/clock interfaces");
806       showRstClkIface->setCheckable(true);
807       showRstClkIface->setChecked(rstClkVisible);
808       showWishboneIface = menu.addAction("Show wishbone interfaces");
809       showWishboneIface->setCheckable(true);
810       showWishboneIface->setChecked(wishboneVisible);
811     }
812     removeAction = menu.addAction("Remove");
813     generateVHDL = menu.addAction("Generate VHDL");
814   }
815
816   QAction* selectedAction = NULL;
817   selectedAction = menu.exec(event->screenPos());
818
819   if(selectedAction == NULL) return ;
820
821   if (selectedAction == removeAction) {
822     if(ifaceItem != NULL) {
823      dispatcher->removeFunctionalInterface(Dispatcher::Design, ifaceItem);
824     }
825     else {
826       dispatcher->removeBoxItem(Dispatcher::Design, this);
827     }
828   }
829   else if (selectedAction == duplicateAction) {
830     dispatcher->duplicateBoxItem(Dispatcher::Design, this);
831   }
832   else if(selectedAction == renameAction){
833     if(ifaceItem != NULL) {
834       dispatcher->renameInterface(Dispatcher::Design, ifaceItem);
835     }
836     else {
837       if (refBlock->isFunctionalBlock()) {          
838         dispatcher->renameFunctionalBlock(Dispatcher::Design, this);
839       }
840       else if (refBlock->isGroupBlock()) {        
841         dispatcher->renameGroupBlock(Dispatcher::Design, childGroupItem);
842       }
843     }   
844   }
845   else if(selectedAction == showProperties){
846     dispatcher->showProperties(Dispatcher::Design, ifaceItem);
847   }
848   else if (selectedAction == connectToGroup){
849     dispatcher->connectInterToGroup(Dispatcher::Design, ifaceItem);
850   }
851   else if (selectedAction == cloneInterface){
852     dispatcher->duplicateInterfaceItem(Dispatcher::Design, ifaceItem);
853   }
854   else if (selectedAction == openWindow){
855     dispatcher->showRaiseWindow(Dispatcher::Design, this);
856   }
857   else if(selectedAction == showRstClkIface) {
858     dispatcher->showRstClkIface(Dispatcher::Design, this);
859   }
860   else if(selectedAction == showWishboneIface) {
861     dispatcher->showWishboneIface(Dispatcher::Design, this);
862   }
863   else if(selectedAction == showParameters) {    
864     new ParametersWindow(refBlock, params, NULL);
865   }
866   else if(selectedAction == showPatterns) {    
867     dispatcher->showPatterns(Dispatcher::Design, ifaceItem);
868   }
869   else if(selectedAction == removeModifier) {
870     dispatcher->removeModifier(Dispatcher::Design, ifaceItem);
871   }
872   else if(selectedAction == showModifier) {
873     dispatcher->showModifier(Dispatcher::Design, ifaceItem);
874   }
875   else if(selectedAction == generateVHDL) {
876     dispatcher->generateBlockVHDL(Dispatcher::Design, this);
877   }
878
879 }
880
881 void BoxItem::loadFunctional(QDomElement funcElement) throw(Exception) {
882
883   bool ok = false;
884
885   int id = funcElement.attribute("id","none").toInt(&ok);
886   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
887
888   QString refXml = funcElement.attribute("ref_xml","none");
889   if(refXml == "none") throw(Exception(PROJECTFILE_CORRUPTED));
890
891   QString refMd5 = funcElement.attribute("ref_md5","none");
892   if(refMd5 == "none") throw(Exception(PROJECTFILE_CORRUPTED));
893
894   cout << "ref md5 : " << refMd5.toStdString() << "\nref xml : " << refXml.toStdString() << endl;
895
896   QString name = funcElement.attribute("name","none");
897   if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
898
899   QStringList positionStr = funcElement.attribute("position","none").split(",");
900   if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
901   int posX = positionStr.at(0).toInt(&ok);
902   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
903   int posY = positionStr.at(1).toInt(&ok);
904   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
905
906   QStringList dimensionStr = funcElement.attribute("dimension","none").split(",");
907   if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
908   int dimX = dimensionStr.at(0).toInt(&ok);
909   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
910   int dimY = dimensionStr.at(1).toInt(&ok);
911   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
912
913   QString visStr = funcElement.attribute("visible","none");
914   bool showItem = true;
915   if (visStr == "false") {
916     showItem = false;
917   }
918   
919   ReferenceBlock *referenceMd5 = NULL;
920   ReferenceBlock *referenceXml = NULL;
921   ReferenceBlock *reference = NULL;
922   if(refMd5 != "none") {
923     referenceMd5 = params->searchBlockByMd5(refMd5);
924   }
925   if(refXml != "none"){
926     referenceXml = params->searchBlockByXml(refXml);
927   }
928   if ((referenceMd5 == NULL) && (referenceXml == NULL)) {
929     throw(Exception(PROJECTFILE_CORRUPTED));
930   }
931   if (referenceMd5 != referenceXml) {
932     reference = referenceXml;
933   }
934   else {
935     reference = referenceMd5;
936   }
937   
938   GroupBlock* parentGroupBlock = AB_TO_GRP(((GroupItem *)parentItem())->getRefBlock());
939   FunctionalBlock* functionalBlock = params->getGraph()->createFunctionalBlock(parentGroupBlock, reference, false);
940   /* NB: addFunctionalBlock creates all interfaces from the reference, which is annoying when
941     reading bif_iface tags. Thus interface are all removed.
942   */
943   functionalBlock->setName(name);
944   setRefBlock(functionalBlock);
945   params->blockToItem.insert(functionalBlock,this);
946
947   setPos(posX,posY);
948   setDimension(dimX,dimY);
949   setId(id);
950
951
952   QDomNodeList blockParamNodes = funcElement.elementsByTagName("bif_parameter");
953   // setting parameters value
954   for(int i=0; i<blockParamNodes.length(); i++){
955     QDomElement currentBlockParamNode = blockParamNodes.at(i).toElement();
956
957     QString name = currentBlockParamNode.attribute("name","none");
958     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
959
960     QString value = currentBlockParamNode.attribute("value","none");
961     if(value == "none") throw(Exception(PROJECTFILE_CORRUPTED));
962
963     BlockParameter *blockParam = NULL;
964     blockParam = functionalBlock->getParameterFromName(name);
965     if (blockParam == NULL) throw(Exception(PROJECTFILE_CORRUPTED));
966     blockParam->setValue(value);
967   }  
968
969   // recreate all (non-control) interfaces because of some may have a multiplicity>1 with several examplars
970   //functionalBlock->removeAllInterfaces();
971   QDomNodeList interfaceNodes = funcElement.elementsByTagName("bif_iface");
972   // setting interfaces (user name, and for multiplicity>1 may be create some new ones)
973   for(int i=0; i<interfaceNodes.length(); i++) {
974
975     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
976
977     QString name = currentInterfaceNode.attribute("name","none");
978     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
979
980     QString refName = currentInterfaceNode.attribute("ref_name","none");
981     if(refName == "none") throw(Exception(PROJECTFILE_CORRUPTED));
982
983     ReferenceInterface* refInter = AI_TO_REF(reference->getIfaceFromName(refName));
984     cout << "creating iface from reference named " << qPrintable(refName) << endl;
985     FunctionalInterface *functionalInterface = new FunctionalInterface(functionalBlock,refInter);
986     functionalInterface->setName(name);
987     functionalBlock->addInterface(functionalInterface);
988     
989     // searching for control interface
990     QString ctlRefName = refName+"_enb";
991     ReferenceInterface* ctlRefIface = AI_TO_REF(reference->getIfaceFromName(ctlRefName));
992     
993     if (ctlRefIface != NULL) {
994       cout << "found a control iface:" << qPrintable(ctlRefName) << endl;
995       FunctionalInterface *ctlIface = new FunctionalInterface(functionalBlock,ctlRefIface);      
996       if (! ctlIface->setAssociatedIface(functionalInterface)) {
997         throw(Exception(PROJECTFILE_CORRUPTED));
998       }      
999       ctlIface->setName(name+"_enb");
1000       functionalBlock->addInterface(ctlIface);
1001     }    
1002   }
1003   
1004   // creating InterfaceItem
1005   createInterfaceItems();
1006   // setting them with saved values
1007   for(int i=0; i<interfaceNodes.length(); i++){
1008
1009     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
1010
1011     int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
1012     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
1013
1014     QString name = currentInterfaceNode.attribute("name","none");
1015     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
1016
1017     QString orientationStr = currentInterfaceNode.attribute("orientation","none");
1018     int orientation = InterfaceItem::getIntOrientation(orientationStr);
1019     if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
1020
1021     double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
1022     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
1023
1024     InterfaceItem *interfaceItem = searchInterfaceItemByName(name);
1025     interfaceItem->setId(id);
1026     interfaceItem->setOrientation(orientation);
1027     interfaceItem->setPositionRatio(position);
1028   }
1029   setVisible(showItem);
1030   updateGeometry(Resize);
1031 }
1032
1033 void BoxItem::save(QXmlStreamWriter &writer) {
1034   if (refBlock->isFunctionalBlock()) {
1035     writer.writeStartElement("bi_functional");
1036
1037     writer.writeAttribute("id",QString::number(id));
1038     writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
1039     writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
1040     writer.writeAttribute("name",refBlock->getName());
1041     QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
1042     writer.writeAttribute("position",attrPos);
1043     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
1044     writer.writeAttribute("dimension",attrDim);
1045     if (!isVisible()) {
1046       writer.writeAttribute("visible","false");
1047     }
1048
1049     writer.writeStartElement("bif_parameters");
1050     foreach(BlockParameter *param,refBlock->getParameters()){
1051       writer.writeStartElement("bif_parameter");
1052
1053       writer.writeAttribute("name",param->getName());
1054       writer.writeAttribute("value",param->getValue().toString());
1055       /*
1056       writer.writeAttribute("context",param->getStrContext());
1057       writer.writeAttribute("type",param->getTypeString());
1058       */
1059       writer.writeEndElement();   //</bif_parameter>
1060     }
1061     writer.writeEndElement();   //</bif_parameters>
1062
1063     writer.writeStartElement("bif_ifaces");
1064     writer.writeAttribute("count",QString::number(interfaces.length()));
1065     foreach(InterfaceItem* inter, interfaces){
1066       writer.writeStartElement("bif_iface");
1067
1068       writer.writeAttribute("id",QString::number(inter->getId()));
1069       writer.writeAttribute("name",inter->getName());
1070       writer.writeAttribute("ref_name",inter->getReferenceName());
1071       writer.writeAttribute("orientation",inter->getStrOrientation());
1072       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
1073
1074       writer.writeEndElement();   //</bif_iface>
1075     }
1076     writer.writeEndElement();   //</bif_ifaces>
1077
1078     writer.writeEndElement();   //</bi_functional>
1079   }
1080   else {
1081     writer.writeStartElement("bi_group");
1082
1083     writer.writeAttribute("id",QString::number(id));
1084     writer.writeAttribute("inside_group",QString::number(childGroupItem->getId()));
1085     QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
1086     writer.writeAttribute("position",attrPos);
1087     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
1088     writer.writeAttribute("dimension",attrDim);
1089
1090     writer.writeStartElement("big_ifaces");
1091     writer.writeAttribute("count",QString::number(interfaces.length()));
1092     foreach(InterfaceItem* inter, interfaces){
1093       writer.writeStartElement("big_iface");
1094
1095       writer.writeAttribute("id",QString::number(inter->getId()));
1096       writer.writeAttribute("ref_name",inter->refInter->getName());
1097       writer.writeAttribute("orientation",inter->getStrOrientation());
1098       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
1099
1100       writer.writeEndElement(); //</big_iface>
1101     }
1102
1103     writer.writeEndElement(); //</big_ifaces>
1104     writer.writeEndElement(); //</bi_group>
1105   }
1106 }
1107
1108 QDataStream &operator <<(QDataStream &out, BoxItem &b) {
1109   out.setVersion(QDataStream::Qt_4_8);
1110
1111   QByteArray blockData;
1112   QDataStream toWrite(&blockData, QIODevice::WriteOnly);
1113
1114   QString refXml = ((FunctionalBlock*)b.refBlock)->getReferenceXmlFile();
1115   QByteArray xmlFile = QByteArray(refXml.toStdString().c_str());
1116   toWrite << xmlFile;
1117
1118   toWrite << b.id;
1119   toWrite << (int)b.x();
1120   toWrite << (int)b.y();
1121   toWrite << b.boxWidth;
1122   toWrite << b.boxHeight;
1123   toWrite << b.getInterfaces().length();
1124
1125   for(int i=0; i<b.getInterfaces().length(); i++){
1126     InterfaceItem *inter = b.getInterfaces().at(i);
1127     toWrite << inter->getId();
1128     //toWrite << inter->getName();
1129     toWrite << inter->getPositionRatio();
1130     toWrite << inter->getOrientation();
1131   }
1132
1133   out << blockData;
1134
1135   return out;
1136 }
1137
1138 QDataStream &operator >>(QDataStream &in, BoxItem &b) {
1139
1140   in.setVersion(QDataStream::Qt_4_8);
1141
1142   int x,y,nbInter;
1143
1144   in >> b.id;
1145   in >> x;
1146   in >> y;
1147
1148   b.setX(x);
1149   b.setY(y);
1150
1151   in >> b.boxWidth;
1152   in >> b.boxHeight;
1153   in >> nbInter;
1154
1155   cout << "nbInter:" << nbInter << endl;
1156   for(int i=0; i<nbInter; i++){
1157
1158     int id, orientation;
1159     double positionRatio;
1160     QString name;
1161
1162     InterfaceItem *inter = b.getInterfaces().at(i);
1163     in >> id;
1164     in >> name;
1165     in >> positionRatio;
1166     in >> orientation;
1167
1168     inter->setId(id);    
1169     inter->setPositionRatio(positionRatio);
1170     inter->setOrientation(orientation);
1171     inter->updatePosition();
1172
1173   }
1174
1175   return in;
1176 }