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 first 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 // creating the clkrstgen item
697 BoxItem* clkResetItem = scene->createBoxItem(newOne, BoxItem::TopLeft, AbstractBoxItem::Position | AbstractBoxItem::Dimension, BoxItem::NoSpan);
698 params->blockToItem.insert(newOne,clkResetItem);
699 // creating top group ext_clk iface item
700 ConnectedInterface* fromIfaceClk = AI_TO_CON(topBlock->getIfaceFromName("ext_clk"));
701 InterfaceItem* fromIfaceItemClk = new InterfaceItem(0.5 , Parameters::West, fromIfaceClk, group, params, true);
702 group->addInterfaceItem(fromIfaceItemClk,true);
703 // creating top group ext_reset iface item
704 ConnectedInterface* fromIfaceReset = AI_TO_CON(topBlock->getIfaceFromName("ext_reset"));
705 InterfaceItem* fromIfaceItemReset = new InterfaceItem(0.5 , Parameters::West, fromIfaceReset, group, params, false);
706 group->addInterfaceItem(fromIfaceItemReset,true);
707 // connecting ext_clk iface items
708 InterfaceItem* toIfaceItemClk = clkResetItem->searchInterfaceItemByName("ext_clk");
709 if (toIfaceItemClk == NULL) {
710 cerr << "Abnormal case while connecting top group ext_clk to clkrstgen" << endl;
712 createConnection(context,fromIfaceItemClk, toIfaceItemClk, false);
713 // connecting ext_reset iface items
714 InterfaceItem* toIfaceItemReset = clkResetItem->searchInterfaceItemByName("ext_reset");
715 if (toIfaceItemReset == NULL) {
716 cerr << "Abnormal case while connecting top group ext_reset to clkrstgen" << endl;
718 createConnection(context,fromIfaceItemReset, toIfaceItemReset, false);
722 groupList.append(topGroupWidget);
723 return topGroupWidget;
726 GroupWidget* Dispatcher::addNewEmptyGroup(Context context, GroupScene* scene, bool show) {
727 static QString fctName = "Dispatcher::addNewEmptyGroup();";
729 cout << "call to " << qPrintable(fctName) << endl;
732 // getting the parent block in the graph
733 GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
734 cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
735 GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent);
736 cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
737 // creating the BlockItem in the scene
738 BoxItem* newItem = scene->createBoxItem(groupBlock);
740 params->unsaveModif = true;
742 GroupWidget* child = createChildScene(context, scene->getGroupWidget(),newItem);
743 if (show) child->show();
748 GroupWidget *Dispatcher::createChildScene(Context context, GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
749 static QString fctName = "Dispatcher::createChildScene()";
751 cout << "call to " << qPrintable(fctName) << endl;
754 GroupWidget* group = NULL;
755 /* NB: this method may be called during design process or when loading
756 a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
757 cannot be initialized yet. This is why there are 2 cases below
760 if (upperItemOfGroupItem != NULL) {
761 // getting back the goup block already created
762 GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
763 // creating the view part of the group
764 GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
766 // creating the group widget
767 group = new GroupWidget(parentWidget, this, params);
768 // getting the newly created scene
769 GroupScene *scene = group->getScene();
770 scene->setId(sceneCounter++);
771 // affecting group item to the scene
772 scene->setGroupItem(groupItem);
773 groupList.append(group);
775 mainWindow->getLibrary()->updateComboScene();
778 GroupItem *groupItem = new GroupItem(this,params);
779 // creating the group widget
780 group = new GroupWidget(parentWidget, this, params);
781 // getting the newly created scene
782 GroupScene *scene = group->getScene();
783 // affecting group item to the scene
784 scene->setGroupItem(groupItem);
785 groupList.append(group);
790 void Dispatcher::destroyScene(Context context, GroupScene *scene) {
791 foreach(GroupScene* s, scene->getChildrenScene()) {
792 destroyScene(context, s);
795 if (scene->getNbChildScene() == 0) {
796 // remove scene from the parent list, if possible
797 if (scene->getParentScene() != NULL) {
798 scene->getParentScene()->removeChildScene(scene);
800 // destroy the GroupWidget
801 groupList.removeAll(scene->getGroupWidget());
802 scene->getGroupWidget()->deleteLater();
805 cerr << "Abnormal case when destroying a scene" << endl;
809 void Dispatcher::showRaiseWindow(Context context, BoxItem *item) {
810 static QString fctName = "Dispatcher::showRaiseWindow()";
812 cout << "call to " << qPrintable(fctName) << endl;
815 cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
816 GroupItem* child = item->getChildGroupItem();
818 cerr << "abnormal case: child group item is null " << endl;
822 GroupWidget* win = child->getScene()->getGroupWidget();
826 win->activateWindow();
828 currentGroupWidget = win;
829 params->setCurrentScene(currentGroupWidget->getScene());
832 void Dispatcher::showRstClkIface(Context context, AbstractBoxItem *item) {
833 static QString fctName = "Dispatcher::showRstClkIface()";
835 cout << "call to " << qPrintable(fctName) << endl;
838 item->setRstClkVisible(!item->isRstClkVisible());
842 void Dispatcher::showWishboneIface(Context context, AbstractBoxItem *item) {
843 static QString fctName = "Dispatcher::showWishboneIface()";
845 cout << "call to " << qPrintable(fctName) << endl;
848 item->setWishboneVisible(!item->isWishboneVisible());
851 void Dispatcher::addNewFullGroup(Context context) {
852 static QString fctName = "Dispatcher::addNewFullGroup()";
854 cout << "call to " << qPrintable(fctName) << endl;
860 QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
861 QList<AbstractBlock*> listAbstractBlocks; //abstract blocks in the group
862 QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
864 /* What must be done:
865 1 - creating a new GroupBlock
866 2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
867 3 - creating a BlockItem that references the new GroupBlock
868 4 - creating a new GroupWidget
869 5 - creating a new GroupItem added to the scene of the GroupWidget
873 /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
874 associated to the GroupItem of the current scene
876 GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
877 GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
878 /* step 2: moving selected blocks */
879 foreach(BlockItem* blockItem, listBlocks) {
880 parentBlock->removeBlock(blockItem->getRefBlock());
881 newGroupBlock->addBlock(blockItem->getRefBlock());
884 GroupItem *parent = currentGroup->getScene()->getGroupItem();
885 GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
886 BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
887 GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
889 //create the new window
890 GroupWidget* win = new GroupWidget(this,params);
891 win->getScene()->setGroupItem(groupItem);
892 win->getScene()->addItem(groupItem);
893 ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
894 params->addWindow(win);
898 params->getCurrentScene()->addBlockItem(blockItem);
899 params->getCurrentScene()->addItem(blockItem);
900 ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
902 //replace selected blocks in the group
903 foreach(AbstractBoxItem *block, listBlocks){
904 ((GroupItem*)block->getParentItem())->removeBlockItem(block);
905 ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
906 params->getCurrentScene()->removeItem(block);
907 params->getCurrentScene()->removeBlockItem(block);
909 groupBlock->addBlock(block->getRefBlock());
910 listAbstractBlocks.append(block->getRefBlock());
912 block->setUpperItem(groupItem);
913 groupItem->addBlockItem(block);
914 win->getScene()->addItem(block);
915 win->getScene()->addBlockItem(block);
918 //replace connection between selected blocks in the group
919 foreach(ConnectionItem *conn, connections){
920 if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
921 if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
922 parent->removeConnection(conn);
923 params->getCurrentScene()->removeItem(conn);
925 groupItem->addConnection(conn);
926 win->getScene()->addItem(conn);
931 //create new interfaces and connections for the new group
932 foreach(AbstractBoxItem *block, listBlocks){
933 foreach(InterfaceItem *inter, block->getInterfaces()){
934 cout << "inter : " << inter->getName().toStdString() << endl;
935 if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
936 cout << "connected from non null" << endl;
937 if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->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 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
948 groupItem->addInterface(ifaceGroupItem);
949 groupItem->resetInterfacesPosition();
950 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
951 if(conn->getToInterfaceItem() == inter){
952 conn->setToInterfaceItem(ifaceItem);
953 ifaceItem->refInter->setConnectedFrom(NULL);
954 conn->getFromInterfaceItem()->refInter->clearConnectedTo();
955 connect(ifaceItem,conn->getFromInterfaceItem());
958 params->setCurrentWindow(win);
960 inter->refInter->setConnectedFrom(NULL);
961 ifaceGroupItem->refInter->clearConnectedTo();
962 connect(inter,ifaceGroupItem);
963 params->setCurrentWindow(mainWindow);
967 if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
968 cout << "connected to non null" << endl;
969 foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
970 if(!listAbstractBlocks.contains(iface->getOwner())){
972 AbstractInterface *iface = inter->refInter->clone(0);
973 iface->setName(iface->getName()+"_group");
974 groupBlock->addInterface(iface);
976 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
977 blockItem->addInterface(ifaceItem);
978 blockItem->resetInterfacesPosition();
980 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
981 if(conn->getFromInterfaceItem() == inter){
982 conn->setFromInterfaceItem(ifaceItem);
983 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
984 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
988 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
989 groupItem->addInterface(ifaceGroupItem);
990 groupItem->resetInterfacesPosition();
991 inter->refInter->clearConnectedTo();
992 ifaceGroupItem->refInter->setConnectedFrom(NULL);
993 connect(ifaceGroupItem,inter);
1002 parent->updateShape();
1003 currentGroup->getScene()->updateConnectionItemsShape();
1005 groupItem->updateShape();
1006 win->getScene()->updateConnectionItemsShape();
1007 groupItem->update(groupItem->boundingRect());
1012 void Dispatcher::removeBoxItem(Context context, BoxItem *item) {
1013 static QString fctName = "Dispatcher::removeBoxItem()";
1014 #ifdef DEBUG_FCTNAME
1015 cout << "call to " << qPrintable(fctName) << endl;
1018 if (context != Design) return;
1020 /* a BoxItem (group of func) can be removed only if none of its
1021 interfaces is connected to a group interface that is itself
1022 connected to another one.
1024 bool canRemove = true;
1026 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1027 foreach(ConnectionItem* conn, ifaceItem->connections) {
1028 InterfaceItem* other = NULL;
1029 if (conn->getFromInterfaceItem() == ifaceItem) {
1030 other = conn->getToInterfaceItem();
1033 other = conn->getFromInterfaceItem();
1036 if (other->getOwner()->isGroupItem()) {
1037 ConnectedInterface* ref = other->refInter;
1038 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
1045 QMessageBox::warning(NULL,"Forbidden operation",
1046 "The block has at least one connection to a group interface that is totally connected.",
1052 if (item->getRefBlock()->isFunctionalBlock()) {
1053 msg = "Removing block ";
1056 msg = "Removing group ";
1058 msg += item->getRefBlock()->getName();
1059 msg += " and all its connections.\n\nAre you sure ?";
1061 int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1062 if (ret == QMessageBox::Cancel) {
1065 removeAllBlockConnections(context, item);
1067 if (item->getRefBlock()->isFunctionalBlock()) {
1068 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1069 item->getScene()->removeBoxItem(item);
1070 params->getGraph()->removeFunctionalBlock(block);
1071 params->blockToItem.remove(block);
1074 else if (item->getRefBlock()->isGroupBlock()) {
1076 GroupBlock* group = AB_TO_GRP(item->getRefBlock());
1078 // remove all child scenes recursively
1079 GroupItem* subgroup = item->getChildGroupItem();
1080 destroyScene(context, subgroup->getScene());
1081 // remove the BoxItem
1082 item->getScene()->removeBoxItem(item);
1083 // remove the group from the graph
1084 params->getGraph()->removeGroupBlock(group);
1088 void Dispatcher::removeAllBlockConnections(Context context, AbstractBoxItem *item) {
1089 static QString fctName = "Dispatcher::removeAllBlockConnection()";
1090 #ifdef DEBUG_FCTNAME
1091 cout << "call to " << qPrintable(fctName) << endl;
1094 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1095 foreach(ConnectionItem* conn, ifaceItem->connections) {
1096 removeConnection(context, conn);
1101 void Dispatcher::removeSourceItem(Context context, SourceItem *item) {
1102 static QString fctName = "Dispatcher::removeSourceItem()";
1103 #ifdef DEBUG_FCTNAME
1104 cout << "call to " << qPrintable(fctName) << endl;
1107 QString msg = "Removing source ";
1109 msg += item->getRefBlock()->getName();
1110 msg += " and all its connections.\n\nAre you sure ?";
1112 int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1113 if (ret == QMessageBox::Cancel) {
1116 removeAllBlockConnections(context, item);
1118 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1119 item->getScene()->removeSourceItem(item);
1120 params->getGraph()->removeSourceBlock(block);
1124 void Dispatcher::removeConnection(Context context, ConnectionItem *connItem) {
1125 static QString fctName = "Dispatcher::removeConnection()";
1126 #ifdef DEBUG_FCTNAME
1127 cout << "call to " << qPrintable(fctName) << endl;
1129 InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
1130 InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
1133 cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1136 InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1137 GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1139 ConnectedInterface *fromInter = fromIfaceItem->refInter;
1140 ConnectedInterface *toInter = toIfaceItem->refInter;
1142 // test if one of the interface bounded to item is owned by a GroupItem
1143 if (fromIfaceItem->getOwner()->isGroupItem()) {
1144 groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1145 groupIfaceItem = fromIfaceItem;
1147 else if (toIfaceItem->getOwner()->isGroupItem()) {
1148 groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1149 groupIfaceItem = toIfaceItem;
1152 groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1155 // removing the connection from graph
1157 cout << "removing connections from graph ..." ;
1159 fromInter->disconnectTo(toInter);
1162 cout << "done." << endl ;
1165 // removing the connection from scene
1167 cout << "removing connections from scene ..." ;
1169 groupItem->getScene()->removeConnectionItem(connItem);
1172 cout << "done." << endl ;
1175 // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1176 if (groupIfaceItem != NULL) {
1178 // determine if the interface must be removed since it has no more connections.
1179 bool groupInterRemove = false;
1180 if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1182 if (groupInterRemove) {
1183 // get the GroupInterface from interface item
1184 ConnectedInterface* groupInter = groupIfaceItem->refInter;
1185 // remove interface from GroupItem, and delete it.
1186 groupItem->removeInterfaceItem(groupIfaceItem);
1187 // get the parent BoxItem of GroupItem if it exists.
1188 BoxItem* parent2Item = groupItem->getParentItem();
1189 if (parent2Item != NULL) {
1190 InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1191 // remove interface intem in parent BoxItem
1192 parent2Item->removeInterfaceItem(group2IfaceItem);
1194 // remove GroupInterface in the graph.
1195 groupInter->getOwner()->removeInterface(groupInter);
1200 void Dispatcher::showBlocksLibrary(){
1201 cout << "showing block library" << endl;
1202 mainWindow->getLibrary()->show();
1203 mainWindow->getLibrary()->raise();
1206 void Dispatcher::showProperties(Context context, InterfaceItem *inter) {
1207 new InterfacePropertiesWindow(inter);
1210 /* connectInterToGroup() :
1211 The only way for a block (functional of group) within a GroupItem to be connected
1212 to the latter is to right-click on one of its interfaces and to choose "connect to group".
1213 That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1216 void Dispatcher::connectInterToGroup(Context context, InterfaceItem *item){
1218 // getting the GroupBlock and GroupItem that are parent of the block that owns item
1219 ConnectedInterface *refInter = item->refInter;
1220 cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1221 GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1222 cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1223 GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1225 // creating/adding the group interface in the graph model
1226 GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());
1227 parentItem->getRefBlock()->addInterface(groupInter);
1228 // creating/adding the group control interface in the graph model if the purpose is data
1229 if (refInter->getPurpose() == AbstractInterface::Data) {
1230 GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1231 groupCtlInter->setAssociatedIface(groupInter);
1232 parentItem->getRefBlock()->addInterface(groupCtlInter);
1234 // creating/adding the group interface in the current scene model, and connection item
1235 InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1236 parentItem->addInterfaceItem(groupIfaceItem,true);
1238 // creating the connection, in graph and with an item
1239 createConnection(context, item, groupIfaceItem);
1241 // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1242 BoxItem* parent2Item = parentItem->getParentItem();
1243 if(parent2Item != NULL){
1244 InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1245 parent2Item->addInterfaceItem(blockIfaceItem,true);
1249 parentItem->getScene()->updateConnectionItemsShape();
1250 unselectAllItems(context);
1251 params->unsaveModif = true;
1254 void Dispatcher::removeFunctionalInterface(Context context, InterfaceItem *item) {
1255 static QString fctName = "Dispatcher::removeBlockInterface()";
1256 #ifdef DEBUG_FCTNAME
1257 cout << "call to " << qPrintable(fctName) << endl;
1260 /* first, remove all connections from item
1261 NB: if there is a connection to a group interface, then this
1262 method should not be called if the group interface is also
1263 connected to another interface. Normally, this is not possible
1264 because such a check is done when creating the contextual menu
1265 that allows to remove an interface.
1267 foreach(ConnectionItem* conn, item->connections) {
1268 removeConnection(context, conn);
1271 ConnectedInterface* ref = item->refInter;
1272 item->getOwner()->removeInterfaceItem(item);
1273 FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1274 fun->removeInterface(ref);
1277 void Dispatcher::removeGroupInterface(Context context, InterfaceItem *item) {
1278 static QString fctName = "Dispatcher::removeGroupInterface()";
1279 #ifdef DEBUG_FCTNAME
1280 cout << "call to " << qPrintable(fctName) << endl;
1283 /* NB: just remove all connections from/to this item, since when there are no more
1284 ones to a GroupItem, it is automatically deleted.
1286 foreach(ConnectionItem* conn, item->connections) {
1287 removeConnection(context, conn);
1291 QMap<int, QString> Dispatcher::getAllGroupNames() {
1293 QMap<int, QString> list;
1294 foreach(GroupWidget *group, groupList) {
1295 list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1300 GroupScene* Dispatcher::getSceneById(int id) {
1301 foreach(GroupWidget *group, groupList){
1302 if(group->getScene()->getId() == id)
1303 return group->getScene();
1305 cout << "search scene by id :" << id << " :: not found..." << endl;
1309 GroupItem *Dispatcher::getGroupItemById(int id) {
1310 foreach(GroupWidget *group, groupList) {
1311 GroupScene* scene = group->getScene();
1312 if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1314 cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1318 BoxItem *Dispatcher::getBoxItemById(int id) {
1319 foreach(GroupWidget *group, groupList) {
1321 GroupScene* scene = group->getScene();
1322 foreach(BoxItem *item, scene->getBoxItems()){
1323 if(item->getId() == id){
1328 cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1332 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1334 foreach(GroupWidget *group, groupList) {
1336 GroupScene* scene = group->getScene();
1338 foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1339 if(item->getId() == id){
1343 foreach(BoxItem *block, scene->getBoxItems()){
1344 foreach(InterfaceItem *item, block->getInterfaces()){
1345 if(item->getId() == id){
1351 cout << "search interface by id :" << id << " :: not found..." << endl;
1355 void Dispatcher::findGraphModifications(Context context, FunctionalBlock *block) {
1356 static QString fctName = "Dispatcher::findGraphModifications()";
1357 #ifdef DEBUG_FCTNAME
1358 cout << "call to " << qPrintable(fctName) << endl;
1361 block->computeAdmittanceDelays();
1362 // get the block item that is associated to block
1363 BoxItem* toBlockItem = params->blockToItem.value(block);
1365 /* VERSION 1: just add delays if needed */
1366 QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1367 QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1368 while (iterD.hasNext()) {
1370 QList<int>* delay = iterD.value();
1371 if (delay->at(0) > 0) {
1372 // create delay and associate it to the connected input
1374 ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1375 AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1376 cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1377 toIface->setInputModifier(mod);
1379 toBlockItem->update();