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

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