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

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