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);
36 updateGeometry(InterfaceMove);
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 // whatever the change, the minimum size may ahve changed
139 if (type == Resize) {
140 // resize implies to move interfaces and to update connections
141 boxSizeChanged = true;
143 else if (type == InterfaceMove) {
144 // if an interface moves, it may change the box size
145 if (boxWidth < minimumBoxWidth) {
146 boxWidth = minimumBoxWidth;
147 boxSizeChanged = true;
149 if (boxHeight < minimumBoxHeight) {
150 boxHeight = minimumBoxHeight;
151 boxSizeChanged = true;
154 if (boxSizeChanged) {
155 updateInterfacesAndConnections();
161 totalWidth = boxWidth;
162 totalHeight = boxHeight;
164 if(isInterfaces(Parameters::East)){
165 totalWidth += params->arrowWidth+params->arrowLineLength;
167 if(isInterfaces(Parameters::West)){
168 totalWidth += params->arrowWidth+params->arrowLineLength;
169 x -= params->arrowWidth+params->arrowLineLength;
171 if(isInterfaces(Parameters::South)){
172 totalHeight += params->arrowWidth+params->arrowLineLength;
174 if(isInterfaces(Parameters::North)){
175 totalHeight += params->arrowWidth+params->arrowLineLength;
176 y -= params->arrowWidth+params->arrowLineLength;
178 QSizeF newSize(totalWidth,totalHeight);
182 if ((boxSizeChanged) || (newSize != oldSize) || (originPoint != oldOrigin)) {
183 prepareGeometryChange();
189 void BoxItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
191 if(params->editState == Parameters::EditBlockMove) {
192 QPointF absPos = currentPosition + originPoint;
193 int marginConn = 2*(params->arrowWidth+params->arrowLineLength);
194 int gapX = event->scenePos().x() - cursorPosition.x();
195 int gapY = event->scenePos().y() - cursorPosition.y();
197 //cout << "block abs. pos: " << absPos.x() << "," << absPos.y() << " | ";
198 //cout << "block current. pos: " << currentPosition.x() << "," << currentPosition.y() << " | ";
200 if (absPos.x()+gapX < marginConn) {
201 gapX = marginConn-absPos.x();
203 if (absPos.y()+gapY < marginConn) {
204 gapY = marginConn-absPos.y();
206 //cout << "gap: " << gapX << "," << gapY << endl;
207 QPointF gap(gapX,gapY);
208 currentPosition = currentPosition+gap;
209 setPos(currentPosition);
210 // update all connections from/to this block
211 foreach(ConnectionItem *item, getScene()->getConnectionItems()){
212 if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
216 cursorPosition = event->scenePos();
218 // udpate the groupitem
219 (getScene()->getGroupItem())->updateShape();
221 else if(params->editState == Parameters::EditBlockResize) {
223 int gapX = event->scenePos().x() - cursorPosition.x();
224 int gapY = event->scenePos().y() - cursorPosition.y();
225 //cout << "gap: " << gapX << "," << gapY << endl;
226 switch(currentBorder){
228 if(boxWidth+gapX > minimumBoxWidth){
234 if(boxHeight+gapY > minimumBoxHeight){
239 case CornerSouthEast: {
240 if(boxWidth+gapX > minimumBoxWidth){
243 if(boxHeight+gapY > minimumBoxHeight){
249 cout << "abnormal case while resizing block" << endl;
252 // recompute the geometry of the block and possibly the group item
253 if (updateGeometry(Resize)) {
254 (getScene()->getGroupItem())->updateShape();
257 cursorPosition = event->scenePos();
259 else if(params->editState == Parameters::EditInterfaceMove) {
260 prepareGeometryChange();
261 moveInterfaceTo(event->pos());
262 // recompute the geometry of the block
263 if (updateGeometry(InterfaceMove)) {
264 cout << "must recompute group item geometry" << endl;
265 (getScene()->getGroupItem())->updateShape();
267 // update connection from/to the selected interface
268 foreach(ConnectionItem *item, getScene()->getConnectionItems()){
269 if ((item->getFromInterfaceItem() == currentInterface) || (item->getToInterfaceItem() == currentInterface)) {
276 void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
278 QPointF pos = event->pos();
282 //QGraphicsItem::mousePressEvent(event);
284 if(event->button() == Qt::RightButton) return;
286 int mode = getScene()->getEditionMode();
288 dispatcher->setCurrentGroupWidget(getScene()->getGroupWindow());
290 if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) {
291 InterfaceItem *inter = getInterfaceFromCursor(x,y);
294 if (params->editState == Parameters::EditNoOperation) {
295 getScene()->setSelectedInterface(1,inter);
296 params->setEditState(Parameters::EditStartConnection);
298 else if (params->editState == Parameters::EditStartConnection) {
299 if (inter == getScene()->getSelectedInterface(1)) {
300 params->setEditState(Parameters::EditAbortConnection);
303 getScene()->setSelectedInterface(2,inter);
304 params->setEditState(Parameters::EditCloseConnection);
309 else if (mode == GroupScene::ItemEdition) {
310 setZValue(zValue()+100);
311 if (params->cursorState == Parameters::CursorOnInterface) {
312 InterfaceItem *inter = getInterfaceFromCursor(x,y);
314 if (inter == currentInterface) {
315 params->setEditState(Parameters::EditInterfaceDeselect);
318 setFlag(ItemIsMovable, false);
319 currentInterface = inter;
320 params->setEditState(Parameters::EditInterfaceMove);
324 else if (params->cursorState == Parameters::CursorInBlock) {
325 selected = !selected;
326 params->setEditState(Parameters::EditBlockMove);
327 cursorPosition = event->scenePos();
328 //cout << "cursor current pos. in scene " << cursorPosition.x() << "," << cursorPosition.y() << endl;
331 else if (params->cursorState == Parameters::CursorOnBorder) {
332 setFlag(ItemIsMovable, false);
333 cursorPosition = event->scenePos();
334 params->setEditState(Parameters::EditBlockResize);
339 void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
341 setZValue(zValue()-100);
343 int mode = getScene()->getEditionMode();
345 if (mode == GroupScene::AddConnection) {
347 if (params->editState == Parameters::EditStartConnection) {
348 InterfaceItem* iface = getScene()->getSelectedInterface(1);
349 iface->selected = true;
350 update(iface->boundingRect());
352 else if (params->editState == Parameters::EditAbortConnection) {
353 InterfaceItem* iface = getScene()->getSelectedInterface(1);
354 iface->selected = false;
355 update(iface->boundingRect());
356 getScene()->setSelectedInterface(1,NULL);
357 params->setEditState(Parameters::EditNoOperation);
359 else if (params->editState == Parameters::EditCloseConnection) {
360 InterfaceItem* iface1 = getScene()->getSelectedInterface(1);
361 InterfaceItem* iface2 = getScene()->getSelectedInterface(2);
362 bool ok = dispatcher->connect(iface1,iface2);
364 iface1->selected = false;
365 // no update needed since the whole scene will be repainted
366 getScene()->setSelectedInterface(1,NULL);
367 getScene()->setSelectedInterface(2,NULL);
368 params->setEditState(Parameters::EditNoOperation);
371 getScene()->setSelectedInterface(2,NULL);
372 params->setEditState(Parameters::EditStartConnection);
376 else if (mode == GroupScene::ItemEdition) {
377 currentInterface = NULL;
378 params->editState = Parameters::EditNoOperation;
379 setFlag(ItemIsMovable);
382 QGraphicsItem::mouseReleaseEvent(event);
385 void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) {
387 QPointF pos = event->pos();
390 currentBorder = NoBorder;
391 int mode = getScene()->getEditionMode();
393 if (mode == GroupScene::AddConnection) {
394 InterfaceItem* iface = getInterfaceFromCursor(x,y);
396 params->cursorState = Parameters::CursorOnInterface;
397 setCursor(Qt::PointingHandCursor);
400 params->cursorState = Parameters::CursorNowhere;
401 setCursor(Qt::ArrowCursor);
404 else if (mode == GroupScene::ItemEdition) {
408 InterfaceItem* iface = getInterfaceFromCursor(x,y);
410 params->cursorState = Parameters::CursorOnInterface;
411 setCursor(Qt::PointingHandCursor);
413 else if ((x>boxWidth-marginE)&&(x<boxWidth)) {
415 params->cursorState = Parameters::CursorOnBorder;
417 if ((y>boxHeight-2*marginS)&&(y<boxHeight)) {
418 currentBorder = CornerSouthEast;
419 setCursor(Qt::SizeFDiagCursor);
422 currentBorder = BorderEast;
423 setCursor(Qt::SizeHorCursor);
426 else if ((y>boxHeight-marginS)&&(y<boxHeight)) {
428 params->cursorState = Parameters::CursorOnBorder;
430 if ((x>boxWidth-2*marginE)&&(x<boxWidth)) {
431 currentBorder = CornerSouthEast;
432 setCursor(Qt::SizeFDiagCursor);
435 currentBorder = BorderSouth;
436 setCursor(Qt::SizeVerCursor);
440 if ((x>0) && (x<boxWidth-marginE) && (y>0) && (y<boxHeight-marginS)) {
441 params->cursorState = Parameters::CursorInBlock;
442 setCursor(Qt::OpenHandCursor);
445 params->cursorState = Parameters::CursorNowhere;
446 setCursor(Qt::ArrowCursor);
450 QGraphicsItem::hoverMoveEvent(event);
454 void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) {
457 QAction* removeAction = menu.addAction("Remove");
458 QAction* duplicateAction = menu.addAction("Duplicate");
459 QAction* renameAction = menu.addAction("Rename");
460 QAction* connectToGroup = NULL;
461 QAction* disconnectFromGroup = NULL;
462 QAction* showProperties = NULL;
463 QAction* cloneInterface = NULL;
464 QAction* openWindow = NULL;
465 QAction* showRstClkInter = NULL;
466 QAction* showParameters = NULL;
468 InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y());
469 if( ifaceItem != NULL){
470 showProperties = menu.addAction("Show properties");
472 ConnectedInterface* iface = ifaceItem->refInter;
473 ConnectedInterface* ifaceGroup = NULL;
476 if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) {
477 connectToGroup = menu.addAction("Connect to group input");
479 else if ((iface->getDirection() == AbstractInterface::Output) && (!iface->isConnectedTo())) {
480 connectToGroup = menu.addAction("Connect to group output");
482 else if (iface->getConnectionFromParentGroup() != NULL) {
483 ifaceGroup = iface->getConnectionFromParentGroup();
484 if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) {
485 disconnectFromGroup = menu.addAction("Disconnect from group");
488 else if (iface->getConnectionToParentGroup() != NULL) {
489 ifaceGroup = iface->getConnectionToParentGroup();
490 if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) {
491 disconnectFromGroup = menu.addAction("Disconnect from group");
495 if (iface->isFunctionalInterface()) {
496 FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter);
497 ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference());
498 if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){
499 cloneInterface = menu.addAction("Clone interface");
503 if(refBlock->isGroupBlock()){
504 openWindow = menu.addAction("Open/show group window");
506 showRstClkInter = menu.addAction("Show reset/clock interfaces");
507 showRstClkInter->setCheckable(true);
508 showRstClkInter->setChecked(rstClkVisible);
510 showParameters = menu.addAction("Show parameters");
513 QAction* selectedAction = NULL;
514 selectedAction = menu.exec(event->screenPos());
516 if(selectedAction == NULL) return ;
518 if (selectedAction == removeAction) {
519 dispatcher->removeBlock(this);
521 else if (selectedAction == duplicateAction) {
522 dispatcher->duplicateBlock(this);
524 else if(selectedAction == renameAction){
525 if(ifaceItem != NULL)
526 dispatcher->rename(ifaceItem);
528 dispatcher->rename(this);
530 else if(selectedAction == showProperties){
531 dispatcher->showProperties(ifaceItem);
533 else if (selectedAction == connectToGroup){
534 dispatcher->connectInterToGroup(ifaceItem);
536 else if (selectedAction == disconnectFromGroup) {
537 dispatcher->disconnectInterFromGroup(ifaceItem);
539 else if (selectedAction == cloneInterface){
540 dispatcher->duplicateInterface(ifaceItem);
542 else if (selectedAction == openWindow){
543 dispatcher->showRaiseWindow(this);
545 else if(selectedAction == showRstClkInter){
546 dispatcher->showRstClkInter(this);
548 else if(selectedAction == showParameters){
549 new ParametersWindow(refBlock, params, NULL);
553 void BoxItem::save(QXmlStreamWriter &writer) {
554 if (refBlock->isFunctionalBlock()) {
555 writer.writeStartElement("bi_functional");
557 writer.writeAttribute("id",QString::number(id));
558 writer.writeAttribute("ref_xml", ((FunctionalBlock*)refBlock)->getReferenceXmlFile());
559 writer.writeAttribute("ref_md5", ((FunctionalBlock*)refBlock)->getReferenceHashMd5());
560 writer.writeAttribute("name",refBlock->getName());
561 QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
562 writer.writeAttribute("position",attrPos);
563 QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
564 writer.writeAttribute("dimension",attrDim);
566 writer.writeStartElement("bif_parameters");
567 foreach(BlockParameter *param,refBlock->getParameters()){
568 writer.writeStartElement("bif_parameter");
570 writer.writeAttribute("name",param->getName());
571 writer.writeAttribute("value",param->getValue().toString());
573 writer.writeAttribute("context",param->getStrContext());
574 writer.writeAttribute("type",param->getTypeString());
576 writer.writeEndElement(); //</bif_parameter>
578 writer.writeEndElement(); //</bif_parameters>
580 writer.writeStartElement("bif_ifaces");
581 writer.writeAttribute("count",QString::number(interfaces.length()));
582 foreach(InterfaceItem* inter, interfaces){
583 writer.writeStartElement("bif_iface");
585 writer.writeAttribute("id",QString::number(inter->getId()));
586 writer.writeAttribute("name",inter->getName());
587 writer.writeAttribute("ref_name",inter->refInter->getName());
588 writer.writeAttribute("orientation",inter->getStrOrientation());
589 writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
591 writer.writeEndElement(); //</bif_iface>
593 writer.writeEndElement(); //</bif_ifaces>
595 writer.writeEndElement(); //</bi_functional>
598 writer.writeStartElement("bi_group");
600 writer.writeAttribute("id",QString::number(id));
601 writer.writeAttribute("inside_group",QString::number(childGroupItem->getId()));
602 QString attrPos = QString::number(pos().x()).append(",").append(QString::number(pos().y()));
603 writer.writeAttribute("position",attrPos);
604 QString attrDim = QString::number(getWidth()).append(",").append(QString::number(getHeight()));
605 writer.writeAttribute("dimension",attrDim);
607 writer.writeStartElement("big_ifaces");
608 writer.writeAttribute("count",QString::number(interfaces.length()));
609 foreach(InterfaceItem* inter, interfaces){
610 writer.writeStartElement("big_iface");
612 writer.writeAttribute("id",QString::number(inter->getId()));
613 writer.writeAttribute("ref_name",inter->refInter->getName());
614 writer.writeAttribute("orientation",inter->getStrOrientation());
615 writer.writeAttribute("position",QString::number(inter->getPositionRatio()));
617 writer.writeEndElement(); //</big_iface>
620 writer.writeEndElement(); //</big_ifaces>
621 writer.writeEndElement(); //</bi_group>
625 QDataStream &operator <<(QDataStream &out, BoxItem &b) {
626 out.setVersion(QDataStream::Qt_4_8);
628 QByteArray blockData;
629 QDataStream toWrite(&blockData, QIODevice::WriteOnly);
631 QString refXml = ((FunctionalBlock*)b.refBlock)->getReferenceXmlFile();
632 QByteArray xmlFile = QByteArray(refXml.toStdString().c_str());
636 toWrite << (int)b.x();
637 toWrite << (int)b.y();
638 toWrite << b.boxWidth;
639 toWrite << b.boxHeight;
640 toWrite << b.getInterfaces().length();
642 for(int i=0; i<b.getInterfaces().length(); i++){
643 InterfaceItem *inter = b.getInterfaces().at(i);
644 toWrite << inter->getId();
645 toWrite << inter->getName();
646 toWrite << inter->getPositionRatio();
647 toWrite << inter->getOrientation();
655 QDataStream &operator >>(QDataStream &in, BoxItem &b)
658 in.setVersion(QDataStream::Qt_4_8);
673 cout << "nbInter:" << nbInter << endl;
674 for(int i=0; i<nbInter; i++){
677 double positionRatio;
680 InterfaceItem *inter = b.getInterfaces().at(i);
687 inter->setName(name);
688 inter->setPositionRatio(positionRatio);
689 inter->setOrientation(orientation);
690 inter->updatePosition();