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

Private GIT Repository
de22f19ce472c4ca8c651e23fe233f5fcb9a13c9
[blast.git] / BoxItem.cpp
1 #include "BoxItem.h"
2 #include "GroupScene.h"
3 #include "ConnectionItem.h"
4 #include "InterfaceItem.h"
5 #include "GroupItem.h"
6 #include "Parameters.h"
7 #include "Exception.h"
8 #include "Dispatcher.h"
9 #include "FunctionalBlock.h"
10 #include "FunctionalInterface.h"
11 #include "ReferenceInterface.h"
12 #include "ReferenceBlock.h"
13 #include "ParametersWindow.h"
14 #include "BlockParameter.h"
15 #include "Graph.h"
16
17
18 BoxItem::BoxItem(AbstractBlock *_refBlock,
19                      Dispatcher *_dispatcher,
20                      Parameters *_params, GroupItem *parent) throw(Exception) : AbstractBoxItem( _refBlock, _dispatcher, _params, parent) {
21
22   /*  NOTE :
23      _refBlock : mandatory a FunctionalBlock or a GroupBlock
24   */
25   if (_refBlock->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
26
27   childGroupItem = NULL;
28   //boxWidth = params->defaultBlockWidth;
29   //boxHeight = params->defaultBlockHeight;
30   currentBorder = NoBorder;
31   selected = false;
32
33   setZValue(100);
34   setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
35
36   initInterfaces();
37   updateGeometry(InterfaceMove);
38   resetInterfacesPosition();
39   QPointF initPos = QPointF(0.0,0.0) - originPoint;
40   setPos(initPos);
41   //cout << "total size of block: " << totalWidth << "," << totalHeight << endl;
42   //cout << "pos in group: " << x() << "," << y() << endl;
43 }
44
45 BoxItem::BoxItem(Dispatcher *_dispatcher, Parameters *_params, GroupItem *parent) throw(Exception) : AbstractBoxItem(_dispatcher, _params, parent) {
46
47   refBlock = NULL;
48   childGroupItem = NULL;
49   currentBorder = NoBorder;
50   selected = false;
51
52   setZValue(100);
53   setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
54
55   boxWidth = params->defaultBlockWidth;
56   boxHeight = params->defaultBlockHeight;
57   //initInterfaces();
58   //updateGeometry(InterfaceMove);
59   //resetInterfacesPosition();
60   //QPointF initPos = QPointF(0.0,0.0) - originPoint;
61   //setPos(initPos);
62   //cout << "total size of block: " << totalWidth << "," << totalHeight << endl;
63   //cout << "pos in group: " << x() << "," << y() << endl;
64 }
65
66 BoxItem::~BoxItem() {
67 }
68
69 void BoxItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
70   QPen pen(Qt::black, 3);
71   if(selected)
72     pen.setColor(Qt::red);
73
74   painter->setPen(pen);
75   painter->setBrush(Qt::yellow);
76
77   painter->drawRect(0,0,boxWidth, boxHeight);
78   painter->drawText(0,0,boxWidth, boxHeight,Qt::AlignCenter | Qt::TextWordWrap,QString(refBlock->getName()));
79   foreach(InterfaceItem *inter, interfaces) {
80     inter->paint(painter);
81   }
82 }
83
84 void BoxItem::moveTo(QPointF dest) {
85   setPos(dest);
86   currentPosition = dest;
87 }
88
89 bool BoxItem::isBoxItem() {
90   return true;
91 }
92
93 void BoxItem::updateMinimumSize() {
94
95   int maxSouth = 0;
96   int maxNorth = 0;
97   int maxEast = 0;
98   int maxWest = 0;
99   int nbSouth = nbInterfacesByOrientation(Parameters::South);
100   int nbNorth = nbInterfacesByOrientation(Parameters::North);
101   int nbMaxSN = nbNorth;
102   if (nbSouth > nbNorth) nbMaxSN = nbSouth;
103   int nbEast = nbInterfacesByOrientation(Parameters::East);
104   int nbWest = nbInterfacesByOrientation(Parameters::West);
105   int nbMaxEW = nbEast;
106   if (nbWest > nbEast) {
107     nbMaxEW = nbWest;
108   }
109
110   int ifaceWidth = 0;
111   int ifaceHeight = 0;
112
113   foreach(InterfaceItem* iface, interfaces) {
114     ifaceWidth = iface->getNameWidth();
115     ifaceHeight = iface->getNameHeight();
116     if (iface->getOrientation() == Parameters::South) {
117       if (ifaceWidth > maxSouth) maxSouth = ifaceWidth;
118     }
119     else if (iface->getOrientation() == Parameters::North) {
120       if (ifaceWidth > maxNorth) maxNorth = ifaceWidth;
121     }
122     else if (iface->getOrientation() == Parameters::East) {
123       if (ifaceWidth > maxEast) maxEast = ifaceWidth;
124     }
125     else if (iface->getOrientation() == Parameters::West) {
126       if (ifaceWidth > maxWest) maxWest = ifaceWidth;
127     }
128   }
129
130   /* NB: the width layout is the following
131      ifaceMargin | maxWest | nameMargin | name | nameMargin | maxEast | ifaceMargin
132    */
133   minimumBoxWidth = maxWest+maxEast+nameWidth+2*(ifaceMargin+nameMargin);
134   // if the minimum is not sufficent taking into account N/S interfaces
135   if (minimumBoxWidth < (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1))) {
136     minimumBoxWidth = (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1));
137   }
138   minimumBoxHeight = maxNorth+maxSouth+3*ifaceMargin;
139   if (minimumBoxHeight < (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1))) {
140     minimumBoxHeight = (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1));
141   }
142 }
143
144
145 /* updateGeometry() :
146
147  */
148 bool BoxItem::updateGeometry(ChangeType type) {
149
150   currentPosition = pos();
151   //cout << "current pos of block: " << currentPosition.x() << "," << currentPosition.y() << endl;
152   QPointF oldOrigin = originPoint;
153   QSize oldSize(totalWidth,totalHeight);
154
155   bool boxSizeChanged = false;
156
157   // whatever the change, the minimum size may have changed
158   updateMinimumSize();
159
160   if (type == Resize) {
161     // resize implies to move interfaces and to update connections
162     boxSizeChanged = true;
163   }
164   else if (type == InterfaceMove) {
165     // if an interface moves, it may change the box size
166     if (boxWidth < minimumBoxWidth) {
167       boxWidth = minimumBoxWidth;
168       boxSizeChanged = true;
169     }
170     if (boxHeight < minimumBoxHeight) {
171       boxHeight = minimumBoxHeight;
172       boxSizeChanged = true;
173     }
174   }
175   if (boxSizeChanged) {
176     updateInterfacesAndConnections();
177   }
178
179
180   double x = 0.0;
181   double y = 0.0;
182   totalWidth = boxWidth;
183   totalHeight = boxHeight;
184
185   if(isInterfaces(Parameters::East)){
186     totalWidth += params->arrowWidth+params->arrowLineLength;
187   }
188   if(isInterfaces(Parameters::West)){
189     totalWidth += params->arrowWidth+params->arrowLineLength;
190     x -= params->arrowWidth+params->arrowLineLength;
191   }
192   if(isInterfaces(Parameters::South)){
193     totalHeight += params->arrowWidth+params->arrowLineLength;
194   }
195   if(isInterfaces(Parameters::North)){
196     totalHeight += params->arrowWidth+params->arrowLineLength;
197     y -= params->arrowWidth+params->arrowLineLength;
198   }
199   QSizeF newSize(totalWidth,totalHeight);
200   originPoint.setX(x);
201   originPoint.setY(y);
202
203   if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
204     prepareGeometryChange();
205     return true;
206   }
207   return false;
208 }
209
210 void BoxItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
211
212   if(params->editState == Parameters::EditBlockMove) {
213     QPointF absPos = currentPosition + originPoint;
214     int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
215     int gapX = event->scenePos().x() - cursorPosition.x();
216     int gapY = event->scenePos().y() - cursorPosition.y();
217
218     //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
219     //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
220
221     if (absPos.x()+gapX < marginConn) {
222       gapX = marginConn-absPos.x();
223     }
224     if (absPos.y()+gapY < marginConn) {
225       gapY = marginConn-absPos.y();
226     }
227     //cout << "gap: " << gapX << "," << gapY << endl;
228     QPointF gap(gapX,gapY);
229     currentPosition = currentPosition+gap;
230     setPos(currentPosition);
231     // update all connections from/to this block
232     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
233       if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
234         item->setPath();
235       }
236     }
237     cursorPosition = event->scenePos();
238
239     // udpate the groupitem
240     (getScene()->getGroupItem())->updateShape();
241   }
242   else if(params->editState == Parameters::EditBlockResize) {
243
244     int gapX = event->scenePos().x() - cursorPosition.x();
245     int gapY = event->scenePos().y() - cursorPosition.y();
246     //cout << "gap: " << gapX << "," << gapY << endl;
247     switch(currentBorder){
248     case BorderEast: {    
249       if(boxWidth+gapX > minimumBoxWidth){
250         boxWidth += gapX;
251       }
252       break;
253     }
254     case BorderSouth: {      
255       if(boxHeight+gapY > minimumBoxHeight){
256         boxHeight += gapY;
257       }
258       break;
259     }
260     case CornerSouthEast: {
261       if(boxWidth+gapX > minimumBoxWidth){
262         boxWidth += gapX;
263       }
264       if(boxHeight+gapY > minimumBoxHeight){
265         boxHeight += gapY;
266       }
267       break;
268     }
269     case NoBorder:
270       cout << "abnormal case while resizing block" << endl;
271       break;
272     }
273     // recompute the geometry of the block and possibly the group item
274     if (updateGeometry(Resize)) {
275       (getScene()->getGroupItem())->updateShape();
276     }
277
278     cursorPosition = event->scenePos();   
279   }
280   else if(params->editState == Parameters::EditInterfaceMove) {
281     prepareGeometryChange();
282     moveInterfaceTo(event->pos());
283     // recompute the geometry of the block
284     if (updateGeometry(InterfaceMove)) {
285       cout << "must recompute group item geometry" << endl;
286       (getScene()->getGroupItem())->updateShape();
287     }
288     // update connection from/to the selected interface
289     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
290       if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
291         item->setPath();
292       }
293     }    
294   }
295 }
296
297 void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
298
299   QPointF pos = event->pos();
300   qreal x = pos.x();
301   qreal y = pos.y();
302
303   //QGraphicsItem::mousePressEvent(event);
304
305   if(event->button() == Qt::RightButton) return;
306
307   int mode = getScene()->getEditionMode();
308
309   dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget());
310
311   if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
312     InterfaceItem *inter = getInterfaceFromCursor(x,y);
313     if (inter != NULL) {
314
315       if (params->editState == Parameters::EditNoOperation) {
316         getScene()->setSelectedInterface(1,inter);
317         params->setEditState(Parameters::EditStartConnection);
318       }
319       else if (params->editState == Parameters::EditStartConnection) {
320         if (inter == getScene()->getSelectedInterface(1)) {
321           params->setEditState(Parameters::EditAbortConnection);
322         }
323         else {
324           getScene()->setSelectedInterface(2,inter);
325           params->setEditState(Parameters::EditCloseConnection);
326         }
327       }
328     }
329   }
330   else if (mode == GroupScene::ItemEdition) {
331     setZValue(zValue()+100);
332     if (params->cursorState == Parameters::CursorOnInterface) {
333       InterfaceItem *inter = getInterfaceFromCursor(x,y);
334       if (inter != NULL) {
335         if (inter == currentInterface) {
336            params->setEditState(Parameters::EditInterfaceDeselect);
337         }
338         else {
339           setFlag(ItemIsMovable, false);
340           currentInterface = inter;
341           params->setEditState(Parameters::EditInterfaceMove);
342         }
343       }
344     }
345     else if (params->cursorState == Parameters::CursorInBlock) {
346       selected = !selected;
347       params->setEditState(Parameters::EditBlockMove);
348       cursorPosition = event->scenePos();
349       //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
350       update();
351     }
352     else if (params->cursorState == Parameters::CursorOnBorder) {
353       setFlag(ItemIsMovable, false);
354       cursorPosition = event->scenePos();
355       params->setEditState(Parameters::EditBlockResize);
356     }
357   }
358 }
359
360 void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
361
362   setZValue(zValue()-100);
363
364   int mode = getScene()->getEditionMode();
365
366   if (mode == GroupScene::AddConnection) {
367
368     if (params->editState == Parameters::EditStartConnection) {
369       InterfaceItem* iface = getScene()->getSelectedInterface(1);
370       iface->selected = true;
371       update(iface->boundingRect());
372     }
373     else if (params->editState == Parameters::EditAbortConnection) {
374       InterfaceItem* iface = getScene()->getSelectedInterface(1);
375       iface->selected = false;
376       update(iface->boundingRect());
377       getScene()->setSelectedInterface(1,NULL);
378       params->setEditState(Parameters::EditNoOperation);
379     }
380     else if (params->editState == Parameters::EditCloseConnection) {
381       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
382       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
383       bool ok = dispatcher->connect(iface1,iface2);
384       if (ok) {
385         iface1->selected = false;
386         // no update needed since the whole scene will be repainted
387         getScene()->setSelectedInterface(1,NULL);
388         getScene()->setSelectedInterface(2,NULL);
389         params->setEditState(Parameters::EditNoOperation);
390       }
391       else {
392         //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok);
393         getScene()->setSelectedInterface(2,NULL);
394         params->setEditState(Parameters::EditStartConnection);
395       }
396     }
397   }
398   else if (mode == GroupScene::ItemEdition) {
399     currentInterface = NULL;
400     params->editState = Parameters::EditNoOperation;
401     setFlag(ItemIsMovable);
402   }
403
404   QGraphicsItem::mouseReleaseEvent(event);
405 }
406
407 void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
408
409   QPointF pos = event->pos();
410   qreal x = pos.x();
411   qreal y = pos.y();
412   currentBorder = NoBorder;
413   int mode = getScene()->getEditionMode();
414
415   if (mode == GroupScene::AddConnection) {
416     InterfaceItem* iface = getInterfaceFromCursor(x,y);
417     if (iface != NULL) {
418       params->cursorState = Parameters::CursorOnInterface;
419       setCursor(Qt::PointingHandCursor);
420     }
421     else {
422       params->cursorState = Parameters::CursorNowhere;
423       setCursor(Qt::ArrowCursor);
424     }
425   }
426   else if (mode == GroupScene::ItemEdition) {
427     int marginE = 5;
428     int marginS = 5;
429
430     InterfaceItem* iface = getInterfaceFromCursor(x,y);
431     if (iface != NULL) {
432       params->cursorState = Parameters::CursorOnInterface;
433       setCursor(Qt::PointingHandCursor);
434     }
435     else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
436
437       params->cursorState = Parameters::CursorOnBorder;
438
439       if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
440         currentBorder = CornerSouthEast;
441         setCursor(Qt::SizeFDiagCursor);
442       }
443       else {
444         currentBorder = BorderEast;
445         setCursor(Qt::SizeHorCursor);
446       }
447     }
448     else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
449
450       params->cursorState = Parameters::CursorOnBorder;
451
452       if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
453         currentBorder = CornerSouthEast;
454         setCursor(Qt::SizeFDiagCursor);
455       }
456       else {
457         currentBorder = BorderSouth;
458         setCursor(Qt::SizeVerCursor);
459       }
460     }
461     else {
462       if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
463         params->cursorState = Parameters::CursorInBlock;
464         setCursor(Qt::OpenHandCursor);
465       }
466       else {
467         params->cursorState = Parameters::CursorNowhere;
468         setCursor(Qt::ArrowCursor);
469       }
470     }
471   }
472   QGraphicsItem::hoverMoveEvent(event);
473 }
474
475
476 void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
477
478   QMenu menu;
479   QAction* titleAction = NULL;
480   QAction* removeAction = NULL;
481   QAction* duplicateAction = NULL;
482   QAction* renameAction = NULL;
483   QAction* connectToGroup = NULL;
484   QAction* disconnectFromGroup = NULL;
485   QAction* showProperties = NULL;
486   QAction* cloneInterface = NULL;
487   QAction* openWindow = NULL;
488   QAction* showRstClkIface = NULL;
489   QAction* showWishboneIface = NULL;
490   QAction* showParameters = NULL;
491
492   InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
493   // menu for interface
494   if( ifaceItem != NULL){
495
496     titleAction = menu.addAction("Interface operations");
497     titleAction->setEnabled(false);
498     menu.addSeparator();
499
500
501     showProperties = menu.addAction("Show properties");
502     renameAction = menu.addAction("Rename");
503
504     ConnectedInterface* iface = ifaceItem->refInter;
505     ConnectedInterface* ifaceGroup = NULL;
506     bool canRemove = true;
507
508
509     if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) {
510         connectToGroup = menu.addAction("Connect to group input");
511     }
512     else if ((iface->getDirection() == AbstractInterface::Output) && (iface->getConnectionToParentGroup() == NULL)) {
513       connectToGroup = menu.addAction("Connect to group output");
514     }
515     else if (iface->getConnectionFromParentGroup() != NULL) {
516       ifaceGroup = iface->getConnectionFromParentGroup();
517       //if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) {
518       if (!ifaceGroup->isConnectedFrom()) {
519         disconnectFromGroup = menu.addAction("Disconnect from group");
520       }
521       else {
522         canRemove = false;
523       }
524     }
525     else if (iface->getConnectionToParentGroup() != NULL) {
526       ifaceGroup = iface->getConnectionToParentGroup();
527       //if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) {
528       if (!ifaceGroup->isConnectedTo()) {
529         disconnectFromGroup = menu.addAction("Disconnect from group");
530       }
531       else {
532         canRemove = false;
533       }
534     }
535
536     if (iface->isFunctionalInterface()) {
537       FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter);
538       ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference());
539       if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){
540         cloneInterface = menu.addAction("Duplicate");
541         if ((canRemove) && (fi->getInterfaceMultiplicity() > 1)) {
542           removeAction = menu.addAction("Remove");
543         }
544       }      
545     }
546   }
547   // menu for blocks (group or func)
548   else {
549     titleAction = menu.addAction("Block operations");
550     titleAction->setEnabled(false);
551     menu.addSeparator();
552
553     if (refBlock->nbParameters() > 0) {
554       showParameters = menu.addAction("Show parameters");
555     }
556     renameAction = menu.addAction("Rename");
557
558     if(refBlock->isGroupBlock()){
559       openWindow = menu.addAction("Open/show group window");
560     }
561     else {
562       duplicateAction = menu.addAction("Duplicate");
563       showRstClkIface = menu.addAction("Show reset/clock interfaces");
564       showRstClkIface->setCheckable(true);
565       showRstClkIface->setChecked(rstClkVisible);
566       showWishboneIface = menu.addAction("Show wishbone interfaces");
567       showWishboneIface->setCheckable(true);
568       showWishboneIface->setChecked(wishboneVisible);
569     }
570     removeAction = menu.addAction("Remove");
571   }
572
573   QAction* selectedAction = NULL;
574   selectedAction = menu.exec(event->screenPos());
575
576   if(selectedAction == NULL) return ;
577
578   if (selectedAction == removeAction) {
579     if(ifaceItem != NULL) {
580      dispatcher->removeBlockInterface(ifaceItem);
581     }
582     else {
583       dispatcher->removeBlock(this);
584     }
585   }
586   else if (selectedAction == duplicateAction) {
587     dispatcher->duplicateBlock(this);
588   }
589   else if(selectedAction == renameAction){
590     if(ifaceItem != NULL)
591       dispatcher->renameInterface(ifaceItem);
592     else
593       dispatcher->renameBlockOrGroup(this);
594   }
595   else if(selectedAction == showProperties){
596     dispatcher->showProperties(ifaceItem);
597   }
598   else if (selectedAction == connectToGroup){
599     dispatcher->connectInterToGroup(ifaceItem);
600   }
601   else if (selectedAction == disconnectFromGroup) {
602     dispatcher->disconnectInterFromGroup(ifaceItem);
603   }
604   else if (selectedAction == cloneInterface){
605     dispatcher->duplicateInterface(ifaceItem);
606   }
607   else if (selectedAction == openWindow){
608     dispatcher->showRaiseWindow(this);
609   }
610   else if(selectedAction == showRstClkIface) {
611     dispatcher->showRstClkIface(this);
612   }
613   else if(selectedAction == showWishboneIface) {
614     dispatcher->showWishboneIface(this);
615   }
616   else if(selectedAction == showParameters){
617     new ParametersWindow(refBlock, params, NULL);
618   }
619 }
620 void BoxItem::loadFunctional(QDomElement funcElement) throw(Exception) {
621
622   bool ok = false;
623
624   int id = funcElement.attribute("id","none").toInt(&ok);
625   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
626
627   QString refXml = funcElement.attribute("ref_xml","none");
628   if(refXml == "none") throw(Exception(PROJECTFILE_CORRUPTED));
629
630   QString refMd5 = funcElement.attribute("ref_md5","none");
631   if(refMd5 == "none") throw(Exception(PROJECTFILE_CORRUPTED));
632
633   cout << "ref md5 : " << refMd5.toStdString() << "\nref xml : " << refXml.toStdString() << endl;
634
635   QString name = funcElement.attribute("name","none");
636   if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
637
638   QStringList positionStr = funcElement.attribute("position","none").split(",");
639   if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
640   int posX = positionStr.at(0).toInt(&ok);
641   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
642   int posY = positionStr.at(1).toInt(&ok);
643   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
644
645   QStringList dimensionStr = funcElement.attribute("dimension","none").split(",");
646   if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
647   int dimX = dimensionStr.at(0).toInt(&ok);
648   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
649   int dimY = dimensionStr.at(1).toInt(&ok);
650   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
651
652   ReferenceBlock *referenceMd5 = NULL;
653   ReferenceBlock *referenceXml = NULL;
654   ReferenceBlock *reference = NULL;
655   if(refMd5 != "none") {
656     referenceMd5 = params->searchBlockByMd5(refMd5);
657   }
658   if(refXml != "none"){
659     referenceXml = params->searchBlockByXml(refXml);
660   }
661   if ((referenceMd5 == NULL) && (referenceXml == NULL)) {
662     throw(Exception(PROJECTFILE_CORRUPTED));
663   }
664   if (referenceMd5 != referenceXml) {
665     throw(Exception(PROJECTFILE_CORRUPTED));
666   }
667   else {
668     reference = referenceMd5;
669   }
670   GroupBlock* parentGroupBlock = AB_TO_GRP(((GroupItem *)parentItem())->getRefBlock());
671   FunctionalBlock* functionalBlock = params->getGraph()->addFunctionalBlock(parentGroupBlock, reference);
672   /* NB: addFunctionalBlock creates all interfaces from the reference, which is annoying when
673     reading bif_iface tags. Thus interface are all removed.
674   */
675   functionalBlock->setName(name);
676   setRefBlock(functionalBlock);
677
678   setPos(posX,posY);
679   setDimension(dimX,dimY);
680   setId(id);
681
682
683   QDomNodeList blockParamNodes = funcElement.elementsByTagName("bif_parameter");
684   // setting parameters value
685   for(int i=0; i<blockParamNodes.length(); i++){
686     QDomElement currentBlockParamNode = blockParamNodes.at(i).toElement();
687
688     QString name = currentBlockParamNode.attribute("name","none");
689     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
690
691     QString value = currentBlockParamNode.attribute("value","none");
692     if(value == "none") throw(Exception(PROJECTFILE_CORRUPTED));
693
694     BlockParameter *blockParam = NULL;
695     blockParam = functionalBlock->getParameterFromName(name);
696     if (blockParam == NULL) throw(Exception(PROJECTFILE_CORRUPTED));
697     blockParam->setValue(value);
698   }
699
700   // recreate all interface because of some may have a multiplicity>1 with several examplars
701   functionalBlock->removeAllInterfaces();
702   QDomNodeList interfaceNodes = funcElement.elementsByTagName("bif_iface");
703   // setting interfaces (user name, and for multiplicity>1 may be create some new ones)
704   for(int i=0; i<interfaceNodes.length(); i++) {
705
706     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
707
708     QString name = currentInterfaceNode.attribute("name","none");
709     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
710
711     QString refName = currentInterfaceNode.attribute("ref_name","none");
712     if(refName == "none") throw(Exception(PROJECTFILE_CORRUPTED));
713
714     ReferenceInterface* refInter = AI_TO_REF(reference->getIfaceFromName(refName));
715     FunctionalInterface *functionalInterface = new FunctionalInterface(functionalBlock,refInter);
716     functionalInterface->setName(name);
717     functionalBlock->addInterface(functionalInterface);
718   }
719   // creating InterfaceItem
720   initInterfaces();
721   // setting them with saved values
722   for(int i=0; i<interfaceNodes.length(); i++){
723
724     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
725
726     int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
727     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
728
729     QString name = currentInterfaceNode.attribute("name","none");
730     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
731
732     QString orientationStr = currentInterfaceNode.attribute("orientation","none");
733     int orientation = InterfaceItem::getIntOrientation(orientationStr);
734     if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
735
736     double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
737     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
738
739     InterfaceItem *interfaceItem = searchInterfaceByName(name);
740     interfaceItem->setId(id);
741     interfaceItem->setOrientation(orientation);
742     interfaceItem->setPositionRatio(position);
743   }
744   updateGeometry(Resize);
745 }
746
747 void BoxItem::save(QXmlStreamWriter &writer) {
748   if (refBlock->isFunctionalBlock()) {
749     writer.writeStartElement("bi_functional");
750
751     writer.writeAttribute("id",QString::number(id));
752     writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
753     writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
754     writer.writeAttribute("name",refBlock->getName());
755     QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
756     writer.writeAttribute("position",attrPos);
757     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
758     writer.writeAttribute("dimension",attrDim);
759
760     writer.writeStartElement("bif_parameters");
761     foreach(BlockParameter *param,refBlock->getParameters()){
762       writer.writeStartElement("bif_parameter");
763
764       writer.writeAttribute("name",param->getName());
765       writer.writeAttribute("value",param->getValue().toString());
766       /*
767       writer.writeAttribute("context",param->getStrContext());
768       writer.writeAttribute("type",param->getTypeString());
769       */
770       writer.writeEndElement();   //</bif_parameter>
771     }
772     writer.writeEndElement();   //</bif_parameters>
773
774     writer.writeStartElement("bif_ifaces");
775     writer.writeAttribute("count",QString::number(interfaces.length()));
776     foreach(InterfaceItem* inter, interfaces){
777       writer.writeStartElement("bif_iface");
778
779       writer.writeAttribute("id",QString::number(inter->getId()));
780       writer.writeAttribute("name",inter->getName());
781       writer.writeAttribute("ref_name",inter->refInter->getName());
782       writer.writeAttribute("orientation",inter->getStrOrientation());
783       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
784
785       writer.writeEndElement();   //</bif_iface>
786     }
787     writer.writeEndElement();   //</bif_ifaces>
788
789     writer.writeEndElement();   //</bi_functional>
790   }
791   else {
792     writer.writeStartElement("bi_group");
793
794     writer.writeAttribute("id",QString::number(id));
795     writer.writeAttribute("inside_group",QString::number(childGroupItem->getId()));
796     QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
797     writer.writeAttribute("position",attrPos);
798     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
799     writer.writeAttribute("dimension",attrDim);
800
801     writer.writeStartElement("big_ifaces");
802     writer.writeAttribute("count",QString::number(interfaces.length()));
803     foreach(InterfaceItem* inter, interfaces){
804       writer.writeStartElement("big_iface");
805
806       writer.writeAttribute("id",QString::number(inter->getId()));
807       writer.writeAttribute("ref_name",inter->refInter->getName());
808       writer.writeAttribute("orientation",inter->getStrOrientation());
809       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
810
811       writer.writeEndElement(); //</big_iface>
812     }
813
814     writer.writeEndElement(); //</big_ifaces>
815     writer.writeEndElement(); //</bi_group>
816   }
817 }
818
819 QDataStream &operator <<(QDataStream &out, BoxItem &b) {
820   out.setVersion(QDataStream::Qt_4_8);
821
822   QByteArray blockData;
823   QDataStream toWrite(&blockData, QIODevice::WriteOnly);
824
825   QString refXml = ((FunctionalBlock*)b.refBlock)->getReferenceXmlFile();
826   QByteArray xmlFile = QByteArray(refXml.toStdString().c_str());
827   toWrite << xmlFile;
828
829   toWrite << b.id;
830   toWrite << (int)b.x();
831   toWrite << (int)b.y();
832   toWrite << b.boxWidth;
833   toWrite << b.boxHeight;
834   toWrite << b.getInterfaces().length();
835
836   for(int i=0; i<b.getInterfaces().length(); i++){
837     InterfaceItem *inter = b.getInterfaces().at(i);
838     toWrite << inter->getId();
839     //toWrite << inter->getName();
840     toWrite << inter->getPositionRatio();
841     toWrite << inter->getOrientation();
842   }
843
844   out << blockData;
845
846   return out;
847 }
848
849 QDataStream &operator >>(QDataStream &in, BoxItem &b) {
850
851   in.setVersion(QDataStream::Qt_4_8);
852
853   int x,y,nbInter;
854
855   in >> b.id;
856   in >> x;
857   in >> y;
858
859   b.setX(x);
860   b.setY(y);
861
862   in >> b.boxWidth;
863   in >> b.boxHeight;
864   in >> nbInter;
865
866   cout << "nbInter:" << nbInter << endl;
867   for(int i=0; i<nbInter; i++){
868
869     int id, orientation;
870     double positionRatio;
871     QString name;
872
873     InterfaceItem *inter = b.getInterfaces().at(i);
874     in >> id;
875     in >> name;
876     in >> positionRatio;
877     in >> orientation;
878
879     inter->setId(id);    
880     inter->setPositionRatio(positionRatio);
881     inter->setOrientation(orientation);
882     inter->updatePosition();
883
884   }
885
886   return in;
887 }