X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/d111eaf49741a0a79d372445f97c314a637e331e..e0eaffd44fc9733bc230a803c80d8d5efd0faca6:/GroupItem.cpp diff --git a/GroupItem.cpp b/GroupItem.cpp index 90c5574..d9e7459 100644 --- a/GroupItem.cpp +++ b/GroupItem.cpp @@ -5,7 +5,7 @@ #include "Dispatcher.h" #include "Parameters.h" #include "BoxItem.h" -#include "SourceItem.h" +#include "StimuliItem.h" #include "AbstractBlock.h" #include "AbstractInterface.h" #include "ConnectedInterface.h" @@ -22,31 +22,32 @@ GroupItem::GroupItem(BoxItem *_parentItem, parentItem = _parentItem; if (parentItem != NULL) { - parentItem->setChildGroupItem(this); + parentItem->setChildGroupItem(this); } - /* - minimumBoxWidth = nameWidth+2*nameMargin; - minimumBoxHeight = 100; - boxHeight = minimumBoxHeight; - boxWidth = minimumBoxWidth; - */ + boxHeight = 1; + boxWidth = 1; rectTitle = QRectF(0,-(nameHeight+2*nameMargin),nameWidth+2*nameMargin,nameHeight+2*nameMargin); + + /* NB: boxPoint represent the position in scene of the top-left corner of the box, thus + * without taking into account the interfaces. It is also the reference position to draw the item. + * Nevertheless, in order to place sources in the scene, the real bouding box of the group is determined + * from originPoint and totalWidth/totalheight. + * */ + boxPoint = QPointF(0,0); /* totalHeight = boxHeight + rectTitle.height(); totalWidth = boxWidth; */ selected = false; - setZValue(100); setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges); - updateGeometry(InterfaceMove); - QPointF initPos = QPointF(0.0,0.0) - originPoint; - setPos(initPos); + updateGeometry(Creation); + setPos(boxPoint); cout << "total size of group: " << totalWidth << "," << totalHeight << endl; cout << "pos in scene: " << x() << "," << y() << endl; } @@ -87,6 +88,9 @@ void GroupItem::setParentItem(BoxItem *_parentItem) { } void GroupItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + + if (!visible) return; + if(boxWidth > 0 && boxHeight > 0){ if(selected) painter->setPen(Qt::red); @@ -125,62 +129,155 @@ void GroupItem::updateMinimumSize() { minimumBoxHeight = 2*marginConn; if (getScene() == NULL) return; - QList blocks = getScene()->getBoxItems(); - if(blocks.length() > 0) { - // first, search for blocks that are at (0,0) - int xMaxZero = 0; - int yMaxZero = 0; - int xMax = 0; - int yMax = 0; - bool isZeroBlocks = false; - bool isOtherBlocks = false; - foreach(BoxItem* item, blocks) { - QPointF p = item->pos() + item->getOriginPoint(); - if ((p.x()==0.0) && (p.y()==0.0)) { - isZeroBlocks = true; - if (item->getTotalWidth() > xMaxZero) { - xMaxZero = item->getTotalWidth(); + if(blocks.length() == 0) return; // no blocks within, keep the miniumum computed before. + + QRectF boxFree; // the bounding box of free blocks. + foreach(BoxItem* item, blocks) { + QRectF boxItem = item->boundingRect(); + if (item->getPosition() == BoxItem::Free) { + boxItem.translate(item->pos()); + if (item->getSpan() == BoxItem::NoSpan) { + boxFree = boxFree.united(boxItem); + } + else if (item->getSpan() == BoxItem::HSpan) { + QRectF r(boxFree.left()+boxFree.width()/2.0,boxItem.top(),1,boxItem.height()); + boxFree = boxFree.united(r); + } + else if (item->getSpan() == BoxItem::VSpan) { + QRectF r(boxItem.left(),boxFree.top()+boxFree.height()/2.0,boxItem.width(),1); + boxFree = boxFree.united(r); + } + } + } + // find the move to apply to freely located items + double gapXLeft = 0.0; + double gapYTop = 0.0; + if (boxFree.left() < marginConn) { + gapXLeft = boxFree.left() - marginConn; + } + if (boxFree.top() < marginConn) { + gapYTop = boxFree.top() - marginConn; + } + // translate the box + boxFree.translate(-gapXLeft,-gapYTop); + minimumBoxWidth = boxFree.right() + marginConn; + minimumBoxHeight = boxFree.bottom() + marginConn; + + // find the highest/largest item stick on top/bottom/left/right + + qreal topHighest = 0.0; + qreal bottomHighest = 0.0; + qreal leftLargest = 0.0; + qreal rightLargest = 0.0; + + foreach(BoxItem* item, blocks) { + QRectF boxItem = item->boundingRect(); + + if (item->getPosition() == BoxItem::Top) { + + if (item->getSpan() == BoxItem::VSpan) { + if (item->getMinimumBoxHeight() > topHighest) { + topHighest = item->getMinimumBoxHeight(); } - if (item->getTotalHeight() > yMaxZero) { - yMaxZero = item->getTotalHeight(); + } + else { + if (boxItem.height()+marginConn > topHighest) { + topHighest = boxItem.height()+marginConn; + } + } + if (item->getSpan() == BoxItem::HSpan) { + if (item->getMinimumBoxWidth() > leftLargest) { + leftLargest = item->getMinimumBoxWidth(); + } + } + } + + if (item->getPosition() == BoxItem::Bottom) { + + if (item->getSpan() == BoxItem::VSpan) { + if (item->getMinimumBoxHeight() > bottomHighest) { + bottomHighest = item->getMinimumBoxHeight(); } } else { - isOtherBlocks = true; - if(p.x()+item->getTotalWidth() > xMax) { - xMax = p.x()+item->getTotalWidth(); + if (boxItem.height()+marginConn > bottomHighest) { + bottomHighest = boxItem.height()+marginConn; } - if(p.y()+item->getTotalHeight() > yMax) { - yMax = p.y()+item->getTotalHeight(); + } + if (item->getSpan() == BoxItem::HSpan) { + if (item->getMinimumBoxWidth() > leftLargest) { + leftLargest = item->getMinimumBoxWidth(); } } } - if (isZeroBlocks) { - if (!isOtherBlocks) { - minimumBoxWidth = xMaxZero+2*marginConn; - minimumBoxHeight = yMaxZero+2*marginConn; + + if (item->getPosition() == BoxItem::Left) { + + if (item->getSpan() == BoxItem::HSpan) { + if (item->getMinimumBoxWidth() > leftLargest) { + leftLargest = item->getMinimumBoxWidth(); + } } else { - if (xMaxZero+marginConn > xMax) { - minimumBoxWidth = xMaxZero+2*marginConn; + if (boxItem.width()+marginConn > leftLargest) { + leftLargest = boxItem.width()+marginConn; } - else { - minimumBoxWidth = xMax+marginConn; + } + if (item->getSpan() == BoxItem::VSpan) { + if (item->getMinimumBoxHeight() > topHighest) { + topHighest = item->getMinimumBoxHeight(); } - if (yMaxZero+marginConn > yMax) { - minimumBoxHeight = yMaxZero+2*marginConn; + } + } + + if (item->getPosition() == BoxItem::Right) { + + if (item->getSpan() == BoxItem::HSpan) { + if (item->getMinimumBoxWidth() > rightLargest) { + rightLargest = item->getMinimumBoxWidth(); } - else { - minimumBoxHeight = yMax+marginConn; + } + else { + if (boxItem.width()+marginConn > rightLargest) { + rightLargest = boxItem.width()+marginConn; + } + } + if (item->getSpan() == BoxItem::VSpan) { + if (item->getMinimumBoxHeight() > topHighest) { + topHighest = item->getMinimumBoxHeight(); } } } - else { - minimumBoxWidth = xMax+marginConn; - minimumBoxHeight = yMax+marginConn; + } + + if (leftLargest > minimumBoxWidth) { + minimumBoxWidth = leftLargest; + } + if (rightLargest > minimumBoxWidth) { + minimumBoxWidth = rightLargest; + } + if (topHighest > minimumBoxHeight) { + minimumBoxHeight = topHighest; + } + if (bottomHighest > minimumBoxHeight) { + minimumBoxHeight = bottomHighest; + } + // must move all free boxitem within of -gapXLeft,-gapYTop + foreach(BoxItem* item, blocks) { + if (item->getPosition() == BoxItem::Free) { + if (item->getSpan() == BoxItem::HSpan) { + item->moveBy(0,-gapYTop); + } + if (item->getSpan() == BoxItem::VSpan) { + item->moveBy(-gapXLeft,0); + } + else { + item->moveBy(-gapXLeft,-gapYTop); + } } } + //cout << "min group size: " << minimumBoxWidth << "," << minimumBoxHeight << endl; } @@ -188,6 +285,35 @@ void GroupItem::updateShape() { updateGeometry(InterfaceMove); } +void GroupItem::updateBorderSpanItems() { + QList blocks = getScene()->getBoxItems(); + bool changed = false; + foreach(BoxItem* item, blocks) { + changed = false; + if (item->getPosition() == BoxItem::Bottom) { + changed = true; + QPointF pos = item->pos(); + item->moveTo(QPointF(pos.x(),boxHeight-item->getTotalHeight())); + } + else if (item->getPosition() == BoxItem::Right) { + changed = true; + QPointF pos = item->pos(); + item->moveTo(QPointF(boxWidth-item->getTotalWidth(),pos.y())); + } + if (item->getSpan() == BoxItem::HSpan) { + changed = true; + item->setWidth(boxWidth); + } + else if (item->getSpan() == BoxItem::VSpan) { + changed = true; + item->setHeight(boxHeight); + } + if (changed) { + item->updateGeometry(Resize); + } + } +} + bool GroupItem::updateGeometry(ChangeType type) { QPointF oldOrigin = originPoint; @@ -198,21 +324,35 @@ bool GroupItem::updateGeometry(ChangeType type) { // whatever the change, the minimum size may have changed updateMinimumSize(); - if (type == Resize) { + if (type == Creation) { boxSizeChanged = true; - } - // if an internal block has moved, the actual box size may be inadequate - if (boxWidth < minimumBoxWidth) { boxWidth = minimumBoxWidth; - boxSizeChanged = true; - } - if (boxHeight < minimumBoxHeight) { boxHeight = minimumBoxHeight; - boxSizeChanged = true; + /* reset and update interfaces positions + * in case of spanning, the interface are positionned + * only on free borders. + */ + resetInterfaceItemsPosition(); } - - if (boxSizeChanged) { - updateInterfacesAndConnections(); + else if (type == Resize) { + boxSizeChanged = true; + updateInterfaceAndConnectionItems(); + updateBorderSpanItems(); + } + else if (type == InterfaceMove) { + // if an internal block has moved, the actual box size may be inadequate + if (boxWidth < minimumBoxWidth) { + boxWidth = minimumBoxWidth; + boxSizeChanged = true; + updateInterfaceAndConnectionItems(); + updateBorderSpanItems(); + } + if (boxHeight < minimumBoxHeight) { + boxHeight = minimumBoxHeight; + boxSizeChanged = true; + updateInterfaceAndConnectionItems(); + updateBorderSpanItems(); + } } @@ -293,7 +433,7 @@ void GroupItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (refBlock->isTopGroupBlock()) { QRectF rectGroup = boundingRectInScene(); rectGroup.moveTo(rectGroup.x()+gapX,rectGroup.y()+gapY); - foreach(SourceItem* source, getScene()->getSourceItems()) { + foreach(StimuliItem* source, getScene()->getSourceItems()) { QRectF rectSource = source->boundingRectInScene(); if (rectGroup.intersects(rectSource)) canMove = false; } @@ -359,7 +499,7 @@ void GroupItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { } else if(params->editState == Parameters::EditInterfaceMove) { prepareGeometryChange(); - moveInterfaceTo(event->pos()); + moveInterfaceItemTo(event->pos()); // recompute the geometry of the block updateGeometry(InterfaceMove); // update connection from/to the selected interface @@ -384,10 +524,10 @@ void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { int mode = getScene()->getEditionMode(); - dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget()); + dispatcher->setCurrentGroupWidget(Dispatcher::Design, getScene()->getGroupWidget()); if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) { - InterfaceItem *inter = getInterfaceFromCursor(x,y); + InterfaceItem *inter = getInterfaceItemFromCursor(x,y); if (inter != NULL) { if (params->editState == Parameters::EditNoOperation) { @@ -408,7 +548,7 @@ void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { else if (mode == GroupScene::ItemEdition) { if (params->cursorState == Parameters::CursorOnInterface) { - InterfaceItem *inter = getInterfaceFromCursor(x,y); + InterfaceItem *inter = getInterfaceItemFromCursor(x,y); if (inter != NULL) { currentInterface = inter; params->setEditState(Parameters::EditInterfaceMove); @@ -448,7 +588,7 @@ void GroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { else if (params->editState == Parameters::EditCloseConnection) { InterfaceItem* iface1 = getScene()->getSelectedInterface(1); InterfaceItem* iface2 = getScene()->getSelectedInterface(2); - bool ok = dispatcher->createConnectionItem(iface1,iface2); + bool ok = dispatcher->createConnection(Dispatcher::Design, iface1,iface2); if (ok) { iface1->selected = false; update(iface1->boundingRect()); @@ -481,7 +621,7 @@ void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { int mode = getScene()->getEditionMode(); if (mode == GroupScene::AddConnection) { - InterfaceItem* iface = getInterfaceFromCursor(x,y); + InterfaceItem* iface = getInterfaceItemFromCursor(x,y); if (iface != NULL) { params->cursorState = Parameters::CursorOnInterface; setCursor(Qt::PointingHandCursor); @@ -495,7 +635,7 @@ void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { int marginE = 5; int marginS = 5; - InterfaceItem* iface = getInterfaceFromCursor(x,y); + InterfaceItem* iface = getInterfaceItemFromCursor(x,y); if (iface != NULL) { params->cursorState = Parameters::CursorOnInterface; setCursor(Qt::PointingHandCursor); @@ -506,11 +646,11 @@ void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { if ((y>boxHeight-2*marginS)&&(yboxHeight-marginS)&&(yboxWidth-2*marginE)&&(xignore(); + } } void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { @@ -548,8 +686,9 @@ void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { QAction* removeAction = NULL; QAction* renameAction = NULL; QAction* showParameters = NULL; + QAction* addExtClkAction = NULL; - InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y()); + InterfaceItem* ifaceItem = getInterfaceItemFromCursor(event->pos().x(), event->pos().y()); // menu for interface if( ifaceItem != NULL) { @@ -578,6 +717,10 @@ void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { showParameters = menu.addAction("Show parameters"); } renameAction = menu.addAction("Rename"); + if (refBlock->isTopGroupBlock()) { + addExtClkAction = menu.addAction("Add new external clock/reset"); + } + } QAction* selectedAction = menu.exec(event->screenPos()); @@ -585,19 +728,25 @@ void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { if(selectedAction == renameAction){ if(ifaceItem != NULL) - dispatcher->renameInterface(ifaceItem); + dispatcher->renameInterface(Dispatcher::Design, ifaceItem); else - dispatcher->renameGroupBlock(this); + dispatcher->renameGroupBlock(Dispatcher::Design, this); } else if(selectedAction == showProperties){ - dispatcher->showProperties(ifaceItem); + dispatcher->showProperties(Dispatcher::Design, ifaceItem); } else if (selectedAction == removeAction) { - dispatcher->removeGroupInterface(ifaceItem); + dispatcher->removeGroupInterface(Dispatcher::Design, ifaceItem); } else if(selectedAction == showParameters) { new ParametersWindow(refBlock, params, NULL); - } + } + else if (selectedAction == addExtClkAction) { + bool ok = false; + double freq = QInputDialog::getDouble(NULL,"Adding a clkrstgen","External clock frequency (in MHz)",100,0,100000,1,&ok); + if (!ok) return; + dispatcher->addClkRstGenBlock(Dispatcher::Design, freq); + } } InterfaceItem* GroupItem::isHoverInterface(QPointF point) { @@ -618,7 +767,7 @@ void GroupItem::load(QDomElement groupElement) throw(Exception) { if(!ok) throw(Exception(PROJECTFILE_CORRUPTED)); QString nameStr = groupElement.attribute("name","none"); - if(nameStr == "none") throw(Exception(PROJECTFILE_CORRUPTED)); + if(nameStr == "none") throw(Exception(PROJECTFILE_CORRUPTED)); QStringList positionStr = groupElement.attribute("position","none").split(","); if(positionStr.length() != 2) throw(Exception(PROJECTFILE_CORRUPTED)); @@ -651,6 +800,10 @@ void GroupItem::load(QDomElement groupElement) throw(Exception) { QString name = currentInterfaceNode.attribute("name","none"); if(name == "none") throw(Exception(PROJECTFILE_CORRUPTED)); + QString purposeStr = currentInterfaceNode.attribute("purpose","none"); + int purpose = AbstractInterface::getIntPurpose(purposeStr); + if(purpose == -1) throw(Exception(PROJECTFILE_CORRUPTED)); + QString directionStr = currentInterfaceNode.attribute("direction","none"); int direction = AbstractInterface::getIntDirection(directionStr); if(direction == -1) throw(Exception(PROJECTFILE_CORRUPTED)); @@ -661,15 +814,24 @@ void GroupItem::load(QDomElement groupElement) throw(Exception) { double position = currentInterfaceNode.attribute("position","none").toDouble(&ok); if(!ok) throw(Exception(PROJECTFILE_CORRUPTED)); + + GroupInterface *groupIface = new GroupInterface(groupBlock,name,direction,purpose); + groupBlock->addInterface(groupIface); + bool show = false; + if ((groupBlock->isTopGroupBlock()) && (purpose == AbstractInterface::Clock)) { + show = true; + } - GroupInterface *groupInterface = new GroupInterface(groupBlock,name,direction,AbstractInterface::Data); - - InterfaceItem *interfaceItem = new InterfaceItem(position,orientation,groupInterface,this,params); + InterfaceItem *interfaceItem = new InterfaceItem(position,orientation,groupIface,this,params,show); interfaceItem->setId(id); + addInterfaceItem(interfaceItem, false); - groupBlock->addInterface(groupInterface); - addInterface(interfaceItem, false); - cout << "interface add to " << groupBlock->getName().toStdString() << endl; + if (purpose == AbstractInterface::Data) { + GroupInterface *groupCtlIface = new GroupInterface(groupBlock,name+"_enb",direction,AbstractInterface::Control); + groupCtlIface->setAssociatedIface(groupIface); + groupBlock->addInterface(groupCtlIface); + } + cout << "interface " << qPrintable(name) << " added to " << groupBlock->getName().toStdString() << endl; } } @@ -703,6 +865,7 @@ void GroupItem::save(QXmlStreamWriter &writer) { writer.writeAttribute("id",QString::number(item->getId())); writer.writeAttribute("name",item->getName()); + writer.writeAttribute("purpose",QString(item->refInter->getPurposeString())); writer.writeAttribute("direction",QString(item->refInter->getDirectionString())); writer.writeAttribute("orientation",item->getStrOrientation()); writer.writeAttribute("position",QString::number(item->getPositionRatio()));