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

Private GIT Repository
finished testbench generation
[blast.git] / GroupItem.cpp
1 #include "GroupItem.h"
2
3 #include "ConnectionItem.h"
4 #include "InterfaceItem.h"
5 #include "Dispatcher.h"
6 #include "Parameters.h"
7 #include "BoxItem.h"
8 #include "StimuliItem.h"
9 #include "AbstractBlock.h"
10 #include "AbstractInterface.h"
11 #include "ConnectedInterface.h"
12 #include "GroupScene.h"
13 #include "ParametersWindow.h"
14 #include "GroupBlock.h"
15 #include "GroupInterface.h"
16
17
18 GroupItem::GroupItem(BoxItem *_parentItem,
19                      AbstractBlock *_refBlock,
20                      Dispatcher *_dispatcher,
21                      Parameters *_params) throw(Exception) :AbstractBoxItem( _refBlock, _dispatcher, _params) {
22
23   parentItem = _parentItem;
24   if (parentItem != NULL) {
25     parentItem->setChildGroupItem(this);    
26   }
27
28   boxHeight = 1;
29   boxWidth = 1;
30   rectTitle = QRectF(0,-(nameHeight+2*nameMargin),nameWidth+2*nameMargin,nameHeight+2*nameMargin);
31
32   /* NB: boxPoint represent the position in scene of the top-left corner of the box, thus
33    * without taking into account the interfaces. It is also the reference position to draw the item.
34    * Nevertheless, in order to place sources in the scene, the real bouding box of the group is determined
35    * from originPoint and totalWidth/totalheight.
36    * */
37   boxPoint = QPointF(0,0);
38   /*
39   totalHeight = boxHeight + rectTitle.height();
40   totalWidth = boxWidth;
41 */
42   selected = false;
43
44   setZValue(100);
45
46   setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);  
47
48
49   updateGeometry(Creation);
50   setPos(boxPoint);
51   cout << "total size of group: " << totalWidth << "," << totalHeight << endl;
52   cout << "pos in scene: " << x() << "," << y() << endl;
53 }
54
55 GroupItem::GroupItem(Dispatcher *_dispatcher,Parameters *_params) throw(Exception) :AbstractBoxItem(_dispatcher, _params) {
56
57   parentItem = NULL;
58   rectTitle = QRectF(0,-(nameHeight+2*nameMargin),nameWidth+2*nameMargin,nameHeight+2*nameMargin);
59   selected = false;
60   setZValue(100);
61   setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
62
63   updateGeometry(InterfaceMove);
64   QPointF initPos = QPointF(0.0,0.0) - originPoint;
65   setPos(initPos);
66   cout << "total size of group: " << totalWidth << "," << totalHeight << endl;
67   cout << "pos in scene: " << x() << "," << y() << endl;
68 }
69
70 GroupItem::~GroupItem() {
71   // since the reference block is nowhere referenced except in this class, it must be deleted here
72   delete refBlock;
73 }
74
75 bool GroupItem::isGroupItem() {
76   return true;
77 }
78
79 BoxItem* GroupItem::getParentItem() {
80   return parentItem;
81 }
82
83 void GroupItem::setParentItem(BoxItem *_parentItem) {
84   parentItem = _parentItem;
85   if (parentItem != NULL) {
86     parentItem->setChildGroupItem(this);
87   }
88 }
89
90 void GroupItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
91
92   if (!visible) return;
93
94   if(boxWidth > 0 && boxHeight > 0){
95     if(selected)
96       painter->setPen(Qt::red);
97     else
98       painter->setPen(Qt::black);
99
100     painter->drawRect(0,0,boxWidth,boxHeight);
101     painter->drawRect(rectTitle);
102     painter->drawText(rectTitle,Qt::AlignCenter | Qt::TextWordWrap,refBlock->getName());
103   }
104   foreach(InterfaceItem *item, interfaces){    
105     item->paint(painter);
106   }
107 }
108
109 /* NOTE:
110    Each time a new block is added in a GroupItem, it is placed
111    at an absolute position of (0,0) within the GroupItem. (NB: the absolute
112    position is computed by item.pos()+item.getOriginPoint()).
113    Thus, there are 3 cases :
114    - a single block is within the GroupItem
115    - several blocks already placed and a new one
116    - several blocks already placed and one is moving.
117
118  */
119 void GroupItem::updateMinimumSize() {
120
121   // compute place taken by blocks.
122   int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
123   if (rectTitle.width() > 2*marginConn) {
124     minimumBoxWidth = rectTitle.width();
125   }
126   else {
127     minimumBoxWidth = 2*marginConn;
128   }
129   minimumBoxHeight = 2*marginConn;
130
131   if (getScene() == NULL) return;
132   QList<BoxItem *> blocks = getScene()->getBoxItems();
133   if(blocks.length() == 0) return; // no blocks within, keep the miniumum computed before.
134
135   QRectF boxFree; // the bounding box of free blocks.
136   foreach(BoxItem* item, blocks) {
137     QRectF boxItem = item->boundingRect();
138     if (item->getPosition() == BoxItem::Free) {
139       boxItem.translate(item->pos());
140       if (item->getSpan() == BoxItem::NoSpan) {
141         boxFree = boxFree.united(boxItem);
142       }
143       else if (item->getSpan() == BoxItem::HSpan) {
144         QRectF r(boxFree.left()+boxFree.width()/2.0,boxItem.top(),1,boxItem.height());
145         boxFree = boxFree.united(r);
146       }
147       else if (item->getSpan() == BoxItem::VSpan) {
148         QRectF r(boxItem.left(),boxFree.top()+boxFree.height()/2.0,boxItem.width(),1);
149         boxFree = boxFree.united(r);
150       }
151     }
152   }
153   // find the move to apply to freely located items
154   double gapXLeft = 0.0;
155   double gapYTop = 0.0;
156   if (boxFree.left() < marginConn) {
157     gapXLeft = boxFree.left() - marginConn;
158   }
159   if (boxFree.top() < marginConn) {
160     gapYTop = boxFree.top() - marginConn;
161   }
162   // translate the box
163   boxFree.translate(-gapXLeft,-gapYTop);
164   minimumBoxWidth = boxFree.right() + marginConn;
165   minimumBoxHeight = boxFree.bottom() + marginConn;
166
167   // find the highest/largest item stick on top/bottom/left/right
168
169   qreal topHighest = 0.0;
170   qreal bottomHighest = 0.0;
171   qreal leftLargest = 0.0;
172   qreal rightLargest = 0.0;
173
174   foreach(BoxItem* item, blocks) {
175     QRectF boxItem = item->boundingRect();
176
177     if (item->getPosition() == BoxItem::Top) {
178
179       if (item->getSpan() == BoxItem::VSpan) {
180         if (item->getMinimumBoxHeight() > topHighest) {
181           topHighest = item->getMinimumBoxHeight();
182         }
183       }
184       else {
185         if (boxItem.height()+marginConn > topHighest) {
186           topHighest = boxItem.height()+marginConn;
187         }
188       }
189       if (item->getSpan() == BoxItem::HSpan) {
190         if (item->getMinimumBoxWidth() > leftLargest) {
191           leftLargest = item->getMinimumBoxWidth();
192         }
193       }
194     }
195
196     if (item->getPosition() == BoxItem::Bottom) {
197
198       if (item->getSpan() == BoxItem::VSpan) {
199         if (item->getMinimumBoxHeight() > bottomHighest) {
200           bottomHighest = item->getMinimumBoxHeight();
201         }
202       }
203       else {
204         if (boxItem.height()+marginConn > bottomHighest) {
205           bottomHighest = boxItem.height()+marginConn;
206         }
207       }
208       if (item->getSpan() == BoxItem::HSpan) {
209         if (item->getMinimumBoxWidth() > leftLargest) {
210           leftLargest = item->getMinimumBoxWidth();
211         }
212       }
213     }
214
215     if (item->getPosition() == BoxItem::Left) {
216
217       if (item->getSpan() == BoxItem::HSpan) {
218         if (item->getMinimumBoxWidth() > leftLargest) {
219           leftLargest = item->getMinimumBoxWidth();
220         }
221       }
222       else {
223         if (boxItem.width()+marginConn > leftLargest) {
224           leftLargest = boxItem.width()+marginConn;
225         }
226       }
227       if (item->getSpan() == BoxItem::VSpan) {
228         if (item->getMinimumBoxHeight() > topHighest) {
229           topHighest = item->getMinimumBoxHeight();
230         }
231       }
232     }
233
234     if (item->getPosition() == BoxItem::Right) {
235
236       if (item->getSpan() == BoxItem::HSpan) {
237         if (item->getMinimumBoxWidth() > rightLargest) {
238           rightLargest = item->getMinimumBoxWidth();
239         }
240       }
241       else {
242         if (boxItem.width()+marginConn > rightLargest) {
243           rightLargest = boxItem.width()+marginConn;
244         }
245       }
246       if (item->getSpan() == BoxItem::VSpan) {
247         if (item->getMinimumBoxHeight() > topHighest) {
248           topHighest = item->getMinimumBoxHeight();
249         }
250       }
251     }
252   }
253
254   if (leftLargest > minimumBoxWidth) {
255     minimumBoxWidth = leftLargest;
256   }
257   if (rightLargest > minimumBoxWidth) {
258     minimumBoxWidth = rightLargest;
259   }
260   if (topHighest > minimumBoxHeight) {
261     minimumBoxHeight = topHighest;
262   }
263   if (bottomHighest > minimumBoxHeight) {
264     minimumBoxHeight = bottomHighest;
265   }
266   // must move all free boxitem within of -gapXLeft,-gapYTop
267   foreach(BoxItem* item, blocks) {
268     if (item->getPosition() == BoxItem::Free) {
269       if (item->getSpan() == BoxItem::HSpan) {
270         item->moveBy(0,-gapYTop);
271       }
272       if (item->getSpan() == BoxItem::VSpan) {
273         item->moveBy(-gapXLeft,0);
274       }
275       else {
276         item->moveBy(-gapXLeft,-gapYTop);
277       }
278     }
279   }
280
281   //cout << "min group size: " << minimumBoxWidth << "," << minimumBoxHeight << endl;
282 }
283
284 void GroupItem::updateShape() {
285   updateGeometry(InterfaceMove);
286 }
287
288 void GroupItem::updateBorderSpanItems() {
289   QList<BoxItem *> blocks = getScene()->getBoxItems();
290   bool changed = false;
291   foreach(BoxItem* item, blocks) {
292     changed = false;
293     if (item->getPosition() == BoxItem::Bottom) {
294       changed = true;
295       QPointF pos = item->pos();
296       item->moveTo(QPointF(pos.x(),boxHeight-item->getTotalHeight()));
297     }
298     else if (item->getPosition() == BoxItem::Right) {
299       changed = true;
300       QPointF pos = item->pos();
301       item->moveTo(QPointF(boxWidth-item->getTotalWidth(),pos.y()));
302     }
303     if (item->getSpan() == BoxItem::HSpan) {
304       changed = true;
305       item->setWidth(boxWidth);
306     }
307     else if (item->getSpan() == BoxItem::VSpan) {
308       changed = true;
309       item->setHeight(boxHeight);
310     }
311     if (changed) {
312       item->updateGeometry(Resize);
313     }
314   }
315 }
316
317 bool GroupItem::updateGeometry(ChangeType type) {
318
319   QPointF oldOrigin = originPoint;
320   QSize oldSize(totalWidth,totalHeight);
321
322   bool boxSizeChanged = false;
323
324   // whatever the change, the minimum size may have changed
325   updateMinimumSize();
326
327   if (type == Creation) {
328     boxSizeChanged = true;
329     boxWidth = minimumBoxWidth;
330     boxHeight = minimumBoxHeight;
331     /* reset and update interfaces positions
332      * in case of spanning, the interface are positionned
333      * only on free borders.
334      */
335     resetInterfaceItemsPosition();
336   }
337   else if (type == Resize) {
338     boxSizeChanged = true;
339     updateInterfaceAndConnectionItems();
340     updateBorderSpanItems();
341   }  
342   else if (type == InterfaceMove) {
343     // if an internal block has moved, the actual box size may be inadequate
344     if (boxWidth < minimumBoxWidth) {
345       boxWidth = minimumBoxWidth;
346       boxSizeChanged = true;
347       updateInterfaceAndConnectionItems();
348       updateBorderSpanItems();
349     }
350     if (boxHeight < minimumBoxHeight) {
351       boxHeight = minimumBoxHeight;
352       boxSizeChanged = true;
353       updateInterfaceAndConnectionItems();
354       updateBorderSpanItems();
355     }
356   }
357
358
359   // compute the max. width of interfaces' name for 4 orientations.  
360   int maxSouth = 0;
361   int maxNorth = 0;
362   int maxEast = 0;
363   int maxWest = 0;
364   int ifaceWidth = 0;
365
366   foreach(InterfaceItem* iface, interfaces) {
367     ifaceWidth = iface->getNameWidth();
368     if (iface->getOrientation() == Parameters::South) {
369       if (ifaceWidth > maxSouth) maxSouth = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
370     }
371     else if (iface->getOrientation() == Parameters::North) {
372       if (ifaceWidth > maxNorth) maxNorth = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
373     }
374     else if (iface->getOrientation() == Parameters::East) {
375       if (ifaceWidth > maxEast) maxEast = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
376     }
377     else if (iface->getOrientation() == Parameters::West) {
378       if (ifaceWidth > maxWest) maxWest = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
379     }
380   }
381   double x = 0.0;
382   double y = 0.0;
383   totalWidth = boxWidth+maxEast;
384   totalHeight = boxHeight+maxSouth;
385
386   if (maxWest > 0) {
387     x -= maxWest;
388     totalWidth += maxWest;
389   }
390   if (maxNorth > (nameHeight+2*nameMargin)) {
391     y -= maxNorth;
392     totalHeight += maxNorth;
393   }
394   else {
395     y -= nameHeight+2*nameMargin;
396     totalHeight += nameHeight+2*nameMargin;
397   }
398   QSizeF newSize(totalWidth,totalHeight);
399   originPoint.setX(x);
400   originPoint.setY(y);
401
402   if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
403     //cout << "GroupItem: must change group item shape" << endl;
404     prepareGeometryChange();
405     return true;
406   }
407   return false;
408 }
409
410 void GroupItem::nameChanged() {
411
412   
413   QFontMetrics fmId(params->defaultBlockFont);
414   nameWidth = fmId.width(refBlock->getName());
415   nameHeight = fmId.height();
416   // changing the BoxItem in the upperscene
417   if (parentItem != NULL) {
418     parentItem->nameChanged();
419   }
420   updateGeometry(InterfaceMove);
421   // force the update in case of the size has not changed
422   update();  
423 }
424
425
426 void GroupItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
427
428   if(params->editState == Parameters::EditGroupMove) {    
429     int gapX = event->scenePos().x() - cursorPosition.x();
430     int gapY = event->scenePos().y() - cursorPosition.y();
431
432     bool canMove = true;
433     if (refBlock->isTopGroupBlock()) {
434       QRectF rectGroup = boundingRectInScene();
435       rectGroup.moveTo(rectGroup.x()+gapX,rectGroup.y()+gapY);
436       foreach(StimuliItem* source, getScene()->getSourceItems()) {
437         QRectF rectSource = source->boundingRectInScene();
438         if (rectGroup.intersects(rectSource)) canMove = false;
439       }
440     }
441         
442     if (canMove) {
443       QPointF gap(gapX,gapY);
444       currentPosition = currentPosition+gap;
445       setPos(currentPosition);
446       
447       // updating all connections of the scene.
448       getScene()->updateConnectionItemsShape();
449     }
450     cursorPosition = event->scenePos();
451   }
452   else if(params->editState == Parameters::EditGroupResize) {
453
454     int gapX = event->scenePos().x() - cursorPosition.x();
455     int gapY = event->scenePos().y() - cursorPosition.y();
456     //cout << "gap: " << gapX << "," << gapY << endl;
457     switch(currentBorder){
458     case BorderEast: {
459       if(boxWidth+gapX > minimumBoxWidth){
460         boxWidth += gapX;
461       }
462       break;
463     }
464     case BorderSouth: {
465       if(boxHeight+gapY > minimumBoxHeight){
466         boxHeight += gapY;
467       }
468       break;
469     }
470     case CornerSouthEast: {
471       if(boxWidth+gapX > minimumBoxWidth){
472         boxWidth += gapX;
473       }
474       if(boxHeight+gapY > minimumBoxHeight){
475         boxHeight += gapY;
476       }
477       break;
478     }
479     case NoBorder:
480       cout << "abnormal case while resizing block" << endl;
481       break;
482     }
483     updateGeometry(Resize);
484     /*
485     // recompute the geometry of the block
486     updateGeometry();
487     // update all interfaces positions
488     foreach(InterfaceItem *item, interfaces){
489       item->updatePosition();
490     }
491     // update all connections from/to this block
492     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
493       if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
494         item->setPathes();
495       }
496     }
497     */
498     cursorPosition = event->scenePos();
499   }
500   else if(params->editState == Parameters::EditInterfaceMove) {
501     prepareGeometryChange();
502     moveInterfaceItemTo(event->pos());
503     // recompute the geometry of the block
504     updateGeometry(InterfaceMove);
505     // update connection from/to the selected interface
506     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
507       if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
508         item->setPath();
509       }
510     }
511     //update();
512   }
513 }
514
515 void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
516
517   QPointF pos = event->pos();
518   qreal x = pos.x();
519   qreal y = pos.y();
520
521   QGraphicsItem::mousePressEvent(event);
522
523   if(event->button() == Qt::RightButton) return;
524
525   int mode = getScene()->getEditionMode();
526
527   dispatcher->setCurrentGroupWidget(Dispatcher::Design, getScene()->getGroupWidget());
528
529   if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
530     InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
531     if (inter != NULL) {
532
533       if (params->editState == Parameters::EditNoOperation) {
534         getScene()->setSelectedInterface(1,inter);
535         params->setEditState(Parameters::EditStartConnection);
536       }
537       else if (params->editState == Parameters::EditStartConnection) {
538         if (inter == getScene()->getSelectedInterface(1)) {
539           params->setEditState(Parameters::EditAbortConnection);
540         }
541         else {
542           getScene()->setSelectedInterface(2,inter);
543           params->setEditState(Parameters::EditCloseConnection);
544         }
545       }
546     }
547   }  
548   else if (mode == GroupScene::ItemEdition) {
549
550     if (params->cursorState == Parameters::CursorOnInterface) {
551       InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
552       if (inter != NULL) {
553         currentInterface = inter;
554         params->setEditState(Parameters::EditInterfaceMove);
555       }
556     }
557     else if (params->cursorState == Parameters::CursorInGroupTitle) {
558       params->setEditState(Parameters::EditGroupMove);
559       cursorPosition = event->scenePos();
560     }
561     else if (params->cursorState == Parameters::CursorOnBorder) {
562       setFlag(ItemIsMovable, false);
563       cursorPosition = event->scenePos();
564       params->setEditState(Parameters::EditGroupResize);
565     }
566   }
567 }
568
569 void GroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
570
571   int mode = getScene()->getEditionMode();
572
573   if (mode == GroupScene::AddConnection) {
574
575     if (params->editState == Parameters::EditStartConnection) {
576       params->setEditState(Parameters::EditStartConnection);
577       InterfaceItem* iface = getScene()->getSelectedInterface(1);
578       iface->selected = true;
579       update(iface->boundingRect());
580     }
581     else if (params->editState == Parameters::EditAbortConnection) {
582       InterfaceItem* iface = getScene()->getSelectedInterface(1);
583       iface->selected = false;
584       update(iface->boundingRect());
585       getScene()->setSelectedInterface(1,NULL);
586       params->setEditState(Parameters::EditNoOperation);
587     }
588     else if (params->editState == Parameters::EditCloseConnection) {
589       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
590       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);      
591       bool ok = dispatcher->createConnection(Dispatcher::Design, iface1,iface2);
592       if (ok) {
593         iface1->selected = false;
594         update(iface1->boundingRect());
595         iface2->selected = false;
596         update(iface2->boundingRect());        
597         getScene()->setSelectedInterface(1,NULL);
598         getScene()->setSelectedInterface(2,NULL);
599         params->setEditState(Parameters::EditNoOperation);
600       }
601       else {
602         //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok);
603         getScene()->setSelectedInterface(2,NULL);
604         params->setEditState(Parameters::EditStartConnection);
605       }
606     }
607   }  
608   else if (mode == GroupScene::ItemEdition) {
609     currentInterface = NULL;
610     setFlag(ItemIsMovable, true);
611     params->editState = Parameters::EditNoOperation;
612   }
613   QGraphicsItem::mouseReleaseEvent(event);
614 }
615
616 void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
617   QPointF pos = event->pos();
618   qreal x = pos.x();
619   qreal y = pos.y();
620   currentBorder = NoBorder;
621   int mode = getScene()->getEditionMode();
622
623   if (mode == GroupScene::AddConnection) {
624     InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
625     if (iface != NULL) {
626       params->cursorState = Parameters::CursorOnInterface;
627       setCursor(Qt::PointingHandCursor);
628     }
629     else {
630       params->cursorState = Parameters::CursorNowhere;
631       setCursor(Qt::ArrowCursor);
632     }
633   }
634   else if (mode == GroupScene::ItemEdition) {
635     int marginE = 5;
636     int marginS = 5;
637
638     InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
639     if (iface != NULL) {
640       params->cursorState = Parameters::CursorOnInterface;
641       setCursor(Qt::PointingHandCursor);
642     }
643     else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
644
645       params->cursorState = Parameters::CursorOnBorder;
646
647       if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
648         currentBorder = CornerSouthEast;
649         setCursor(Qt::SizeFDiagCursor);        
650       }
651       else {
652         currentBorder = BorderEast;
653         setCursor(Qt::SizeHorCursor);        
654       }
655     }
656     else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
657
658       params->cursorState = Parameters::CursorOnBorder;
659
660       if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
661         currentBorder = CornerSouthEast;
662         setCursor(Qt::SizeFDiagCursor);        
663       }
664       else {
665         currentBorder = BorderSouth;
666         setCursor(Qt::SizeVerCursor);        
667       }
668     }
669     else {
670       if (rectTitle.contains(x,y)) {
671         params->cursorState = Parameters::CursorInGroupTitle;
672         setCursor(Qt::OpenHandCursor);
673       }
674       else {
675         params->cursorState = Parameters::CursorNowhere;
676         setCursor(Qt::ArrowCursor);
677       }
678     }
679   }  
680 }
681
682 void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
683   QMenu menu;
684   QAction* titleAction = NULL;
685   QAction* showProperties = NULL;
686   QAction* removeAction = NULL;
687   QAction* renameAction = NULL;
688   QAction* showParameters = NULL;
689   QAction* addExtClkAction = NULL;
690
691   InterfaceItem* ifaceItem = getInterfaceItemFromCursor(event->pos().x(), event->pos().y());
692
693   // menu for interface
694   if( ifaceItem != NULL) {
695     titleAction = menu.addAction("Interface operations");
696     titleAction->setEnabled(false);
697     menu.addSeparator();
698     showProperties = menu.addAction("Show properties");
699     renameAction = menu.addAction("Rename");
700     menu.addSeparator();
701     /* CAUTION : the interface can be removed only if its
702       connected to only one side, i.e. connectedFrom is null
703       or connectedTo is empty.
704
705     */
706     ConnectedInterface* ref = ifaceItem->refInter;
707     if ((!ref->isConnectedFrom()) || (!ref->isConnectedTo())) {
708       removeAction = menu.addAction("Remove");
709     }
710   }
711   else {
712     titleAction = menu.addAction("Block operations");
713     titleAction->setEnabled(false);
714     menu.addSeparator();
715
716     if (refBlock->nbParameters() > 0) {
717       showParameters = menu.addAction("Show parameters");
718     }
719     renameAction = menu.addAction("Rename");
720     if (refBlock->isTopGroupBlock()) {
721       addExtClkAction = menu.addAction("Add new external clock/reset");
722     }
723
724   }
725   QAction* selectedAction = menu.exec(event->screenPos());
726
727   if(selectedAction == NULL) return;
728
729   if(selectedAction == renameAction){
730     if(ifaceItem != NULL)
731       dispatcher->renameInterface(Dispatcher::Design, ifaceItem);
732     else
733       dispatcher->renameGroupBlock(Dispatcher::Design, this);
734   }
735   else if(selectedAction == showProperties){
736     dispatcher->showProperties(Dispatcher::Design, ifaceItem);
737   }  
738   else if (selectedAction == removeAction) {
739     dispatcher->removeGroupInterface(Dispatcher::Design, ifaceItem);
740   }
741   else if(selectedAction == showParameters) {
742     new ParametersWindow(refBlock, params, NULL);
743   }
744   else if (selectedAction == addExtClkAction) {
745     bool ok = false;
746     double freq = QInputDialog::getDouble(NULL,"Adding a clkrstgen","External clock frequency (in MHz)",100,0,100000,1,&ok);
747     if (!ok) return;
748     dispatcher->addClkRstGenBlock(Dispatcher::Design, freq);
749   }
750 }
751
752 InterfaceItem* GroupItem::isHoverInterface(QPointF point) {
753   foreach(InterfaceItem *inter, interfaces){
754     if(inter->boundingRect().contains(point))
755       return inter;
756   }
757   return NULL;
758 }
759
760 void GroupItem::load(QDomElement groupElement) throw(Exception) {
761
762   GroupBlock* groupBlock = AB_TO_GRP(refBlock);
763
764   bool ok = false;
765
766   int id = groupElement.attribute("id","none").toInt(&ok);
767   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
768
769   QString nameStr = groupElement.attribute("name","none");
770   if(nameStr == "none") throw(Exception(PROJECTFILE_CORRUPTED));    
771
772   QStringList positionStr = groupElement.attribute("position","none").split(",");
773   if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
774   int posX = positionStr.at(0).toInt(&ok);
775   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
776   int posY = positionStr.at(1).toInt(&ok);
777   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
778
779   QStringList dimensionStr = groupElement.attribute("dimension","none").split(",");
780   if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
781   int dimX = dimensionStr.at(0).toInt(&ok);
782   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
783   int dimY = dimensionStr.at(1).toInt(&ok);
784   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
785
786   setId(id);
787   setPos(posX,posY);
788   setDimension(dimX,dimY);
789   groupBlock->setName(nameStr);
790
791   cout << "group info : \n-id : " << id << "\n-pos : " << posX << ", " << posY << "\n-dim : " << dimX << ", " << dimY << "\n-name : " << nameStr.toStdString() << endl;
792
793   QDomNodeList interfaces = groupElement.elementsByTagName("group_iface");
794   for(int j=0; j<interfaces.length(); j++){
795     QDomElement currentInterfaceNode = interfaces.at(j).toElement();
796
797     int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
798     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
799
800     QString name = currentInterfaceNode.attribute("name","none");
801     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
802
803     QString purposeStr = currentInterfaceNode.attribute("purpose","none");
804     int purpose = AbstractInterface::getIntPurpose(purposeStr);
805     if(purpose == -1) throw(Exception(PROJECTFILE_CORRUPTED));
806     
807     QString directionStr = currentInterfaceNode.attribute("direction","none");
808     int direction = AbstractInterface::getIntDirection(directionStr);
809     if(direction == -1) throw(Exception(PROJECTFILE_CORRUPTED));
810
811     QString orientationStr = currentInterfaceNode.attribute("orientation","none");
812     int orientation = InterfaceItem::getIntOrientation(orientationStr);
813     if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
814
815     double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
816     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
817     
818     GroupInterface *groupIface = new GroupInterface(groupBlock,name,direction,purpose);
819     groupBlock->addInterface(groupIface);
820     bool show = false;
821     if ((groupBlock->isTopGroupBlock()) && (purpose == AbstractInterface::Clock)) {
822       show = true;
823     }
824
825     InterfaceItem *interfaceItem = new InterfaceItem(position,orientation,groupIface,this,params,show);
826     interfaceItem->setId(id);
827     addInterfaceItem(interfaceItem, false);
828
829     if (purpose == AbstractInterface::Data) {
830       GroupInterface *groupCtlIface = new GroupInterface(groupBlock,name+"_enb",direction,AbstractInterface::Control);
831       groupCtlIface->setAssociatedIface(groupIface);
832       groupBlock->addInterface(groupCtlIface);
833     }
834     cout << "interface " << qPrintable(name) << " added to " << groupBlock->getName().toStdString() << endl;
835   }
836
837 }
838
839 void GroupItem::save(QXmlStreamWriter &writer) {
840
841   writer.writeStartElement("group_item");
842
843   QString attrId = QString::number(id);
844   QString attrName(getRefBlock()->getName());
845   QString attrUpperItem = QString::number(-1);
846   if(parentItem != NULL){
847     attrUpperItem = QString::number(parentItem->getId());
848   }
849   QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
850   QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
851
852
853   writer.writeAttribute("id",attrId);
854   writer.writeAttribute("upper_item",attrUpperItem);
855   writer.writeAttribute("name",attrName);
856   writer.writeAttribute("position", attrPos);
857   writer.writeAttribute("dimension", attrDim);
858
859   writer.writeStartElement("group_ifaces");
860
861   writer.writeAttribute("count",QString::number(interfaces.length()));
862
863   foreach(InterfaceItem *item, interfaces){
864     writer.writeStartElement("group_iface");
865
866     writer.writeAttribute("id",QString::number(item->getId()));
867     writer.writeAttribute("name",item->getName());    
868     writer.writeAttribute("purpose",QString(item->refInter->getPurposeString()));    
869     writer.writeAttribute("direction",QString(item->refInter->getDirectionString()));
870     writer.writeAttribute("orientation",item->getStrOrientation());
871     writer.writeAttribute("position",QString::number(item->getPositionRatio()));
872
873     writer.writeEndElement();
874   }
875
876   writer.writeEndElement();//</interfaces>
877
878   writer.writeEndElement();//</group_item>
879 }