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"
17 BoxItem::BoxItem(AbstractBlock *_refBlock,
18 Dispatcher *_dispatcher,
19 Parameters *_params, GroupItem *parent) throw(Exception) : AbstractBoxItem( _refBlock, _dispatcher, _params, parent) {
22 _refBlock : mandatory a FunctionalBlock or a GroupBlock
24 if (_refBlock->isReferenceBlock()) throw(Exception(BLOCK_INVALID_TYPE));
26 childGroupItem = NULL;
27 //boxWidth = params->defaultBlockWidth;
28 //boxHeight = params->defaultBlockHeight;
29 currentBorder = NoBorder;
33 setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
37 resetInterfacesPosition();
38 QPointF initPos = QPointF(0.0,0.0) - originPoint;
40 //cout << "total size of block: " << totalWidth << "," << totalHeight << endl;
41 //cout << "pos in group: " << x() << "," << y() << endl;
48 void BoxItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
49 QPen pen(Qt::black, 3);
51 pen.setColor(Qt::red);
54 painter->setBrush(Qt::yellow);
56 painter->drawRect(0,0,boxWidth, boxHeight);
57 painter->drawText(0,0,boxWidth, boxHeight,Qt::AlignCenter | Qt::TextWordWrap,QString(refBlock->getName()));
58 foreach(InterfaceItem *inter, interfaces) {
59 inter->paint(painter);
63 void BoxItem::moveTo(QPointF dest) {
65 currentPosition = dest;
68 bool BoxItem::isBoxItem() {
72 void BoxItem::updateMinimumSize() {
78 int nbSouth = nbInterfacesByOrientation(Parameters::South);
79 int nbNorth = nbInterfacesByOrientation(Parameters::North);
80 int nbMaxSN = nbNorth;
81 if (nbSouth > nbNorth) nbMaxSN = nbSouth;
82 int nbEast = nbInterfacesByOrientation(Parameters::East);
83 int nbWest = nbInterfacesByOrientation(Parameters::West);
85 if (nbWest > nbEast) {
92 foreach(InterfaceItem* iface, interfaces) {
93 ifaceWidth = iface->getNameWidth();
94 ifaceHeight = iface->getNameHeight();
95 if (iface->getOrientation() == Parameters::South) {
96 if (ifaceWidth > maxSouth) maxSouth = ifaceWidth;
98 else if (iface->getOrientation() == Parameters::North) {
99 if (ifaceWidth > maxNorth) maxNorth = ifaceWidth;
101 else if (iface->getOrientation() == Parameters::East) {
102 if (ifaceWidth > maxEast) maxEast = ifaceWidth;
104 else if (iface->getOrientation() == Parameters::West) {
105 if (ifaceWidth > maxWest) maxWest = ifaceWidth;
109 /* NB: the width layout is the following
110 ifaceMargin | maxWest | nameMargin | name | nameMargin | maxEast | ifaceMargin
112 minimumBoxWidth = maxWest+maxEast+nameWidth+2*(ifaceMargin+nameMargin);
113 // if the minimum is not sufficent taking into account N/S interfaces
114 if (minimumBoxWidth < (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1))) {
115 minimumBoxWidth = (nbMaxSN*ifaceHeight+ifaceMargin*(nbMaxSN+1));
117 minimumBoxHeight = maxNorth+maxSouth+3*ifaceMargin;
118 if (minimumBoxHeight < (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1))) {
119 minimumBoxHeight = (nbMaxEW*ifaceHeight+ifaceMargin*(nbMaxEW+1));
124 /* updateGeometry() :
127 bool BoxItem::updateGeometry(ChangeType type) {
129 currentPosition = pos();
130 //cout << "current pos of block: " << currentPosition.x() << "," << currentPosition.y() << endl;
131 QPointF oldOrigin = originPoint;
132 QSize oldSize(totalWidth,totalHeight);
134 bool boxSizeChanged = false;
136 if ((type == Resize) || (type == InterfaceMove)) {
140 if (type == Resize) {
141 prepareGeometryChange();
142 updateInterfacesAndConnections();
143 boxSizeChanged = true;
145 if (boxWidth < minimumBoxWidth) {
146 boxWidth = minimumBoxWidth;
147 boxSizeChanged = true;
149 if (boxHeight < minimumBoxHeight) {
150 boxHeight = minimumBoxHeight;
151 boxSizeChanged = true;
153 if (boxSizeChanged) {
154 updateInterfacesAndConnections();
159 totalWidth = boxWidth;
160 totalHeight = boxHeight;
162 if(isInterfaces(Parameters::East)){
163 totalWidth += params->arrowWidth+params->arrowLineLength;
165 if(isInterfaces(Parameters::West)){
166 totalWidth += params->arrowWidth+params->arrowLineLength;
167 x -= params->arrowWidth+params->arrowLineLength;
169 if(isInterfaces(Parameters::South)){
170 totalHeight += params->arrowWidth+params->arrowLineLength;
172 if(isInterfaces(Parameters::North)){
173 totalHeight += params->arrowWidth+params->arrowLineLength;
174 y -= params->arrowWidth+params->arrowLineLength;
176 QSizeF newSize(totalWidth,totalHeight);
180 if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
181 prepareGeometryChange();
187 void BoxItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
189 if(params->editState == Parameters::EditBlockMove) {
190 QPointF absPos = currentPosition + originPoint;
191 int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
192 int gapX = event->scenePos().x() - cursorPosition.x();
193 int gapY = event->scenePos().y() - cursorPosition.y();
195 //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
196 //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
198 if (absPos.x()+gapX < marginConn) {
199 gapX = marginConn-absPos.x();
201 if (absPos.y()+gapY < marginConn) {
202 gapY = marginConn-absPos.y();
204 //cout << "gap: " << gapX << "," << gapY << endl;
205 QPointF gap(gapX,gapY);
206 currentPosition = currentPosition+gap;
207 setPos(currentPosition);
208 // update all connections from/to this block
209 foreach(ConnectionItem *item, getScene()->getConnectionItems()){
210 if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
214 cursorPosition = event->scenePos();
216 // udpate the groupitem
217 (getScene()->getGroupItem())->updateShape();
219 else if(params->editState == Parameters::EditBlockResize) {
221 int gapX = event->scenePos().x() - cursorPosition.x();
222 int gapY = event->scenePos().y() - cursorPosition.y();
223 //cout << "gap: " << gapX << "," << gapY << endl;
224 switch(currentBorder){
226 if(boxWidth+gapX > minimumBoxWidth){
232 if(boxHeight+gapY > minimumBoxHeight){
237 case CornerSouthEast: {
238 if(boxWidth+gapX > minimumBoxWidth){
241 if(boxHeight+gapY > minimumBoxHeight){
247 cout << "abnormal case while resizing block" << endl;
250 // recompute the geometry of the block and possibly the group item
251 if (updateGeometry()) {
252 (getScene()->getGroupItem())->updateShape();
255 cursorPosition = event->scenePos();
257 else if(params->editState == Parameters::EditInterfaceMove) {
258 prepareGeometryChange();
259 deplaceInterface(event->pos());
260 // recompute the geometry of the block
261 if (updateGeometry()) {
262 cout << "must recompute group item geometry" << endl;
263 (getScene()->getGroupItem())->updateShape();
265 // update connection from/to the selected interface
266 foreach(ConnectionItem *item, getScene()->getConnectionItems()){
267 if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
274 void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
276 QPointF pos = event->pos();
280 //QGraphicsItem::mousePressEvent(event);
282 if(event->button() == Qt::RightButton) return;
284 int mode = getScene()->getEditionMode();
286 dispatcher->setCurrentGroupWidget(getScene()->getGroupWindow());
288 if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
289 InterfaceItem *inter = getInterfaceFromCursor(x,y);
292 if (params->editState == Parameters::EditNoOperation) {
293 getScene()->setSelectedInterface(1,inter);
294 params->setEditState(Parameters::EditStartConnection);
296 else if (params->editState == Parameters::EditStartConnection) {
297 if (inter == getScene()->getSelectedInterface(1)) {
298 params->setEditState(Parameters::EditAbortConnection);
301 getScene()->setSelectedInterface(2,inter);
302 params->setEditState(Parameters::EditCloseConnection);
307 else if (mode == GroupScene::ItemEdition) {
308 setZValue(zValue()+100);
309 if (params->cursorState == Parameters::CursorOnInterface) {
310 InterfaceItem *inter = getInterfaceFromCursor(x,y);
312 if (inter == currentInterface) {
313 params->setEditState(Parameters::EditInterfaceDeselect);
316 setFlag(ItemIsMovable, false);
317 currentInterface = inter;
318 params->setEditState(Parameters::EditInterfaceMove);
322 else if (params->cursorState == Parameters::CursorInBlock) {
323 selected = !selected;
324 params->setEditState(Parameters::EditBlockMove);
325 cursorPosition = event->scenePos();
326 //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
329 else if (params->cursorState == Parameters::CursorOnBorder) {
330 setFlag(ItemIsMovable, false);
331 cursorPosition = event->scenePos();
332 params->setEditState(Parameters::EditBlockResize);
337 void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
339 setZValue(zValue()-100);
341 int mode = getScene()->getEditionMode();
343 if (mode == GroupScene::AddConnection) {
345 if (params->editState == Parameters::EditStartConnection) {
346 InterfaceItem* iface = getScene()->getSelectedInterface(1);
347 iface->selected = true;
348 update(iface->boundingRect());
350 else if (params->editState == Parameters::EditAbortConnection) {
351 InterfaceItem* iface = getScene()->getSelectedInterface(1);
352 iface->selected = false;
353 update(iface->boundingRect());
354 getScene()->setSelectedInterface(1,NULL);
355 params->setEditState(Parameters::EditNoOperation);
357 else if (params->editState == Parameters::EditCloseConnection) {
358 InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
359 InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
360 bool ok = dispatcher->connect(iface1,iface2);
362 iface1->selected = false;
363 // no update needed since the whole scene will be repainted
364 getScene()->setSelectedInterface(1,NULL);
365 getScene()->setSelectedInterface(2,NULL);
366 params->setEditState(Parameters::EditNoOperation);
369 getScene()->setSelectedInterface(2,NULL);
370 params->setEditState(Parameters::EditStartConnection);
374 else if (mode == GroupScene::ItemEdition) {
375 currentInterface = NULL;
376 params->editState = Parameters::EditNoOperation;
377 setFlag(ItemIsMovable);
380 QGraphicsItem::mouseReleaseEvent(event);
383 void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
385 QPointF pos = event->pos();
388 currentBorder = NoBorder;
389 int mode = getScene()->getEditionMode();
391 if (mode == GroupScene::AddConnection) {
392 InterfaceItem* iface = getInterfaceFromCursor(x,y);
394 params->cursorState = Parameters::CursorOnInterface;
395 setCursor(Qt::PointingHandCursor);
398 params->cursorState = Parameters::CursorNowhere;
399 setCursor(Qt::ArrowCursor);
402 else if (mode == GroupScene::ItemEdition) {
406 InterfaceItem* iface = getInterfaceFromCursor(x,y);
408 params->cursorState = Parameters::CursorOnInterface;
409 setCursor(Qt::PointingHandCursor);
411 else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
413 params->cursorState = Parameters::CursorOnBorder;
415 if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
416 currentBorder = CornerSouthEast;
417 setCursor(Qt::SizeFDiagCursor);
420 currentBorder = BorderEast;
421 setCursor(Qt::SizeHorCursor);
424 else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
426 params->cursorState = Parameters::CursorOnBorder;
428 if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
429 currentBorder = CornerSouthEast;
430 setCursor(Qt::SizeFDiagCursor);
433 currentBorder = BorderSouth;
434 setCursor(Qt::SizeVerCursor);
438 if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
439 params->cursorState = Parameters::CursorInBlock;
440 setCursor(Qt::OpenHandCursor);
443 params->cursorState = Parameters::CursorNowhere;
444 setCursor(Qt::ArrowCursor);
448 QGraphicsItem::hoverMoveEvent(event);
452 void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
455 QAction* removeAction = menu.addAction("Remove");
456 QAction* duplicateAction = menu.addAction("Duplicate");
457 QAction* renameAction = menu.addAction("Rename");
458 QAction* connectToGroup = NULL;
459 QAction* disconnectFromGroup = NULL;
460 QAction* showProperties = NULL;
461 QAction* cloneInterface = NULL;
462 QAction* openWindow = NULL;
463 QAction* showRstClkInter = NULL;
464 QAction* showParameters = NULL;
466 InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
467 if( ifaceItem != NULL){
468 showProperties = menu.addAction("Show properties");
470 ConnectedInterface* iface = ifaceItem->refInter;
471 if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) {
472 connectToGroup = menu.addAction("Connect to group input");
474 else if ((iface->getDirection() == AbstractInterface::Output) && (!iface->isConnectedTo())) {
475 connectToGroup = menu.addAction("Connect to group output");
477 else if ((iface->getConnectionFromParentGroup() != NULL) || (iface->getConnectionToParentGroup() != NULL)) {
478 disconnectFromGroup = menu.addAction("Disconnect from group");
481 if (iface->isFunctionalInterface()) {
482 FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter);
483 ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference());
484 if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){
485 cloneInterface = menu.addAction("Clone interface");
489 if(refBlock->isGroupBlock()){
490 openWindow = menu.addAction("Open/show group window");
492 showRstClkInter = menu.addAction("Show reset/clock interfaces");
493 showRstClkInter->setCheckable(true);
494 showRstClkInter->setChecked(rstClkVisible);
496 showParameters = menu.addAction("Show parameters");
499 QAction* selectedAction = NULL;
500 selectedAction = menu.exec(event->screenPos());
502 if(selectedAction == NULL) return ;
504 if (selectedAction == removeAction) {
505 dispatcher->removeBlock(this);
507 else if (selectedAction == duplicateAction) {
508 dispatcher->duplicateBlock(this);
510 else if(selectedAction == renameAction){
511 if(ifaceItem != NULL)
512 dispatcher->rename(ifaceItem);
514 dispatcher->rename(this);
516 else if(selectedAction == showProperties){
517 dispatcher->showProperties(ifaceItem);
519 else if (selectedAction == connectToGroup){
520 dispatcher->connectInterToGroup(ifaceItem);
522 else if (selectedAction == disconnectFromGroup) {
523 dispatcher->disconnectInterFromGroup(ifaceItem);
525 else if (selectedAction == cloneInterface){
526 dispatcher->duplicateInterface(ifaceItem);
528 else if (selectedAction == openWindow){
529 dispatcher->showRaiseWindow(this);
531 else if(selectedAction == showRstClkInter){
532 dispatcher->showRstClkInter(this);
534 else if(selectedAction == showParameters){
535 new ParametersWindow(refBlock, params, NULL);
539 void BoxItem::save(QXmlStreamWriter &writer) {
540 if (refBlock->isFunctionalBlock()) {
541 writer.writeStartElement("bi_functional");
543 writer.writeAttribute("id",QString::number(id));
544 writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
545 writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
546 writer.writeAttribute("name",refBlock->getName());
547 QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
548 writer.writeAttribute("position",attrPos);
549 QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
550 writer.writeAttribute("dimension",attrDim);
552 writer.writeStartElement("bif_parameters");
553 foreach(BlockParameter *param,refBlock->getParameters()){
554 writer.writeStartElement("bif_parameter");
556 writer.writeAttribute("name",param->getName());
557 writer.writeAttribute("value",param->getValue().toString());
559 writer.writeAttribute("context",param->getStrContext());
560 writer.writeAttribute("type",param->getTypeString());
562 writer.writeEndElement(); //</bif_parameter>
564 writer.writeEndElement(); //</bif_parameters>
566 writer.writeStartElement("bif_ifaces");
567 writer.writeAttribute("count",QString::number(interfaces.length()));
568 foreach(InterfaceItem* inter, interfaces){
569 writer.writeStartElement("bif_iface");
571 writer.writeAttribute("id",QString::number(inter->getId()));
572 writer.writeAttribute("name",inter->getName());
573 writer.writeAttribute("ref_name",inter->refInter->getName());
574 writer.writeAttribute("orientation",inter->getStrOrientation());
575 writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
577 writer.writeEndElement(); //</bif_iface>
579 writer.writeEndElement(); //</bif_ifaces>
581 writer.writeEndElement(); //</bi_functional>
584 writer.writeStartElement("bi_group");
586 writer.writeAttribute("id",QString::number(id));
587 writer.writeAttribute("inside_group",QString::number(childGroupItem->getId()));
588 QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
589 writer.writeAttribute("position",attrPos);
590 QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
591 writer.writeAttribute("dimension",attrDim);
593 writer.writeStartElement("big_ifaces");
594 writer.writeAttribute("count",QString::number(interfaces.length()));
595 foreach(InterfaceItem* inter, interfaces){
596 writer.writeStartElement("big_iface");
598 writer.writeAttribute("id",QString::number(inter->getId()));
599 writer.writeAttribute("ref_name",inter->refInter->getName());
600 writer.writeAttribute("orientation",inter->getStrOrientation());
601 writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
603 writer.writeEndElement(); //</big_iface>
606 writer.writeEndElement(); //</big_ifaces>
607 writer.writeEndElement(); //</bi_group>
611 QDataStream &operator <<(QDataStream &out, BoxItem &b) {
612 out.setVersion(QDataStream::Qt_4_8);
614 QByteArray blockData;
615 QDataStream toWrite(&blockData, QIODevice::WriteOnly);
617 QString refXml = ((FunctionalBlock*)b.refBlock)->getReferenceXmlFile();
618 QByteArray xmlFile = QByteArray(refXml.toStdString().c_str());
622 toWrite << (int)b.x();
623 toWrite << (int)b.y();
624 toWrite << b.boxWidth;
625 toWrite << b.boxHeight;
626 toWrite << b.getInterfaces().length();
628 for(int i=0; i<b.getInterfaces().length(); i++){
629 InterfaceItem *inter = b.getInterfaces().at(i);
630 toWrite << inter->getId();
631 toWrite << inter->getName();
632 toWrite << inter->getPositionRatio();
633 toWrite << inter->getOrientation();
641 QDataStream &operator >>(QDataStream &in, BoxItem &b)
644 in.setVersion(QDataStream::Qt_4_8);
659 cout << "nbInter:" << nbInter << endl;
660 for(int i=0; i<nbInter; i++){
663 double positionRatio;
666 InterfaceItem *inter = b.getInterfaces().at(i);
673 inter->setName(name);
674 inter->setPositionRatio(positionRatio);
675 inter->setOrientation(orientation);
676 inter->updatePosition();