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

Private GIT Repository
adding xsd files to master
[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()->getBlockItems();
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 << "must change group item shape" << endl;
263     prepareGeometryChange();
264     return true;
265   }
266   return false;
267 }
268
269 void GroupItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
270
271   if(params->editState == Parameters::EditGroupMove) {
272     QPointF absPos = currentPosition + originPoint;    
273     int gapX = event->scenePos().x() - cursorPosition.x();
274     int gapY = event->scenePos().y() - cursorPosition.y();
275
276     //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
277     //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
278 /*
279     if (absPos.x()+gapX < 0) {
280       gapX = -absPos.x();
281     }
282     if (absPos.y()+gapY < 0) {
283       gapY = -absPos.y();
284     }
285     */
286     //cout << "gap: " << gapX << "," << gapY << " | ";
287     //cout << "scene: " << getScene()->sceneRect().x() << "," << getScene()->sceneRect().y() << endl;
288     QPointF gap(gapX,gapY);
289     currentPosition = currentPosition+gap;
290     setPos(currentPosition);
291     cursorPosition = event->scenePos();
292   }
293   else if(params->editState == Parameters::EditGroupResize) {
294
295     int gapX = event->scenePos().x() - cursorPosition.x();
296     int gapY = event->scenePos().y() - cursorPosition.y();
297     //cout << "gap: " << gapX << "," << gapY << endl;
298     switch(currentBorder){
299     case BorderEast: {
300       if(boxWidth+gapX > minimumBoxWidth){
301         boxWidth += gapX;
302       }
303       break;
304     }
305     case BorderSouth: {
306       if(boxHeight+gapY > minimumBoxHeight){
307         boxHeight += gapY;
308       }
309       break;
310     }
311     case CornerSouthEast: {
312       if(boxWidth+gapX > minimumBoxWidth){
313         boxWidth += gapX;
314       }
315       if(boxHeight+gapY > minimumBoxHeight){
316         boxHeight += gapY;
317       }
318       break;
319     }
320     case NoBorder:
321       cout << "abnormal case while resizing block" << endl;
322       break;
323     }
324     updateGeometry(Resize);
325     /*
326     // recompute the geometry of the block
327     updateGeometry();
328     // update all interfaces positions
329     foreach(InterfaceItem *item, interfaces){
330       item->updatePosition();
331     }
332     // update all connections from/to this block
333     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
334       if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
335         item->setPathes();
336       }
337     }
338     */
339     cursorPosition = event->scenePos();
340   }
341   else if(params->editState == Parameters::EditInterfaceMove) {
342     prepareGeometryChange();
343     moveInterfaceTo(event->pos());
344     // recompute the geometry of the block
345     updateGeometry(InterfaceMove);
346     // update connection from/to the selected interface
347     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
348       if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
349         item->setPath();
350       }
351     }
352     //update();
353   }
354 }
355
356 void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
357
358   QPointF pos = event->pos();
359   qreal x = pos.x();
360   qreal y = pos.y();
361
362   QGraphicsItem::mousePressEvent(event);
363
364   if(event->button() == Qt::RightButton) return;
365
366   int mode = getScene()->getEditionMode();
367
368   dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget());
369
370   /* NOTE : commneted because group interface are normally
371      created and the connected directly to a block within
372      the group. Furthermore, there can be a single connection
373      from a groupe interface.
374
375   if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
376     InterfaceItem *inter = getInterfaceFromCursor(x,y);
377     if (inter != NULL) {
378
379       if (params->editState == Parameters::EditNoOperation) {
380         getScene()->setSelectedInterface(1,inter);
381         params->setEditState(Parameters::EditStartConnection);
382       }
383       else if (params->editState == Parameters::EditStartConnection) {
384         if (inter == getScene()->getSelectedInterface(1)) {
385           params->setEditState(Parameters::EditAbortConnection);
386         }
387         else {
388           getScene()->setSelectedInterface(2,inter);
389           params->setEditState(Parameters::EditCloseConnection);
390         }
391       }
392     }
393   }
394   */
395   if (mode == GroupScene::ItemEdition) {
396
397     if (params->cursorState == Parameters::CursorOnInterface) {
398       InterfaceItem *inter = getInterfaceFromCursor(x,y);
399       if (inter != NULL) {
400         currentInterface = inter;
401         params->setEditState(Parameters::EditInterfaceMove);
402       }
403     }
404     else if (params->cursorState == Parameters::CursorInGroupTitle) {
405       params->setEditState(Parameters::EditGroupMove);
406       cursorPosition = event->scenePos();
407     }
408     else if (params->cursorState == Parameters::CursorOnBorder) {
409       setFlag(ItemIsMovable, false);
410       cursorPosition = event->scenePos();
411       params->setEditState(Parameters::EditGroupResize);
412     }
413   }
414 }
415
416 void GroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
417
418   int mode = getScene()->getEditionMode();
419
420   /* NOTE : commneted because group interface are normally
421      created and the connected directly to a block within
422      the group. Furthermore, there can be a single connection
423      from a groupe interface.
424
425   if (mode == GroupScene::AddConnection) {
426
427     if (params->editState == Parameters::EditStartConnection) {
428       params->setEditState(Parameters::EditStartConnection);
429       InterfaceItem* iface = getScene()->getSelectedInterface(1);
430       iface->selected = true;
431       update(iface->boundingRect());
432     }
433     else if (params->editState == Parameters::EditAbortConnection) {
434       InterfaceItem* iface = getScene()->getSelectedInterface(1);
435       iface->selected = false;
436       update(iface->boundingRect());
437       getScene()->setSelectedInterface(1,NULL);
438       params->setEditState(Parameters::EditNoOperation);
439     }
440     else if (params->editState == Parameters::EditCloseConnection) {
441       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
442       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
443       bool ok = dispatcher->connect(iface1,iface2);
444       if (ok) {
445         iface1->selected = false;
446         update(iface1->boundingRect());
447         getScene()->setSelectedInterface(1,NULL);
448         getScene()->setSelectedInterface(2,NULL);
449         params->setEditState(Parameters::EditNoOperation);
450       }
451     }
452   }
453   */
454   if (mode == GroupScene::ItemEdition) {
455     currentInterface = NULL;
456     setFlag(ItemIsMovable, true);
457     params->editState = Parameters::EditNoOperation;
458   }
459   QGraphicsItem::mouseReleaseEvent(event);
460 }
461
462 void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
463   QPointF pos = event->pos();
464   qreal x = pos.x();
465   qreal y = pos.y();
466   currentBorder = NoBorder;
467   int mode = getScene()->getEditionMode();
468
469   if (mode == GroupScene::AddConnection) {
470     InterfaceItem* iface = getInterfaceFromCursor(x,y);
471     if (iface != NULL) {
472       params->cursorState = Parameters::CursorOnInterface;
473       setCursor(Qt::PointingHandCursor);
474     }
475     else {
476       params->cursorState = Parameters::CursorNowhere;
477       setCursor(Qt::ArrowCursor);
478     }
479   }
480   else if (mode == GroupScene::ItemEdition) {
481     int marginE = 5;
482     int marginS = 5;
483
484     InterfaceItem* iface = getInterfaceFromCursor(x,y);
485     if (iface != NULL) {
486       params->cursorState = Parameters::CursorOnInterface;
487       setCursor(Qt::PointingHandCursor);
488     }
489     else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
490
491       params->cursorState = Parameters::CursorOnBorder;
492
493       if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
494         currentBorder = CornerSouthEast;
495         setCursor(Qt::SizeFDiagCursor);
496       }
497       else {
498         currentBorder = BorderEast;
499         setCursor(Qt::SizeHorCursor);
500       }
501     }
502     else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
503
504       params->cursorState = Parameters::CursorOnBorder;
505
506       if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
507         currentBorder = CornerSouthEast;
508         setCursor(Qt::SizeFDiagCursor);
509       }
510       else {
511         currentBorder = BorderSouth;
512         setCursor(Qt::SizeVerCursor);
513       }
514     }
515     else {
516       if (rectTitle.contains(x,y)) {
517         params->cursorState = Parameters::CursorInGroupTitle;
518         setCursor(Qt::OpenHandCursor);
519       }
520       else {
521         params->cursorState = Parameters::CursorNowhere;
522         setCursor(Qt::ArrowCursor);
523       }
524     }
525   }
526   QGraphicsItem::hoverMoveEvent(event);
527 }
528
529 void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
530   QMenu menu;
531   QAction* titleAction = NULL;
532   QAction* showProperties = NULL;
533   QAction* removeAction = NULL;
534   QAction* renameAction = NULL;
535   QAction* showParameters = NULL;
536
537   InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
538
539   // menu for interface
540   if( ifaceItem != NULL) {
541     titleAction = menu.addAction("Interface operations");
542     titleAction->setEnabled(false);
543     menu.addSeparator();
544     showProperties = menu.addAction("Show properties");
545     renameAction = menu.addAction("Rename");
546     menu.addSeparator();
547     /* CAUTION : the interface can be removed only if its
548       connected to only one side, i.e. connectedFrom is null
549       or connectedTo is empty.
550
551     */
552     ConnectedInterface* ref = ifaceItem->refInter;
553     if ((!ref->isConnectedFrom()) || (!ref->isConnectedTo())) {
554       removeAction = menu.addAction("Remove");
555     }
556   }
557   else {
558     titleAction = menu.addAction("Block operations");
559     titleAction->setEnabled(false);
560     menu.addSeparator();
561
562     if (refBlock->nbParameters() > 0) {
563       showParameters = menu.addAction("Show parameters");
564     }
565     renameAction = menu.addAction("Rename");
566   }
567   QAction* selectedAction = menu.exec(event->screenPos());
568
569   if(selectedAction == NULL) return;
570
571   if(selectedAction == renameAction){
572     if(ifaceItem != NULL)
573       dispatcher->renameInterface(ifaceItem);
574     else
575       dispatcher->renameBlockOrGroup(this);
576   }
577   else if(selectedAction == showProperties){
578     dispatcher->showProperties(ifaceItem);
579   }  
580   else if (selectedAction == removeAction) {
581     dispatcher->removeGroupInterface(ifaceItem);
582   }
583   else if(selectedAction == showParameters) {
584     new ParametersWindow(refBlock, params, NULL);
585   }
586 }
587
588 InterfaceItem* GroupItem::isHoverInterface(QPointF point) {
589   foreach(InterfaceItem *inter, interfaces){
590     if(inter->boundingRect().contains(point))
591       return inter;
592   }
593   return NULL;
594 }
595
596 void GroupItem::load(QDomElement groupElement) throw(Exception) {
597
598   GroupBlock* groupBlock = AB_TO_GRP(refBlock);
599
600   bool ok = false;
601
602   int id = groupElement.attribute("id","none").toInt(&ok);
603   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
604
605   QString nameStr = groupElement.attribute("name","none");
606   if(nameStr == "none") throw(Exception(PROJECTFILE_CORRUPTED));
607
608   QStringList positionStr = groupElement.attribute("position","none").split(",");
609   if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
610   int posX = positionStr.at(0).toInt(&ok);
611   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
612   int posY = positionStr.at(1).toInt(&ok);
613   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
614
615   QStringList dimensionStr = groupElement.attribute("dimension","none").split(",");
616   if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
617   int dimX = dimensionStr.at(0).toInt(&ok);
618   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
619   int dimY = dimensionStr.at(1).toInt(&ok);
620   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
621
622   setId(id);
623   setPos(posX,posY);
624   setDimension(dimX,dimY);
625   groupBlock->setName(nameStr);
626
627   cout << "group info : \n-id : " << id << "\n-pos : " << posX << ", " << posY << "\n-dim : " << dimX << ", " << dimY << "\n-name : " << nameStr.toStdString() << endl;
628
629   QDomNodeList interfaces = groupElement.elementsByTagName("group_iface");
630   for(int j=0; j<interfaces.length(); j++){
631     QDomElement currentInterfaceNode = interfaces.at(j).toElement();
632
633     int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
634     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
635
636     QString name = currentInterfaceNode.attribute("name","none");
637     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
638
639     QString directionStr = currentInterfaceNode.attribute("direction","none");
640     int direction = AbstractInterface::getIntDirection(directionStr);
641     if(direction == -1) throw(Exception(PROJECTFILE_CORRUPTED));
642
643     QString orientationStr = currentInterfaceNode.attribute("orientation","none");
644     int orientation = InterfaceItem::getIntOrientation(orientationStr);
645     if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
646
647     double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
648     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
649
650     GroupInterface *groupInterface = new GroupInterface(groupBlock,name,direction);
651
652     InterfaceItem *interfaceItem = new InterfaceItem(position,orientation,groupInterface,this,params);
653     interfaceItem->setId(id);
654
655     groupBlock->addInterface(groupInterface);
656     addInterface(interfaceItem, false);
657     cout << "interface add to " << groupBlock->getName().toStdString() << endl;
658   }
659
660 }
661
662 void GroupItem::save(QXmlStreamWriter &writer) {
663
664   writer.writeStartElement("group_item");
665
666   QString attrId = QString::number(id);
667   QString attrName(getRefBlock()->getName());
668   QString attrUpperItem = QString::number(-1);
669   if(parentItem != NULL){
670     attrUpperItem = QString::number(parentItem->getId());
671   }
672   QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
673   QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
674
675
676   writer.writeAttribute("id",attrId);
677   writer.writeAttribute("upper_item",attrUpperItem);
678   writer.writeAttribute("name",attrName);
679   writer.writeAttribute("position", attrPos);
680   writer.writeAttribute("dimension", attrDim);
681
682   writer.writeStartElement("group_ifaces");
683
684   writer.writeAttribute("count",QString::number(interfaces.length()));
685
686   foreach(InterfaceItem *item, interfaces){
687     writer.writeStartElement("group_iface");
688
689     writer.writeAttribute("id",QString::number(item->getId()));
690     writer.writeAttribute("name",item->getName());    
691     writer.writeAttribute("direction",QString(item->refInter->getDirectionString()));
692     writer.writeAttribute("orientation",item->getStrOrientation());
693     writer.writeAttribute("position",QString::number(item->getPositionRatio()));
694
695     writer.writeEndElement();
696   }
697
698   writer.writeEndElement();//</interfaces>
699
700   writer.writeEndElement();//</group_item>
701 }