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

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