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

Private GIT Repository
ae15002120d4596156879144c449e905b5dcc3f4
[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 ((position == Left) || (position == Right)) {
410       gapX = 0;
411     }
412     else if ((gapX < 0) && (absPos.x() == marginConn)) {
413       gapX = 0;
414     }
415     else if (absPos.x()+gapX < marginConn) {
416       gapX = marginConn-absPos.x();
417     }
418     if ((position == Top) || (position == Bottom)) {
419       gapY = 0;
420     }
421     else if ((gapY < 0) && (absPos.y() == marginConn)) {
422       gapY = 0;
423     }
424     else if (absPos.y()+gapY < marginConn) {
425       gapY = marginConn-absPos.y();
426     }
427     //cout << "gap: " << gapX << "," << gapY << endl;
428     if ((gapX != 0) || (gapY != 0)) {
429       QPointF gap(gapX,gapY);
430       currentPosition = currentPosition+gap;
431       setPos(currentPosition);
432       // update all connections from/to this block
433       foreach(ConnectionItem *item, getScene()->getConnectionItems()){
434         if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
435           item->setPath();
436         }
437       }
438       // udpate the groupitem
439       (getScene()->getGroupItem())->updateShape();
440     }
441   }
442   else if(params->editState == Parameters::EditBlockResize) {
443
444     if (isDimensionLock()) return;
445     int gapX = event->scenePos().x() - cursorPosition.x();
446     int gapY = event->scenePos().y() - cursorPosition.y();
447     //cout << "gap: " << gapX << "," << gapY << endl;
448     switch(currentBorder){
449     case BorderEast: {    
450       if(boxWidth+gapX > minimumBoxWidth){
451         boxWidth += gapX;
452       }
453       break;
454     }
455     case BorderSouth: {      
456       if(boxHeight+gapY > minimumBoxHeight){
457         boxHeight += gapY;
458       }
459       break;
460     }
461     case CornerSouthEast: {
462       if(boxWidth+gapX > minimumBoxWidth){
463         boxWidth += gapX;
464       }
465       if(boxHeight+gapY > minimumBoxHeight){
466         boxHeight += gapY;
467       }
468       break;
469     }
470     case Title:
471       cout << "abnormal case while resizing block" << endl;
472       break;
473     case BorderWest:
474       cout << "abnormal case while resizing block" << endl;
475       break;
476     case BorderNorth:
477       cout << "abnormal case while resizing block" << endl;
478       break;
479     case NoBorder:
480       cout << "abnormal case while resizing block" << endl;
481       break;
482     }
483     // recompute the geometry of the block and possibly the group item
484     if (updateGeometry(Resize)) {
485       (getScene()->getGroupItem())->updateShape();
486     }
487
488     cursorPosition = event->scenePos();   
489   }
490   else if(params->editState == Parameters::EditInterfaceMove) {
491     prepareGeometryChange();
492     moveInterfaceItemTo(event->pos());
493     // recompute the geometry of the block
494     if (updateGeometry(InterfaceMove)) {
495       //cout << "must recompute group item geometry" << endl;
496       (getScene()->getGroupItem())->updateShape();
497     }
498     // update connection from/to the selected interface
499     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
500       if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
501         item->setPath();
502       }
503     }    
504   }
505 }
506
507 void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
508
509   QPointF pos = event->pos();
510   qreal x = pos.x();
511   qreal y = pos.y();
512
513   //QGraphicsItem::mousePressEvent(event);
514
515   if(event->button() == Qt::RightButton) return;
516
517   int mode = getScene()->getEditionMode();
518
519   dispatcher->setCurrentGroupWidget(Dispatcher::Design, getScene()->getGroupWidget());
520
521   if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
522     InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
523     if (inter != NULL) {
524
525       if (params->editState == Parameters::EditNoOperation) {
526         getScene()->setSelectedInterface(1,inter);
527         params->setEditState(Parameters::EditStartConnection);
528       }
529       else if (params->editState == Parameters::EditStartConnection) {
530         if (inter == getScene()->getSelectedInterface(1)) {
531           params->setEditState(Parameters::EditAbortConnection);
532         }
533         else {
534           getScene()->setSelectedInterface(2,inter);
535           params->setEditState(Parameters::EditCloseConnection);
536         }
537       }
538     }
539   }
540   else if (mode == GroupScene::ItemEdition) {
541     //setZValue(zValue()+100);
542     if (params->cursorState == Parameters::CursorOnInterface) {
543       InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
544       if (inter != NULL) {
545         if (inter == currentInterface) {
546            params->setEditState(Parameters::EditInterfaceDeselect);
547         }
548         else {
549           setFlag(ItemIsMovable, false);
550           currentInterface = inter;
551           params->setEditState(Parameters::EditInterfaceMove);
552         }
553       }
554     }
555     else if (params->cursorState == Parameters::CursorInBlock) {
556       selected = !selected;
557       params->setEditState(Parameters::EditBlockMove);
558       cursorPosition = event->scenePos();
559       //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
560       update();
561     }
562     else if (params->cursorState == Parameters::CursorOnBorder) {
563       if (isDimensionLock()) {
564         if ((position == Bottom)||(position == Right)) {
565           event->ignore();
566         }
567       }
568       else {
569         setFlag(ItemIsMovable, false);
570         cursorPosition = event->scenePos();
571         params->setEditState(Parameters::EditBlockResize);
572       }
573     }
574   }
575 }
576
577 void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
578
579   //setZValue(zValue()-100);
580
581   int mode = getScene()->getEditionMode();
582
583   if (mode == GroupScene::AddConnection) {
584
585     if (params->editState == Parameters::EditStartConnection) {
586       InterfaceItem* iface = getScene()->getSelectedInterface(1);
587       iface->selected = true;
588       update(iface->boundingRect());
589     }
590     else if (params->editState == Parameters::EditAbortConnection) {
591       InterfaceItem* iface = getScene()->getSelectedInterface(1);
592       iface->selected = false;
593       update(iface->boundingRect());
594       getScene()->setSelectedInterface(1,NULL);
595       params->setEditState(Parameters::EditNoOperation);
596     }
597     else if (params->editState == Parameters::EditCloseConnection) {
598       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
599       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
600       bool ok = dispatcher->createConnection(Dispatcher::Design, iface1,iface2);
601       if (ok) {
602         iface1->selected = false;
603         update(iface1->boundingRect());
604         iface2->selected = false;
605         update(iface2->boundingRect());        
606         getScene()->setSelectedInterface(1,NULL);
607         getScene()->setSelectedInterface(2,NULL);
608         params->setEditState(Parameters::EditNoOperation);
609       }
610       else {
611         //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok);
612         getScene()->setSelectedInterface(2,NULL);
613         params->setEditState(Parameters::EditStartConnection);
614       }
615     }
616   }
617   else if (mode == GroupScene::ItemEdition) {
618     currentInterface = NULL;
619     params->editState = Parameters::EditNoOperation;
620     setFlag(ItemIsMovable);
621   }
622
623   QGraphicsItem::mouseReleaseEvent(event);
624 }
625
626 void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
627
628   QPointF evPos = event->pos();
629   qreal x = evPos.x();
630   qreal y = evPos.y();
631   currentBorder = NoBorder;
632   int mode = getScene()->getEditionMode();
633
634   if (mode == GroupScene::AddConnection) {
635     InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
636     if (iface != NULL) {
637       params->cursorState = Parameters::CursorOnInterface;
638       setCursor(Qt::PointingHandCursor);
639     }
640     else {
641       params->cursorState = Parameters::CursorNowhere;
642       setCursor(Qt::ArrowCursor);
643     }
644   }
645   else if (mode == GroupScene::ItemEdition) {
646     int marginE = 5;
647     int marginS = 5;
648
649     InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
650     if (iface != NULL) {
651       params->cursorState = Parameters::CursorOnInterface;
652       setCursor(Qt::PointingHandCursor);
653     }
654     else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
655
656       params->cursorState = Parameters::CursorOnBorder;
657
658       if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
659         currentBorder = CornerSouthEast;
660         setCursor(Qt::SizeFDiagCursor);
661       }
662       else {
663         currentBorder = BorderEast;
664         setCursor(Qt::SizeHorCursor);
665       }
666     }
667     else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
668
669       params->cursorState = Parameters::CursorOnBorder;
670
671       if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
672         currentBorder = CornerSouthEast;
673         setCursor(Qt::SizeFDiagCursor);
674       }
675       else {
676         currentBorder = BorderSouth;
677         setCursor(Qt::SizeVerCursor);
678       }
679     }
680     else {
681       if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
682         params->cursorState = Parameters::CursorInBlock;
683         setCursor(Qt::OpenHandCursor);
684       }
685       else {
686         params->cursorState = Parameters::CursorNowhere;
687         setCursor(Qt::ArrowCursor);
688       }
689     }
690   }
691   if (params->cursorState == Parameters::CursorOnBorder) {
692     if (isDimensionLock()) {
693       if ((position == Bottom)||(position == Right)) {
694         event->setPos(evPos+pos());
695         getScene()->getGroupItem()->hoverMoveEvent(event);
696       }
697     }
698   }
699 }
700
701
702 void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {  
703   
704   QMenu menu;
705   QAction* titleAction = NULL;
706   QAction* removeAction = NULL;
707   QAction* duplicateAction = NULL;
708   QAction* renameAction = NULL;
709   QAction* connectToGroup = NULL;  
710   QAction* showProperties = NULL;
711   QAction* cloneInterface = NULL;
712   QAction* openWindow = NULL;
713   QAction* showRstClkIface = NULL;
714   QAction* showWishboneIface = NULL;
715   QAction* showParameters = NULL;
716   QAction* showPatterns = NULL;
717   QAction* showModifier = NULL;
718   QAction* removeModifier = NULL;
719   QAction* generateVHDL = NULL;
720
721   InterfaceItem* ifaceItem = getInterfaceItemFromCursor(event->pos().x(), event->pos().y());
722   // menu for interface
723   if( ifaceItem != NULL){
724
725     titleAction = menu.addAction("Interface operations");
726     titleAction->setEnabled(false);
727     menu.addSeparator();
728
729
730     showProperties = menu.addAction("Show properties");
731     renameAction = menu.addAction("Rename");
732
733     ConnectedInterface* iface = ifaceItem->refInter;
734     ConnectedInterface* ifaceGroup = NULL;
735     bool canRemove = true;
736
737     if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) {
738         connectToGroup = menu.addAction("Connect to group input");
739     }
740     else if ((iface->getDirection() == AbstractInterface::Output) && (iface->getConnectionToParentGroup() == NULL)) {
741       connectToGroup = menu.addAction("Connect to group output");
742     }
743     else if (iface->getConnectionFromParentGroup() != NULL) {
744       ifaceGroup = iface->getConnectionFromParentGroup();     
745       if (ifaceGroup->isConnectedFrom()) {        
746         canRemove = false;
747       }
748     }
749     else if (iface->getConnectionToParentGroup() != NULL) {
750       ifaceGroup = iface->getConnectionToParentGroup();      
751       if (ifaceGroup->isConnectedTo()) {
752         canRemove = false;
753       }
754     }
755
756     if (iface->isFunctionalInterface()) {
757       FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter);
758       ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference());
759       if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){
760         cloneInterface = menu.addAction("Duplicate");
761         if ((canRemove) && (fi->getInterfaceMultiplicity() > 1)) {
762           removeAction = menu.addAction("Remove");
763         }
764       }      
765     }
766     if (iface->getAssociatedIface() != NULL) {
767       if (iface->getDirection() == AbstractInterface::Output) {
768         showPatterns = menu.addAction("Show output pattern");
769       }
770       else if (iface->getDirection() == AbstractInterface::Input) {
771         showPatterns = menu.addAction("Show input pattern");
772       }
773     }    
774
775     if (iface->getAssociatedIface() != NULL) {
776       ConnectedInterface* assoIface = AI_TO_CON(iface->getAssociatedIface());
777       if (assoIface->getInputModifier() != NULL) {
778         removeModifier = menu.addAction("Remove input modifier");
779       }
780       if (assoIface->getInputModifier() != NULL) {
781         showModifier = menu.addAction("Show input modifier parameters");
782       }
783     }
784
785   }
786   // menu for blocks (group or func)
787   else {
788     titleAction = menu.addAction("Block operations");
789     titleAction->setEnabled(false);
790     menu.addSeparator();
791
792     if (refBlock->nbParameters() > 0) {
793       showParameters = menu.addAction("Show parameters");
794     }
795     renameAction = menu.addAction("Rename");
796
797     if(refBlock->isGroupBlock()){
798       openWindow = menu.addAction("Open/show group window");
799     }
800     else {
801       duplicateAction = menu.addAction("Duplicate");
802       showRstClkIface = menu.addAction("Show reset/clock interfaces");
803       showRstClkIface->setCheckable(true);
804       showRstClkIface->setChecked(rstClkVisible);
805       showWishboneIface = menu.addAction("Show wishbone interfaces");
806       showWishboneIface->setCheckable(true);
807       showWishboneIface->setChecked(wishboneVisible);
808     }
809     removeAction = menu.addAction("Remove");
810     generateVHDL = menu.addAction("Generate VHDL");
811   }
812
813   QAction* selectedAction = NULL;
814   selectedAction = menu.exec(event->screenPos());
815
816   if(selectedAction == NULL) return ;
817
818   if (selectedAction == removeAction) {
819     if(ifaceItem != NULL) {
820      dispatcher->removeFunctionalInterface(Dispatcher::Design, ifaceItem);
821     }
822     else {
823       dispatcher->removeBoxItem(Dispatcher::Design, this);
824     }
825   }
826   else if (selectedAction == duplicateAction) {
827     dispatcher->duplicateBoxItem(Dispatcher::Design, this);
828   }
829   else if(selectedAction == renameAction){
830     if(ifaceItem != NULL) {
831       dispatcher->renameInterface(Dispatcher::Design, ifaceItem);
832     }
833     else {
834       if (refBlock->isFunctionalBlock()) {          
835         dispatcher->renameFunctionalBlock(Dispatcher::Design, this);
836       }
837       else if (refBlock->isGroupBlock()) {        
838         dispatcher->renameGroupBlock(Dispatcher::Design, childGroupItem);
839       }
840     }   
841   }
842   else if(selectedAction == showProperties){
843     dispatcher->showProperties(Dispatcher::Design, ifaceItem);
844   }
845   else if (selectedAction == connectToGroup){
846     dispatcher->connectInterToGroup(Dispatcher::Design, ifaceItem);
847   }
848   else if (selectedAction == cloneInterface){
849     dispatcher->duplicateInterfaceItem(Dispatcher::Design, ifaceItem);
850   }
851   else if (selectedAction == openWindow){
852     dispatcher->showRaiseWindow(Dispatcher::Design, this);
853   }
854   else if(selectedAction == showRstClkIface) {
855     dispatcher->showRstClkIface(Dispatcher::Design, this);
856   }
857   else if(selectedAction == showWishboneIface) {
858     dispatcher->showWishboneIface(Dispatcher::Design, this);
859   }
860   else if(selectedAction == showParameters) {    
861     new ParametersWindow(refBlock, params, NULL);
862   }
863   else if(selectedAction == showPatterns) {    
864     dispatcher->showPatterns(Dispatcher::Design, ifaceItem);
865   }
866   else if(selectedAction == removeModifier) {
867     dispatcher->removeModifier(Dispatcher::Design, ifaceItem);
868   }
869   else if(selectedAction == showModifier) {
870     dispatcher->showModifier(Dispatcher::Design, ifaceItem);
871   }
872   else if(selectedAction == generateVHDL) {
873     dispatcher->generateBlockVHDL(Dispatcher::Design, this);
874   }
875
876 }
877
878 void BoxItem::loadFunctional(QDomElement funcElement) throw(Exception) {
879
880   bool ok = false;
881
882   int id = funcElement.attribute("id","none").toInt(&ok);
883   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
884
885   QString refXml = funcElement.attribute("ref_xml","none");
886   if(refXml == "none") throw(Exception(PROJECTFILE_CORRUPTED));
887
888   QString refMd5 = funcElement.attribute("ref_md5","none");
889   if(refMd5 == "none") throw(Exception(PROJECTFILE_CORRUPTED));
890
891   cout << "ref md5 : " << refMd5.toStdString() << "\nref xml : " << refXml.toStdString() << endl;
892
893   QString name = funcElement.attribute("name","none");
894   if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
895
896   QStringList positionStr = funcElement.attribute("position","none").split(",");
897   if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
898   int posX = positionStr.at(0).toInt(&ok);
899   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
900   int posY = positionStr.at(1).toInt(&ok);
901   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
902
903   QStringList dimensionStr = funcElement.attribute("dimension","none").split(",");
904   if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
905   int dimX = dimensionStr.at(0).toInt(&ok);
906   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
907   int dimY = dimensionStr.at(1).toInt(&ok);
908   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
909   
910   ReferenceBlock *referenceMd5 = NULL;
911   ReferenceBlock *referenceXml = NULL;
912   ReferenceBlock *reference = NULL;
913   if(refMd5 != "none") {
914     referenceMd5 = params->searchBlockByMd5(refMd5);
915   }
916   if(refXml != "none"){
917     referenceXml = params->searchBlockByXml(refXml);
918   }
919   if ((referenceMd5 == NULL) && (referenceXml == NULL)) {
920     throw(Exception(PROJECTFILE_CORRUPTED));
921   }
922   if (referenceMd5 != referenceXml) {
923     reference = referenceXml;
924   }
925   else {
926     reference = referenceMd5;
927   }
928   
929   GroupBlock* parentGroupBlock = AB_TO_GRP(((GroupItem *)parentItem())->getRefBlock());
930   FunctionalBlock* functionalBlock = params->getGraph()->createFunctionalBlock(parentGroupBlock, reference);
931   /* NB: addFunctionalBlock creates all interfaces from the reference, which is annoying when
932     reading bif_iface tags. Thus interface are all removed.
933   */
934   functionalBlock->setName(name);
935   setRefBlock(functionalBlock);
936   params->blockToItem.insert(functionalBlock,this);
937
938   setPos(posX,posY);
939   setDimension(dimX,dimY);
940   setId(id);
941
942
943   QDomNodeList blockParamNodes = funcElement.elementsByTagName("bif_parameter");
944   // setting parameters value
945   for(int i=0; i<blockParamNodes.length(); i++){
946     QDomElement currentBlockParamNode = blockParamNodes.at(i).toElement();
947
948     QString name = currentBlockParamNode.attribute("name","none");
949     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
950
951     QString value = currentBlockParamNode.attribute("value","none");
952     if(value == "none") throw(Exception(PROJECTFILE_CORRUPTED));
953
954     BlockParameter *blockParam = NULL;
955     blockParam = functionalBlock->getParameterFromName(name);
956     if (blockParam == NULL) throw(Exception(PROJECTFILE_CORRUPTED));
957     blockParam->setValue(value);
958   }  
959
960   // recreate all (non-control) interfaces because of some may have a multiplicity>1 with several examplars
961   functionalBlock->removeAllInterfaces();
962   QDomNodeList interfaceNodes = funcElement.elementsByTagName("bif_iface");
963   // setting interfaces (user name, and for multiplicity>1 may be create some new ones)
964   for(int i=0; i<interfaceNodes.length(); i++) {
965
966     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
967
968     QString name = currentInterfaceNode.attribute("name","none");
969     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
970
971     QString refName = currentInterfaceNode.attribute("ref_name","none");
972     if(refName == "none") throw(Exception(PROJECTFILE_CORRUPTED));
973
974     ReferenceInterface* refInter = AI_TO_REF(reference->getIfaceFromName(refName));
975     cout << "creating iface from reference named " << qPrintable(refName) << endl;
976     FunctionalInterface *functionalInterface = new FunctionalInterface(functionalBlock,refInter);
977     functionalInterface->setName(name);
978     functionalBlock->addInterface(functionalInterface);
979     
980     // searching for control interface
981     QString ctlRefName = refName+"_enb";
982     ReferenceInterface* ctlRefIface = AI_TO_REF(reference->getIfaceFromName(ctlRefName));
983     
984     if (ctlRefIface != NULL) {
985       cout << "found a control iface:" << qPrintable(ctlRefName) << endl;
986       FunctionalInterface *ctlIface = new FunctionalInterface(functionalBlock,ctlRefIface);      
987       if (! ctlIface->setAssociatedIface(functionalInterface)) {
988         throw(Exception(PROJECTFILE_CORRUPTED));
989       }      
990       ctlIface->setName(name+"_enb");
991       functionalBlock->addInterface(ctlIface);
992     }    
993   }
994   
995   // creating InterfaceItem
996   createInterfaceItems();
997   // setting them with saved values
998   for(int i=0; i<interfaceNodes.length(); i++){
999
1000     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
1001
1002     int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
1003     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
1004
1005     QString name = currentInterfaceNode.attribute("name","none");
1006     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
1007
1008     QString orientationStr = currentInterfaceNode.attribute("orientation","none");
1009     int orientation = InterfaceItem::getIntOrientation(orientationStr);
1010     if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
1011
1012     double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
1013     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
1014
1015     InterfaceItem *interfaceItem = searchInterfaceItemByName(name);
1016     interfaceItem->setId(id);
1017     interfaceItem->setOrientation(orientation);
1018     interfaceItem->setPositionRatio(position);
1019   }
1020   updateGeometry(Resize);
1021 }
1022
1023 void BoxItem::save(QXmlStreamWriter &writer) {
1024   if (refBlock->isFunctionalBlock()) {
1025     writer.writeStartElement("bi_functional");
1026
1027     writer.writeAttribute("id",QString::number(id));
1028     writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
1029     writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
1030     writer.writeAttribute("name",refBlock->getName());
1031     QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
1032     writer.writeAttribute("position",attrPos);
1033     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
1034     writer.writeAttribute("dimension",attrDim);
1035
1036     writer.writeStartElement("bif_parameters");
1037     foreach(BlockParameter *param,refBlock->getParameters()){
1038       writer.writeStartElement("bif_parameter");
1039
1040       writer.writeAttribute("name",param->getName());
1041       writer.writeAttribute("value",param->getValue().toString());
1042       /*
1043       writer.writeAttribute("context",param->getStrContext());
1044       writer.writeAttribute("type",param->getTypeString());
1045       */
1046       writer.writeEndElement();   //</bif_parameter>
1047     }
1048     writer.writeEndElement();   //</bif_parameters>
1049
1050     writer.writeStartElement("bif_ifaces");
1051     writer.writeAttribute("count",QString::number(interfaces.length()));
1052     foreach(InterfaceItem* inter, interfaces){
1053       writer.writeStartElement("bif_iface");
1054
1055       writer.writeAttribute("id",QString::number(inter->getId()));
1056       writer.writeAttribute("name",inter->getName());
1057       writer.writeAttribute("ref_name",inter->refInter->getName());
1058       writer.writeAttribute("orientation",inter->getStrOrientation());
1059       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
1060
1061       writer.writeEndElement();   //</bif_iface>
1062     }
1063     writer.writeEndElement();   //</bif_ifaces>
1064
1065     writer.writeEndElement();   //</bi_functional>
1066   }
1067   else {
1068     writer.writeStartElement("bi_group");
1069
1070     writer.writeAttribute("id",QString::number(id));
1071     writer.writeAttribute("inside_group",QString::number(childGroupItem->getId()));
1072     QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
1073     writer.writeAttribute("position",attrPos);
1074     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
1075     writer.writeAttribute("dimension",attrDim);
1076
1077     writer.writeStartElement("big_ifaces");
1078     writer.writeAttribute("count",QString::number(interfaces.length()));
1079     foreach(InterfaceItem* inter, interfaces){
1080       writer.writeStartElement("big_iface");
1081
1082       writer.writeAttribute("id",QString::number(inter->getId()));
1083       writer.writeAttribute("ref_name",inter->refInter->getName());
1084       writer.writeAttribute("orientation",inter->getStrOrientation());
1085       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
1086
1087       writer.writeEndElement(); //</big_iface>
1088     }
1089
1090     writer.writeEndElement(); //</big_ifaces>
1091     writer.writeEndElement(); //</bi_group>
1092   }
1093 }
1094
1095 QDataStream &operator <<(QDataStream &out, BoxItem &b) {
1096   out.setVersion(QDataStream::Qt_4_8);
1097
1098   QByteArray blockData;
1099   QDataStream toWrite(&blockData, QIODevice::WriteOnly);
1100
1101   QString refXml = ((FunctionalBlock*)b.refBlock)->getReferenceXmlFile();
1102   QByteArray xmlFile = QByteArray(refXml.toStdString().c_str());
1103   toWrite << xmlFile;
1104
1105   toWrite << b.id;
1106   toWrite << (int)b.x();
1107   toWrite << (int)b.y();
1108   toWrite << b.boxWidth;
1109   toWrite << b.boxHeight;
1110   toWrite << b.getInterfaces().length();
1111
1112   for(int i=0; i<b.getInterfaces().length(); i++){
1113     InterfaceItem *inter = b.getInterfaces().at(i);
1114     toWrite << inter->getId();
1115     //toWrite << inter->getName();
1116     toWrite << inter->getPositionRatio();
1117     toWrite << inter->getOrientation();
1118   }
1119
1120   out << blockData;
1121
1122   return out;
1123 }
1124
1125 QDataStream &operator >>(QDataStream &in, BoxItem &b) {
1126
1127   in.setVersion(QDataStream::Qt_4_8);
1128
1129   int x,y,nbInter;
1130
1131   in >> b.id;
1132   in >> x;
1133   in >> y;
1134
1135   b.setX(x);
1136   b.setY(y);
1137
1138   in >> b.boxWidth;
1139   in >> b.boxHeight;
1140   in >> nbInter;
1141
1142   cout << "nbInter:" << nbInter << endl;
1143   for(int i=0; i<nbInter; i++){
1144
1145     int id, orientation;
1146     double positionRatio;
1147     QString name;
1148
1149     InterfaceItem *inter = b.getInterfaces().at(i);
1150     in >> id;
1151     in >> name;
1152     in >> positionRatio;
1153     in >> orientation;
1154
1155     inter->setId(id);    
1156     inter->setPositionRatio(positionRatio);
1157     inter->setOrientation(orientation);
1158     inter->updatePosition();
1159
1160   }
1161
1162   return in;
1163 }