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

Private GIT Repository
90c5574f025c58578e1277154f3371b8143775dc
[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 "SourceItem.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   /*
29   minimumBoxWidth = nameWidth+2*nameMargin;
30   minimumBoxHeight = 100;
31   boxHeight = minimumBoxHeight;
32   boxWidth = minimumBoxWidth;
33   */
34   rectTitle = QRectF(0,-(nameHeight+2*nameMargin),nameWidth+2*nameMargin,nameHeight+2*nameMargin);
35   /*
36   totalHeight = boxHeight + rectTitle.height();
37   totalWidth = boxWidth;
38 */
39   selected = false;
40
41
42   setZValue(100);
43
44   setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);  
45
46
47   updateGeometry(InterfaceMove);
48   QPointF initPos = QPointF(0.0,0.0) - originPoint;
49   setPos(initPos);
50   cout << "total size of group: " << totalWidth << "," << totalHeight << endl;
51   cout << "pos in scene: " << x() << "," << y() << endl;
52 }
53
54 GroupItem::GroupItem(Dispatcher *_dispatcher,Parameters *_params) throw(Exception) :AbstractBoxItem(_dispatcher, _params) {
55
56   parentItem = NULL;
57   rectTitle = QRectF(0,-(nameHeight+2*nameMargin),nameWidth+2*nameMargin,nameHeight+2*nameMargin);
58   selected = false;
59   setZValue(100);
60   setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
61
62   updateGeometry(InterfaceMove);
63   QPointF initPos = QPointF(0.0,0.0) - originPoint;
64   setPos(initPos);
65   cout << "total size of group: " << totalWidth << "," << totalHeight << endl;
66   cout << "pos in scene: " << x() << "," << y() << endl;
67 }
68
69 GroupItem::~GroupItem() {
70   // since the reference block is nowhere referenced except in this class, it must be deleted here
71   delete refBlock;
72 }
73
74 bool GroupItem::isGroupItem() {
75   return true;
76 }
77
78 BoxItem* GroupItem::getParentItem() {
79   return parentItem;
80 }
81
82 void GroupItem::setParentItem(BoxItem *_parentItem) {
83   parentItem = _parentItem;
84   if (parentItem != NULL) {
85     parentItem->setChildGroupItem(this);
86   }
87 }
88
89 void GroupItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
90   if(boxWidth > 0 && boxHeight > 0){
91     if(selected)
92       painter->setPen(Qt::red);
93     else
94       painter->setPen(Qt::black);
95
96     painter->drawRect(0,0,boxWidth,boxHeight);
97     painter->drawRect(rectTitle);
98     painter->drawText(rectTitle,Qt::AlignCenter | Qt::TextWordWrap,refBlock->getName());
99   }
100   foreach(InterfaceItem *item, interfaces){    
101     item->paint(painter);
102   }
103 }
104
105 /* NOTE:
106    Each time a new block is added in a GroupItem, it is placed
107    at an absolute position of (0,0) within the GroupItem. (NB: the absolute
108    position is computed by item.pos()+item.getOriginPoint()).
109    Thus, there are 3 cases :
110    - a single block is within the GroupItem
111    - several blocks already placed and a new one
112    - several blocks already placed and one is moving.
113
114  */
115 void GroupItem::updateMinimumSize() {
116
117   // compute place taken by blocks.
118   int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
119   if (rectTitle.width() > 2*marginConn) {
120     minimumBoxWidth = rectTitle.width();
121   }
122   else {
123     minimumBoxWidth = 2*marginConn;
124   }
125   minimumBoxHeight = 2*marginConn;
126
127   if (getScene() == NULL) return;
128
129   QList<BoxItem *> blocks = getScene()->getBoxItems();
130   if(blocks.length() > 0) {
131     // first, search for blocks that are at (0,0)
132     int xMaxZero = 0;
133     int yMaxZero = 0;
134     int xMax = 0;
135     int yMax = 0;
136     bool isZeroBlocks = false;
137     bool isOtherBlocks = false;
138     foreach(BoxItem* item, blocks) {
139       QPointF p = item->pos() + item->getOriginPoint();
140       if ((p.x()==0.0) && (p.y()==0.0)) {
141         isZeroBlocks = true;
142         if (item->getTotalWidth() > xMaxZero) {
143           xMaxZero = item->getTotalWidth();
144         }
145         if (item->getTotalHeight() > yMaxZero) {
146           yMaxZero = item->getTotalHeight();
147         }
148       }
149       else {
150         isOtherBlocks = true;
151         if(p.x()+item->getTotalWidth() > xMax) {
152           xMax = p.x()+item->getTotalWidth();
153         }
154         if(p.y()+item->getTotalHeight() > yMax) {
155           yMax = p.y()+item->getTotalHeight();
156         }
157       }
158     }
159     if (isZeroBlocks) {
160       if (!isOtherBlocks) {
161         minimumBoxWidth = xMaxZero+2*marginConn;
162         minimumBoxHeight = yMaxZero+2*marginConn;
163       }
164       else {
165         if (xMaxZero+marginConn > xMax) {
166           minimumBoxWidth = xMaxZero+2*marginConn;
167         }
168         else {
169           minimumBoxWidth = xMax+marginConn;
170         }
171         if (yMaxZero+marginConn > yMax) {
172           minimumBoxHeight = yMaxZero+2*marginConn;
173         }
174         else {
175           minimumBoxHeight = yMax+marginConn;
176         }
177       }
178     }
179     else {
180       minimumBoxWidth = xMax+marginConn;
181       minimumBoxHeight = yMax+marginConn;
182     }
183   }
184   //cout << "min group size: " << minimumBoxWidth << "," << minimumBoxHeight << endl;
185 }
186
187 void GroupItem::updateShape() {
188   updateGeometry(InterfaceMove);
189 }
190
191 bool GroupItem::updateGeometry(ChangeType type) {
192
193   QPointF oldOrigin = originPoint;
194   QSize oldSize(totalWidth,totalHeight);
195
196   bool boxSizeChanged = false;
197
198   // whatever the change, the minimum size may have changed
199   updateMinimumSize();
200
201   if (type == Resize) {
202     boxSizeChanged = true;
203   }
204   // if an internal block has moved, the actual box size may be inadequate
205   if (boxWidth < minimumBoxWidth) {
206     boxWidth = minimumBoxWidth;
207     boxSizeChanged = true;
208   }
209   if (boxHeight < minimumBoxHeight) {
210     boxHeight = minimumBoxHeight;
211     boxSizeChanged = true;
212   }
213
214   if (boxSizeChanged) {
215     updateInterfacesAndConnections();
216   }
217
218
219   // compute the max. width of interfaces' name for 4 orientations.  
220   int maxSouth = 0;
221   int maxNorth = 0;
222   int maxEast = 0;
223   int maxWest = 0;
224   int ifaceWidth = 0;
225
226   foreach(InterfaceItem* iface, interfaces) {
227     ifaceWidth = iface->getNameWidth();
228     if (iface->getOrientation() == Parameters::South) {
229       if (ifaceWidth > maxSouth) maxSouth = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
230     }
231     else if (iface->getOrientation() == Parameters::North) {
232       if (ifaceWidth > maxNorth) maxNorth = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
233     }
234     else if (iface->getOrientation() == Parameters::East) {
235       if (ifaceWidth > maxEast) maxEast = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
236     }
237     else if (iface->getOrientation() == Parameters::West) {
238       if (ifaceWidth > maxWest) maxWest = ifaceWidth+ifaceMargin+params->arrowWidth+params->arrowLineLength;
239     }
240   }
241   double x = 0.0;
242   double y = 0.0;
243   totalWidth = boxWidth+maxEast;
244   totalHeight = boxHeight+maxSouth;
245
246   if (maxWest > 0) {
247     x -= maxWest;
248     totalWidth += maxWest;
249   }
250   if (maxNorth > (nameHeight+2*nameMargin)) {
251     y -= maxNorth;
252     totalHeight += maxNorth;
253   }
254   else {
255     y -= nameHeight+2*nameMargin;
256     totalHeight += nameHeight+2*nameMargin;
257   }
258   QSizeF newSize(totalWidth,totalHeight);
259   originPoint.setX(x);
260   originPoint.setY(y);
261
262   if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
263     //cout << "GroupItem: must change group item shape" << endl;
264     prepareGeometryChange();
265     return true;
266   }
267   return false;
268 }
269
270 void GroupItem::nameChanged() {
271
272   
273   QFontMetrics fmId(params->defaultBlockFont);
274   nameWidth = fmId.width(refBlock->getName());
275   nameHeight = fmId.height();
276   // changing the BoxItem in the upperscene
277   if (parentItem != NULL) {
278     parentItem->nameChanged();
279   }
280   updateGeometry(InterfaceMove);
281   // force the update in case of the size has not changed
282   update();  
283 }
284
285
286 void GroupItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
287
288   if(params->editState == Parameters::EditGroupMove) {    
289     int gapX = event->scenePos().x() - cursorPosition.x();
290     int gapY = event->scenePos().y() - cursorPosition.y();
291
292     bool canMove = true;
293     if (refBlock->isTopGroupBlock()) {
294       QRectF rectGroup = boundingRectInScene();
295       rectGroup.moveTo(rectGroup.x()+gapX,rectGroup.y()+gapY);
296       foreach(SourceItem* source, getScene()->getSourceItems()) {
297         QRectF rectSource = source->boundingRectInScene();
298         if (rectGroup.intersects(rectSource)) canMove = false;
299       }
300     }
301         
302     if (canMove) {
303       QPointF gap(gapX,gapY);
304       currentPosition = currentPosition+gap;
305       setPos(currentPosition);
306       
307       // updating all connections of the scene.
308       getScene()->updateConnectionItemsShape();
309     }
310     cursorPosition = event->scenePos();
311   }
312   else if(params->editState == Parameters::EditGroupResize) {
313
314     int gapX = event->scenePos().x() - cursorPosition.x();
315     int gapY = event->scenePos().y() - cursorPosition.y();
316     //cout << "gap: " << gapX << "," << gapY << endl;
317     switch(currentBorder){
318     case BorderEast: {
319       if(boxWidth+gapX > minimumBoxWidth){
320         boxWidth += gapX;
321       }
322       break;
323     }
324     case BorderSouth: {
325       if(boxHeight+gapY > minimumBoxHeight){
326         boxHeight += gapY;
327       }
328       break;
329     }
330     case CornerSouthEast: {
331       if(boxWidth+gapX > minimumBoxWidth){
332         boxWidth += gapX;
333       }
334       if(boxHeight+gapY > minimumBoxHeight){
335         boxHeight += gapY;
336       }
337       break;
338     }
339     case NoBorder:
340       cout << "abnormal case while resizing block" << endl;
341       break;
342     }
343     updateGeometry(Resize);
344     /*
345     // recompute the geometry of the block
346     updateGeometry();
347     // update all interfaces positions
348     foreach(InterfaceItem *item, interfaces){
349       item->updatePosition();
350     }
351     // update all connections from/to this block
352     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
353       if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
354         item->setPathes();
355       }
356     }
357     */
358     cursorPosition = event->scenePos();
359   }
360   else if(params->editState == Parameters::EditInterfaceMove) {
361     prepareGeometryChange();
362     moveInterfaceTo(event->pos());
363     // recompute the geometry of the block
364     updateGeometry(InterfaceMove);
365     // update connection from/to the selected interface
366     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
367       if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
368         item->setPath();
369       }
370     }
371     //update();
372   }
373 }
374
375 void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
376
377   QPointF pos = event->pos();
378   qreal x = pos.x();
379   qreal y = pos.y();
380
381   QGraphicsItem::mousePressEvent(event);
382
383   if(event->button() == Qt::RightButton) return;
384
385   int mode = getScene()->getEditionMode();
386
387   dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget());
388
389   if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
390     InterfaceItem *inter = getInterfaceFromCursor(x,y);
391     if (inter != NULL) {
392
393       if (params->editState == Parameters::EditNoOperation) {
394         getScene()->setSelectedInterface(1,inter);
395         params->setEditState(Parameters::EditStartConnection);
396       }
397       else if (params->editState == Parameters::EditStartConnection) {
398         if (inter == getScene()->getSelectedInterface(1)) {
399           params->setEditState(Parameters::EditAbortConnection);
400         }
401         else {
402           getScene()->setSelectedInterface(2,inter);
403           params->setEditState(Parameters::EditCloseConnection);
404         }
405       }
406     }
407   }  
408   else if (mode == GroupScene::ItemEdition) {
409
410     if (params->cursorState == Parameters::CursorOnInterface) {
411       InterfaceItem *inter = getInterfaceFromCursor(x,y);
412       if (inter != NULL) {
413         currentInterface = inter;
414         params->setEditState(Parameters::EditInterfaceMove);
415       }
416     }
417     else if (params->cursorState == Parameters::CursorInGroupTitle) {
418       params->setEditState(Parameters::EditGroupMove);
419       cursorPosition = event->scenePos();
420     }
421     else if (params->cursorState == Parameters::CursorOnBorder) {
422       setFlag(ItemIsMovable, false);
423       cursorPosition = event->scenePos();
424       params->setEditState(Parameters::EditGroupResize);
425     }
426   }
427 }
428
429 void GroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
430
431   int mode = getScene()->getEditionMode();
432
433   if (mode == GroupScene::AddConnection) {
434
435     if (params->editState == Parameters::EditStartConnection) {
436       params->setEditState(Parameters::EditStartConnection);
437       InterfaceItem* iface = getScene()->getSelectedInterface(1);
438       iface->selected = true;
439       update(iface->boundingRect());
440     }
441     else if (params->editState == Parameters::EditAbortConnection) {
442       InterfaceItem* iface = getScene()->getSelectedInterface(1);
443       iface->selected = false;
444       update(iface->boundingRect());
445       getScene()->setSelectedInterface(1,NULL);
446       params->setEditState(Parameters::EditNoOperation);
447     }
448     else if (params->editState == Parameters::EditCloseConnection) {
449       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
450       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);      
451       bool ok = dispatcher->createConnectionItem(iface1,iface2);     
452       if (ok) {
453         iface1->selected = false;
454         update(iface1->boundingRect());
455         iface2->selected = false;
456         update(iface2->boundingRect());        
457         getScene()->setSelectedInterface(1,NULL);
458         getScene()->setSelectedInterface(2,NULL);
459         params->setEditState(Parameters::EditNoOperation);
460       }
461       else {
462         //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok);
463         getScene()->setSelectedInterface(2,NULL);
464         params->setEditState(Parameters::EditStartConnection);
465       }
466     }
467   }  
468   else if (mode == GroupScene::ItemEdition) {
469     currentInterface = NULL;
470     setFlag(ItemIsMovable, true);
471     params->editState = Parameters::EditNoOperation;
472   }
473   QGraphicsItem::mouseReleaseEvent(event);
474 }
475
476 void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
477   QPointF pos = event->pos();
478   qreal x = pos.x();
479   qreal y = pos.y();
480   currentBorder = NoBorder;
481   int mode = getScene()->getEditionMode();
482
483   if (mode == GroupScene::AddConnection) {
484     InterfaceItem* iface = getInterfaceFromCursor(x,y);
485     if (iface != NULL) {
486       params->cursorState = Parameters::CursorOnInterface;
487       setCursor(Qt::PointingHandCursor);
488     }
489     else {
490       params->cursorState = Parameters::CursorNowhere;
491       setCursor(Qt::ArrowCursor);
492     }
493   }
494   else if (mode == GroupScene::ItemEdition) {
495     int marginE = 5;
496     int marginS = 5;
497
498     InterfaceItem* iface = getInterfaceFromCursor(x,y);
499     if (iface != NULL) {
500       params->cursorState = Parameters::CursorOnInterface;
501       setCursor(Qt::PointingHandCursor);
502     }
503     else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
504
505       params->cursorState = Parameters::CursorOnBorder;
506
507       if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
508         currentBorder = CornerSouthEast;
509         setCursor(Qt::SizeFDiagCursor);
510       }
511       else {
512         currentBorder = BorderEast;
513         setCursor(Qt::SizeHorCursor);
514       }
515     }
516     else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
517
518       params->cursorState = Parameters::CursorOnBorder;
519
520       if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
521         currentBorder = CornerSouthEast;
522         setCursor(Qt::SizeFDiagCursor);
523       }
524       else {
525         currentBorder = BorderSouth;
526         setCursor(Qt::SizeVerCursor);
527       }
528     }
529     else {
530       if (rectTitle.contains(x,y)) {
531         params->cursorState = Parameters::CursorInGroupTitle;
532         setCursor(Qt::OpenHandCursor);
533       }
534       else {
535         params->cursorState = Parameters::CursorNowhere;
536         setCursor(Qt::ArrowCursor);
537       }
538     }
539   }
540   //QGraphicsItem::hoverMoveEvent(event);
541   event->ignore();
542 }
543
544 void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
545   QMenu menu;
546   QAction* titleAction = NULL;
547   QAction* showProperties = NULL;
548   QAction* removeAction = NULL;
549   QAction* renameAction = NULL;
550   QAction* showParameters = NULL;
551
552   InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
553
554   // menu for interface
555   if( ifaceItem != NULL) {
556     titleAction = menu.addAction("Interface operations");
557     titleAction->setEnabled(false);
558     menu.addSeparator();
559     showProperties = menu.addAction("Show properties");
560     renameAction = menu.addAction("Rename");
561     menu.addSeparator();
562     /* CAUTION : the interface can be removed only if its
563       connected to only one side, i.e. connectedFrom is null
564       or connectedTo is empty.
565
566     */
567     ConnectedInterface* ref = ifaceItem->refInter;
568     if ((!ref->isConnectedFrom()) || (!ref->isConnectedTo())) {
569       removeAction = menu.addAction("Remove");
570     }
571   }
572   else {
573     titleAction = menu.addAction("Block operations");
574     titleAction->setEnabled(false);
575     menu.addSeparator();
576
577     if (refBlock->nbParameters() > 0) {
578       showParameters = menu.addAction("Show parameters");
579     }
580     renameAction = menu.addAction("Rename");
581   }
582   QAction* selectedAction = menu.exec(event->screenPos());
583
584   if(selectedAction == NULL) return;
585
586   if(selectedAction == renameAction){
587     if(ifaceItem != NULL)
588       dispatcher->renameInterface(ifaceItem);
589     else
590       dispatcher->renameGroupBlock(this);
591   }
592   else if(selectedAction == showProperties){
593     dispatcher->showProperties(ifaceItem);
594   }  
595   else if (selectedAction == removeAction) {
596     dispatcher->removeGroupInterface(ifaceItem);
597   }
598   else if(selectedAction == showParameters) {
599     new ParametersWindow(refBlock, params, NULL);
600   }   
601 }
602
603 InterfaceItem* GroupItem::isHoverInterface(QPointF point) {
604   foreach(InterfaceItem *inter, interfaces){
605     if(inter->boundingRect().contains(point))
606       return inter;
607   }
608   return NULL;
609 }
610
611 void GroupItem::load(QDomElement groupElement) throw(Exception) {
612
613   GroupBlock* groupBlock = AB_TO_GRP(refBlock);
614
615   bool ok = false;
616
617   int id = groupElement.attribute("id","none").toInt(&ok);
618   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
619
620   QString nameStr = groupElement.attribute("name","none");
621   if(nameStr == "none") throw(Exception(PROJECTFILE_CORRUPTED));
622
623   QStringList positionStr = groupElement.attribute("position","none").split(",");
624   if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
625   int posX = positionStr.at(0).toInt(&ok);
626   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
627   int posY = positionStr.at(1).toInt(&ok);
628   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
629
630   QStringList dimensionStr = groupElement.attribute("dimension","none").split(",");
631   if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
632   int dimX = dimensionStr.at(0).toInt(&ok);
633   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
634   int dimY = dimensionStr.at(1).toInt(&ok);
635   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
636
637   setId(id);
638   setPos(posX,posY);
639   setDimension(dimX,dimY);
640   groupBlock->setName(nameStr);
641
642   cout << "group info : \n-id : " << id << "\n-pos : " << posX << ", " << posY << "\n-dim : " << dimX << ", " << dimY << "\n-name : " << nameStr.toStdString() << endl;
643
644   QDomNodeList interfaces = groupElement.elementsByTagName("group_iface");
645   for(int j=0; j<interfaces.length(); j++){
646     QDomElement currentInterfaceNode = interfaces.at(j).toElement();
647
648     int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
649     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
650
651     QString name = currentInterfaceNode.attribute("name","none");
652     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
653
654     QString directionStr = currentInterfaceNode.attribute("direction","none");
655     int direction = AbstractInterface::getIntDirection(directionStr);
656     if(direction == -1) throw(Exception(PROJECTFILE_CORRUPTED));
657
658     QString orientationStr = currentInterfaceNode.attribute("orientation","none");
659     int orientation = InterfaceItem::getIntOrientation(orientationStr);
660     if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
661
662     double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
663     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
664
665     GroupInterface *groupInterface = new GroupInterface(groupBlock,name,direction,AbstractInterface::Data);
666
667     InterfaceItem *interfaceItem = new InterfaceItem(position,orientation,groupInterface,this,params);
668     interfaceItem->setId(id);
669
670     groupBlock->addInterface(groupInterface);
671     addInterface(interfaceItem, false);
672     cout << "interface add to " << groupBlock->getName().toStdString() << endl;
673   }
674
675 }
676
677 void GroupItem::save(QXmlStreamWriter &writer) {
678
679   writer.writeStartElement("group_item");
680
681   QString attrId = QString::number(id);
682   QString attrName(getRefBlock()->getName());
683   QString attrUpperItem = QString::number(-1);
684   if(parentItem != NULL){
685     attrUpperItem = QString::number(parentItem->getId());
686   }
687   QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
688   QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
689
690
691   writer.writeAttribute("id",attrId);
692   writer.writeAttribute("upper_item",attrUpperItem);
693   writer.writeAttribute("name",attrName);
694   writer.writeAttribute("position", attrPos);
695   writer.writeAttribute("dimension", attrDim);
696
697   writer.writeStartElement("group_ifaces");
698
699   writer.writeAttribute("count",QString::number(interfaces.length()));
700
701   foreach(InterfaceItem *item, interfaces){
702     writer.writeStartElement("group_iface");
703
704     writer.writeAttribute("id",QString::number(item->getId()));
705     writer.writeAttribute("name",item->getName());    
706     writer.writeAttribute("direction",QString(item->refInter->getDirectionString()));
707     writer.writeAttribute("orientation",item->getStrOrientation());
708     writer.writeAttribute("position",QString::number(item->getPositionRatio()));
709
710     writer.writeEndElement();
711   }
712
713   writer.writeEndElement();//</interfaces>
714
715   writer.writeEndElement();//</group_item>
716 }