X-Git-Url: https://bilbo.iut-bm.univ-fcomte.fr/and/gitweb/blast.git/blobdiff_plain/d30c9cf675ad7141d1c8e31d2e72315267d45cf2..7b1c7e44123b9b2626205a89e27b2a4712ea30c6:/Dispatcher.cpp?ds=sidebyside diff --git a/Dispatcher.cpp b/Dispatcher.cpp index 810396e..ee72743 100644 --- a/Dispatcher.cpp +++ b/Dispatcher.cpp @@ -16,6 +16,7 @@ #include "GroupScene.h" #include "GroupItem.h" #include "BoxItem.h" +#include "SourceItem.h" #include "InterfaceItem.h" #include "ConnectionItem.h" @@ -44,6 +45,7 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) { return NULL; } + /* // creating the top widget/scene topGroup = new GroupWidget(NULL,this,params); currentGroup = topGroup; @@ -52,9 +54,9 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) { params->setTopScene(scene); params->setCurrentScene(scene); - +*/ try { - params->loadProject(root); + topGroup = params->loadProject(root); } catch(Exception e){ cerr << qPrintable(e.getDefaultMessage()) << endl; @@ -72,25 +74,33 @@ void Dispatcher::closeCurrentProject() { foreach(GroupWidget* win, groupList) { win->deleteLater(); } + groupList.clear(); params->destroyGraph(); + topGroup = NULL; + currentGroup = NULL; + sceneCounter = 0; } -bool Dispatcher::connect(InterfaceItem *iface1, InterfaceItem *iface2) { - +bool Dispatcher::createConnection(InterfaceItem *iface1, InterfaceItem *iface2) { + ConnectedInterface* ref1 = iface1->refInter; ConnectedInterface* ref2 = iface2->refInter; + ConnectedInterface* asso1 = (ConnectedInterface*)(iface1->refInter->getAssociatedIface()); + ConnectedInterface* asso2 = (ConnectedInterface*)(iface2->refInter->getAssociatedIface()); // connect both interface bool ok1 = false; bool ok2 = false; - if (ref1->canConnectTo(ref2)) { - ok1 = ref1->connectTo(ref2); - ok1 = ok1 & ref2->connectFrom(ref1); + // test the ref1->ref2 connection + if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) { + ref1->connectTo(ref2); + ok1 = true; } - if (ref2->canConnectTo(ref1)) { - ok2 = ref2->connectTo(ref1); - ok2 = ok2 & ref1->connectFrom(ref2); + // if the frist one did not work, test ref2->ref1 + if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) { + ref2->connectTo(ref1); + ok2 = true; } if ((ok1 == true) || (ok2 == true)) { @@ -98,38 +108,18 @@ bool Dispatcher::connect(InterfaceItem *iface1, InterfaceItem *iface2) { unselectAllItems(); params->unsaveModif = true; + cout << "created a connection from " << qPrintable(ref1->getName()) << " to " << qPrintable(ref2->getName()) << endl; return true; } return false; } -void Dispatcher::checkSelection(){ - InterfaceItem *iface1 = NULL; - InterfaceItem *iface2 = NULL; - - GroupScene *scene = params->getCurrentScene(); - QList list = scene->getGroupAndBlocks(); - foreach(AbstractBoxItem *block, list){ - InterfaceItem *tmp = block->getCurrentInterface(); - if (tmp != NULL) { - if (iface1 == NULL) { - iface1 = tmp; - } - else { - iface2 = tmp; - } - } - } - if(iface1 != NULL && iface2 != NULL){ - connect(iface1,iface2); - } -} void Dispatcher::unselectAllItems(int direction){ GroupScene *scene = params->getCurrentScene(); - foreach(BoxItem* block, scene->getBlockItems()) { + foreach(BoxItem* block, scene->getBoxItems()) { block->setSelected(false); block->setCurrentInterface(NULL); } @@ -179,66 +169,217 @@ void Dispatcher::changeConnectionMode(int mode){ */ } -void Dispatcher::rename(AbstractBoxItem *item){ - - bool ok; - QString text = QInputDialog::getText(NULL, "Rename an element", +void Dispatcher::renameFunctionalBlock(BoxItem *item){ + static QString fctName = "Dispatcher::renameFunctionalBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + GroupWidget* win = item->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename a functional block", "New name:", QLineEdit::Normal, item->getRefBlock()->getName(), &ok); - - if(ok){ - if(!text.isEmpty() && text.length() < 30){ - item->getRefBlock()->setName(text); - if(item->isGroupItem()){ - if (currentGroup->isTopGroup()) { - mainWindow->setWindowTitle("blast - "+text); - } - else { - currentGroup->setWindowTitle("blast - "+text); - } - } - - mainWindow->getLibrary()->updateComboScene(); + if (!ok) return; + + if (text == item->getRefBlock()->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the block name must be shorter than 30 characters, cannot be empty", + QMessageBox::Ok); + ok = false; } else { - QMessageBox::warning(NULL,"Error in given name", - "the element name must be shorter than 30 characters and can't be empty!", + FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent())); + if (block != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another functional block within the group", + QMessageBox::Ok); + ok = false; + } + } + } + + item->getRefBlock()->setName(text); + item->nameChanged(); +} + +void Dispatcher::renameGroupBlock(GroupItem *item){ + static QString fctName = "Dispatcher::renameGroupBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + GroupWidget* win = item->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename a group", + "New name:", QLineEdit::Normal, + item->getRefBlock()->getName(), &ok); + if (!ok) return; + + if (text == item->getRefBlock()->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the block name must be shorter than 30 characters, cannot be empty", QMessageBox::Ok); - rename(item); + ok = false; } + else { + GroupBlock* block = params->getGraph()->getGroupBlockByName(text); + if (block != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another group", + QMessageBox::Ok); + ok = false; + } + } + } + + item->getRefBlock()->setName(text); + if(item->getScene()->getGroupWidget()->isTopGroup()) { + mainWindow->setWindowTitle("blast - "+text); } + else { + item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text); + } + item->nameChanged(); + mainWindow->getLibrary()->updateComboScene(); } -void Dispatcher::rename(InterfaceItem *item){ - bool ok; - QString text = QInputDialog::getText(NULL, "Rename an interface", +void Dispatcher::renameSourceBlock(SourceItem *item){ + static QString fctName = "Dispatcher::renameSourceBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + GroupWidget* win = item->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename a source", "New name:", QLineEdit::Normal, - item->refInter->getName(), &ok); + item->getRefBlock()->getName(), &ok); + if (!ok) return; + + if (text == item->getRefBlock()->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the block name must be shorter than 30 characters, cannot be empty", + QMessageBox::Ok); + ok = false; + } + else { + FunctionalBlock* block = params->getGraph()->getSourceBlockByName(text); + if (block != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another source block within the top group", + QMessageBox::Ok); + ok = false; + } + } + } - /* CAUTION: when renaming an interface item, there are two cases : - - it refers to a functional block interface (fbi): the fbi keeps its name - and the new name is given to item - - it refers to a group block interface (gbi) : both gbi and item store the new name + item->getRefBlock()->setName(text); + item->nameChanged(); +} - */ - if(ok && !text.isEmpty() && text.length() < 30) { - if (item->refInter->getOwner()->isGroupBlock()) { - item->refInter->setName(text); + +void Dispatcher::renameInterface(InterfaceItem *item) { + static QString fctName = "Dispatcher::renameInterface()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + GroupWidget* win = item->getOwner()->getScene()->getGroupWidget(); + + bool ok = false; + QString text = ""; + while (!ok) { + text = QInputDialog::getText(win, "Rename an interface", + "New name:", QLineEdit::Normal, + item->refInter->getName(), &ok); + + if (!ok) return; + + if (text == item->refInter->getName()) return; + + if( (text.isEmpty()) || (text.length() > 30)) { + QMessageBox::warning(win,"Error in given name", + "the interface name must be shorter than 30 characters, cannot be empty", + QMessageBox::Ok); + ok = false; + } + else { + AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text); + if (iface != NULL) { + QMessageBox::warning(win,"Error in given name", + "the name provided is similar to that of another interface", + QMessageBox::Ok); + ok = false; + } } - item->setName(text); + } + item->refInter->setName(text); + AbstractInterface* assoIface = item->refInter->getAssociatedIface(); + if (assoIface != NULL) { + assoIface->setName(text+"_enb"); + } + item->updateName(text); + item->getOwner()->nameChanged(); +} +void Dispatcher::showPatterns(InterfaceItem *item) { + static QString fctName = "Dispatcher::showPatterns()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface()); + foreach(char c, *(iface->getOutputPattern())) { + cout << (int)c; } - else { - 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); + cout << endl; +} + +void Dispatcher::duplicateBoxItem(BoxItem *item){ + static QString fctName = "Dispatcher::duplicateBoxItem()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + GroupScene *scene = item->getScene(); + AbstractBlock* block = item->getRefBlock(); + AbstractBlock *newBlock; + + // only duplicate functional blocks + if(block->isFunctionalBlock()) { + + // adding to the model + FunctionalBlock* funBlock = (FunctionalBlock*)block; + newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock); + // adding to the view + scene->createBoxItem(newBlock); + + params->unsaveModif = true; } } -void Dispatcher::duplicateBlock(BoxItem *item){ +void Dispatcher::duplicateSourceItem(SourceItem *item) { + static QString fctName = "Dispatcher::duplicateSourceItem()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif - GroupScene *scene = params->getCurrentScene(); + GroupScene *scene = item->getScene(); AbstractBlock* block = item->getRefBlock(); AbstractBlock *newBlock; @@ -247,15 +388,20 @@ void Dispatcher::duplicateBlock(BoxItem *item){ // adding to the model FunctionalBlock* funBlock = (FunctionalBlock*)block; - newBlock = params->duplicateFunctionalBlock(funBlock); + newBlock = params->getGraph()->duplicateSourceBlock(funBlock); // adding to the view - scene->createBlockItem(newBlock); + scene->createSourceItem(newBlock); params->unsaveModif = true; } } -void Dispatcher::duplicateInterface(InterfaceItem *item){ +void Dispatcher::duplicateInterfaceItem(InterfaceItem *item) { + static QString fctName = "Dispatcher::duplicateInterfaceItem()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + AbstractInterface *refI = item->refInter; if (! refI->isFunctionalInterface()) return; @@ -263,28 +409,62 @@ void Dispatcher::duplicateInterface(InterfaceItem *item){ if(! refB->isFunctionalBlock()) return; FunctionalInterface* iface = (FunctionalInterface*)refI; - AbstractInterface *otherRef = iface->clone(); - if (otherRef == NULL) { + AbstractInterface *cloneIface = iface->clone(); + if (cloneIface == NULL) { QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok); return; } - refB->addInterface(otherRef); - - InterfaceItem *otherIface = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)otherRef,item->getOwner(),params); - item->getOwner()->addInterface(otherIface,true); + refB->addInterface(cloneIface); + + InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params); + item->getOwner()->addInterfaceItem(cloneIfaceItem,true); + + // creating control interface if needed + if (refI->getAssociatedIface() != NULL) { + QString ctlName = cloneIface->getName()+"_enb"; + ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,"boolean","1",cloneIface->getDirection(), AbstractInterface::Control, 1); + refB->addInterface(ctlIface); + if (! ctlIface->setAssociatedIface(cloneIface)) { + cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl; + } + } } void Dispatcher::addBlock(int idCategory, int idBlock, int idScene) { - - GroupScene *scene = searchSceneById(idScene); - FunctionalBlock* newOne = params->addFunctionalBlock(idCategory, idBlock); - scene->createBlockItem(newOne); + static QString fctName = "Dispatcher::addBlock()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + bool newSource = false; + GroupScene *scene = getSceneById(idScene); + ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock); + // if block has no inputs, propose to add it as a source to top scene + if ((scene->isTopScene()) && (ref->isGeneratorBlock())) { + int ret = QMessageBox::question(NULL,"Adding a block to top scene","Selected block may be used as a source for the top scene. Do you want to add it as a source ?"); + if (ret == QMessageBox::Yes) { + newSource = true; + } + } + if (newSource) { + FunctionalBlock* newOne = params->getGraph()->createSourceBlock(ref); + scene->createSourceItem(newOne); + } + else { + GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock()); + FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref); + scene->createBoxItem(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,52 +494,136 @@ GroupWidget *Dispatcher::createTopScene(){ return topGroup; } -GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) { +GroupWidget* Dispatcher::addNewEmptyGroup(GroupScene* scene, bool show) { + static QString fctName = "Dispatcher::addNewEmptyGroup();"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif - // getting back the goup block already created - GroupBlock* groupBlock = NULL; - if (upperItemOfGroupItem != NULL) { - groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock()); - } - // creating the view part of the group - GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params); - // creating the group widget - GroupWidget* group = new GroupWidget(parentWidget, this, params); - // getting the newly created scene - GroupScene *scene = group->getScene(); - scene->setId(sceneCounter++); - // affecting group item to the scene - scene->setGroupItem(groupItem); - groupList.append(group); + // 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()->createChildGroupBlock(parent); + cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl; + // creating the BlockItem in the scene + BoxItem* newItem = scene->createBoxItem(groupBlock); + + params->unsaveModif = true; - mainWindow->getLibrary()->updateComboScene(); + GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem); + if (show) child->show(); + return child; +} + +GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) { + static QString fctName = "Dispatcher::createChildScene()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + GroupWidget* group = NULL; + /* NB: this method may be called during design process or when loading + a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things + cannot be initialized yet. This is why there are 2 cases below + */ + + if (upperItemOfGroupItem != NULL) { + // getting back the goup block already created + GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock()); + // creating the view part of the group + GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params); + // creating the group widget + group = new GroupWidget(parentWidget, this, params); + // getting the newly created scene + GroupScene *scene = group->getScene(); + scene->setId(sceneCounter++); + // affecting group item to the scene + scene->setGroupItem(groupItem); + groupList.append(group); + + mainWindow->getLibrary()->updateComboScene(); + } + else { + GroupItem *groupItem = new GroupItem(this,params); + // creating the group widget + group = new GroupWidget(parentWidget, this, params); + // getting the newly created scene + GroupScene *scene = group->getScene(); + // affecting group item to the scene + scene->setGroupItem(groupItem); + groupList.append(group); + } 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, if possible + if (scene->getParentScene() != NULL) { + 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) { +void Dispatcher::showRstClkIface(AbstractBoxItem *item) { + static QString fctName = "Dispatcher::showRstClkIface()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif item->setRstClkVisible(!item->isRstClkVisible()); - item->resetInterfacesPosition(); + +} + +void Dispatcher::showWishboneIface(AbstractBoxItem *item) { + static QString fctName = "Dispatcher::showWishboneIface()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif - item->getScene()->updateConnectionItemsShape(); + item->setWishboneVisible(!item->isWishboneVisible()); } void Dispatcher::addNewFullGroup() { + static QString fctName = "Dispatcher::addNewFullGroup()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + #ifdef DEBUG_INCLFUN @@ -515,88 +779,189 @@ 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::removeBoxItem(BoxItem *item) { + static QString fctName = "Dispatcher::removeBoxItem()"; +#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()->removeBoxItem(item); + params->getGraph()->removeFunctionalBlock(block); + } + 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()->removeBoxItem(item); + // remove the group from the graph + params->getGraph()->removeGroupBlock(group); + } } -void Dispatcher::removeAllBlockConnections(AbstractBoxItem *block) { +void Dispatcher::removeAllBlockConnections(AbstractBoxItem *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) { +void Dispatcher::removeSourceItem(SourceItem *item) { + static QString fctName = "Dispatcher::removeSourceItem()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + + QString msg = "Removing source "; + + msg += item->getRefBlock()->getName(); + msg += " and all its connections.\n\nAre you sure ?"; + + int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); + if (ret == QMessageBox::Cancel) { + return; + } + removeAllBlockConnections(item); + + FunctionalBlock* block = AB_TO_FUN(item->getRefBlock()); + item->getScene()->removeSourceItem(item); + params->getGraph()->removeSourceBlock(block); +} - GroupScene *scene = params->getCurrentScene(); - GroupItem* currentGroup = scene->getGroupItem(); - conn->getFromInterfaceItem()->unconnectTo(conn->getToInterfaceItem()); +void Dispatcher::removeConnection(ConnectionItem *connItem) { + static QString fctName = "Dispatcher::removeConnection()"; +#ifdef DEBUG_FCTNAME + cout << "call to " << qPrintable(fctName) << endl; +#endif + InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem(); + InterfaceItem* toIfaceItem = connItem->getToInterfaceItem(); - scene->removeConnectionItem(conn); - delete conn; +#ifdef DEBUG + cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl; +#endif - currentGroup->updateInterfacesAndConnections(); - params->unsaveModif = true; -} + InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not + GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem -void Dispatcher::removeUselessGroupInterfaces() { + ConnectedInterface *fromInter = fromIfaceItem->refInter; + ConnectedInterface *toInter = toIfaceItem->refInter; + + // test if one of the interface bounded to item is owned by a GroupItem + if (fromIfaceItem->getOwner()->isGroupItem()) { + groupItem = ABI_TO_GI(fromIfaceItem->getOwner()); + groupIfaceItem = fromIfaceItem; + } + else if (toIfaceItem->getOwner()->isGroupItem()) { + groupItem = ABI_TO_GI(toIfaceItem->getOwner()); + groupIfaceItem = toIfaceItem; + } + else { + groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem(); + } - GroupScene *scene = params->getCurrentScene(); - GroupItem* currentGroup = scene->getGroupItem(); + // removing the connection from graph +#ifdef DEBUG + cout << "removing connections from graph ..." ; +#endif + fromInter->disconnectTo(toInter); + +#ifdef DEBUG + cout << "done." << endl ; +#endif - foreach(InterfaceItem *inter, currentGroup->getInterfaces()) { - if(inter->refInter->getConnectedTo().length() == 0) { - // NB : remove from view also remove from model - currentGroup->removeInterface(inter); + // removing the connection from scene +#ifdef DEBUG + cout << "removing connections from scene ..." ; +#endif + groupItem->getScene()->removeConnectionItem(connItem); + +#ifdef DEBUG + cout << "done." << endl ; +#endif + + // if one of the interface bounded to connItem is owned by the GroupItem of the scene + if (groupIfaceItem != NULL) { + + // determine if the interface must be removed since it has no more connections. + bool groupInterRemove = false; + if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true; + + if (groupInterRemove) { + // get the GroupInterface from interface item + ConnectedInterface* groupInter = groupIfaceItem->refInter; + // remove interface from GroupItem, and delete it. + groupItem->removeInterfaceItem(groupIfaceItem); + // get the parent BoxItem of GroupItem if it exists. + BoxItem* parent2Item = groupItem->getParentItem(); + if (parent2Item != NULL) { + InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter); + // remove interface intem in parent BoxItem + parent2Item->removeInterfaceItem(group2IfaceItem); + } + // remove GroupInterface in the graph. + groupInter->getOwner()->removeInterface(groupInter); } } - scene->updateConnectionItemsShape(); } void Dispatcher::showBlocksLibrary(){ @@ -605,8 +970,7 @@ void Dispatcher::showBlocksLibrary(){ mainWindow->getLibrary()->raise(); } -void Dispatcher::showProperties(InterfaceItem *inter) -{ +void Dispatcher::showProperties(InterfaceItem *inter) { new InterfacePropertiesWindow(inter); } @@ -626,147 +990,53 @@ void Dispatcher::connectInterToGroup(InterfaceItem *item){ GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem(); // creating/adding the group interface in the graph model - GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getLevel()); - groupInter->setType(refInter->getType()); - groupInter->setWidth(refInter->getWidth()); - groupInter->setPurpose(refInter->getPurpose()); + GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose()); parentItem->getRefBlock()->addInterface(groupInter); - - // connect both interface - bool ok = true; - if (refInter->getDirection() == AbstractInterface::Output) { - ok = refInter->connectTo(groupInter); - ok = ok & groupInter->connectFrom(refInter); - } - else if (refInter->getDirection() == AbstractInterface::Input) { - ok = groupInter->connectTo(refInter); - ok = ok & refInter->connectFrom(groupInter); - } - else if (refInter->getDirection() == AbstractInterface::InOut) { - ok = refInter->connectTo(groupInter); - ok = ok & groupInter->connectFrom(refInter); - ok = ok & groupInter->connectTo(refInter); - ok = ok & refInter->connectFrom(groupInter); - } - if (!ok) { - cerr << "abnormal case while connecting a block iface to its parent group" << endl; - } + // creating/adding the group control interface in the graph model + GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control); + groupCtlInter->setAssociatedIface(groupInter); + parentItem->getRefBlock()->addInterface(groupCtlInter); // creating/adding the group interface in the current scene model, and connection item InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params); - parentItem->addInterface(groupIfaceItem,true); + parentItem->addInterfaceItem(groupIfaceItem,true); - parentItem->getScene()->createConnectionItem(item, groupIfaceItem); + // creating the connection, in graph and with an item + createConnection(item, groupIfaceItem); // if groupItem is not topGroup, must also add a new interface to the parent BlockItem BoxItem* parent2Item = parentItem->getParentItem(); if(parent2Item != NULL){ InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params); - parent2Item->addInterface(blockIfaceItem,true); + parent2Item->addInterfaceItem(blockIfaceItem,true); } parentItem->getScene()->updateConnectionItemsShape(); unselectAllItems(); params->unsaveModif = true; - - } -void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) { - static QString fctName = "Dispatcher::disconnectInterFromGroup()"; +void Dispatcher::removeFunctionalInterface(InterfaceItem *item) { + static QString fctName = "Dispatcher::removeBlockInterface()"; #ifdef DEBUG_FCTNAME cout << "call to " << qPrintable(fctName) << endl; #endif - // getting the GroupBlock and GroupItem that are parent of the block that owns item - ConnectedInterface *refInter = item->refInter; - ConnectedInterface *groupInter = NULL; - GroupBlock* parentGroup = AB_TO_GRP(refInter->getOwner()->getParent()); - GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem(); - - // removing the connection from graph -#ifdef DEBUG - cout << "removing connections from graph ..." ; -#endif - - if (refInter->getDirection() == AbstractInterface::Output) { - groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to - refInter->clearConnectedTo(); - groupInter->clearConnectedFrom(); - } - else if (refInter->getDirection() == AbstractInterface::Input) { - groupInter = refInter->getConnectedFrom(); - refInter->clearConnectedFrom(); - groupInter->clearConnectedTo(); - } - else if (refInter->getDirection() == AbstractInterface::InOut) { - groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to - refInter->clearConnectedTo(); - refInter->clearConnectedFrom(); - groupInter->clearConnectedTo(); - groupInter->clearConnectedFrom(); - } -#ifdef DEBUG - cout << "done." << endl ; -#endif - - if (groupInter == NULL) { - cerr << "abnormal case 1 while removing an interface item of a block, linked to a parent group" << endl; - } - -#ifdef DEBUG - cout << "getting group interface item, and connection item ..." ; -#endif - - - InterfaceItem* groupIfaceItem = parentItem->searchInterfaceByRef(groupInter); - if (groupIfaceItem == NULL) { - cerr << "abnormal case 2 while removing an interface item of a block, linked to a parent group" << endl; - } - ConnectionItem* conn = parentItem->getScene()->searchConnectionItem(item,groupIfaceItem); - if (conn == NULL) { - cerr << "abnormal case 3 while removing an interface item of a block, linked to a parent group" << endl; - } -#ifdef DEBUG - cout << "done." << endl ; -#endif - - // removing the interface group item from the group item, and the connection item -#ifdef DEBUG - cout << "removing group interface item, and connection item ..." ; -#endif - - item->removeConnectionItem(conn); - groupIfaceItem->removeConnectionItem(conn); - parentItem->removeInterface(groupIfaceItem); // CAUTION : this deletes the interface item. - parentItem->getScene()->removeConnectionItem(conn); -#ifdef DEBUG - cout << "done." << endl ; -#endif - - // removing the interface box item in the parent scene -#ifdef DEBUG - cout << "removing the inteeface item of box item in parent scene if needed ..." ; -#endif - - BoxItem* parent2Item = parentItem->getParentItem(); - if (parent2Item != NULL) { - InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter); - parent2Item->removeInterface(group2IfaceItem); + /* 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); } -#ifdef DEBUG - cout << "done." << endl ; -#endif - - // removing the interface group from the group -#ifdef DEBUG - cout << "removing group interface ..." ; -#endif - parentGroup->removeInterface(groupInter); -#ifdef DEBUG - cout << "done." << endl ; -#endif + ConnectedInterface* ref = item->refInter; + item->getOwner()->removeInterfaceItem(item); + FunctionalBlock* fun = AB_TO_FUN(ref->getOwner()); + fun->removeInterface(ref); } void Dispatcher::removeGroupInterface(InterfaceItem *item) { @@ -775,15 +1045,11 @@ void Dispatcher::removeGroupInterface(InterfaceItem *item) { cout << "call to " << qPrintable(fctName) << endl; #endif - /* NB: there is a single connection between item and another one that is owned - by a BoxItem. Thus, we just have to find it and to call disconnectInterFromGroup(); + /* NB: just remove all connections from/to this item, since when there are no more + ones to a GroupItem, it is automatically deleted. */ - ConnectionItem* conn = item->connections.at(0); - if (conn->getFromInterfaceItem() == item) { - disconnectInterFromGroup(conn->getToInterfaceItem()); - } - else { - disconnectInterFromGroup(conn->getFromInterfaceItem()); + foreach(ConnectionItem* conn, item->connections) { + removeConnection(conn); } } @@ -796,7 +1062,7 @@ QMap Dispatcher::getAllGroupNames() { return list; } -GroupScene* Dispatcher::searchSceneById(int id) { +GroupScene* Dispatcher::getSceneById(int id) { foreach(GroupWidget *group, groupList){ if(group->getScene()->getId() == id) return group->getScene(); @@ -805,7 +1071,7 @@ GroupScene* Dispatcher::searchSceneById(int id) { return NULL; } -GroupItem *Dispatcher::searchGroupItemById(int id) { +GroupItem *Dispatcher::getGroupItemById(int id) { foreach(GroupWidget *group, groupList) { GroupScene* scene = group->getScene(); if (scene->getGroupItem()->getId() == id) return scene->getGroupItem(); @@ -814,11 +1080,11 @@ GroupItem *Dispatcher::searchGroupItemById(int id) { return NULL; } -BoxItem *Dispatcher::searchBlockItemById(int id) { +BoxItem *Dispatcher::getBoxItemById(int id) { foreach(GroupWidget *group, groupList) { GroupScene* scene = group->getScene(); - foreach(BoxItem *item, scene->getBlockItems()){ + foreach(BoxItem *item, scene->getBoxItems()){ if(item->getId() == id){ return item; } @@ -828,7 +1094,7 @@ BoxItem *Dispatcher::searchBlockItemById(int id) { return NULL; } -InterfaceItem* Dispatcher::searchInterfaceItemById(int id) { +InterfaceItem* Dispatcher::getInterfaceItemById(int id) { foreach(GroupWidget *group, groupList) { @@ -839,7 +1105,7 @@ InterfaceItem* Dispatcher::searchInterfaceItemById(int id) { return item; } } - foreach(BoxItem *block, scene->getBlockItems()){ + foreach(BoxItem *block, scene->getBoxItems()){ foreach(InterfaceItem *item, block->getInterfaces()){ if(item->getId() == id){ return item;