1 #include "SourceItem.h"
2 #include "GroupScene.h"
3 #include "ConnectionItem.h"
4 #include "InterfaceItem.h"
6 #include "Parameters.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"
18 SourceItem::SourceItem(AbstractBlock *_refBlock,
19 Dispatcher *_dispatcher,
20 Parameters *_params) throw(Exception) : AbstractBoxItem( _refBlock, _dispatcher, _params) {
23 _refBlock : mandatory a FunctionalBlock or a GroupBlock
25 if (_refBlock->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
27 currentBorder = NoBorder;
31 setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
34 updateGeometry(InterfaceMove);
35 resetInterfaceItemsPosition();
36 QPointF initPos = QPointF(0.0,0.0) - originPoint;
38 //cout << "total size of block: " << totalWidth << "," << totalHeight << endl;
39 //cout << "pos in group: " << x() << "," << y() << endl;
42 SourceItem::SourceItem(Dispatcher *_dispatcher, Parameters *_params) throw(Exception) : AbstractBoxItem(_dispatcher, _params) {
45 currentBorder = NoBorder;
49 setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
51 boxWidth = params->defaultBlockWidth;
52 boxHeight = params->defaultBlockHeight;
55 SourceItem::~SourceItem() {
58 void SourceItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
59 QPen pen(Qt::black, 3);
61 pen.setColor(Qt::red);
64 painter->setBrush(Qt::darkCyan);
66 painter->drawRect(0,0,boxWidth, boxHeight);
67 painter->drawText(0,0,boxWidth, boxHeight,Qt::AlignCenter | Qt::TextWordWrap,QString(refBlock->getName()));
68 foreach(InterfaceItem *inter, interfaces) {
70 inter->paint(painter);
74 void SourceItem::moveTo(QPointF dest) {
76 currentPosition = dest;
79 bool SourceItem::isSourceItem() {
83 void SourceItem::nameChanged() {
86 QFontMetrics fmId(params->defaultBlockFont);
87 nameWidth = fmId.width(refBlock->getName());
88 nameHeight = fmId.height();
89 updateGeometry(InterfaceMove);
90 // force the update in case of the size has not changed
94 void SourceItem::updateMinimumSize() {
100 int nbSouth = nbInterfacesByOrientation(Parameters::South);
101 int nbNorth = nbInterfacesByOrientation(Parameters::North);
102 int nbMaxSN = nbNorth;
103 if (nbSouth > nbNorth) nbMaxSN = nbSouth;
104 int nbEast = nbInterfacesByOrientation(Parameters::East);
105 int nbWest = nbInterfacesByOrientation(Parameters::West);
106 int nbMaxEW = nbEast;
107 if (nbWest > nbEast) {
114 foreach(InterfaceItem* iface, interfaces) {
115 ifaceWidth = iface->getNameWidth();
116 ifaceHeight = iface->getNameHeight();
117 if (iface->visible) {
118 if (iface->getOrientation() == Parameters::South) {
119 if (ifaceWidth > maxSouth) maxSouth = ifaceWidth;
121 else if (iface->getOrientation() == Parameters::North) {
122 if (ifaceWidth > maxNorth) maxNorth = ifaceWidth;
124 else if (iface->getOrientation() == Parameters::East) {
125 if (ifaceWidth > maxEast) maxEast = ifaceWidth;
127 else if (iface->getOrientation() == Parameters::West) {
128 if (ifaceWidth > maxWest) maxWest = ifaceWidth;
133 /* NB: the width layout is the following
134 ifaceMargin | maxWest | nameMargin | name | nameMargin | maxEast | ifaceMargin
136 minimumBoxWidth = maxWest+maxEast+nameWidth+2*(ifaceMargin+nameMargin);
137 // if the minimum is not sufficent taking into account N/S interfaces
138 if (minimumBoxWidth < (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1))) {
139 minimumBoxWidth = (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1));
141 minimumBoxHeight = maxNorth+maxSouth+3*ifaceMargin;
142 if (minimumBoxHeight < (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1))) {
143 minimumBoxHeight = (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1));
145 cout << "source minimum size = " << minimumBoxWidth << "x" << minimumBoxHeight << endl;
149 /* updateGeometry() :
152 bool SourceItem::updateGeometry(ChangeType type) {
154 currentPosition = pos();
155 //cout << "current pos of block: " << currentPosition.x() << "," << currentPosition.y() << endl;
156 QPointF oldOrigin = originPoint;
157 QSize oldSize(totalWidth,totalHeight);
159 bool boxSizeChanged = false;
161 // whatever the change, the minimum size may have changed
164 if (type == Resize) {
165 // resize implies to move interfaces and to update connections
166 boxSizeChanged = true;
168 else if (type == InterfaceMove) {
169 // if an interface moves, it may change the box size
170 if (boxWidth < minimumBoxWidth) {
171 boxWidth = minimumBoxWidth;
172 boxSizeChanged = true;
174 if (boxHeight < minimumBoxHeight) {
175 boxHeight = minimumBoxHeight;
176 boxSizeChanged = true;
179 if (boxSizeChanged) {
180 updateInterfaceAndConnectionItems();
186 totalWidth = boxWidth;
187 totalHeight = boxHeight;
189 if(isInterfaces(Parameters::East)){
190 totalWidth += params->arrowWidth+params->arrowLineLength;
192 if(isInterfaces(Parameters::West)){
193 totalWidth += params->arrowWidth+params->arrowLineLength;
194 x -= params->arrowWidth+params->arrowLineLength;
196 if(isInterfaces(Parameters::South)){
197 totalHeight += params->arrowWidth+params->arrowLineLength;
199 if(isInterfaces(Parameters::North)){
200 totalHeight += params->arrowWidth+params->arrowLineLength;
201 y -= params->arrowWidth+params->arrowLineLength;
203 QSizeF newSize(totalWidth,totalHeight);
207 cout << "source size = " << totalWidth << "x" << totalHeight << endl;
208 if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
209 prepareGeometryChange();
215 void SourceItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
217 if(params->editState == Parameters::EditBlockMove) {
218 QPointF absPos = currentPosition + originPoint;
220 int gapX = event->scenePos().x() - cursorPosition.x();
221 int gapY = event->scenePos().y() - cursorPosition.y();
225 QRectF rectSource = boundingRectInScene();
226 rectSource.moveTo(rectSource.x()+gapX,rectSource.y()+gapY);
227 GroupItem* group = getScene()->getGroupItem();
228 QRectF rectGroup = group->boundingRectInScene();
229 if (rectSource.intersects(rectGroup)) canMove = false;
232 foreach(SourceItem* source, getScene()->getSourceItems()) {
233 QRectF rectOther = source->boundingRectInScene();
234 if ((source != this) && (rectSource.intersects(rectOther))) canMove = false;
239 QPointF gap(gapX,gapY);
240 currentPosition = currentPosition+gap;
241 setPos(currentPosition);
242 // update all connections from/to this block
243 foreach(ConnectionItem *item, getScene()->getConnectionItems()){
244 if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
249 cursorPosition = event->scenePos();
251 else if(params->editState == Parameters::EditBlockResize) {
253 int gapX = event->scenePos().x() - cursorPosition.x();
254 int gapY = event->scenePos().y() - cursorPosition.y();
255 //cout << "gap: " << gapX << "," << gapY << endl;
256 switch(currentBorder){
258 if(boxWidth+gapX > minimumBoxWidth){
264 if(boxHeight+gapY > minimumBoxHeight){
269 case CornerSouthEast: {
270 if(boxWidth+gapX > minimumBoxWidth){
273 if(boxHeight+gapY > minimumBoxHeight){
279 cout << "abnormal case while resizing block" << endl;
282 // recompute the geometry of the block and possibly the group item
283 if (updateGeometry(Resize)) {
284 (getScene()->getGroupItem())->updateShape();
287 cursorPosition = event->scenePos();
289 else if(params->editState == Parameters::EditInterfaceMove) {
290 prepareGeometryChange();
291 moveInterfaceItemTo(event->pos());
292 // recompute the geometry of the block
293 if (updateGeometry(InterfaceMove)) {
294 //cout << "must recompute group item geometry" << endl;
295 (getScene()->getGroupItem())->updateShape();
297 // update connection from/to the selected interface
298 foreach(ConnectionItem *item, getScene()->getConnectionItems()){
299 if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
306 void SourceItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
308 QPointF pos = event->pos();
312 //QGraphicsItem::mousePressEvent(event);
314 if(event->button() == Qt::RightButton) return;
316 int mode = getScene()->getEditionMode();
318 dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget());
320 if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
321 InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
324 if (params->editState == Parameters::EditNoOperation) {
325 getScene()->setSelectedInterface(1,inter);
326 params->setEditState(Parameters::EditStartConnection);
328 else if (params->editState == Parameters::EditStartConnection) {
329 if (inter == getScene()->getSelectedInterface(1)) {
330 params->setEditState(Parameters::EditAbortConnection);
333 getScene()->setSelectedInterface(2,inter);
334 params->setEditState(Parameters::EditCloseConnection);
339 else if (mode == GroupScene::ItemEdition) {
340 //setZValue(zValue()+100);
341 if (params->cursorState == Parameters::CursorOnInterface) {
342 InterfaceItem *inter = getInterfaceItemFromCursor(x,y);
344 if (inter == currentInterface) {
345 params->setEditState(Parameters::EditInterfaceDeselect);
348 setFlag(ItemIsMovable, false);
349 currentInterface = inter;
350 params->setEditState(Parameters::EditInterfaceMove);
354 else if (params->cursorState == Parameters::CursorInBlock) {
355 selected = !selected;
356 params->setEditState(Parameters::EditBlockMove);
357 cursorPosition = event->scenePos();
358 //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
361 else if (params->cursorState == Parameters::CursorOnBorder) {
362 setFlag(ItemIsMovable, false);
363 cursorPosition = event->scenePos();
364 params->setEditState(Parameters::EditBlockResize);
369 void SourceItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
371 //setZValue(zValue()-100);
373 int mode = getScene()->getEditionMode();
375 if (mode == GroupScene::AddConnection) {
377 if (params->editState == Parameters::EditStartConnection) {
378 InterfaceItem* iface = getScene()->getSelectedInterface(1);
379 iface->selected = true;
380 update(iface->boundingRect());
382 else if (params->editState == Parameters::EditAbortConnection) {
383 InterfaceItem* iface = getScene()->getSelectedInterface(1);
384 iface->selected = false;
385 update(iface->boundingRect());
386 getScene()->setSelectedInterface(1,NULL);
387 params->setEditState(Parameters::EditNoOperation);
389 else if (params->editState == Parameters::EditCloseConnection) {
390 InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
391 InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
392 bool ok = dispatcher->createConnection(iface1,iface2);
394 iface1->selected = false;
395 update(iface1->boundingRect());
396 iface2->selected = false;
397 update(iface2->boundingRect());
398 getScene()->setSelectedInterface(1,NULL);
399 getScene()->setSelectedInterface(2,NULL);
400 params->setEditState(Parameters::EditNoOperation);
403 //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok);
404 getScene()->setSelectedInterface(2,NULL);
405 params->setEditState(Parameters::EditStartConnection);
409 else if (mode == GroupScene::ItemEdition) {
410 currentInterface = NULL;
411 params->editState = Parameters::EditNoOperation;
412 setFlag(ItemIsMovable);
415 QGraphicsItem::mouseReleaseEvent(event);
418 void SourceItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
420 QPointF pos = event->pos();
423 currentBorder = NoBorder;
424 int mode = getScene()->getEditionMode();
426 if (mode == GroupScene::AddConnection) {
427 InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
429 params->cursorState = Parameters::CursorOnInterface;
430 setCursor(Qt::PointingHandCursor);
433 params->cursorState = Parameters::CursorNowhere;
434 setCursor(Qt::ArrowCursor);
437 else if (mode == GroupScene::ItemEdition) {
441 InterfaceItem* iface = getInterfaceItemFromCursor(x,y);
443 params->cursorState = Parameters::CursorOnInterface;
444 setCursor(Qt::PointingHandCursor);
446 else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
448 params->cursorState = Parameters::CursorOnBorder;
450 if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
451 currentBorder = CornerSouthEast;
452 setCursor(Qt::SizeFDiagCursor);
455 currentBorder = BorderEast;
456 setCursor(Qt::SizeHorCursor);
459 else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
461 params->cursorState = Parameters::CursorOnBorder;
463 if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
464 currentBorder = CornerSouthEast;
465 setCursor(Qt::SizeFDiagCursor);
468 currentBorder = BorderSouth;
469 setCursor(Qt::SizeVerCursor);
473 if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
474 params->cursorState = Parameters::CursorInBlock;
475 setCursor(Qt::OpenHandCursor);
478 params->cursorState = Parameters::CursorNowhere;
479 setCursor(Qt::ArrowCursor);
483 //QGraphicsItem::hoverMoveEvent(event);
488 void SourceItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
493 QAction* titleAction = NULL;
494 QAction* removeAction = NULL;
495 QAction* duplicateAction = NULL;
496 QAction* renameAction = NULL;
497 QAction* showProperties = NULL;
498 QAction* showParameters = NULL;
501 InterfaceItem* ifaceItem = getInterfaceItemFromCursor(event->pos().x(), event->pos().y());
502 // menu for interface
503 if( ifaceItem != NULL){
505 titleAction = menu.addAction("Interface operations");
506 titleAction->setEnabled(false);
510 showProperties = menu.addAction("Show properties");
511 renameAction = menu.addAction("Rename");
516 titleAction = menu.addAction("Block operations");
517 titleAction->setEnabled(false);
520 if (refBlock->nbParameters() > 0) {
521 showParameters = menu.addAction("Show parameters");
523 renameAction = menu.addAction("Rename");
525 duplicateAction = menu.addAction("Duplicate");
526 removeAction = menu.addAction("Remove");
529 QAction* selectedAction = NULL;
530 selectedAction = menu.exec(event->screenPos());
532 if(selectedAction == NULL) return ;
534 if (selectedAction == removeAction) {
535 dispatcher->removeSourceItem(this);
537 else if (selectedAction == duplicateAction) {
538 dispatcher->duplicateSourceItem(this);
540 else if(selectedAction == renameAction){
541 if(ifaceItem != NULL) {
542 dispatcher->renameInterface(ifaceItem);
545 dispatcher->renameSourceBlock(this);
548 else if(selectedAction == showProperties){
549 dispatcher->showProperties(ifaceItem);
551 else if(selectedAction == showParameters){
552 new ParametersWindow(refBlock, params, NULL);
556 void SourceItem::load(QDomElement funcElement) throw(Exception) {
560 int id = funcElement.attribute("id","none").toInt(&ok);
561 if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
563 QString refXml = funcElement.attribute("ref_xml","none");
564 if(refXml == "none") throw(Exception(PROJECTFILE_CORRUPTED));
566 QString refMd5 = funcElement.attribute("ref_md5","none");
567 if(refMd5 == "none") throw(Exception(PROJECTFILE_CORRUPTED));
569 cout << "ref md5 : " << refMd5.toStdString() << "\nref xml : " << refXml.toStdString() << endl;
571 QString name = funcElement.attribute("name","none");
572 if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
574 QStringList positionStr = funcElement.attribute("position","none").split(",");
575 if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
576 int posX = positionStr.at(0).toInt(&ok);
577 if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
578 int posY = positionStr.at(1).toInt(&ok);
579 if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
581 QStringList dimensionStr = funcElement.attribute("dimension","none").split(",");
582 if(dimensionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED));
583 int dimX = dimensionStr.at(0).toInt(&ok);
584 if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
585 int dimY = dimensionStr.at(1).toInt(&ok);
586 if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
588 ReferenceBlock *referenceMd5 = NULL;
589 ReferenceBlock *referenceXml = NULL;
590 ReferenceBlock *reference = NULL;
591 if(refMd5 != "none") {
592 referenceMd5 = params->searchBlockByMd5(refMd5);
594 if(refXml != "none"){
595 referenceXml = params->searchBlockByXml(refXml);
597 if ((referenceMd5 == NULL) && (referenceXml == NULL)) {
598 throw(Exception(PROJECTFILE_CORRUPTED));
600 if (referenceMd5 != referenceXml) {
601 throw(Exception(PROJECTFILE_CORRUPTED));
604 reference = referenceMd5;
607 GroupBlock* parentGroupBlock = AB_TO_GRP(((GroupItem *)parentItem())->getRefBlock());
608 FunctionalBlock* functionalBlock = params->getGraph()->createFunctionalBlock(parentGroupBlock, reference);
609 /* NB: addFunctionalBlock creates all interfaces from the reference, which is annoying when
610 reading bif_iface tags. Thus interface are all removed.
612 functionalBlock->setName(name);
613 setRefBlock(functionalBlock);
616 setDimension(dimX,dimY);
620 QDomNodeList blockParamNodes = funcElement.elementsByTagName("bif_parameter");
621 // setting parameters value
622 for(int i=0; i<blockParamNodes.length(); i++){
623 QDomElement currentBlockParamNode = blockParamNodes.at(i).toElement();
625 QString name = currentBlockParamNode.attribute("name","none");
626 if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
628 QString value = currentBlockParamNode.attribute("value","none");
629 if(value == "none") throw(Exception(PROJECTFILE_CORRUPTED));
631 BlockParameter *blockParam = NULL;
632 blockParam = functionalBlock->getParameterFromName(name);
633 if (blockParam == NULL) throw(Exception(PROJECTFILE_CORRUPTED));
634 blockParam->setValue(value);
637 // recreate all (non-control) interfaces because of some may have a multiplicity>1 with several examplars
638 functionalBlock->removeAllInterfaces();
639 QDomNodeList interfaceNodes = funcElement.elementsByTagName("bif_iface");
640 // setting interfaces (user name, and for multiplicity>1 may be create some new ones)
641 for(int i=0; i<interfaceNodes.length(); i++) {
643 QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
645 QString name = currentInterfaceNode.attribute("name","none");
646 if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
648 QString refName = currentInterfaceNode.attribute("ref_name","none");
649 if(refName == "none") throw(Exception(PROJECTFILE_CORRUPTED));
651 ReferenceInterface* refInter = AI_TO_REF(reference->getIfaceFromName(refName));
652 cout << "creating iface from reference named " << qPrintable(refName) << endl;
653 FunctionalInterface *functionalInterface = new FunctionalInterface(functionalBlock,refInter);
654 functionalInterface->setName(name);
655 functionalBlock->addInterface(functionalInterface);
657 // searching for control interface
658 QString ctlRefName = refName+"_enb";
659 ReferenceInterface* ctlRefIface = AI_TO_REF(reference->getIfaceFromName(ctlRefName));
661 if (ctlRefIface != NULL) {
662 cout << "found a control iface:" << qPrintable(ctlRefName) << endl;
663 FunctionalInterface *ctlIface = new FunctionalInterface(functionalBlock,ctlRefIface);
664 if (! ctlIface->setAssociatedIface(functionalInterface)) {
665 throw(Exception(PROJECTFILE_CORRUPTED));
667 ctlIface->setName(name+"_enb");
668 functionalBlock->addInterface(ctlIface);
672 // creating InterfaceItem
673 initInterfaceItems();
674 // setting them with saved values
675 for(int i=0; i<interfaceNodes.length(); i++){
677 QDomElement currentInterfaceNode = interfaceNodes.at(i).toElement();
679 int id = currentInterfaceNode.attribute("id","none").toInt(&ok);
680 if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
682 QString name = currentInterfaceNode.attribute("name","none");
683 if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED));
685 QString orientationStr = currentInterfaceNode.attribute("orientation","none");
686 int orientation = InterfaceItem::getIntOrientation(orientationStr);
687 if(orientation == -1) throw(Exception(PROJECTFILE_CORRUPTED));
689 double position = currentInterfaceNode.attribute("position","none").toDouble(&ok);
690 if(!ok) throw(Exception(PROJECTFILE_CORRUPTED));
692 InterfaceItem *interfaceItem = searchInterfaceItemByName(name);
693 interfaceItem->setId(id);
694 interfaceItem->setOrientation(orientation);
695 interfaceItem->setPositionRatio(position);
697 updateGeometry(Resize);
700 void SourceItem::save(QXmlStreamWriter &writer) {
702 writer.writeStartElement("source_item");
704 writer.writeAttribute("id",QString::number(id));
705 writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
706 writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
707 writer.writeAttribute("name",refBlock->getName());
708 QString attrPos = QString::number((int)(pos().x())).append(",").append(QString::number((int)(pos().y())));
709 writer.writeAttribute("position",attrPos);
710 QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
711 writer.writeAttribute("dimension",attrDim);
713 writer.writeStartElement("source_parameters");
714 foreach(BlockParameter *param,refBlock->getParameters()){
715 writer.writeStartElement("source_parameter");
717 writer.writeAttribute("name",param->getName());
718 writer.writeAttribute("value",param->getValue().toString());
720 writer.writeAttribute("context",param->getStrContext());
721 writer.writeAttribute("type",param->getTypeString());
723 writer.writeEndElement(); //</source_parameter>
725 writer.writeEndElement(); //</source_parameters>
727 writer.writeStartElement("source_ifaces");
728 writer.writeAttribute("count",QString::number(interfaces.length()));
729 foreach(InterfaceItem* inter, interfaces){
730 writer.writeStartElement("source_iface");
732 writer.writeAttribute("id",QString::number(inter->getId()));
733 writer.writeAttribute("name",inter->getName());
734 writer.writeAttribute("ref_name",inter->refInter->getName());
735 writer.writeAttribute("orientation",inter->getStrOrientation());
736 writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
738 writer.writeEndElement(); //</source_iface>
740 writer.writeEndElement(); //</source_ifaces>
742 writer.writeEndElement(); //</source_item>