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

Private GIT Repository
a107198654913fdc6badc66bc19ed9b13f784d47
[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::interfaceRenamed() {
211   if (updateGeometry(InterfaceMove)) {
212     //cout << "must recompute group item geometry" << endl;
213     (getScene()->getGroupItem())->updateShape();
214   }  
215 }
216
217 void BoxItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
218
219   if(params->editState == Parameters::EditBlockMove) {
220     QPointF absPos = currentPosition + originPoint;
221     int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
222     int gapX = event->scenePos().x() - cursorPosition.x();
223     int gapY = event->scenePos().y() - cursorPosition.y();
224
225     //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
226     //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
227
228     if (absPos.x()+gapX < marginConn) {
229       gapX = marginConn-absPos.x();
230     }
231     if (absPos.y()+gapY < marginConn) {
232       gapY = marginConn-absPos.y();
233     }
234     //cout << "gap: " << gapX << "," << gapY << endl;
235     QPointF gap(gapX,gapY);
236     currentPosition = currentPosition+gap;
237     setPos(currentPosition);
238     // update all connections from/to this block
239     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
240       if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
241         item->setPath();
242       }
243     }
244     cursorPosition = event->scenePos();
245
246     // udpate the groupitem
247     (getScene()->getGroupItem())->updateShape();
248   }
249   else if(params->editState == Parameters::EditBlockResize) {
250
251     int gapX = event->scenePos().x() - cursorPosition.x();
252     int gapY = event->scenePos().y() - cursorPosition.y();
253     //cout << "gap: " << gapX << "," << gapY << endl;
254     switch(currentBorder){
255     case BorderEast: {    
256       if(boxWidth+gapX > minimumBoxWidth){
257         boxWidth += gapX;
258       }
259       break;
260     }
261     case BorderSouth: {      
262       if(boxHeight+gapY > minimumBoxHeight){
263         boxHeight += gapY;
264       }
265       break;
266     }
267     case CornerSouthEast: {
268       if(boxWidth+gapX > minimumBoxWidth){
269         boxWidth += gapX;
270       }
271       if(boxHeight+gapY > minimumBoxHeight){
272         boxHeight += gapY;
273       }
274       break;
275     }
276     case NoBorder:
277       cout << "abnormal case while resizing block" << endl;
278       break;
279     }
280     // recompute the geometry of the block and possibly the group item
281     if (updateGeometry(Resize)) {
282       (getScene()->getGroupItem())->updateShape();
283     }
284
285     cursorPosition = event->scenePos();   
286   }
287   else if(params->editState == Parameters::EditInterfaceMove) {
288     prepareGeometryChange();
289     moveInterfaceTo(event->pos());
290     // recompute the geometry of the block
291     if (updateGeometry(InterfaceMove)) {
292       //cout << "must recompute group item geometry" << endl;
293       (getScene()->getGroupItem())->updateShape();
294     }
295     // update connection from/to the selected interface
296     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
297       if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
298         item->setPath();
299       }
300     }    
301   }
302 }
303
304 void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
305
306   QPointF pos = event->pos();
307   qreal x = pos.x();
308   qreal y = pos.y();
309
310   //QGraphicsItem::mousePressEvent(event);
311
312   if(event->button() == Qt::RightButton) return;
313
314   int mode = getScene()->getEditionMode();
315
316   dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget());
317
318   if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
319     InterfaceItem *inter = getInterfaceFromCursor(x,y);
320     if (inter != NULL) {
321
322       if (params->editState == Parameters::EditNoOperation) {
323         getScene()->setSelectedInterface(1,inter);
324         params->setEditState(Parameters::EditStartConnection);
325       }
326       else if (params->editState == Parameters::EditStartConnection) {
327         if (inter == getScene()->getSelectedInterface(1)) {
328           params->setEditState(Parameters::EditAbortConnection);
329         }
330         else {
331           getScene()->setSelectedInterface(2,inter);
332           params->setEditState(Parameters::EditCloseConnection);
333         }
334       }
335     }
336   }
337   else if (mode == GroupScene::ItemEdition) {
338     setZValue(zValue()+100);
339     if (params->cursorState == Parameters::CursorOnInterface) {
340       InterfaceItem *inter = getInterfaceFromCursor(x,y);
341       if (inter != NULL) {
342         if (inter == currentInterface) {
343            params->setEditState(Parameters::EditInterfaceDeselect);
344         }
345         else {
346           setFlag(ItemIsMovable, false);
347           currentInterface = inter;
348           params->setEditState(Parameters::EditInterfaceMove);
349         }
350       }
351     }
352     else if (params->cursorState == Parameters::CursorInBlock) {
353       selected = !selected;
354       params->setEditState(Parameters::EditBlockMove);
355       cursorPosition = event->scenePos();
356       //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
357       update();
358     }
359     else if (params->cursorState == Parameters::CursorOnBorder) {
360       setFlag(ItemIsMovable, false);
361       cursorPosition = event->scenePos();
362       params->setEditState(Parameters::EditBlockResize);
363     }
364   }
365 }
366
367 void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent  *event) {
368
369   setZValue(zValue()-100);
370
371   int mode = getScene()->getEditionMode();
372
373   if (mode == GroupScene::AddConnection) {
374
375     if (params->editState == Parameters::EditStartConnection) {
376       InterfaceItem* iface = getScene()->getSelectedInterface(1);
377       iface->selected = true;
378       update(iface->boundingRect());
379     }
380     else if (params->editState == Parameters::EditAbortConnection) {
381       InterfaceItem* iface = getScene()->getSelectedInterface(1);
382       iface->selected = false;
383       update(iface->boundingRect());
384       getScene()->setSelectedInterface(1,NULL);
385       params->setEditState(Parameters::EditNoOperation);
386     }
387     else if (params->editState == Parameters::EditCloseConnection) {
388       InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
389       InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
390       bool ok = dispatcher->connect(iface1,iface2);
391       if (ok) {
392         iface1->selected = false;
393         // no update needed since the whole scene will be repainted
394         getScene()->setSelectedInterface(1,NULL);
395         getScene()->setSelectedInterface(2,NULL);
396         params->setEditState(Parameters::EditNoOperation);
397       }
398       else {
399         //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok);
400         getScene()->setSelectedInterface(2,NULL);
401         params->setEditState(Parameters::EditStartConnection);
402       }
403     }
404   }
405   else if (mode == GroupScene::ItemEdition) {
406     currentInterface = NULL;
407     params->editState = Parameters::EditNoOperation;
408     setFlag(ItemIsMovable);
409   }
410
411   QGraphicsItem::mouseReleaseEvent(event);
412 }
413
414 void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
415
416   QPointF pos = event->pos();
417   qreal x = pos.x();
418   qreal y = pos.y();
419   currentBorder = NoBorder;
420   int mode = getScene()->getEditionMode();
421
422   if (mode == GroupScene::AddConnection) {
423     InterfaceItem* iface = getInterfaceFromCursor(x,y);
424     if (iface != NULL) {
425       params->cursorState = Parameters::CursorOnInterface;
426       setCursor(Qt::PointingHandCursor);
427     }
428     else {
429       params->cursorState = Parameters::CursorNowhere;
430       setCursor(Qt::ArrowCursor);
431     }
432   }
433   else if (mode == GroupScene::ItemEdition) {
434     int marginE = 5;
435     int marginS = 5;
436
437     InterfaceItem* iface = getInterfaceFromCursor(x,y);
438     if (iface != NULL) {
439       params->cursorState = Parameters::CursorOnInterface;
440       setCursor(Qt::PointingHandCursor);
441     }
442     else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
443
444       params->cursorState = Parameters::CursorOnBorder;
445
446       if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
447         currentBorder = CornerSouthEast;
448         setCursor(Qt::SizeFDiagCursor);
449       }
450       else {
451         currentBorder = BorderEast;
452         setCursor(Qt::SizeHorCursor);
453       }
454     }
455     else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
456
457       params->cursorState = Parameters::CursorOnBorder;
458
459       if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
460         currentBorder = CornerSouthEast;
461         setCursor(Qt::SizeFDiagCursor);
462       }
463       else {
464         currentBorder = BorderSouth;
465         setCursor(Qt::SizeVerCursor);
466       }
467     }
468     else {
469       if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
470         params->cursorState = Parameters::CursorInBlock;
471         setCursor(Qt::OpenHandCursor);
472       }
473       else {
474         params->cursorState = Parameters::CursorNowhere;
475         setCursor(Qt::ArrowCursor);
476       }
477     }
478   }
479   QGraphicsItem::hoverMoveEvent(event);
480 }
481
482
483 void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
484
485   QMenu menu;
486   QAction* titleAction = NULL;
487   QAction* removeAction = NULL;
488   QAction* duplicateAction = NULL;
489   QAction* renameAction = NULL;
490   QAction* connectToGroup = NULL;
491   QAction* disconnectFromGroup = NULL;
492   QAction* showProperties = NULL;
493   QAction* cloneInterface = NULL;
494   QAction* openWindow = NULL;
495   QAction* showRstClkIface = NULL;
496   QAction* showWishboneIface = NULL;
497   QAction* showParameters = NULL;
498
499   InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
500   // menu for interface
501   if( ifaceItem != NULL){
502
503     titleAction = menu.addAction("Interface operations");
504     titleAction->setEnabled(false);
505     menu.addSeparator();
506
507
508     showProperties = menu.addAction("Show properties");
509     renameAction = menu.addAction("Rename");
510
511     ConnectedInterface* iface = ifaceItem->refInter;
512     ConnectedInterface* ifaceGroup = NULL;
513     bool canRemove = true;
514
515
516     if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) {
517         connectToGroup = menu.addAction("Connect to group input");
518     }
519     else if ((iface->getDirection() == AbstractInterface::Output) && (iface->getConnectionToParentGroup() == NULL)) {
520       connectToGroup = menu.addAction("Connect to group output");
521     }
522     else if (iface->getConnectionFromParentGroup() != NULL) {
523       ifaceGroup = iface->getConnectionFromParentGroup();
524       //if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) {
525       if (!ifaceGroup->isConnectedFrom()) {
526         disconnectFromGroup = menu.addAction("Disconnect from group");
527       }
528       else {
529         canRemove = false;
530       }
531     }
532     else if (iface->getConnectionToParentGroup() != NULL) {
533       ifaceGroup = iface->getConnectionToParentGroup();
534       //if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) {
535       if (!ifaceGroup->isConnectedTo()) {
536         disconnectFromGroup = menu.addAction("Disconnect from group");
537       }
538       else {
539         canRemove = false;
540       }
541     }
542
543     if (iface->isFunctionalInterface()) {
544       FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter);
545       ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference());
546       if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){
547         cloneInterface = menu.addAction("Duplicate");
548         if ((canRemove) && (fi->getInterfaceMultiplicity() > 1)) {
549           removeAction = menu.addAction("Remove");
550         }
551       }      
552     }
553   }
554   // menu for blocks (group or func)
555   else {
556     titleAction = menu.addAction("Block operations");
557     titleAction->setEnabled(false);
558     menu.addSeparator();
559
560     if (refBlock->nbParameters() > 0) {
561       showParameters = menu.addAction("Show parameters");
562     }
563     renameAction = menu.addAction("Rename");
564
565     if(refBlock->isGroupBlock()){
566       openWindow = menu.addAction("Open/show group window");
567     }
568     else {
569       duplicateAction = menu.addAction("Duplicate");
570       showRstClkIface = menu.addAction("Show reset/clock interfaces");
571       showRstClkIface->setCheckable(true);
572       showRstClkIface->setChecked(rstClkVisible);
573       showWishboneIface = menu.addAction("Show wishbone interfaces");
574       showWishboneIface->setCheckable(true);
575       showWishboneIface->setChecked(wishboneVisible);
576     }
577     removeAction = menu.addAction("Remove");
578   }
579
580   QAction* selectedAction = NULL;
581   selectedAction = menu.exec(event->screenPos());
582
583   if(selectedAction == NULL) return ;
584
585   if (selectedAction == removeAction) {
586     if(ifaceItem != NULL) {
587      dispatcher->removeFunctionalInterface(ifaceItem);
588     }
589     else {
590       dispatcher->removeBlock(this);
591     }
592   }
593   else if (selectedAction == duplicateAction) {
594     dispatcher->duplicateBlock(this);
595   }
596   else if(selectedAction == renameAction){
597     if(ifaceItem != NULL)
598       dispatcher->renameInterface(ifaceItem);
599     else
600       dispatcher->renameBlockOrGroup(this);
601   }
602   else if(selectedAction == showProperties){
603     dispatcher->showProperties(ifaceItem);
604   }
605   else if (selectedAction == connectToGroup){
606     dispatcher->connectInterToGroup(ifaceItem);
607   }
608   else if (selectedAction == disconnectFromGroup) {
609     dispatcher->disconnectInterFromGroup(ifaceItem);
610   }
611   else if (selectedAction == cloneInterface){
612     dispatcher->duplicateInterface(ifaceItem);
613   }
614   else if (selectedAction == openWindow){
615     dispatcher->showRaiseWindow(this);
616   }
617   else if(selectedAction == showRstClkIface) {
618     dispatcher->showRstClkIface(this);
619   }
620   else if(selectedAction == showWishboneIface) {
621     dispatcher->showWishboneIface(this);
622   }
623   else if(selectedAction == showParameters){
624     new ParametersWindow(refBlock, params, NULL);
625   }
626 }
627 void BoxItem::loadFunctional(QDomElement funcElement) throw(Exception) {
628
629   bool ok = false;
630
631   int id = funcElement.attribute("id","none").toInt(&ok);
632   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
633
634   QString refXml = funcElement.attribute("ref_xml","none");
635   if(refXml == "none") throw(Exception(PROJECTFILE_CORRUPTED));
636
637   QString refMd5 = funcElement.attribute("ref_md5","none");
638   if(refMd5 == "none") throw(Exception(PROJECTFILE_CORRUPTED));
639
640   cout << "ref md5 : " << refMd5.toStdString() << "\nref xml : " << refXml.toStdString() << endl;
641
642   QString name = funcElement.attribute("name","none");
643   if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
644
645   QStringList positionStr = funcElement.attribute("position","none").split(",");
646   if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
647   int posX = positionStr.at(0).toInt(&ok);
648   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
649   int posY = positionStr.at(1).toInt(&ok);
650   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
651
652   QStringList dimensionStr = funcElement.attribute("dimension","none").split(",");
653   if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
654   int dimX = dimensionStr.at(0).toInt(&ok);
655   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
656   int dimY = dimensionStr.at(1).toInt(&ok);
657   if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
658   
659   ReferenceBlock *referenceMd5 = NULL;
660   ReferenceBlock *referenceXml = NULL;
661   ReferenceBlock *reference = NULL;
662   if(refMd5 != "none") {
663     referenceMd5 = params->searchBlockByMd5(refMd5);
664   }
665   if(refXml != "none"){
666     referenceXml = params->searchBlockByXml(refXml);
667   }
668   if ((referenceMd5 == NULL) && (referenceXml == NULL)) {
669     throw(Exception(PROJECTFILE_CORRUPTED));
670   }
671   if (referenceMd5 != referenceXml) {
672     throw(Exception(PROJECTFILE_CORRUPTED));
673   }
674   else {
675     reference = referenceMd5;
676   }
677   
678   GroupBlock* parentGroupBlock = AB_TO_GRP(((GroupItem *)parentItem())->getRefBlock());
679   FunctionalBlock* functionalBlock = params->getGraph()->addFunctionalBlock(parentGroupBlock, reference);
680   /* NB: addFunctionalBlock creates all interfaces from the reference, which is annoying when
681     reading bif_iface tags. Thus interface are all removed.
682   */
683   functionalBlock->setName(name);
684   setRefBlock(functionalBlock);
685
686   setPos(posX,posY);
687   setDimension(dimX,dimY);
688   setId(id);
689
690
691   QDomNodeList blockParamNodes = funcElement.elementsByTagName("bif_parameter");
692   // setting parameters value
693   for(int i=0; i<blockParamNodes.length(); i++){
694     QDomElement currentBlockParamNode = blockParamNodes.at(i).toElement();
695
696     QString name = currentBlockParamNode.attribute("name","none");
697     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
698
699     QString value = currentBlockParamNode.attribute("value","none");
700     if(value == "none") throw(Exception(PROJECTFILE_CORRUPTED));
701
702     BlockParameter *blockParam = NULL;
703     blockParam = functionalBlock->getParameterFromName(name);
704     if (blockParam == NULL) throw(Exception(PROJECTFILE_CORRUPTED));
705     blockParam->setValue(value);
706   }  
707
708   // recreate all (non-control) interfaces because of some may have a multiplicity>1 with several examplars
709   functionalBlock->removeAllInterfaces();
710   QDomNodeList interfaceNodes = funcElement.elementsByTagName("bif_iface");
711   // setting interfaces (user name, and for multiplicity>1 may be create some new ones)
712   for(int i=0; i<interfaceNodes.length(); i++) {
713
714     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
715
716     QString name = currentInterfaceNode.attribute("name","none");
717     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
718
719     QString refName = currentInterfaceNode.attribute("ref_name","none");
720     if(refName == "none") throw(Exception(PROJECTFILE_CORRUPTED));
721
722     ReferenceInterface* refInter = AI_TO_REF(reference->getIfaceFromName(refName));
723     cout << "creating iface from reference named " << qPrintable(refName) << endl;
724     FunctionalInterface *functionalInterface = new FunctionalInterface(functionalBlock,refInter);
725     functionalInterface->setName(name);
726     functionalBlock->addInterface(functionalInterface);
727     
728     // searching for control interface
729     QString ctlRefName = refName+"_ctl";
730     ReferenceInterface* ctlRefIface = AI_TO_REF(reference->getIfaceFromName(ctlRefName));
731     
732     if (ctlRefIface != NULL) {
733       cout << "found a control iface:" << qPrintable(ctlRefName) << endl;
734       FunctionalInterface *ctlIface = new FunctionalInterface(functionalBlock,ctlRefIface);      
735       if (! ctlIface->setAssociatedIface(functionalInterface)) {
736         throw(Exception(PROJECTFILE_CORRUPTED));
737       }      
738       ctlIface->setName(name+"_ctl");
739       functionalBlock->addInterface(ctlIface);
740     }    
741   }
742   
743   // creating InterfaceItem
744   initInterfaces();
745   // setting them with saved values
746   for(int i=0; i<interfaceNodes.length(); i++){
747
748     QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
749
750     int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
751     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
752
753     QString name = currentInterfaceNode.attribute("name","none");
754     if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
755
756     QString orientationStr = currentInterfaceNode.attribute("orientation","none");
757     int orientation = InterfaceItem::getIntOrientation(orientationStr);
758     if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
759
760     double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
761     if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
762
763     InterfaceItem *interfaceItem = searchInterfaceByName(name);
764     interfaceItem->setId(id);
765     interfaceItem->setOrientation(orientation);
766     interfaceItem->setPositionRatio(position);
767   }
768   updateGeometry(Resize);
769 }
770
771 void BoxItem::save(QXmlStreamWriter &writer) {
772   if (refBlock->isFunctionalBlock()) {
773     writer.writeStartElement("bi_functional");
774
775     writer.writeAttribute("id",QString::number(id));
776     writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
777     writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
778     writer.writeAttribute("name",refBlock->getName());
779     QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
780     writer.writeAttribute("position",attrPos);
781     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
782     writer.writeAttribute("dimension",attrDim);
783
784     writer.writeStartElement("bif_parameters");
785     foreach(BlockParameter *param,refBlock->getParameters()){
786       writer.writeStartElement("bif_parameter");
787
788       writer.writeAttribute("name",param->getName());
789       writer.writeAttribute("value",param->getValue().toString());
790       /*
791       writer.writeAttribute("context",param->getStrContext());
792       writer.writeAttribute("type",param->getTypeString());
793       */
794       writer.writeEndElement();   //</bif_parameter>
795     }
796     writer.writeEndElement();   //</bif_parameters>
797
798     writer.writeStartElement("bif_ifaces");
799     writer.writeAttribute("count",QString::number(interfaces.length()));
800     foreach(InterfaceItem* inter, interfaces){
801       writer.writeStartElement("bif_iface");
802
803       writer.writeAttribute("id",QString::number(inter->getId()));
804       writer.writeAttribute("name",inter->getName());
805       writer.writeAttribute("ref_name",inter->refInter->getName());
806       writer.writeAttribute("orientation",inter->getStrOrientation());
807       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
808
809       writer.writeEndElement();   //</bif_iface>
810     }
811     writer.writeEndElement();   //</bif_ifaces>
812
813     writer.writeEndElement();   //</bi_functional>
814   }
815   else {
816     writer.writeStartElement("bi_group");
817
818     writer.writeAttribute("id",QString::number(id));
819     writer.writeAttribute("inside_group",QString::number(childGroupItem->getId()));
820     QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
821     writer.writeAttribute("position",attrPos);
822     QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
823     writer.writeAttribute("dimension",attrDim);
824
825     writer.writeStartElement("big_ifaces");
826     writer.writeAttribute("count",QString::number(interfaces.length()));
827     foreach(InterfaceItem* inter, interfaces){
828       writer.writeStartElement("big_iface");
829
830       writer.writeAttribute("id",QString::number(inter->getId()));
831       writer.writeAttribute("ref_name",inter->refInter->getName());
832       writer.writeAttribute("orientation",inter->getStrOrientation());
833       writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
834
835       writer.writeEndElement(); //</big_iface>
836     }
837
838     writer.writeEndElement(); //</big_ifaces>
839     writer.writeEndElement(); //</bi_group>
840   }
841 }
842
843 QDataStream &operator <<(QDataStream &out, BoxItem &b) {
844   out.setVersion(QDataStream::Qt_4_8);
845
846   QByteArray blockData;
847   QDataStream toWrite(&blockData, QIODevice::WriteOnly);
848
849   QString refXml = ((FunctionalBlock*)b.refBlock)->getReferenceXmlFile();
850   QByteArray xmlFile = QByteArray(refXml.toStdString().c_str());
851   toWrite << xmlFile;
852
853   toWrite << b.id;
854   toWrite << (int)b.x();
855   toWrite << (int)b.y();
856   toWrite << b.boxWidth;
857   toWrite << b.boxHeight;
858   toWrite << b.getInterfaces().length();
859
860   for(int i=0; i<b.getInterfaces().length(); i++){
861     InterfaceItem *inter = b.getInterfaces().at(i);
862     toWrite << inter->getId();
863     //toWrite << inter->getName();
864     toWrite << inter->getPositionRatio();
865     toWrite << inter->getOrientation();
866   }
867
868   out << blockData;
869
870   return out;
871 }
872
873 QDataStream &operator >>(QDataStream &in, BoxItem &b) {
874
875   in.setVersion(QDataStream::Qt_4_8);
876
877   int x,y,nbInter;
878
879   in >> b.id;
880   in >> x;
881   in >> y;
882
883   b.setX(x);
884   b.setY(y);
885
886   in >> b.boxWidth;
887   in >> b.boxHeight;
888   in >> nbInter;
889
890   cout << "nbInter:" << nbInter << endl;
891   for(int i=0; i<nbInter; i++){
892
893     int id, orientation;
894     double positionRatio;
895     QString name;
896
897     InterfaceItem *inter = b.getInterfaces().at(i);
898     in >> id;
899     in >> name;
900     in >> positionRatio;
901     in >> orientation;
902
903     inter->setId(id);    
904     inter->setPositionRatio(positionRatio);
905     inter->setOrientation(orientation);
906     inter->updatePosition();
907
908   }
909
910   return in;
911 }