From: stephane Domas Date: Thu, 27 Apr 2017 21:25:12 +0000 (+0200) Subject: insert/move/remove block/groups/interface done. Next to fo: loading project file X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/commitdiff_plain/f311fbc3e1436bf248c54225f0743cfa671c4bd7?hp=d30c9cf675ad7141d1c8e31d2e72315267d45cf2 insert/move/remove block/groups/interface done. Next to fo: loading project file --- diff --git a/AbstractBlock.h b/AbstractBlock.h index 2c89cbf..19209b7 100644 --- a/AbstractBlock.h +++ b/AbstractBlock.h @@ -25,6 +25,7 @@ public: // getters inline QString getName() { return name; } + inline int nbParameters() { return params.size(); } inline QList getParameters() { return params; } inline QList getInputs() { return inputs; } inline QList getOutputs() { return outputs; } diff --git a/BoxItem.cpp b/BoxItem.cpp index 0b1cd03..237c7ee 100644 --- a/BoxItem.cpp +++ b/BoxItem.cpp @@ -285,7 +285,7 @@ void BoxItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { int mode = getScene()->getEditionMode(); - dispatcher->setCurrentGroupWidget(getScene()->getGroupWindow()); + dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget()); if ((mode == GroupScene::AddConnection) && (params->cursorState == Parameters::CursorOnInterface)) { InterfaceItem *inter = getInterfaceFromCursor(x,y); @@ -368,6 +368,7 @@ void BoxItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { params->setEditState(Parameters::EditNoOperation); } else { + //QMessageBox::warning(NULL,"Error","Cannot connect selected interfaces", QMessageBox::Ok); getScene()->setSelectedInterface(2,NULL); params->setEditState(Parameters::EditStartConnection); } @@ -454,9 +455,10 @@ void BoxItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event) { void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { QMenu menu; - QAction* removeAction = menu.addAction("Remove"); - QAction* duplicateAction = menu.addAction("Duplicate"); - QAction* renameAction = menu.addAction("Rename"); + QAction* titleAction = NULL; + QAction* removeAction = NULL; + QAction* duplicateAction = NULL; + QAction* renameAction = NULL; QAction* connectToGroup = NULL; QAction* disconnectFromGroup = NULL; QAction* showProperties = NULL; @@ -466,48 +468,81 @@ void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { QAction* showParameters = NULL; InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y()); + // menu for interface if( ifaceItem != NULL){ + + titleAction = menu.addAction("Interface operations"); + titleAction->setEnabled(false); + menu.addSeparator(); + + showProperties = menu.addAction("Show properties"); + renameAction = menu.addAction("Rename"); ConnectedInterface* iface = ifaceItem->refInter; ConnectedInterface* ifaceGroup = NULL; + bool canRemove = true; if ((iface->getDirection() == AbstractInterface::Input) && (iface->getConnectedFrom() == NULL)) { connectToGroup = menu.addAction("Connect to group input"); } - else if ((iface->getDirection() == AbstractInterface::Output) && (!iface->isConnectedTo())) { + else if ((iface->getDirection() == AbstractInterface::Output) && (iface->getConnectionToParentGroup() == NULL)) { connectToGroup = menu.addAction("Connect to group output"); } else if (iface->getConnectionFromParentGroup() != NULL) { ifaceGroup = iface->getConnectionFromParentGroup(); - if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) { + //if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) { + if (!ifaceGroup->isConnectedFrom()) { disconnectFromGroup = menu.addAction("Disconnect from group"); } + else { + canRemove = false; + } } else if (iface->getConnectionToParentGroup() != NULL) { ifaceGroup = iface->getConnectionToParentGroup(); - if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) { + //if ((!ifaceGroup->isConnectedFrom()) || (!ifaceGroup->isConnectedTo())) { + if (!ifaceGroup->isConnectedTo()) { disconnectFromGroup = menu.addAction("Disconnect from group"); } + else { + canRemove = false; + } } if (iface->isFunctionalInterface()) { FunctionalInterface* fi = AI_TO_FUN(ifaceItem->refInter); ReferenceInterface* ri = (ReferenceInterface*)(fi->getReference()); if(ri->getMultiplicity() == -1 || ri->getMultiplicity() > 1){ - cloneInterface = menu.addAction("Clone interface"); - } + cloneInterface = menu.addAction("Duplicate"); + if ((canRemove) && (fi->getInterfaceMultiplicity() > 1)) { + removeAction = menu.addAction("Remove"); + } + } } } - if(refBlock->isGroupBlock()){ - openWindow = menu.addAction("Open/show group window"); - } else { - showRstClkInter = menu.addAction("Show reset/clock interfaces"); - showRstClkInter->setCheckable(true); - showRstClkInter->setChecked(rstClkVisible); + // menu for blocks (group or func) + else { + titleAction = menu.addAction("Block operations"); + titleAction->setEnabled(false); + menu.addSeparator(); + + if (refBlock->nbParameters() > 0) { + showParameters = menu.addAction("Show parameters"); + } + renameAction = menu.addAction("Rename"); - showParameters = menu.addAction("Show parameters"); + if(refBlock->isGroupBlock()){ + openWindow = menu.addAction("Open/show group window"); + } + else { + duplicateAction = menu.addAction("Duplicate"); + showRstClkInter = menu.addAction("Show reset/clock interfaces"); + showRstClkInter->setCheckable(true); + showRstClkInter->setChecked(rstClkVisible); + } + removeAction = menu.addAction("Remove"); } QAction* selectedAction = NULL; @@ -516,16 +551,21 @@ void BoxItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { if(selectedAction == NULL) return ; if (selectedAction == removeAction) { - dispatcher->removeBlock(this); + if(ifaceItem != NULL) { + dispatcher->removeBlockInterface(ifaceItem); + } + else { + dispatcher->removeBlock(this); + } } else if (selectedAction == duplicateAction) { dispatcher->duplicateBlock(this); } else if(selectedAction == renameAction){ if(ifaceItem != NULL) - dispatcher->rename(ifaceItem); + dispatcher->renameInterface(ifaceItem); else - dispatcher->rename(this); + dispatcher->renameBlockOrGroup(this); } else if(selectedAction == showProperties){ dispatcher->showProperties(ifaceItem); diff --git a/ConnectionItem.cpp b/ConnectionItem.cpp index b6d99a5..eaf46c2 100644 --- a/ConnectionItem.cpp +++ b/ConnectionItem.cpp @@ -727,13 +727,37 @@ void ConnectionItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { } void ConnectionItem::contextMenuEvent(QGraphicsSceneContextMenuEvent * event) { - QMenu menu; - QAction* removeAction = menu.addAction("Remove"); - QAction * selectedAction= menu.exec(event->screenPos()); + /* have to check if the connection can be removed. + If the from or to InterfaceItem is owned by a group item, and this item + is both connected to and from, thus it is impossible to remove this connection + */ + bool canRemove = true; + InterfaceItem* groupIfaceItem = NULL; + if (fromInterfaceItem->getOwner()->isGroupItem()) { + groupIfaceItem = fromInterfaceItem; + } + else if (toInterfaceItem->getOwner()->isGroupItem()) { + groupIfaceItem = toInterfaceItem; + } + + if (groupIfaceItem != NULL) { + ConnectedInterface* ref = groupIfaceItem->refInter; + if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) { + canRemove = false; + } + } - if(selectedAction == removeAction){ - dispatcher->removeConnection(this); - dispatcher->removeUselessGroupInterfaces(); + if (canRemove) { + QMenu menu; + QAction* titleAction = menu.addAction("Connection operations"); + titleAction->setEnabled(false); + menu.addSeparator(); + QAction* removeAction = menu.addAction("Remove"); + QAction * selectedAction= menu.exec(event->screenPos()); + + if(selectedAction == removeAction){ + dispatcher->removeConnection(this); + } } } diff --git a/ConnectionItem.h b/ConnectionItem.h index 867e811..6370c90 100644 --- a/ConnectionItem.h +++ b/ConnectionItem.h @@ -10,6 +10,7 @@ class Dispatcher; class Parameters; class InterfaceItem; +class GroupScene; using namespace std; using namespace Qt; @@ -51,6 +52,7 @@ public: void prepareChange(); + inline GroupScene* getScene() { return (GroupScene*)(scene()); } inline InterfaceItem* getToInterfaceItem(){ return toInterfaceItem; } inline void setToInterfaceItem(InterfaceItem *iface){ toInterfaceItem = iface; } inline InterfaceItem* getFromInterfaceItem(){ return fromInterfaceItem; } diff --git a/Dispatcher.cpp b/Dispatcher.cpp index 810396e..b191651 100644 --- a/Dispatcher.cpp +++ b/Dispatcher.cpp @@ -179,10 +179,14 @@ void Dispatcher::changeConnectionMode(int mode){ */ } -void Dispatcher::rename(AbstractBoxItem *item){ +void Dispatcher::renameBlockOrGroup(AbstractBoxItem *item){ + static QString fctName = "Dispatcher::renameBlockOrGroup()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif bool ok; - QString text = QInputDialog::getText(NULL, "Rename an element", + QString text = QInputDialog::getText(NULL, "Rename an block/group", "New name:", QLineEdit::Normal, item->getRefBlock()->getName(), &ok); @@ -204,12 +208,17 @@ void Dispatcher::rename(AbstractBoxItem *item){ QMessageBox::warning(NULL,"Error in given name", "the element name must be shorter than 30 characters and can't be empty!", QMessageBox::Ok); - rename(item); + renameBlockOrGroup(item); } } } -void Dispatcher::rename(InterfaceItem *item){ +void Dispatcher::renameInterface(InterfaceItem *item) { + static QString fctName = "Dispatcher::renameInterface()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + bool ok; QString text = QInputDialog::getText(NULL, "Rename an interface", "New name:", QLineEdit::Normal, @@ -232,13 +241,17 @@ void Dispatcher::rename(InterfaceItem *item){ QMessageBox::warning(NULL,"Error in given name", "the interface name must be shorter than 30 characters and can't be empty!", QMessageBox::Ok); - rename(item); + renameInterface(item); } } void Dispatcher::duplicateBlock(BoxItem *item){ + static QString fctName = "Dispatcher::duplicateBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif - GroupScene *scene = params->getCurrentScene(); + GroupScene *scene = item->getScene(); AbstractBlock* block = item->getRefBlock(); AbstractBlock *newBlock; @@ -255,7 +268,12 @@ void Dispatcher::duplicateBlock(BoxItem *item){ } } -void Dispatcher::duplicateInterface(InterfaceItem *item){ +void Dispatcher::duplicateInterface(InterfaceItem *item) { + static QString fctName = "Dispatcher::duplicateInterface()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + AbstractInterface *refI = item->refInter; if (! refI->isFunctionalInterface()) return; @@ -277,14 +295,25 @@ void Dispatcher::duplicateInterface(InterfaceItem *item){ void Dispatcher::addBlock(int idCategory, int idBlock, int idScene) { + static QString fctName = "Dispatcher::addBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif GroupScene *scene = searchSceneById(idScene); - FunctionalBlock* newOne = params->addFunctionalBlock(idCategory, idBlock); + ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock); + GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); + FunctionalBlock* newOne = params->getGraph()->addFunctionalBlock(group, ref); scene->createBlockItem(newOne); + params->unsaveModif = true; } GroupWidget *Dispatcher::createTopScene(){ + static QString fctName = "Dispatcher::createTopScene()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif // creating the model part of the group Graph* graph = params->createGraph(); @@ -314,7 +343,32 @@ GroupWidget *Dispatcher::createTopScene(){ return topGroup; } +void Dispatcher::addNewEmptyGroup(GroupScene* scene) { + static QString fctName = "Dispatcher::addNewEmptyGroup();"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + // getting the parent block in the graph + GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); + cout << "new group : parent = "<< qPrintable(parent->getName()) << endl; + GroupBlock* groupBlock = params->getGraph()->createChildBlock(parent); + cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl; + // creating the BlockItem in the scene + BoxItem* newItem = scene->createBlockItem(groupBlock); + + params->unsaveModif = true; + + GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem); + child->show(); + +} + GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) { + static QString fctName = "Dispatcher::createChildScene()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif // getting back the goup block already created GroupBlock* groupBlock = NULL; @@ -337,21 +391,51 @@ GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *up return group; } -void Dispatcher::showRaiseWindow(AbstractBoxItem *item) { - GroupWidget* win = item->getScene()->getGroupWindow(); - if (win->isTopGroup()) { - mainWindow->show(); - mainWindow->raise(); +void Dispatcher::destroyScene(GroupScene *scene) { + foreach(GroupScene* s, scene->getChildrenScene()) { + destroyScene(s); + } + + if (scene->getNbChildScene() == 0) { + // remove scene from the parent list + scene->getParentScene()->removeChildScene(scene); + // destroy the GroupWidget + groupList.removeAll(scene->getGroupWidget()); + scene->getGroupWidget()->deleteLater(); } else { - win->show(); - win->raise(); + cerr << "Abnormal case when destroying a scene" << endl; + } +} + +void Dispatcher::showRaiseWindow(BoxItem *item) { + static QString fctName = "Dispatcher::showRaiseWindow()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl; + GroupItem* child = item->getChildGroupItem(); + if (child == NULL) { + cerr << "abnormal case: child group item is null " << endl; + return; } + + GroupWidget* win = child->getScene()->getGroupWidget(); + + win->showNormal(); + win->raise(); + win->activateWindow(); + currentGroup = win; params->setCurrentScene(currentGroup->getScene()); } void Dispatcher::showRstClkInter(AbstractBoxItem *item) { + static QString fctName = "Dispatcher::showRstClkInter()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif item->setRstClkVisible(!item->isRstClkVisible()); item->resetInterfacesPosition(); @@ -360,6 +444,11 @@ void Dispatcher::showRstClkInter(AbstractBoxItem *item) { } void Dispatcher::addNewFullGroup() { + static QString fctName = "Dispatcher::addNewFullGroup()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + #ifdef DEBUG_INCLFUN @@ -515,88 +604,162 @@ void Dispatcher::addNewFullGroup() { #endif } -void Dispatcher::removeBlock(AbstractBoxItem *item) { - -#ifdef DEBUG_INCLFUN - - GroupScene *scene = params->getCurrentScene(); - AbstractBlock* block = item->getRefBlock(); - if (block->isReferenceBlock()) return; - - GroupBlock* group = (GroupBlock*)item->getParentItem()->getRefBlock(); +void Dispatcher::removeBlock(BoxItem *item) { + static QString fctName = "Dispatcher::removeBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif - removeConnections(item); + /* a BoxItem (group of func) can be removed only if none of its + interfaces is connected to a group interface that is itself + connected to another one. + */ + bool canRemove = true; - //récupérer l'objet - group->removeBlock(block); + foreach(InterfaceItem* ifaceItem, item->getInterfaces()) { + foreach(ConnectionItem* conn, ifaceItem->connections) { + InterfaceItem* other = NULL; + if (conn->getFromInterfaceItem() == ifaceItem) { + other = conn->getToInterfaceItem(); + } + else { + other = conn->getFromInterfaceItem(); + } - //remove the associated window - if(block->isGroupBlock()){ - foreach(QWidget *window, params->windows){ - if(!window->inherits("MainWindow")){ - if(((GroupWidget*)window)->getScene()->getGroupItem()->getRefBlock() == block){ - params->removeWindow(window); - delete window; + if (other->getOwner()->isGroupItem()) { + ConnectedInterface* ref = other->refInter; + if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) { + canRemove = false; } } } } + if (!canRemove) { + QMessageBox::warning(NULL,"Forbidden operation", + "The block has at least one connection to a group interface that is totally connected.", + QMessageBox::Ok); + return; + } - delete block; + QString msg = ""; + if (item->getRefBlock()->isFunctionalBlock()) { + msg = "Removing block "; + } + else { + msg = "Removing group "; + } + msg += item->getRefBlock()->getName(); + msg += " and all its connections.\n\nAre you sure ?"; - //supprimer l'item de la scène - cout << "dispatcher : remove item of scene " << params->currentWindow << endl; - ((GroupItem *)scene->getGroupItem())->removeBlockItem(item); - scene->removeItem(item); - scene->removeBlockItem(item); - delete item; + int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); + if (ret == QMessageBox::Cancel) { + return; + } + removeAllBlockConnections(item); - ((GroupItem *)scene->getGroupItem())->updateShape(); + if (item->getRefBlock()->isFunctionalBlock()) { + FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); + GroupBlock* group = AB_TO_GRP(block->getParent()); + item->getScene()->removeBlockItem(item); + params->getGraph()->removeFunctionalBlock(block,group); + } + else if (item->getRefBlock()->isGroupBlock()) { - params->updateToolbar(); - params->unsaveModif = true; + GroupBlock* group = AB_TO_GRP(item->getRefBlock()); -#endif + // remove all child scenes recursively + GroupItem* subgroup = item->getChildGroupItem(); + destroyScene(subgroup->getScene()); + // remove the BoxItem + item->getScene()->removeBlockItem(item); + // remove the group from the graph + params->getGraph()->removeGroupBlock(group); + } } -void Dispatcher::removeAllBlockConnections(AbstractBoxItem *block) { +void Dispatcher::removeAllBlockConnections(BoxItem *item) { + static QString fctName = "Dispatcher::removeAllBlockConnection()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif - GroupScene* scene = block->getScene(); - // supprimer les connections associées au bloc - foreach (ConnectionItem *conn, scene->getConnectionItems()) { - if(conn->getToInterfaceItem()->owner == block || conn->getFromInterfaceItem()->owner == block){ + foreach(InterfaceItem* ifaceItem, item->getInterfaces()) { + foreach(ConnectionItem* conn, ifaceItem->connections) { removeConnection(conn); } } - scene->getGroupItem()->updateInterfacesAndConnections(); } void Dispatcher::removeConnection(ConnectionItem *conn) { + static QString fctName = "Dispatcher::removeConnection()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + InterfaceItem* fromIfaceItem = conn->getFromInterfaceItem(); + InterfaceItem* toIfaceItem = conn->getToInterfaceItem(); - GroupScene *scene = params->getCurrentScene(); - GroupItem* currentGroup = scene->getGroupItem(); +#ifdef DEBUG + cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl; +#endif + + InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem + GroupItem* groupItem = NULL; - conn->getFromInterfaceItem()->unconnectTo(conn->getToInterfaceItem()); + if (fromIfaceItem->getOwner()->isGroupItem()) { + groupIfaceItem = fromIfaceItem; + groupItem = toIfaceItem->getOwner()->getScene()->getGroupItem(); + } + else if (toIfaceItem->getOwner()->isGroupItem()) { + groupIfaceItem = toIfaceItem; + groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem(); + } + else { + groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem(); + } - scene->removeConnectionItem(conn); - delete conn; + // removing the connection from graph +#ifdef DEBUG + cout << "removing connections from graph ..." ; +#endif + ConnectedInterface *fromInter = fromIfaceItem->refInter; + ConnectedInterface *toInter = toIfaceItem->refInter; + if (fromInter->getDirection() == AbstractInterface::InOut) { + fromInter->clearConnectedTo(); + fromInter->clearConnectedFrom(); + toInter->clearConnectedTo(); + toInter->clearConnectedFrom(); + } + else { + fromInter->removeConnectedTo(toInter); + toInter->clearConnectedFrom(); + } +#ifdef DEBUG + cout << "done." << endl ; +#endif - currentGroup->updateInterfacesAndConnections(); - params->unsaveModif = true; -} + // removing the connection from scene +#ifdef DEBUG + cout << "removing connections from scene ..." ; +#endif + fromIfaceItem->removeConnectionItem(conn); + toIfaceItem->removeConnectionItem(conn); + groupItem->getScene()->removeConnectionItem(conn); -void Dispatcher::removeUselessGroupInterfaces() { +#ifdef DEBUG + cout << "done." << endl ; +#endif - GroupScene *scene = params->getCurrentScene(); - GroupItem* currentGroup = scene->getGroupItem(); + if (groupIfaceItem != NULL) { + ConnectedInterface* groupInter = groupIfaceItem->refInter; + groupItem->removeInterface(groupIfaceItem); - foreach(InterfaceItem *inter, currentGroup->getInterfaces()) { - if(inter->refInter->getConnectedTo().length() == 0) { - // NB : remove from view also remove from model - currentGroup->removeInterface(inter); + BoxItem* parent2Item = groupItem->getParentItem(); + if (parent2Item != NULL) { + InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter); + parent2Item->removeInterface(group2IfaceItem); } + groupInter->getOwner()->removeInterface(groupInter); } - scene->updateConnectionItemsShape(); } void Dispatcher::showBlocksLibrary(){ @@ -691,7 +854,7 @@ void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) { if (refInter->getDirection() == AbstractInterface::Output) { groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to - refInter->clearConnectedTo(); + refInter->removeConnectedTo(groupInter); groupInter->clearConnectedFrom(); } else if (refInter->getDirection() == AbstractInterface::Input) { @@ -768,6 +931,28 @@ void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) { #endif } +void Dispatcher::removeBlockInterface(InterfaceItem *item) { + static QString fctName = "Dispatcher::removeBlockInterface()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + /* first, remove all connections from item + NB: if there is a connection to a group interface, then this + method should not be called if the group interface is also + connected to another interface. Normally, this is not possible + because such a check is done when creating the contextual menu + that allows to remove an interface. + */ + foreach(ConnectionItem* conn, item->connections) { + removeConnection(conn); + } + + ConnectedInterface* ref = item->refInter; + item->getOwner()->removeInterface(item); + FunctionalBlock* fun = AB_TO_FUN(ref->getOwner()); + fun->removeInterface(ref); +} void Dispatcher::removeGroupInterface(InterfaceItem *item) { static QString fctName = "Dispatcher::removeGroupInterface()"; diff --git a/Dispatcher.h b/Dispatcher.h index fa77360..fd61087 100644 --- a/Dispatcher.h +++ b/Dispatcher.h @@ -37,13 +37,14 @@ public: void unselectAllItems(int direction=0); void setCurrentGroupWidget(GroupWidget *win); void changeConnectionMode(int mode = -1); - void rename(AbstractBoxItem* item); - void rename(InterfaceItem* item); + + GroupWidget* createTopScene(); GroupWidget* createChildScene(GroupWidget* parentWidget, BoxItem* upperItemOfGroupItem = NULL); - void showRaiseWindow(AbstractBoxItem *item); + void destroyScene(GroupScene* scene); + void showRaiseWindow(BoxItem *item); void showRstClkInter(AbstractBoxItem *item); - void addNewEmptyGroup(); + void addNewEmptyGroup(GroupScene *scene); void addNewFullGroup(); inline GroupWidget* getCurrentGroup() { return currentGroup; } @@ -58,21 +59,64 @@ public slots: GroupItem* searchGroupItemById(int id); InterfaceItem* searchInterfaceItemById(int id); - void removeBlock(AbstractBoxItem* item); + // block ops + void addBlock(int idCategory, int idBlock, int idScene); + void removeBlock(BoxItem* item); void duplicateBlock(BoxItem* item); + void renameBlockOrGroup(AbstractBoxItem* item); + + // interface ops + /*! + * \brief connectInterToGroup + * \param item item is always owned by a BoxItem + * + * This method is called only when the user right clicks on an InterfaceItem (that belongs + * to a BoxItem and if it is NOT connected to an InterfaceItem of the GroupItem) and chooses + * connect to group in the contextual menu. + * Thus, parameter item is always owned by a BoxItem + */ + void connectInterToGroup(InterfaceItem* item); + /*! + * \brief disconnectInterFromGroup + * \param item item is always owned by a BoxItem + * + * This method is called only when the user right clicks on an InterfaceItem (that belongs + * to a BoxItem and if it IS connected to an InterfaceItem of the GroupItem) and chooses + * disconnect from group in the contextual menu. + * Thus, parameter item is always owned by a BoxItem + */ + void disconnectInterFromGroup(InterfaceItem* item); + /*! + * \brief removeBlockInterface + * \param item item is always owned by a BoxItem + * + * This method is called only when the user right clicks on an InterfaceItem (that belongs + * to a BoxItem and has a multiplicity > 1) and chooses remove in the contextual menu. + * Thus, parameter item is always owned by a BoxItem + */ + void removeBlockInterface(InterfaceItem* item); + /*! + * \brief removeGroupInterface + * \param item item is always owned by a GroupItem + * + * This method is called only when the user right clicks on an InterfaceItem (that belongs + * to a GroupItem and if it is connected only to an inner interface) and chooses remove in the contextual menu. + * Thus, parameter item is always owned by a GroupItem + */ + void removeGroupInterface(InterfaceItem* item); void duplicateInterface(InterfaceItem* item); - void addBlock(int idCategory, int idBlock, int idScene); + void showProperties(InterfaceItem *inter); + void renameInterface(InterfaceItem* item); + + // connection ops ConnectionItem *addConnection(InterfaceItem *input, InterfaceItem *output); - void removeAllBlockConnections(AbstractBoxItem *block); + void removeAllBlockConnections(BoxItem *item); void removeConnection(ConnectionItem *conn); - void removeUselessGroupInterfaces(); + + + // others void showBlocksLibrary(); - void showProperties(InterfaceItem *inter); - void connectInterToGroup(InterfaceItem* item); - void disconnectInterFromGroup(InterfaceItem* item); - void removeGroupInterface(InterfaceItem* item); - void addConnection(); void closeCurrentProject(); diff --git a/FunctionalInterface.cpp b/FunctionalInterface.cpp index cc9f765..bce7ca1 100644 --- a/FunctionalInterface.cpp +++ b/FunctionalInterface.cpp @@ -65,10 +65,10 @@ int FunctionalInterface::getInterfaceMultiplicity() { return -1; } else if ( reference->getMultiplicity() == -1) { - return ifaceCount+1; + return ifaceCount; } - else if ( reference->getMultiplicity() > ifaceCount) { - return ifaceCount+1; + else if ( ifaceCount < reference->getMultiplicity()) { + return ifaceCount; } return -1; } @@ -82,7 +82,7 @@ AbstractInterface *FunctionalInterface::clone() { inter->setPurpose(purpose); inter->setLevel(level); inter->connectFrom(NULL); - inter->setName(reference->getName()+"_"+QString::number(id)); + inter->setName(reference->getName()+"_"+QString::number(id+1)); return inter; } diff --git a/Graph.cpp b/Graph.cpp index 1c87123..8cd0f99 100644 --- a/Graph.cpp +++ b/Graph.cpp @@ -29,3 +29,13 @@ FunctionalBlock* Graph::addFunctionalBlock(GroupBlock* group, ReferenceBlock* re return newBlock; } + +bool Graph::removeFunctionalBlock(FunctionalBlock* block, GroupBlock *group) { + group->removeBlock(block); +} + +bool Graph::removeGroupBlock(GroupBlock *group) { + group->removeAllBlocks(); + GroupBlock* parent = AB_TO_GRP(group->getParent()); + parent->removeBlock(group); +} diff --git a/Graph.h b/Graph.h index 7f34682..723e8eb 100644 --- a/Graph.h +++ b/Graph.h @@ -26,6 +26,8 @@ public: GroupBlock* createChildBlock(GroupBlock* parent); FunctionalBlock* addFunctionalBlock(GroupBlock *group, ReferenceBlock *ref); + bool removeFunctionalBlock(FunctionalBlock* block, GroupBlock *group); + bool removeGroupBlock(GroupBlock *group); private: GroupBlock* topGroup; diff --git a/GroupBlock.cpp b/GroupBlock.cpp index 4ec7f6b..74ec197 100644 --- a/GroupBlock.cpp +++ b/GroupBlock.cpp @@ -40,9 +40,22 @@ void GroupBlock::setParent(AbstractBlock *_parent) { topGroup = false; } } +void GroupBlock::removeAllBlocks() { + foreach(AbstractBlock* block, blocks) { + if (block->isGroupBlock()) { + GroupBlock* group = AB_TO_GRP(block); + group->removeAllBlocks(); + } + removeBlock(block); + } +} void GroupBlock::removeBlock(AbstractBlock* block) { - blocks.removeAll(block); + /* CAUTION: no check is done if the block has connected interface + or not. Thus, they must be deleted elsewhere. + */ + blocks.removeAll(block); + delete block; } void GroupBlock::parametersValidation(QList *checkedBlocks, QList *blocksToConfigure) { diff --git a/GroupBlock.h b/GroupBlock.h index 3316637..5a03236 100644 --- a/GroupBlock.h +++ b/GroupBlock.h @@ -21,7 +21,7 @@ public: virtual ~GroupBlock(); // getters - + inline QList getBlocks() { return blocks; } // setters void setParent(AbstractBlock *_parent); @@ -32,6 +32,7 @@ public: // others inline void addBlock(AbstractBlock* block) { blocks.append(block); } void removeBlock(AbstractBlock* block); + void removeAllBlocks(); void parametersValidation(QList *checkedBlocks, QList* blocksToConfigure); void addGenericParameter(QString name, QString type, QString value); void removeGenericParameter(QString name); @@ -40,7 +41,7 @@ public: private: bool topGroup; - QList blocks; // contains instances of FunctionalBlock or GroupBlock + QList blocks; // contains instances of FunctionalBlock or GroupBlock that are children of this group }; diff --git a/GroupItem.cpp b/GroupItem.cpp index bb26e53..fa341b2 100644 --- a/GroupItem.cpp +++ b/GroupItem.cpp @@ -9,6 +9,7 @@ #include "AbstractInterface.h" #include "ConnectedInterface.h" #include "GroupScene.h" +#include "ParametersWindow.h" GroupItem::GroupItem(BoxItem *_parentItem, @@ -17,6 +18,9 @@ GroupItem::GroupItem(BoxItem *_parentItem, Parameters *_params) throw(Exception) :AbstractBoxItem( _refBlock, _dispatcher, _params) { parentItem = _parentItem; + if (parentItem != NULL) { + parentItem->setChildGroupItem(this); + } /* minimumBoxWidth = nameWidth+2*nameMargin; @@ -337,7 +341,7 @@ void GroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { int mode = getScene()->getEditionMode(); - dispatcher->setCurrentGroupWidget(getScene()->getGroupWindow()); + dispatcher->setCurrentGroupWidget(getScene()->getGroupWidget()); /* NOTE : commneted because group interface are normally created and the connected directly to a block within @@ -500,12 +504,19 @@ void GroupItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { QMenu menu; + QAction* titleAction = NULL; QAction* showProperties = NULL; QAction* removeAction = NULL; QAction* renameAction = NULL; + QAction* showParameters = NULL; InterfaceItem* ifaceItem = getInterfaceFromCursor(event->pos().x(), event->pos().y()); - if( ifaceItem != NULL){ + + // menu for interface + if( ifaceItem != NULL) { + titleAction = menu.addAction("Interface operations"); + titleAction->setEnabled(false); + menu.addSeparator(); showProperties = menu.addAction("Show properties"); renameAction = menu.addAction("Rename"); menu.addSeparator(); @@ -520,6 +531,13 @@ void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { } } else { + titleAction = menu.addAction("Block operations"); + titleAction->setEnabled(false); + menu.addSeparator(); + + if (refBlock->nbParameters() > 0) { + showParameters = menu.addAction("Show parameters"); + } renameAction = menu.addAction("Rename"); } QAction* selectedAction = menu.exec(event->screenPos()); @@ -528,16 +546,19 @@ void GroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { if(selectedAction == renameAction){ if(ifaceItem != NULL) - dispatcher->rename(ifaceItem); + dispatcher->renameInterface(ifaceItem); else - dispatcher->rename(this); + dispatcher->renameBlockOrGroup(this); } else if(selectedAction == showProperties){ dispatcher->showProperties(ifaceItem); - } + } else if (selectedAction == removeAction) { dispatcher->removeGroupInterface(ifaceItem); } + else if(selectedAction == showParameters) { + new ParametersWindow(refBlock, params, NULL); + } } InterfaceItem* GroupItem::isHoverInterface(QPointF point) { diff --git a/GroupScene.h b/GroupScene.h index 3078305..e7b42ec 100644 --- a/GroupScene.h +++ b/GroupScene.h @@ -51,7 +51,8 @@ public: inline QList getBlockItems() { return blockItems; } inline QList getConnectionItems() { return connectionItems; } inline QList getChildrenScene() { return childrenScene; } - inline GroupWidget* getGroupWindow() { return window; } + inline GroupScene* getParentScene() { return parentScene; } + inline GroupWidget* getGroupWidget() { return window; } inline int getId() { return id; } inline EditMode getEditionMode() { return editMode; } InterfaceItem* getSelectedInterface(int id); @@ -77,6 +78,8 @@ public: void removeConnectionItem(ConnectionItem* item); void removeGroupItem(); inline void addChildScene(GroupScene* child) { childrenScene.append(child); } + inline void removeChildScene(GroupScene* child) { childrenScene.removeAll(child); } + inline int getNbChildScene() { return childrenScene.size(); } void unselecteInterfaces(); QList getGroupAndBlocks(); @@ -94,7 +97,7 @@ public: private: Dispatcher *dispatcher; Parameters *params; - GroupScene* parentScene; // the parnet scene, =NULL for top scene + GroupScene* parentScene; // the parent scene, =NULL for top scene GroupWidget* window; // the GroupWindow that contains that scene int id; GroupItem *groupItem; // mandatory to be an instance of GroupItem. diff --git a/GroupWidget.cpp b/GroupWidget.cpp index 043561e..2ef7cd1 100644 --- a/GroupWidget.cpp +++ b/GroupWidget.cpp @@ -95,6 +95,7 @@ void GroupWidget::focusInEvent(QFocusEvent *e) { void GroupWidget::closeEvent(QCloseEvent *e) { clearFocus(); focusNextChild(); + } @@ -222,16 +223,8 @@ void GroupWidget::updateBlockButton() { void GroupWidget::slotNewEmptyGroup() { - // creating the GroupBlock in graph model - GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); - cout << "new group : parent = "<< qPrintable(parent->getName()) << endl; - GroupBlock* groupBlock = params->getGraph()->createChildBlock(parent); - cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl; - // creating the BlockItem in the scene - BoxItem* newItem = scene->createBlockItem(groupBlock); + dispatcher->addNewEmptyGroup(scene); - GroupWidget* child = dispatcher->createChildScene(this,newItem); - child->show(); } void GroupWidget::slotNewGroup() diff --git a/MainWindow.cpp b/MainWindow.cpp index 1f8c1c0..e9f8414 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -291,6 +291,7 @@ void MainWindow::slotNewProject(){ GroupWidget* topGroup = dispatcher->createTopScene(); addTopGroup(topGroup); library->updateComboScene(); + params->isCurrentProject = true; } void MainWindow::slotCloseProject(){ diff --git a/Parameters.cpp b/Parameters.cpp index c991e5f..fce0435 100644 --- a/Parameters.cpp +++ b/Parameters.cpp @@ -69,37 +69,23 @@ void Parameters::destroyGraph() { delete graph; } -GroupBlock* Parameters::addGroupBlock() { - GroupBlock* parent = AB_TO_GRP(currentScene->getGroupItem()->getRefBlock()); - GroupBlock* newOne = graph->createChildBlock(parent); - return newOne; -} - -FunctionalBlock* Parameters::addFunctionalBlock(int idCategory, int idBlock) { +ReferenceBlock* Parameters::getReferenceBlock(int idCategory, int idBlock) { BlockCategory* blockCat = categoryTree->searchCategory(idCategory); if (blockCat == NULL) return NULL; - GroupBlock* group = AB_TO_GRP(currentScene->getGroupItem()->getRefBlock()); ReferenceBlock* ref = blockCat->getBlock(idBlock); - if (ref == NULL) return NULL; - - FunctionalBlock* newOne = graph->addFunctionalBlock(group, ref); - unsaveModif = true; - - return newOne; + return ref; } + FunctionalBlock* Parameters::duplicateFunctionalBlock(FunctionalBlock *block) { ReferenceBlock* ref = block->getReference(); GroupBlock* group = AB_TO_GRP(block->getParent()); - // adding to the group - FunctionalBlock* newBlock = new FunctionalBlock(group,ref); - newBlock->populate(); - group->addBlock(newBlock); - + // adding to the graph + FunctionalBlock* newBlock = graph->addFunctionalBlock(group,ref); return newBlock; } @@ -1032,11 +1018,11 @@ void Parameters::updateToolbar() { int nb = currentScene->getBlockItems().length(); for(int i = 0; igetBlockItems().at(i)->isSelected()){ - currentScene->getGroupWindow()->enableGroupButton(true); + currentScene->getGroupWidget()->enableGroupButton(true); return; } } - currentScene->getGroupWindow()->enableGroupButton(false); + currentScene->getGroupWidget()->enableGroupButton(false); } @@ -1098,9 +1084,6 @@ void Parameters::save(QString confFile) { // cross the scene level by level using a FIFO QList fifoScene; fifoScene.append(topScene); - foreach(ConnectionItem* item, topScene->getConnectionItems()) { - allConnections.append(item); - } GroupScene *scene; while (!fifoScene.isEmpty()) { @@ -1109,11 +1092,12 @@ void Parameters::save(QString confFile) { foreach(GroupScene* s, scene->getChildrenScene()) { fifoScene.append(s); } - foreach(ConnectionItem* item, topScene->getConnectionItems()) { + + foreach(ConnectionItem* item, scene->getConnectionItems()) { allConnections.append(item); } } - + writer.writeEndElement(); // writer.writeStartElement("connections"); foreach(ConnectionItem* item, allConnections) { diff --git a/Parameters.h b/Parameters.h index 69887a9..7f14814 100644 --- a/Parameters.h +++ b/Parameters.h @@ -35,6 +35,13 @@ class Exception; using namespace std; using namespace Qt; +/*! + * \brief The Parameters class + * + * Parameters class represents the Model part of blast in MVC paradigm. + * It contains all data necessary to create a design: the graph of blocks, + * the scenes, ... + */ class Parameters { public : @@ -113,9 +120,8 @@ public : Graph* createGraph(); void destroyGraph(); - inline Graph* getGraph() { return graph; } - GroupBlock* addGroupBlock(); // adding an empty GroupBlock to the current group - FunctionalBlock* addFunctionalBlock(int idCategory, int idBlock); // adding a functional block to current group + inline Graph* getGraph() { return graph; } + ReferenceBlock* getReferenceBlock(int idCategory, int idBlock); // get the reference block from its category and index FunctionalBlock* duplicateFunctionalBlock(FunctionalBlock* block); // adding a copy of a functional block to current group diff --git a/ParametersWindow.cpp b/ParametersWindow.cpp index 07f96fa..182460d 100644 --- a/ParametersWindow.cpp +++ b/ParametersWindow.cpp @@ -20,6 +20,7 @@ ParametersWindow::ParametersWindow(AbstractBlock *_block, Parameters *_params, B comboBox = new QComboBox; + cout << "block has " <getParameters().size() << " params" << endl; foreach(BlockParameter *param, block->getParameters()){ comboBox->addItem(param->getName()); } diff --git a/blast.creator.user b/blast.creator.user index 868e2d3..9930e19 100755 --- a/blast.creator.user +++ b/blast.creator.user @@ -1,10 +1,10 @@ - + EnvironmentId - {3701e197-5b6c-48ea-9e98-a6cf6de18672} + {c8006d66-d34f-42be-ad10-d0207752286d} ProjectExplorer.Project.ActiveTarget @@ -60,7 +60,7 @@ Desktop Desktop - {ed04208c-8774-456b-99b9-4a02094ca7a4} + {2c9bf876-3476-44eb-8065-1f0844704dda} 0 0 0 diff --git a/projectfile.xsd b/projectfile.xsd index 36fe54e..8a35bc9 100644 --- a/projectfile.xsd +++ b/projectfile.xsd @@ -184,9 +184,9 @@ - - - + + +