1 #include "Dispatcher.h"
2 #include "Parameters.h"
3 #include "MainWindow.h"
5 #include "ExternalResource.h"
8 #include "ReferenceBlock.h"
9 #include "GroupBlock.h"
10 #include "FunctionalBlock.h"
12 #include "ConnectedInterface.h"
13 #include "ReferenceInterface.h"
14 #include "GroupInterface.h"
15 #include "FunctionalInterface.h"
17 #include "GroupWidget.h"
18 #include "GroupScene.h"
19 #include "GroupItem.h"
21 #include "SourceItem.h"
22 #include "InterfaceItem.h"
23 #include "ConnectionItem.h"
25 #include "BlockLibraryWidget.h"
26 #include "BlockLibraryTree.h"
28 #include "AbstractInputModifier.h"
29 #include "DelayInputModifier.h"
32 #include "InterfacePropertiesWindow.h"
34 int Dispatcher::sceneCounter = 0;
36 Dispatcher::Dispatcher(Parameters* _params, MainWindow* _window) {
39 params->setDispatcher(this);
44 GroupWidget *Dispatcher::loadProject(const QString& filename) {
48 root = params->openProjectFile(filename);
50 catch(Exception err) {
55 // creating the top widget/scene
56 topGroup = new GroupWidget(NULL,this,params);
57 currentGroup = topGroup;
58 // getting the newly created scene
59 GroupScene *scene = topGroup->getScene();
61 params->setTopScene(scene);
62 params->setCurrentScene(scene);
65 topGroup = params->loadProject(root);
68 cerr << qPrintable(e.getDefaultMessage()) << endl;
69 cerr << "Aborting ..." << endl;
70 // TO DO : deleteting topGroup and all
74 QFileInfo info(filename);
75 params->projectPath = info.absolutePath();
76 params->projectName = info.baseName();
77 cout << "project path = " << qPrintable(params->projectPath) << endl;
78 groupList.append(topGroup);
82 void Dispatcher::closeCurrentProject() {
84 foreach(GroupWidget* win, groupList) {
88 params->destroyGraph();
94 bool Dispatcher::createConnection(InterfaceItem *iface1, InterfaceItem *iface2, bool visible) {
96 ConnectedInterface* ref1 = iface1->refInter;
97 ConnectedInterface* ref2 = iface2->refInter;
98 // connect both interface
103 // test the ref1->ref2 connection
104 if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) {
105 ref1->connectTo(ref2);
108 // if the frist one did not work, test ref2->ref1
109 if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) {
110 ref2->connectTo(ref1);
113 if ((ok1 == true) || (ok2 == true)) {
115 iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible);
118 params->unsaveModif = true;
119 cout << "created a connection from " << qPrintable(ref1->getName()) << " to " << qPrintable(ref2->getName()) << endl;
126 void Dispatcher::unselectAllItems(int direction){
128 GroupScene *scene = params->getCurrentScene();
130 foreach(BoxItem* block, scene->getBoxItems()) {
131 block->setSelected(false);
132 block->setCurrentInterface(NULL);
134 scene->unselecteInterfaces();
138 void Dispatcher::setCurrentGroupWidget(GroupWidget *win){
140 win->changeConnectionMode(-1);
142 params->setCurrentScene(win->getScene());
145 void Dispatcher::changeConnectionMode(int mode){
148 foreach(GroupWidget* win, groupList){
150 QToolButton* buttonNewConnection = win->getButtonNewConnection();
152 QPalette pal = buttonNewConnection->palette();
155 if(params->sceneMode != Parameters::EditOnConnection){
156 params->sceneMode = Parameters::EditOnConnection;
157 pal.setColor(QPalette::Button, QColor(Qt::lightGray));
159 params->sceneMode = Parameters::EditNoOperation;
160 pal.setColor(QPalette::Button, QColor("#edeceb"));
163 else if(mode == Parameters::EditOnConnection){
164 params->sceneMode = Parameters::EditOnConnection;
165 pal.setColor(QPalette::Button, QColor(Qt::lightGray));
168 params->sceneMode = Parameters::EditNoOperation;
169 pal.setColor(QPalette::Button, QColor("#edeceb"));
171 unselectAllInterfaces();
173 buttonNewConnection->setAutoFillBackground(true);
174 buttonNewConnection->setPalette(pal);
175 buttonNewConnection->update();
180 void Dispatcher::generateVHDL() throw(Exception) {
181 static QString fctName = "Dispatcher::generateVHDL()";
183 cout << "call to " << qPrintable(fctName) << endl;
186 QDir baseDir(params->projectPath);
187 QDir srcDir(params->projectPath+"/src");
189 if (!baseDir.exists()) {
190 cerr << "Project path " << qPrintable(params->projectPath) << " no longer exists. First, recreate it and put the project file within. Then retry to generate." << endl;
194 if (srcDir.exists()) {
195 srcDir.removeRecursively();
197 baseDir.mkdir("src");
199 if (! baseDir.exists("testbench")) {
200 baseDir.mkdir("testbench");
202 if (! baseDir.exists("Makefile")) {
203 QFile make("/home/sdomas/Projet/Blast/code/blast/Makefile-isim");
204 QString dest = params->projectPath;
209 // copying external resources
210 QString dest = params->projectPath;
213 params->getGraph()->generateVHDL(dest);
215 QList<QString> extResources = params->getGraph()->getExternalResources();
216 foreach(QString name, extResources) {
217 cout << qPrintable(name) << endl;
218 QList<ExternalResource*> lstRes = params->searchResourceByName(name);
219 foreach(ExternalResource* res, lstRes) {
220 QFile resFile(res->getFile());
221 QFileInfo info(res->getFile());
222 QString destFile = dest+info.fileName();
223 cout << "copying " << qPrintable(res->getFile()) << " into " << qPrintable(destFile) << endl;
224 resFile.copy(destFile);
232 // creating parameters file
233 QString paramName = params->projectPath+"/params-isim.txt";
234 QFile paramFile(paramName);
235 if (!paramFile.open(QIODevice::WriteOnly)) {
236 throw(Exception(PROJECTPATH_NOACCESS));
238 QTextStream out(¶mFile);
239 out << "PROJECT_NAME := " << params->projectName << endl << endl;
240 out << "SRC_DIR := src" << endl;
241 out << "TB_DIR := testbench" << endl << endl;
242 out << "VHDL_SRC := ";
245 srcDir.setNameFilters(filter);
246 QStringList listVHDL = srcDir.entryList();
247 for(int j=0;j<listVHDL.size();j++) {
251 out << "$(SRC_DIR)/" << qPrintable(listVHDL.at(j));
252 if (j != listVHDL.size()-1) {
258 out << "VL_SRC := ${XILINX}/verilog/src/glbl.v" << endl << endl;
259 out << "TB_SRC := $(TB_DIR)/read_csv.vhd \\" << endl;
260 out << "\t$(TB_DIR)/$(PROJECT_NAME)_tb.vhd" << endl << endl;
261 out << "SIMU_EXE := $(PROJECT_NAME)_tb" << endl << endl;
265 QString msg = "VHDL generation completed successfully. Go to ";
266 msg += params->projectPath+" and type the following commands to launch a simulation:\n";
267 msg += "\tmake clean\n";
269 msg += "\tmake view\n";
270 QMessageBox::information(mainWindow,"VHDL generation", msg, QMessageBox::Ok);
274 void Dispatcher::generateBlockVHDL(BoxItem *item){
275 static QString fctName = "Dispatcher::generateBlockVHDL()";
277 cout << "call to " << qPrintable(fctName) << endl;
280 if (item->getRefBlock()->isFunctionalBlock()) {
281 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
283 block->generateVHDL(params->projectPath);
286 cout << qPrintable(e.getMessage()) << endl;
291 void Dispatcher::renameFunctionalBlock(BoxItem *item){
292 static QString fctName = "Dispatcher::renameFunctionalBlock()";
294 cout << "call to " << qPrintable(fctName) << endl;
297 GroupWidget* win = item->getScene()->getGroupWidget();
302 text = QInputDialog::getText(win, "Rename a functional block",
303 "New name:", QLineEdit::Normal,
304 item->getRefBlock()->getName(), &ok);
307 if (text == item->getRefBlock()->getName()) return;
309 if( (text.isEmpty()) || (text.length() > 30)) {
310 QMessageBox::warning(win,"Error in given name",
311 "the block name must be shorter than 30 characters, cannot be empty",
316 FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent()));
318 QMessageBox::warning(win,"Error in given name",
319 "the name provided is similar to that of another functional block within the group",
326 item->getRefBlock()->setName(text);
330 void Dispatcher::renameGroupBlock(GroupItem *item){
331 static QString fctName = "Dispatcher::renameGroupBlock()";
333 cout << "call to " << qPrintable(fctName) << endl;
336 GroupWidget* win = item->getScene()->getGroupWidget();
341 text = QInputDialog::getText(win, "Rename a group",
342 "New name:", QLineEdit::Normal,
343 item->getRefBlock()->getName(), &ok);
346 if (text == item->getRefBlock()->getName()) return;
348 if( (text.isEmpty()) || (text.length() > 30)) {
349 QMessageBox::warning(win,"Error in given name",
350 "the block name must be shorter than 30 characters, cannot be empty",
355 GroupBlock* block = params->getGraph()->getGroupBlockByName(text);
357 QMessageBox::warning(win,"Error in given name",
358 "the name provided is similar to that of another group",
365 item->getRefBlock()->setName(text);
366 if(item->getScene()->getGroupWidget()->isTopGroup()) {
367 mainWindow->setWindowTitle("blast - "+text);
370 item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text);
373 mainWindow->getLibrary()->updateComboScene();
376 void Dispatcher::renameSourceBlock(SourceItem *item){
377 static QString fctName = "Dispatcher::renameSourceBlock()";
379 cout << "call to " << qPrintable(fctName) << endl;
382 GroupWidget* win = item->getScene()->getGroupWidget();
387 text = QInputDialog::getText(win, "Rename a source",
388 "New name:", QLineEdit::Normal,
389 item->getRefBlock()->getName(), &ok);
392 if (text == item->getRefBlock()->getName()) return;
394 if( (text.isEmpty()) || (text.length() > 30)) {
395 QMessageBox::warning(win,"Error in given name",
396 "the block name must be shorter than 30 characters, cannot be empty",
401 FunctionalBlock* block = params->getGraph()->getSourceBlockByName(text);
403 QMessageBox::warning(win,"Error in given name",
404 "the name provided is similar to that of another source block within the top group",
411 item->getRefBlock()->setName(text);
416 void Dispatcher::renameInterface(InterfaceItem *item) {
417 static QString fctName = "Dispatcher::renameInterface()";
419 cout << "call to " << qPrintable(fctName) << endl;
422 GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
427 text = QInputDialog::getText(win, "Rename an interface",
428 "New name:", QLineEdit::Normal,
429 item->refInter->getName(), &ok);
433 if (text == item->refInter->getName()) return;
435 if( (text.isEmpty()) || (text.length() > 30)) {
436 QMessageBox::warning(win,"Error in given name",
437 "the interface name must be shorter than 30 characters, cannot be empty",
442 AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text);
444 QMessageBox::warning(win,"Error in given name",
445 "the name provided is similar to that of another interface",
451 item->refInter->setName(text);
452 AbstractInterface* assoIface = item->refInter->getAssociatedIface();
453 if (assoIface != NULL) {
454 assoIface->setName(text+"_enb");
456 item->updateName(text);
457 item->getOwner()->nameChanged();
460 void Dispatcher::showPatterns(InterfaceItem *item) {
461 static QString fctName = "Dispatcher::showPatterns()";
463 cout << "call to " << qPrintable(fctName) << endl;
466 if (item->refInter->getDirection() == AbstractInterface::Input) {
467 msg = "Input pattern of iface ";
468 msg += item->refInter->getName();
470 msg += item->refInter->getOwner()->getName();
472 // get the precursor output pattern
473 ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface());
474 QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
476 AbstractInputModifier* modifier = connIface->getInputModifier();
477 // check if the input is modified
478 if (modifier != NULL) {
480 out = modifier->getModifiedInput(out);
483 foreach(char c, *out) {
484 msg += QString::number((int)c);
488 else if (item->refInter->getDirection() == AbstractInterface::Output) {
489 msg = "Output pattern of iface ";
490 msg += item->refInter->getName();
492 msg += item->refInter->getOwner()->getName();
494 ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
495 if (iface->getOutputPattern() == NULL) return;
496 foreach(char c, *(iface->getOutputPattern())) {
497 msg += QString::number((int)c);
501 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
504 void Dispatcher::showModifier(InterfaceItem *item) {
505 static QString fctName = "Dispatcher::showModifier()";
507 cout << "call to " << qPrintable(fctName) << endl;
510 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
511 AbstractInputModifier* mod = assoIface->getInputModifier();
512 if (mod->isDelay()) {
513 DelayInputModifier* delay = (DelayInputModifier *)mod;
514 msg = "Pattern of iface ";
515 msg += item->refInter->getName();
517 msg += item->refInter->getOwner()->getName();
518 msg += " is modified by a simple delay of ";
519 msg += QString::number(delay->getDelayLength());
522 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
525 void Dispatcher::removeModifier(InterfaceItem *item) {
526 static QString fctName = "Dispatcher::showModifier()";
528 cout << "call to " << qPrintable(fctName) << endl;
531 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
532 assoIface->clearInputModifier();
536 void Dispatcher::duplicateBoxItem(BoxItem *item){
537 static QString fctName = "Dispatcher::duplicateBoxItem()";
539 cout << "call to " << qPrintable(fctName) << endl;
542 GroupScene *scene = item->getScene();
543 AbstractBlock* block = item->getRefBlock();
544 AbstractBlock *newBlock;
546 // only duplicate functional blocks
547 if(block->isFunctionalBlock()) {
549 // adding to the model
550 FunctionalBlock* funBlock = (FunctionalBlock*)block;
551 newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock);
552 // adding to the view
553 scene->createBoxItem(newBlock);
555 params->unsaveModif = true;
559 void Dispatcher::duplicateSourceItem(SourceItem *item) {
560 static QString fctName = "Dispatcher::duplicateSourceItem()";
562 cout << "call to " << qPrintable(fctName) << endl;
565 GroupScene *scene = item->getScene();
566 AbstractBlock* block = item->getRefBlock();
567 AbstractBlock *newBlock;
569 // only duplicate functional blocks
570 if(block->isFunctionalBlock()) {
572 // adding to the model
573 FunctionalBlock* funBlock = (FunctionalBlock*)block;
574 newBlock = params->getGraph()->duplicateSourceBlock(funBlock);
575 // adding to the view
576 scene->createSourceItem(newBlock);
578 params->unsaveModif = true;
582 void Dispatcher::duplicateInterfaceItem(InterfaceItem *item) {
583 static QString fctName = "Dispatcher::duplicateInterfaceItem()";
585 cout << "call to " << qPrintable(fctName) << endl;
588 AbstractInterface *refI = item->refInter;
589 if (! refI->isFunctionalInterface()) return;
591 AbstractBlock *refB = refI->getOwner();
592 if(! refB->isFunctionalBlock()) return;
594 FunctionalInterface* iface = (FunctionalInterface*)refI;
595 AbstractInterface *cloneIface = iface->clone();
596 if (cloneIface == NULL) {
597 QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
601 refB->addInterface(cloneIface);
603 InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params);
604 item->getOwner()->addInterfaceItem(cloneIfaceItem,true);
606 // creating control interface if needed
607 if (refI->getAssociatedIface() != NULL) {
608 QString ctlName = cloneIface->getName()+"_enb";
609 ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
610 refB->addInterface(ctlIface);
611 if (! ctlIface->setAssociatedIface(cloneIface)) {
612 cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl;
618 BoxItem* Dispatcher::addBlock(int idCategory, int idBlock, int idScene) {
619 static QString fctName = "Dispatcher::addBlock()";
621 cout << "call to " << qPrintable(fctName) << endl;
623 bool newSource = false;
624 BoxItem* item = NULL;
625 GroupScene *scene = getSceneById(idScene);
626 ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
627 // if block has no inputs, propose to add it as a source to top scene
628 if ((scene->isTopScene()) && (ref->isGeneratorBlock())) {
629 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 ?");
630 if (ret == QMessageBox::Yes) {
635 FunctionalBlock* newOne = params->getGraph()->createSourceBlock(ref);
636 scene->createSourceItem(newOne);
639 GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
640 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref);
641 item = scene->createBoxItem(newOne);
642 params->blockToItem.insert(newOne,item);
644 params->unsaveModif = true;
649 GroupWidget *Dispatcher::createTopScene(){
650 static QString fctName = "Dispatcher::createTopScene()";
652 cout << "call to " << qPrintable(fctName) << endl;
655 // creating the model part of the group
656 Graph* graph = params->createGraph();
657 GroupBlock *topBlock = graph->getTopGroup();
658 // creating the clkrstgen block
659 ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen");
660 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(topBlock, ref);
661 ConnectedInterface* fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_clk"));
662 ConnectedInterface* toIface = AI_TO_CON(newOne->getIfaceFromName("ext_clk"));
663 fromIface->connectTo(toIface);
664 fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_reset"));
665 toIface = AI_TO_CON(newOne->getIfaceFromName("ext_reset"));
666 fromIface->connectTo(toIface);
668 // creating a fake and not connected interface
669 //AbstractInterface* iface = new GroupInterface(refBlock,"grp_iface",AbstractInterface::Input,AbstractInterface::Top);
671 // creating the group widget
672 topGroup = new GroupWidget(NULL,this,params);
673 currentGroup = topGroup;
674 // getting the newly created scene
675 GroupScene *scene = topGroup->getScene();
676 scene->setId(sceneCounter++);
677 params->setTopScene(scene);
678 params->setCurrentScene(scene);
679 // creating the view part of the group
680 GroupItem *group = new GroupItem(NULL,topBlock,this,params);
683 // adding the fake interface to the top group item
684 //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
685 //group->addInterface(item,true);
687 scene->setGroupItem(group);
689 groupList.append(topGroup);
693 GroupWidget* Dispatcher::addNewEmptyGroup(GroupScene* scene, bool show) {
694 static QString fctName = "Dispatcher::addNewEmptyGroup();";
696 cout << "call to " << qPrintable(fctName) << endl;
699 // getting the parent block in the graph
700 GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
701 cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
702 GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent);
703 cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
704 // creating the BlockItem in the scene
705 BoxItem* newItem = scene->createBoxItem(groupBlock);
707 params->unsaveModif = true;
709 GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem);
710 if (show) child->show();
715 GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
716 static QString fctName = "Dispatcher::createChildScene()";
718 cout << "call to " << qPrintable(fctName) << endl;
721 GroupWidget* group = NULL;
722 /* NB: this method may be called during design process or when loading
723 a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
724 cannot be initialized yet. This is why there are 2 cases below
727 if (upperItemOfGroupItem != NULL) {
728 // getting back the goup block already created
729 GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
730 // creating the view part of the group
731 GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
733 // creating the group widget
734 group = new GroupWidget(parentWidget, this, params);
735 // getting the newly created scene
736 GroupScene *scene = group->getScene();
737 scene->setId(sceneCounter++);
738 // affecting group item to the scene
739 scene->setGroupItem(groupItem);
740 groupList.append(group);
742 mainWindow->getLibrary()->updateComboScene();
745 GroupItem *groupItem = new GroupItem(this,params);
746 // creating the group widget
747 group = new GroupWidget(parentWidget, this, params);
748 // getting the newly created scene
749 GroupScene *scene = group->getScene();
750 // affecting group item to the scene
751 scene->setGroupItem(groupItem);
752 groupList.append(group);
757 void Dispatcher::destroyScene(GroupScene *scene) {
758 foreach(GroupScene* s, scene->getChildrenScene()) {
762 if (scene->getNbChildScene() == 0) {
763 // remove scene from the parent list, if possible
764 if (scene->getParentScene() != NULL) {
765 scene->getParentScene()->removeChildScene(scene);
767 // destroy the GroupWidget
768 groupList.removeAll(scene->getGroupWidget());
769 scene->getGroupWidget()->deleteLater();
772 cerr << "Abnormal case when destroying a scene" << endl;
776 void Dispatcher::showRaiseWindow(BoxItem *item) {
777 static QString fctName = "Dispatcher::showRaiseWindow()";
779 cout << "call to " << qPrintable(fctName) << endl;
782 cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
783 GroupItem* child = item->getChildGroupItem();
785 cerr << "abnormal case: child group item is null " << endl;
789 GroupWidget* win = child->getScene()->getGroupWidget();
793 win->activateWindow();
796 params->setCurrentScene(currentGroup->getScene());
799 void Dispatcher::showRstClkIface(AbstractBoxItem *item) {
800 static QString fctName = "Dispatcher::showRstClkIface()";
802 cout << "call to " << qPrintable(fctName) << endl;
805 item->setRstClkVisible(!item->isRstClkVisible());
809 void Dispatcher::showWishboneIface(AbstractBoxItem *item) {
810 static QString fctName = "Dispatcher::showWishboneIface()";
812 cout << "call to " << qPrintable(fctName) << endl;
815 item->setWishboneVisible(!item->isWishboneVisible());
818 void Dispatcher::addNewFullGroup() {
819 static QString fctName = "Dispatcher::addNewFullGroup()";
821 cout << "call to " << qPrintable(fctName) << endl;
827 QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
828 QList<AbstractBlock*> listAbstractBlocks; //abstract blocks in the group
829 QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
831 /* What must be done:
832 1 - creating a new GroupBlock
833 2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
834 3 - creating a BlockItem that references the new GroupBlock
835 4 - creating a new GroupWidget
836 5 - creating a new GroupItem added to the scene of the GroupWidget
840 /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
841 associated to the GroupItem of the current scene
843 GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
844 GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
845 /* step 2: moving selected blocks */
846 foreach(BlockItem* blockItem, listBlocks) {
847 parentBlock->removeBlock(blockItem->getRefBlock());
848 newGroupBlock->addBlock(blockItem->getRefBlock());
851 GroupItem *parent = currentGroup->getScene()->getGroupItem();
852 GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
853 BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
854 GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
856 //create the new window
857 GroupWidget* win = new GroupWidget(this,params);
858 win->getScene()->setGroupItem(groupItem);
859 win->getScene()->addItem(groupItem);
860 ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
861 params->addWindow(win);
865 params->getCurrentScene()->addBlockItem(blockItem);
866 params->getCurrentScene()->addItem(blockItem);
867 ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
869 //replace selected blocks in the group
870 foreach(AbstractBoxItem *block, listBlocks){
871 ((GroupItem*)block->getParentItem())->removeBlockItem(block);
872 ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
873 params->getCurrentScene()->removeItem(block);
874 params->getCurrentScene()->removeBlockItem(block);
876 groupBlock->addBlock(block->getRefBlock());
877 listAbstractBlocks.append(block->getRefBlock());
879 block->setUpperItem(groupItem);
880 groupItem->addBlockItem(block);
881 win->getScene()->addItem(block);
882 win->getScene()->addBlockItem(block);
885 //replace connection between selected blocks in the group
886 foreach(ConnectionItem *conn, connections){
887 if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
888 if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
889 parent->removeConnection(conn);
890 params->getCurrentScene()->removeItem(conn);
892 groupItem->addConnection(conn);
893 win->getScene()->addItem(conn);
898 //create new interfaces and connections for the new group
899 foreach(AbstractBoxItem *block, listBlocks){
900 foreach(InterfaceItem *inter, block->getInterfaces()){
901 cout << "inter : " << inter->getName().toStdString() << endl;
902 if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
903 cout << "connected from non null" << endl;
904 if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
906 AbstractInterface *iface = inter->refInter->clone(0);
907 iface->setName(iface->getName()+"_group");
908 groupBlock->addInterface(iface);
910 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
911 blockItem->addInterface(ifaceItem);
912 blockItem->resetInterfacesPosition();
914 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
915 groupItem->addInterface(ifaceGroupItem);
916 groupItem->resetInterfacesPosition();
917 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
918 if(conn->getToInterfaceItem() == inter){
919 conn->setToInterfaceItem(ifaceItem);
920 ifaceItem->refInter->setConnectedFrom(NULL);
921 conn->getFromInterfaceItem()->refInter->clearConnectedTo();
922 connect(ifaceItem,conn->getFromInterfaceItem());
925 params->setCurrentWindow(win);
927 inter->refInter->setConnectedFrom(NULL);
928 ifaceGroupItem->refInter->clearConnectedTo();
929 connect(inter,ifaceGroupItem);
930 params->setCurrentWindow(mainWindow);
934 if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
935 cout << "connected to non null" << endl;
936 foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
937 if(!listAbstractBlocks.contains(iface->getOwner())){
939 AbstractInterface *iface = inter->refInter->clone(0);
940 iface->setName(iface->getName()+"_group");
941 groupBlock->addInterface(iface);
943 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
944 blockItem->addInterface(ifaceItem);
945 blockItem->resetInterfacesPosition();
947 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
948 if(conn->getFromInterfaceItem() == inter){
949 conn->setFromInterfaceItem(ifaceItem);
950 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
951 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
955 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
956 groupItem->addInterface(ifaceGroupItem);
957 groupItem->resetInterfacesPosition();
958 inter->refInter->clearConnectedTo();
959 ifaceGroupItem->refInter->setConnectedFrom(NULL);
960 connect(ifaceGroupItem,inter);
969 parent->updateShape();
970 currentGroup->getScene()->updateConnectionItemsShape();
972 groupItem->updateShape();
973 win->getScene()->updateConnectionItemsShape();
974 groupItem->update(groupItem->boundingRect());
979 void Dispatcher::removeBoxItem(BoxItem *item) {
980 static QString fctName = "Dispatcher::removeBoxItem()";
982 cout << "call to " << qPrintable(fctName) << endl;
985 /* a BoxItem (group of func) can be removed only if none of its
986 interfaces is connected to a group interface that is itself
987 connected to another one.
989 bool canRemove = true;
991 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
992 foreach(ConnectionItem* conn, ifaceItem->connections) {
993 InterfaceItem* other = NULL;
994 if (conn->getFromInterfaceItem() == ifaceItem) {
995 other = conn->getToInterfaceItem();
998 other = conn->getFromInterfaceItem();
1001 if (other->getOwner()->isGroupItem()) {
1002 ConnectedInterface* ref = other->refInter;
1003 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
1010 QMessageBox::warning(NULL,"Forbidden operation",
1011 "The block has at least one connection to a group interface that is totally connected.",
1017 if (item->getRefBlock()->isFunctionalBlock()) {
1018 msg = "Removing block ";
1021 msg = "Removing group ";
1023 msg += item->getRefBlock()->getName();
1024 msg += " and all its connections.\n\nAre you sure ?";
1026 int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1027 if (ret == QMessageBox::Cancel) {
1030 removeAllBlockConnections(item);
1032 if (item->getRefBlock()->isFunctionalBlock()) {
1033 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1034 item->getScene()->removeBoxItem(item);
1035 params->getGraph()->removeFunctionalBlock(block);
1036 params->blockToItem.remove(block);
1039 else if (item->getRefBlock()->isGroupBlock()) {
1041 GroupBlock* group = AB_TO_GRP(item->getRefBlock());
1043 // remove all child scenes recursively
1044 GroupItem* subgroup = item->getChildGroupItem();
1045 destroyScene(subgroup->getScene());
1046 // remove the BoxItem
1047 item->getScene()->removeBoxItem(item);
1048 // remove the group from the graph
1049 params->getGraph()->removeGroupBlock(group);
1053 void Dispatcher::removeAllBlockConnections(AbstractBoxItem *item) {
1054 static QString fctName = "Dispatcher::removeAllBlockConnection()";
1055 #ifdef DEBUG_FCTNAME
1056 cout << "call to " << qPrintable(fctName) << endl;
1059 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1060 foreach(ConnectionItem* conn, ifaceItem->connections) {
1061 removeConnection(conn);
1066 void Dispatcher::removeSourceItem(SourceItem *item) {
1067 static QString fctName = "Dispatcher::removeSourceItem()";
1068 #ifdef DEBUG_FCTNAME
1069 cout << "call to " << qPrintable(fctName) << endl;
1072 QString msg = "Removing source ";
1074 msg += item->getRefBlock()->getName();
1075 msg += " and all its connections.\n\nAre you sure ?";
1077 int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1078 if (ret == QMessageBox::Cancel) {
1081 removeAllBlockConnections(item);
1083 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1084 item->getScene()->removeSourceItem(item);
1085 params->getGraph()->removeSourceBlock(block);
1089 void Dispatcher::removeConnection(ConnectionItem *connItem) {
1090 static QString fctName = "Dispatcher::removeConnection()";
1091 #ifdef DEBUG_FCTNAME
1092 cout << "call to " << qPrintable(fctName) << endl;
1094 InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
1095 InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
1098 cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1101 InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1102 GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1104 ConnectedInterface *fromInter = fromIfaceItem->refInter;
1105 ConnectedInterface *toInter = toIfaceItem->refInter;
1107 // test if one of the interface bounded to item is owned by a GroupItem
1108 if (fromIfaceItem->getOwner()->isGroupItem()) {
1109 groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1110 groupIfaceItem = fromIfaceItem;
1112 else if (toIfaceItem->getOwner()->isGroupItem()) {
1113 groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1114 groupIfaceItem = toIfaceItem;
1117 groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1120 // removing the connection from graph
1122 cout << "removing connections from graph ..." ;
1124 fromInter->disconnectTo(toInter);
1127 cout << "done." << endl ;
1130 // removing the connection from scene
1132 cout << "removing connections from scene ..." ;
1134 groupItem->getScene()->removeConnectionItem(connItem);
1137 cout << "done." << endl ;
1140 // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1141 if (groupIfaceItem != NULL) {
1143 // determine if the interface must be removed since it has no more connections.
1144 bool groupInterRemove = false;
1145 if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1147 if (groupInterRemove) {
1148 // get the GroupInterface from interface item
1149 ConnectedInterface* groupInter = groupIfaceItem->refInter;
1150 // remove interface from GroupItem, and delete it.
1151 groupItem->removeInterfaceItem(groupIfaceItem);
1152 // get the parent BoxItem of GroupItem if it exists.
1153 BoxItem* parent2Item = groupItem->getParentItem();
1154 if (parent2Item != NULL) {
1155 InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1156 // remove interface intem in parent BoxItem
1157 parent2Item->removeInterfaceItem(group2IfaceItem);
1159 // remove GroupInterface in the graph.
1160 groupInter->getOwner()->removeInterface(groupInter);
1165 void Dispatcher::showBlocksLibrary(){
1166 cout << "showing block library" << endl;
1167 mainWindow->getLibrary()->show();
1168 mainWindow->getLibrary()->raise();
1171 void Dispatcher::showProperties(InterfaceItem *inter) {
1172 new InterfacePropertiesWindow(inter);
1175 /* connectInterToGroup() :
1176 The only way for a block (functional of group) within a GroupItem to be connected
1177 to the latter is to right-click on one of its interfaces and to choose "connect to group".
1178 That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1181 void Dispatcher::connectInterToGroup(InterfaceItem *item){
1183 // getting the GroupBlock and GroupItem that are parent of the block that owns item
1184 ConnectedInterface *refInter = item->refInter;
1185 cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1186 GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1187 cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1188 GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1190 // creating/adding the group interface in the graph model
1191 GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());
1192 parentItem->getRefBlock()->addInterface(groupInter);
1193 // creating/adding the group control interface in the graph model if the purpose is data
1194 if (refInter->getPurpose() == AbstractInterface::Data) {
1195 GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1196 groupCtlInter->setAssociatedIface(groupInter);
1197 parentItem->getRefBlock()->addInterface(groupCtlInter);
1199 // creating/adding the group interface in the current scene model, and connection item
1200 InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1201 parentItem->addInterfaceItem(groupIfaceItem,true);
1203 // creating the connection, in graph and with an item
1204 createConnection(item, groupIfaceItem);
1206 // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1207 BoxItem* parent2Item = parentItem->getParentItem();
1208 if(parent2Item != NULL){
1209 InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1210 parent2Item->addInterfaceItem(blockIfaceItem,true);
1214 parentItem->getScene()->updateConnectionItemsShape();
1216 params->unsaveModif = true;
1219 void Dispatcher::removeFunctionalInterface(InterfaceItem *item) {
1220 static QString fctName = "Dispatcher::removeBlockInterface()";
1221 #ifdef DEBUG_FCTNAME
1222 cout << "call to " << qPrintable(fctName) << endl;
1225 /* first, remove all connections from item
1226 NB: if there is a connection to a group interface, then this
1227 method should not be called if the group interface is also
1228 connected to another interface. Normally, this is not possible
1229 because such a check is done when creating the contextual menu
1230 that allows to remove an interface.
1232 foreach(ConnectionItem* conn, item->connections) {
1233 removeConnection(conn);
1236 ConnectedInterface* ref = item->refInter;
1237 item->getOwner()->removeInterfaceItem(item);
1238 FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1239 fun->removeInterface(ref);
1242 void Dispatcher::removeGroupInterface(InterfaceItem *item) {
1243 static QString fctName = "Dispatcher::removeGroupInterface()";
1244 #ifdef DEBUG_FCTNAME
1245 cout << "call to " << qPrintable(fctName) << endl;
1248 /* NB: just remove all connections from/to this item, since when there are no more
1249 ones to a GroupItem, it is automatically deleted.
1251 foreach(ConnectionItem* conn, item->connections) {
1252 removeConnection(conn);
1256 QMap<int, QString> Dispatcher::getAllGroupNames() {
1258 QMap<int, QString> list;
1259 foreach(GroupWidget *group, groupList) {
1260 list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1265 GroupScene* Dispatcher::getSceneById(int id) {
1266 foreach(GroupWidget *group, groupList){
1267 if(group->getScene()->getId() == id)
1268 return group->getScene();
1270 cout << "search scene by id :" << id << " :: not found..." << endl;
1274 GroupItem *Dispatcher::getGroupItemById(int id) {
1275 foreach(GroupWidget *group, groupList) {
1276 GroupScene* scene = group->getScene();
1277 if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1279 cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1283 BoxItem *Dispatcher::getBoxItemById(int id) {
1284 foreach(GroupWidget *group, groupList) {
1286 GroupScene* scene = group->getScene();
1287 foreach(BoxItem *item, scene->getBoxItems()){
1288 if(item->getId() == id){
1293 cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1297 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1299 foreach(GroupWidget *group, groupList) {
1301 GroupScene* scene = group->getScene();
1303 foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1304 if(item->getId() == id){
1308 foreach(BoxItem *block, scene->getBoxItems()){
1309 foreach(InterfaceItem *item, block->getInterfaces()){
1310 if(item->getId() == id){
1316 cout << "search interface by id :" << id << " :: not found..." << endl;
1320 void Dispatcher::findGraphModifications(FunctionalBlock *block) {
1321 static QString fctName = "Dispatcher::findGraphModifications()";
1322 #ifdef DEBUG_FCTNAME
1323 cout << "call to " << qPrintable(fctName) << endl;
1326 block->computeAdmittanceDelays();
1327 // get the block item that is associated to block
1328 BoxItem* toBlockItem = params->blockToItem.value(block);
1330 /* VERSION 1: just add delays if needed */
1331 QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1332 QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1333 while (iterD.hasNext()) {
1335 QList<int>* delay = iterD.value();
1336 if (delay->at(0) > 0) {
1337 // create delay and associate it to the connected input
1339 ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1340 AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1341 cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1342 toIface->setInputModifier(mod);
1344 toBlockItem->update();