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

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