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);
40 currentGroupWidget = NULL;
41 topGroupWidget = NULL;
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 topGroupWidget = 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(topGroupWidget);
79 return topGroupWidget;
82 void Dispatcher::closeCurrentProject() {
84 foreach(GroupWidget* win, groupList) {
88 params->destroyGraph();
89 topGroupWidget = NULL;
90 currentGroupWidget = NULL;
94 void Dispatcher::setSceneCounter(Context context, int value) {
96 if (context != Load) return;
100 bool Dispatcher::createConnection(Context context, InterfaceItem *iface1, InterfaceItem *iface2, bool visible) {
102 ConnectedInterface* ref1 = iface1->refInter;
103 ConnectedInterface* ref2 = iface2->refInter;
104 // connect both interface
109 // test the ref1->ref2 connection
110 if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) {
111 ref1->connectTo(ref2);
114 // if the frist one did not work, test ref2->ref1
115 if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) {
116 ref2->connectTo(ref1);
119 if ((ok1 == true) || (ok2 == true)) {
121 iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible);
123 unselectAllItems(context);
124 params->unsaveModif = true;
125 cout << "created a connection from " << qPrintable(ref1->getName()) << " to " << qPrintable(ref2->getName()) << endl;
132 void Dispatcher::unselectAllItems(Context context, int direction){
134 GroupScene *scene = params->getCurrentScene();
136 foreach(BoxItem* block, scene->getBoxItems()) {
137 block->setSelected(false);
138 block->setCurrentInterface(NULL);
140 scene->unselecteInterfaces();
144 void Dispatcher::setCurrentGroupWidget(Context context, GroupWidget *win){
146 win->changeConnectionMode(-1);
147 currentGroupWidget = win;
148 params->setCurrentScene(win->getScene());
151 void Dispatcher::changeConnectionMode(Context context, int mode){
154 foreach(GroupWidget* win, groupList){
156 QToolButton* buttonNewConnection = win->getButtonNewConnection();
158 QPalette pal = buttonNewConnection->palette();
161 if(params->sceneMode != Parameters::EditOnConnection){
162 params->sceneMode = Parameters::EditOnConnection;
163 pal.setColor(QPalette::Button, QColor(Qt::lightGray));
165 params->sceneMode = Parameters::EditNoOperation;
166 pal.setColor(QPalette::Button, QColor("#edeceb"));
169 else if(mode == Parameters::EditOnConnection){
170 params->sceneMode = Parameters::EditOnConnection;
171 pal.setColor(QPalette::Button, QColor(Qt::lightGray));
174 params->sceneMode = Parameters::EditNoOperation;
175 pal.setColor(QPalette::Button, QColor("#edeceb"));
177 unselectAllInterfaces();
179 buttonNewConnection->setAutoFillBackground(true);
180 buttonNewConnection->setPalette(pal);
181 buttonNewConnection->update();
186 void Dispatcher::generateVHDL(Context context) throw(Exception) {
187 static QString fctName = "Dispatcher::generateVHDL()";
189 cout << "call to " << qPrintable(fctName) << endl;
192 QDir baseDir(params->projectPath);
193 QDir srcDir(params->projectPath+"/src");
195 if (!baseDir.exists()) {
196 cerr << "Project path " << qPrintable(params->projectPath) << " no longer exists. First, recreate it and put the project file within. Then retry to generate." << endl;
200 if (srcDir.exists()) {
201 srcDir.removeRecursively();
203 baseDir.mkdir("src");
205 if (! baseDir.exists("testbench")) {
206 baseDir.mkdir("testbench");
208 if (! baseDir.exists("Makefile")) {
209 QFile make("/home/sdomas/Projet/Blast/code/blast/Makefile-isim");
210 QString dest = params->projectPath;
215 // copying external resources
216 QString dest = params->projectPath;
219 params->getGraph()->generateVHDL(dest);
221 QList<QString> extResources = params->getGraph()->getExternalResources();
222 foreach(QString name, extResources) {
223 cout << qPrintable(name) << endl;
224 QList<ExternalResource*> lstRes = params->searchResourceByName(name);
225 foreach(ExternalResource* res, lstRes) {
226 QFile resFile(res->getFile());
227 QFileInfo info(res->getFile());
228 QString destFile = dest+info.fileName();
229 cout << "copying " << qPrintable(res->getFile()) << " into " << qPrintable(destFile) << endl;
230 resFile.copy(destFile);
238 // creating parameters file
239 QString paramName = params->projectPath+"/params-isim.txt";
240 QFile paramFile(paramName);
241 if (!paramFile.open(QIODevice::WriteOnly)) {
242 throw(Exception(PROJECTPATH_NOACCESS));
244 QTextStream out(¶mFile);
245 out << "PROJECT_NAME := " << params->projectName << endl << endl;
246 out << "SRC_DIR := src" << endl;
247 out << "TB_DIR := testbench" << endl << endl;
248 out << "VHDL_SRC := ";
251 srcDir.setNameFilters(filter);
252 QStringList listVHDL = srcDir.entryList();
253 for(int j=0;j<listVHDL.size();j++) {
257 out << "$(SRC_DIR)/" << qPrintable(listVHDL.at(j));
258 if (j != listVHDL.size()-1) {
264 out << "VL_SRC := ${XILINX}/verilog/src/glbl.v" << endl << endl;
265 out << "TB_SRC := $(TB_DIR)/read_csv.vhd \\" << endl;
266 out << "\t$(TB_DIR)/$(PROJECT_NAME)_tb.vhd" << endl << endl;
267 out << "SIMU_EXE := $(PROJECT_NAME)_tb" << endl << endl;
271 QString msg = "VHDL generation completed successfully. Go to ";
272 msg += params->projectPath+" and type the following commands to launch a simulation:\n";
273 msg += "\tmake clean\n";
275 msg += "\tmake view\n";
276 QMessageBox::information(mainWindow,"VHDL generation", msg, QMessageBox::Ok);
280 void Dispatcher::generateBlockVHDL(Context context, BoxItem *item){
281 static QString fctName = "Dispatcher::generateBlockVHDL()";
283 cout << "call to " << qPrintable(fctName) << endl;
286 if (item->getRefBlock()->isFunctionalBlock()) {
287 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
289 block->generateVHDL(params->projectPath);
292 cout << qPrintable(e.getMessage()) << endl;
297 void Dispatcher::renameFunctionalBlock(Context context, BoxItem *item){
298 static QString fctName = "Dispatcher::renameFunctionalBlock()";
300 cout << "call to " << qPrintable(fctName) << endl;
303 GroupWidget* win = item->getScene()->getGroupWidget();
308 text = QInputDialog::getText(win, "Rename a functional block",
309 "New name:", QLineEdit::Normal,
310 item->getRefBlock()->getName(), &ok);
313 if (text == item->getRefBlock()->getName()) return;
315 if( (text.isEmpty()) || (text.length() > 30)) {
316 QMessageBox::warning(win,"Error in given name",
317 "the block name must be shorter than 30 characters, cannot be empty",
322 FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent()));
324 QMessageBox::warning(win,"Error in given name",
325 "the name provided is similar to that of another functional block within the group",
332 item->getRefBlock()->setName(text);
336 void Dispatcher::renameGroupBlock(Context context, GroupItem *item){
337 static QString fctName = "Dispatcher::renameGroupBlock()";
339 cout << "call to " << qPrintable(fctName) << endl;
342 GroupWidget* win = item->getScene()->getGroupWidget();
347 text = QInputDialog::getText(win, "Rename a group",
348 "New name:", QLineEdit::Normal,
349 item->getRefBlock()->getName(), &ok);
352 if (text == item->getRefBlock()->getName()) return;
354 if( (text.isEmpty()) || (text.length() > 30)) {
355 QMessageBox::warning(win,"Error in given name",
356 "the block name must be shorter than 30 characters, cannot be empty",
361 GroupBlock* block = params->getGraph()->getGroupBlockByName(text);
363 QMessageBox::warning(win,"Error in given name",
364 "the name provided is similar to that of another group",
371 item->getRefBlock()->setName(text);
372 if(item->getScene()->getGroupWidget()->isTopGroup()) {
373 mainWindow->setWindowTitle("blast - "+text);
376 item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text);
379 mainWindow->getLibrary()->updateComboScene();
382 void Dispatcher::renameSourceBlock(Context context, SourceItem *item){
383 static QString fctName = "Dispatcher::renameSourceBlock()";
385 cout << "call to " << qPrintable(fctName) << endl;
388 GroupWidget* win = item->getScene()->getGroupWidget();
393 text = QInputDialog::getText(win, "Rename a source",
394 "New name:", QLineEdit::Normal,
395 item->getRefBlock()->getName(), &ok);
398 if (text == item->getRefBlock()->getName()) return;
400 if( (text.isEmpty()) || (text.length() > 30)) {
401 QMessageBox::warning(win,"Error in given name",
402 "the block name must be shorter than 30 characters, cannot be empty",
407 FunctionalBlock* block = params->getGraph()->getSourceBlockByName(text);
409 QMessageBox::warning(win,"Error in given name",
410 "the name provided is similar to that of another source block within the top group",
417 item->getRefBlock()->setName(text);
422 void Dispatcher::renameInterface(Context context, InterfaceItem *item) {
423 static QString fctName = "Dispatcher::renameInterface()";
425 cout << "call to " << qPrintable(fctName) << endl;
428 GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
433 text = QInputDialog::getText(win, "Rename an interface",
434 "New name:", QLineEdit::Normal,
435 item->refInter->getName(), &ok);
439 if (text == item->refInter->getName()) return;
441 if( (text.isEmpty()) || (text.length() > 30)) {
442 QMessageBox::warning(win,"Error in given name",
443 "the interface name must be shorter than 30 characters, cannot be empty",
448 AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text);
450 QMessageBox::warning(win,"Error in given name",
451 "the name provided is similar to that of another interface",
457 item->refInter->setName(text);
458 AbstractInterface* assoIface = item->refInter->getAssociatedIface();
459 if (assoIface != NULL) {
460 assoIface->setName(text+"_enb");
462 item->updateName(text);
463 item->getOwner()->nameChanged();
466 void Dispatcher::showPatterns(Context context, InterfaceItem *item) {
467 static QString fctName = "Dispatcher::showPatterns()";
469 cout << "call to " << qPrintable(fctName) << endl;
472 if (item->refInter->getDirection() == AbstractInterface::Input) {
473 msg = "Input pattern of iface ";
474 msg += item->refInter->getName();
476 msg += item->refInter->getOwner()->getName();
478 // get the precursor output pattern
479 ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface());
480 QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
482 AbstractInputModifier* modifier = connIface->getInputModifier();
483 // check if the input is modified
484 if (modifier != NULL) {
486 out = modifier->getModifiedInput(out);
489 foreach(char c, *out) {
490 msg += QString::number((int)c);
494 else if (item->refInter->getDirection() == AbstractInterface::Output) {
495 msg = "Output pattern of iface ";
496 msg += item->refInter->getName();
498 msg += item->refInter->getOwner()->getName();
500 ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
501 if (iface->getOutputPattern() == NULL) return;
502 foreach(char c, *(iface->getOutputPattern())) {
503 msg += QString::number((int)c);
507 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
510 void Dispatcher::showModifier(Context context, InterfaceItem *item) {
511 static QString fctName = "Dispatcher::showModifier()";
513 cout << "call to " << qPrintable(fctName) << endl;
516 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
517 AbstractInputModifier* mod = assoIface->getInputModifier();
518 if (mod->isDelay()) {
519 DelayInputModifier* delay = (DelayInputModifier *)mod;
520 msg = "Pattern of iface ";
521 msg += item->refInter->getName();
523 msg += item->refInter->getOwner()->getName();
524 msg += " is modified by a simple delay of ";
525 msg += QString::number(delay->getDelayLength());
528 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
531 void Dispatcher::removeModifier(Context context, InterfaceItem *item) {
532 static QString fctName = "Dispatcher::showModifier()";
534 cout << "call to " << qPrintable(fctName) << endl;
537 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
538 assoIface->clearInputModifier();
542 void Dispatcher::duplicateBoxItem(Context context, BoxItem *item){
543 static QString fctName = "Dispatcher::duplicateBoxItem()";
545 cout << "call to " << qPrintable(fctName) << endl;
548 GroupScene *scene = item->getScene();
549 AbstractBlock* block = item->getRefBlock();
550 AbstractBlock *newBlock;
552 // only duplicate functional blocks
553 if(block->isFunctionalBlock()) {
555 // adding to the model
556 FunctionalBlock* funBlock = (FunctionalBlock*)block;
557 newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock);
558 // adding to the view
559 scene->createBoxItem(newBlock);
561 params->unsaveModif = true;
565 void Dispatcher::duplicateSourceItem(Context context, SourceItem *item) {
566 static QString fctName = "Dispatcher::duplicateSourceItem()";
568 cout << "call to " << qPrintable(fctName) << endl;
571 GroupScene *scene = item->getScene();
572 AbstractBlock* block = item->getRefBlock();
573 AbstractBlock *newBlock;
575 // only duplicate functional blocks
576 if(block->isFunctionalBlock()) {
578 // adding to the model
579 FunctionalBlock* funBlock = (FunctionalBlock*)block;
580 newBlock = params->getGraph()->duplicateSourceBlock(funBlock);
581 // adding to the view
582 scene->createSourceItem(newBlock);
584 params->unsaveModif = true;
588 void Dispatcher::duplicateInterfaceItem(Context context, InterfaceItem *item) {
589 static QString fctName = "Dispatcher::duplicateInterfaceItem()";
591 cout << "call to " << qPrintable(fctName) << endl;
594 AbstractInterface *refI = item->refInter;
595 if (! refI->isFunctionalInterface()) return;
597 AbstractBlock *refB = refI->getOwner();
598 if(! refB->isFunctionalBlock()) return;
600 FunctionalInterface* iface = (FunctionalInterface*)refI;
601 AbstractInterface *cloneIface = iface->clone();
602 if (cloneIface == NULL) {
603 QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
607 refB->addInterface(cloneIface);
609 InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params);
610 item->getOwner()->addInterfaceItem(cloneIfaceItem,true);
612 // creating control interface if needed
613 if (refI->getAssociatedIface() != NULL) {
614 QString ctlName = cloneIface->getName()+"_enb";
615 ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
616 refB->addInterface(ctlIface);
617 if (! ctlIface->setAssociatedIface(cloneIface)) {
618 cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl;
624 BoxItem* Dispatcher::addBlock(Context context, int idCategory, int idBlock, int idScene) {
625 static QString fctName = "Dispatcher::addBlock()";
627 cout << "call to " << qPrintable(fctName) << endl;
629 bool newSource = false;
630 BoxItem* item = NULL;
632 /* For now, this method is only used while designing and not loading */
633 if (context == Design) {
634 GroupScene *scene = getSceneById(idScene);
635 ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
636 // if block has no inputs, propose to add it as a source to top scene
637 if ((scene->isTopScene()) && (ref->isGeneratorBlock())) {
638 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 ?");
639 if (ret == QMessageBox::Yes) {
644 FunctionalBlock* newOne = params->getGraph()->createSourceBlock(ref, true);
645 scene->createSourceItem(newOne);
648 GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
649 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref, true);
650 item = scene->createBoxItem(newOne);
651 params->blockToItem.insert(newOne,item);
653 params->unsaveModif = true;
660 GroupWidget *Dispatcher::createTopScene(Context context){
661 static QString fctName = "Dispatcher::createTopScene()";
663 cout << "call to " << qPrintable(fctName) << endl;
666 bool createIfaces = true;
667 if (context == Load) {
668 createIfaces = false;
670 // creating the graph and thus, the topgroup
671 Graph* graph = params->createGraph(createIfaces);
673 GroupBlock *topBlock = graph->getTopGroup();
674 // creating the top group widget
675 topGroupWidget = new GroupWidget(NULL,this,params);
676 currentGroupWidget = topGroupWidget;
677 // getting the newly created scene
678 GroupScene *scene = topGroupWidget->getScene();
679 scene->setId(sceneCounter++);
680 params->setTopScene(scene);
681 params->setCurrentScene(scene);
682 // creating the view part of the group
683 GroupItem *group = new GroupItem(NULL,topBlock,this,params);
684 // associate the top scene to the top group iten
685 scene->setGroupItem(group);
687 // adding the fake interface to the top group item
688 //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
689 //group->addInterface(item,true);
692 if (context == Design) {
693 // creating the clkrstgen block
694 ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen");
695 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(topBlock, ref, true);
696 ConnectedInterface* fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_clk"));
697 ConnectedInterface* toIface = AI_TO_CON(newOne->getIfaceFromName("ext_clk"));
698 fromIface->connectTo(toIface);
699 fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_reset"));
700 toIface = AI_TO_CON(newOne->getIfaceFromName("ext_reset"));
701 fromIface->connectTo(toIface);
702 // create the clkrstgen boxitem
703 BoxItem* item = scene->createBoxItem(newOne, GroupScene::Left, GroupScene::Top, AbstractBoxItem::Position, BoxItem::HSpan);
704 params->blockToItem.insert(newOne,item);
708 groupList.append(topGroupWidget);
709 return topGroupWidget;
712 GroupWidget* Dispatcher::addNewEmptyGroup(Context context, GroupScene* scene, bool show) {
713 static QString fctName = "Dispatcher::addNewEmptyGroup();";
715 cout << "call to " << qPrintable(fctName) << endl;
718 // getting the parent block in the graph
719 GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
720 cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
721 GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent);
722 cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
723 // creating the BlockItem in the scene
724 BoxItem* newItem = scene->createBoxItem(groupBlock);
726 params->unsaveModif = true;
728 GroupWidget* child = createChildScene(context, scene->getGroupWidget(),newItem);
729 if (show) child->show();
734 GroupWidget *Dispatcher::createChildScene(Context context, GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
735 static QString fctName = "Dispatcher::createChildScene()";
737 cout << "call to " << qPrintable(fctName) << endl;
740 GroupWidget* group = NULL;
741 /* NB: this method may be called during design process or when loading
742 a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
743 cannot be initialized yet. This is why there are 2 cases below
746 if (upperItemOfGroupItem != NULL) {
747 // getting back the goup block already created
748 GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
749 // creating the view part of the group
750 GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
752 // creating the group widget
753 group = new GroupWidget(parentWidget, this, params);
754 // getting the newly created scene
755 GroupScene *scene = group->getScene();
756 scene->setId(sceneCounter++);
757 // affecting group item to the scene
758 scene->setGroupItem(groupItem);
759 groupList.append(group);
761 mainWindow->getLibrary()->updateComboScene();
764 GroupItem *groupItem = new GroupItem(this,params);
765 // creating the group widget
766 group = new GroupWidget(parentWidget, this, params);
767 // getting the newly created scene
768 GroupScene *scene = group->getScene();
769 // affecting group item to the scene
770 scene->setGroupItem(groupItem);
771 groupList.append(group);
776 void Dispatcher::destroyScene(Context context, GroupScene *scene) {
777 foreach(GroupScene* s, scene->getChildrenScene()) {
778 destroyScene(context, s);
781 if (scene->getNbChildScene() == 0) {
782 // remove scene from the parent list, if possible
783 if (scene->getParentScene() != NULL) {
784 scene->getParentScene()->removeChildScene(scene);
786 // destroy the GroupWidget
787 groupList.removeAll(scene->getGroupWidget());
788 scene->getGroupWidget()->deleteLater();
791 cerr << "Abnormal case when destroying a scene" << endl;
795 void Dispatcher::showRaiseWindow(Context context, BoxItem *item) {
796 static QString fctName = "Dispatcher::showRaiseWindow()";
798 cout << "call to " << qPrintable(fctName) << endl;
801 cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
802 GroupItem* child = item->getChildGroupItem();
804 cerr << "abnormal case: child group item is null " << endl;
808 GroupWidget* win = child->getScene()->getGroupWidget();
812 win->activateWindow();
814 currentGroupWidget = win;
815 params->setCurrentScene(currentGroupWidget->getScene());
818 void Dispatcher::showRstClkIface(Context context, AbstractBoxItem *item) {
819 static QString fctName = "Dispatcher::showRstClkIface()";
821 cout << "call to " << qPrintable(fctName) << endl;
824 item->setRstClkVisible(!item->isRstClkVisible());
828 void Dispatcher::showWishboneIface(Context context, AbstractBoxItem *item) {
829 static QString fctName = "Dispatcher::showWishboneIface()";
831 cout << "call to " << qPrintable(fctName) << endl;
834 item->setWishboneVisible(!item->isWishboneVisible());
837 void Dispatcher::addNewFullGroup(Context context) {
838 static QString fctName = "Dispatcher::addNewFullGroup()";
840 cout << "call to " << qPrintable(fctName) << endl;
846 QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
847 QList<AbstractBlock*> listAbstractBlocks; //abstract blocks in the group
848 QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
850 /* What must be done:
851 1 - creating a new GroupBlock
852 2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
853 3 - creating a BlockItem that references the new GroupBlock
854 4 - creating a new GroupWidget
855 5 - creating a new GroupItem added to the scene of the GroupWidget
859 /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
860 associated to the GroupItem of the current scene
862 GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
863 GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
864 /* step 2: moving selected blocks */
865 foreach(BlockItem* blockItem, listBlocks) {
866 parentBlock->removeBlock(blockItem->getRefBlock());
867 newGroupBlock->addBlock(blockItem->getRefBlock());
870 GroupItem *parent = currentGroup->getScene()->getGroupItem();
871 GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
872 BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
873 GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
875 //create the new window
876 GroupWidget* win = new GroupWidget(this,params);
877 win->getScene()->setGroupItem(groupItem);
878 win->getScene()->addItem(groupItem);
879 ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
880 params->addWindow(win);
884 params->getCurrentScene()->addBlockItem(blockItem);
885 params->getCurrentScene()->addItem(blockItem);
886 ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
888 //replace selected blocks in the group
889 foreach(AbstractBoxItem *block, listBlocks){
890 ((GroupItem*)block->getParentItem())->removeBlockItem(block);
891 ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
892 params->getCurrentScene()->removeItem(block);
893 params->getCurrentScene()->removeBlockItem(block);
895 groupBlock->addBlock(block->getRefBlock());
896 listAbstractBlocks.append(block->getRefBlock());
898 block->setUpperItem(groupItem);
899 groupItem->addBlockItem(block);
900 win->getScene()->addItem(block);
901 win->getScene()->addBlockItem(block);
904 //replace connection between selected blocks in the group
905 foreach(ConnectionItem *conn, connections){
906 if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
907 if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
908 parent->removeConnection(conn);
909 params->getCurrentScene()->removeItem(conn);
911 groupItem->addConnection(conn);
912 win->getScene()->addItem(conn);
917 //create new interfaces and connections for the new group
918 foreach(AbstractBoxItem *block, listBlocks){
919 foreach(InterfaceItem *inter, block->getInterfaces()){
920 cout << "inter : " << inter->getName().toStdString() << endl;
921 if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
922 cout << "connected from non null" << endl;
923 if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
925 AbstractInterface *iface = inter->refInter->clone(0);
926 iface->setName(iface->getName()+"_group");
927 groupBlock->addInterface(iface);
929 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
930 blockItem->addInterface(ifaceItem);
931 blockItem->resetInterfacesPosition();
933 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
934 groupItem->addInterface(ifaceGroupItem);
935 groupItem->resetInterfacesPosition();
936 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
937 if(conn->getToInterfaceItem() == inter){
938 conn->setToInterfaceItem(ifaceItem);
939 ifaceItem->refInter->setConnectedFrom(NULL);
940 conn->getFromInterfaceItem()->refInter->clearConnectedTo();
941 connect(ifaceItem,conn->getFromInterfaceItem());
944 params->setCurrentWindow(win);
946 inter->refInter->setConnectedFrom(NULL);
947 ifaceGroupItem->refInter->clearConnectedTo();
948 connect(inter,ifaceGroupItem);
949 params->setCurrentWindow(mainWindow);
953 if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
954 cout << "connected to non null" << endl;
955 foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
956 if(!listAbstractBlocks.contains(iface->getOwner())){
958 AbstractInterface *iface = inter->refInter->clone(0);
959 iface->setName(iface->getName()+"_group");
960 groupBlock->addInterface(iface);
962 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
963 blockItem->addInterface(ifaceItem);
964 blockItem->resetInterfacesPosition();
966 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
967 if(conn->getFromInterfaceItem() == inter){
968 conn->setFromInterfaceItem(ifaceItem);
969 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
970 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
974 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
975 groupItem->addInterface(ifaceGroupItem);
976 groupItem->resetInterfacesPosition();
977 inter->refInter->clearConnectedTo();
978 ifaceGroupItem->refInter->setConnectedFrom(NULL);
979 connect(ifaceGroupItem,inter);
988 parent->updateShape();
989 currentGroup->getScene()->updateConnectionItemsShape();
991 groupItem->updateShape();
992 win->getScene()->updateConnectionItemsShape();
993 groupItem->update(groupItem->boundingRect());
998 void Dispatcher::removeBoxItem(Context context, BoxItem *item) {
999 static QString fctName = "Dispatcher::removeBoxItem()";
1000 #ifdef DEBUG_FCTNAME
1001 cout << "call to " << qPrintable(fctName) << endl;
1004 if (context != Design) return;
1006 /* a BoxItem (group of func) can be removed only if none of its
1007 interfaces is connected to a group interface that is itself
1008 connected to another one.
1010 bool canRemove = true;
1012 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1013 foreach(ConnectionItem* conn, ifaceItem->connections) {
1014 InterfaceItem* other = NULL;
1015 if (conn->getFromInterfaceItem() == ifaceItem) {
1016 other = conn->getToInterfaceItem();
1019 other = conn->getFromInterfaceItem();
1022 if (other->getOwner()->isGroupItem()) {
1023 ConnectedInterface* ref = other->refInter;
1024 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
1031 QMessageBox::warning(NULL,"Forbidden operation",
1032 "The block has at least one connection to a group interface that is totally connected.",
1038 if (item->getRefBlock()->isFunctionalBlock()) {
1039 msg = "Removing block ";
1042 msg = "Removing group ";
1044 msg += item->getRefBlock()->getName();
1045 msg += " and all its connections.\n\nAre you sure ?";
1047 int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1048 if (ret == QMessageBox::Cancel) {
1051 removeAllBlockConnections(context, item);
1053 if (item->getRefBlock()->isFunctionalBlock()) {
1054 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1055 item->getScene()->removeBoxItem(item);
1056 params->getGraph()->removeFunctionalBlock(block);
1057 params->blockToItem.remove(block);
1060 else if (item->getRefBlock()->isGroupBlock()) {
1062 GroupBlock* group = AB_TO_GRP(item->getRefBlock());
1064 // remove all child scenes recursively
1065 GroupItem* subgroup = item->getChildGroupItem();
1066 destroyScene(context, subgroup->getScene());
1067 // remove the BoxItem
1068 item->getScene()->removeBoxItem(item);
1069 // remove the group from the graph
1070 params->getGraph()->removeGroupBlock(group);
1074 void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *item) {
1075 static QString fctName = "Dispatcher::removeAllBlockConnection()";
1076 #ifdef DEBUG_FCTNAME
1077 cout << "call to " << qPrintable(fctName) << endl;
1080 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1081 foreach(ConnectionItem* conn, ifaceItem->connections) {
1082 removeConnection(context, conn);
1087 void Dispatcher::removeSourceItem(Context context, SourceItem *item) {
1088 static QString fctName = "Dispatcher::removeSourceItem()";
1089 #ifdef DEBUG_FCTNAME
1090 cout << "call to " << qPrintable(fctName) << endl;
1093 QString msg = "Removing source ";
1095 msg += item->getRefBlock()->getName();
1096 msg += " and all its connections.\n\nAre you sure ?";
1098 int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1099 if (ret == QMessageBox::Cancel) {
1102 removeAllBlockConnections(context, item);
1104 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1105 item->getScene()->removeSourceItem(item);
1106 params->getGraph()->removeSourceBlock(block);
1110 void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) {
1111 static QString fctName = "Dispatcher::removeConnection()";
1112 #ifdef DEBUG_FCTNAME
1113 cout << "call to " << qPrintable(fctName) << endl;
1115 InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
1116 InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
1119 cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1122 InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1123 GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1125 ConnectedInterface *fromInter = fromIfaceItem->refInter;
1126 ConnectedInterface *toInter = toIfaceItem->refInter;
1128 // test if one of the interface bounded to item is owned by a GroupItem
1129 if (fromIfaceItem->getOwner()->isGroupItem()) {
1130 groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1131 groupIfaceItem = fromIfaceItem;
1133 else if (toIfaceItem->getOwner()->isGroupItem()) {
1134 groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1135 groupIfaceItem = toIfaceItem;
1138 groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1141 // removing the connection from graph
1143 cout << "removing connections from graph ..." ;
1145 fromInter->disconnectTo(toInter);
1148 cout << "done." << endl ;
1151 // removing the connection from scene
1153 cout << "removing connections from scene ..." ;
1155 groupItem->getScene()->removeConnectionItem(connItem);
1158 cout << "done." << endl ;
1161 // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1162 if (groupIfaceItem != NULL) {
1164 // determine if the interface must be removed since it has no more connections.
1165 bool groupInterRemove = false;
1166 if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1168 if (groupInterRemove) {
1169 // get the GroupInterface from interface item
1170 ConnectedInterface* groupInter = groupIfaceItem->refInter;
1171 // remove interface from GroupItem, and delete it.
1172 groupItem->removeInterfaceItem(groupIfaceItem);
1173 // get the parent BoxItem of GroupItem if it exists.
1174 BoxItem* parent2Item = groupItem->getParentItem();
1175 if (parent2Item != NULL) {
1176 InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1177 // remove interface intem in parent BoxItem
1178 parent2Item->removeInterfaceItem(group2IfaceItem);
1180 // remove GroupInterface in the graph.
1181 groupInter->getOwner()->removeInterface(groupInter);
1186 void Dispatcher::showBlocksLibrary(){
1187 cout << "showing block library" << endl;
1188 mainWindow->getLibrary()->show();
1189 mainWindow->getLibrary()->raise();
1192 void Dispatcher::showProperties(Context context, InterfaceItem *inter) {
1193 new InterfacePropertiesWindow(inter);
1196 /* connectInterToGroup() :
1197 The only way for a block (functional of group) within a GroupItem to be connected
1198 to the latter is to right-click on one of its interfaces and to choose "connect to group".
1199 That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1202 void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){
1204 // getting the GroupBlock and GroupItem that are parent of the block that owns item
1205 ConnectedInterface *refInter = item->refInter;
1206 cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1207 GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1208 cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1209 GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1211 // creating/adding the group interface in the graph model
1212 GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());
1213 parentItem->getRefBlock()->addInterface(groupInter);
1214 // creating/adding the group control interface in the graph model if the purpose is data
1215 if (refInter->getPurpose() == AbstractInterface::Data) {
1216 GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1217 groupCtlInter->setAssociatedIface(groupInter);
1218 parentItem->getRefBlock()->addInterface(groupCtlInter);
1220 // creating/adding the group interface in the current scene model, and connection item
1221 InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1222 parentItem->addInterfaceItem(groupIfaceItem,true);
1224 // creating the connection, in graph and with an item
1225 createConnection(context, item, groupIfaceItem);
1227 // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1228 BoxItem* parent2Item = parentItem->getParentItem();
1229 if(parent2Item != NULL){
1230 InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1231 parent2Item->addInterfaceItem(blockIfaceItem,true);
1235 parentItem->getScene()->updateConnectionItemsShape();
1236 unselectAllItems(context);
1237 params->unsaveModif = true;
1240 void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item) {
1241 static QString fctName = "Dispatcher::removeBlockInterface()";
1242 #ifdef DEBUG_FCTNAME
1243 cout << "call to " << qPrintable(fctName) << endl;
1246 /* first, remove all connections from item
1247 NB: if there is a connection to a group interface, then this
1248 method should not be called if the group interface is also
1249 connected to another interface. Normally, this is not possible
1250 because such a check is done when creating the contextual menu
1251 that allows to remove an interface.
1253 foreach(ConnectionItem* conn, item->connections) {
1254 removeConnection(context, conn);
1257 ConnectedInterface* ref = item->refInter;
1258 item->getOwner()->removeInterfaceItem(item);
1259 FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1260 fun->removeInterface(ref);
1263 void Dispatcher::removeGroupInterface(Context context, InterfaceItem *item) {
1264 static QString fctName = "Dispatcher::removeGroupInterface()";
1265 #ifdef DEBUG_FCTNAME
1266 cout << "call to " << qPrintable(fctName) << endl;
1269 /* NB: just remove all connections from/to this item, since when there are no more
1270 ones to a GroupItem, it is automatically deleted.
1272 foreach(ConnectionItem* conn, item->connections) {
1273 removeConnection(context, conn);
1277 QMap<int, QString> Dispatcher::getAllGroupNames() {
1279 QMap<int, QString> list;
1280 foreach(GroupWidget *group, groupList) {
1281 list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1286 GroupScene* Dispatcher::getSceneById(int id) {
1287 foreach(GroupWidget *group, groupList){
1288 if(group->getScene()->getId() == id)
1289 return group->getScene();
1291 cout << "search scene by id :" << id << " :: not found..." << endl;
1295 GroupItem *Dispatcher::getGroupItemById(int id) {
1296 foreach(GroupWidget *group, groupList) {
1297 GroupScene* scene = group->getScene();
1298 if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1300 cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1304 BoxItem *Dispatcher::getBoxItemById(int id) {
1305 foreach(GroupWidget *group, groupList) {
1307 GroupScene* scene = group->getScene();
1308 foreach(BoxItem *item, scene->getBoxItems()){
1309 if(item->getId() == id){
1314 cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1318 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1320 foreach(GroupWidget *group, groupList) {
1322 GroupScene* scene = group->getScene();
1324 foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1325 if(item->getId() == id){
1329 foreach(BoxItem *block, scene->getBoxItems()){
1330 foreach(InterfaceItem *item, block->getInterfaces()){
1331 if(item->getId() == id){
1337 cout << "search interface by id :" << id << " :: not found..." << endl;
1341 void Dispatcher::findGraphModifications(Context context, FunctionalBlock *block) {
1342 static QString fctName = "Dispatcher::findGraphModifications()";
1343 #ifdef DEBUG_FCTNAME
1344 cout << "call to " << qPrintable(fctName) << endl;
1347 block->computeAdmittanceDelays();
1348 // get the block item that is associated to block
1349 BoxItem* toBlockItem = params->blockToItem.value(block);
1351 /* VERSION 1: just add delays if needed */
1352 QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1353 QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1354 while (iterD.hasNext()) {
1356 QList<int>* delay = iterD.value();
1357 if (delay->at(0) > 0) {
1358 // create delay and associate it to the connected input
1360 ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1361 AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1362 cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1363 toIface->setInputModifier(mod);
1365 toBlockItem->update();