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)/$(PROJECT_NAME)_tb.vhd" << endl << endl;
260 out << "SIMU_EXE := $(PROJECT_NAME)_tb" << endl << endl;
267 void Dispatcher::generateBlockVHDL(BoxItem *item){
268 static QString fctName = "Dispatcher::generateBlockVHDL()";
270 cout << "call to " << qPrintable(fctName) << endl;
273 if (item->getRefBlock()->isFunctionalBlock()) {
274 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
276 block->generateVHDL(params->projectPath);
279 cout << qPrintable(e.getMessage()) << endl;
284 void Dispatcher::renameFunctionalBlock(BoxItem *item){
285 static QString fctName = "Dispatcher::renameFunctionalBlock()";
287 cout << "call to " << qPrintable(fctName) << endl;
290 GroupWidget* win = item->getScene()->getGroupWidget();
295 text = QInputDialog::getText(win, "Rename a functional block",
296 "New name:", QLineEdit::Normal,
297 item->getRefBlock()->getName(), &ok);
300 if (text == item->getRefBlock()->getName()) return;
302 if( (text.isEmpty()) || (text.length() > 30)) {
303 QMessageBox::warning(win,"Error in given name",
304 "the block name must be shorter than 30 characters, cannot be empty",
309 FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent()));
311 QMessageBox::warning(win,"Error in given name",
312 "the name provided is similar to that of another functional block within the group",
319 item->getRefBlock()->setName(text);
323 void Dispatcher::renameGroupBlock(GroupItem *item){
324 static QString fctName = "Dispatcher::renameGroupBlock()";
326 cout << "call to " << qPrintable(fctName) << endl;
329 GroupWidget* win = item->getScene()->getGroupWidget();
334 text = QInputDialog::getText(win, "Rename a group",
335 "New name:", QLineEdit::Normal,
336 item->getRefBlock()->getName(), &ok);
339 if (text == item->getRefBlock()->getName()) return;
341 if( (text.isEmpty()) || (text.length() > 30)) {
342 QMessageBox::warning(win,"Error in given name",
343 "the block name must be shorter than 30 characters, cannot be empty",
348 GroupBlock* block = params->getGraph()->getGroupBlockByName(text);
350 QMessageBox::warning(win,"Error in given name",
351 "the name provided is similar to that of another group",
358 item->getRefBlock()->setName(text);
359 if(item->getScene()->getGroupWidget()->isTopGroup()) {
360 mainWindow->setWindowTitle("blast - "+text);
363 item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text);
366 mainWindow->getLibrary()->updateComboScene();
369 void Dispatcher::renameSourceBlock(SourceItem *item){
370 static QString fctName = "Dispatcher::renameSourceBlock()";
372 cout << "call to " << qPrintable(fctName) << endl;
375 GroupWidget* win = item->getScene()->getGroupWidget();
380 text = QInputDialog::getText(win, "Rename a source",
381 "New name:", QLineEdit::Normal,
382 item->getRefBlock()->getName(), &ok);
385 if (text == item->getRefBlock()->getName()) return;
387 if( (text.isEmpty()) || (text.length() > 30)) {
388 QMessageBox::warning(win,"Error in given name",
389 "the block name must be shorter than 30 characters, cannot be empty",
394 FunctionalBlock* block = params->getGraph()->getSourceBlockByName(text);
396 QMessageBox::warning(win,"Error in given name",
397 "the name provided is similar to that of another source block within the top group",
404 item->getRefBlock()->setName(text);
409 void Dispatcher::renameInterface(InterfaceItem *item) {
410 static QString fctName = "Dispatcher::renameInterface()";
412 cout << "call to " << qPrintable(fctName) << endl;
415 GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
420 text = QInputDialog::getText(win, "Rename an interface",
421 "New name:", QLineEdit::Normal,
422 item->refInter->getName(), &ok);
426 if (text == item->refInter->getName()) return;
428 if( (text.isEmpty()) || (text.length() > 30)) {
429 QMessageBox::warning(win,"Error in given name",
430 "the interface name must be shorter than 30 characters, cannot be empty",
435 AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text);
437 QMessageBox::warning(win,"Error in given name",
438 "the name provided is similar to that of another interface",
444 item->refInter->setName(text);
445 AbstractInterface* assoIface = item->refInter->getAssociatedIface();
446 if (assoIface != NULL) {
447 assoIface->setName(text+"_enb");
449 item->updateName(text);
450 item->getOwner()->nameChanged();
453 void Dispatcher::showPatterns(InterfaceItem *item) {
454 static QString fctName = "Dispatcher::showPatterns()";
456 cout << "call to " << qPrintable(fctName) << endl;
459 if (item->refInter->getDirection() == AbstractInterface::Input) {
460 msg = "Input pattern of iface ";
461 msg += item->refInter->getName();
463 msg += item->refInter->getOwner()->getName();
465 // get the precursor output pattern
466 ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface());
467 QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
469 AbstractInputModifier* modifier = connIface->getInputModifier();
470 // check if the input is modified
471 if (modifier != NULL) {
473 out = modifier->getModifiedInput(out);
476 foreach(char c, *out) {
477 msg += QString::number((int)c);
481 else if (item->refInter->getDirection() == AbstractInterface::Output) {
482 msg = "Output pattern of iface ";
483 msg += item->refInter->getName();
485 msg += item->refInter->getOwner()->getName();
487 ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
488 if (iface->getOutputPattern() == NULL) return;
489 foreach(char c, *(iface->getOutputPattern())) {
490 msg += QString::number((int)c);
494 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
497 void Dispatcher::showModifier(InterfaceItem *item) {
498 static QString fctName = "Dispatcher::showModifier()";
500 cout << "call to " << qPrintable(fctName) << endl;
503 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
504 AbstractInputModifier* mod = assoIface->getInputModifier();
505 if (mod->isDelay()) {
506 DelayInputModifier* delay = (DelayInputModifier *)mod;
507 msg = "Pattern of iface ";
508 msg += item->refInter->getName();
510 msg += item->refInter->getOwner()->getName();
511 msg += " is modified by a simple delay of ";
512 msg += QString::number(delay->getDelayLength());
515 QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
518 void Dispatcher::removeModifier(InterfaceItem *item) {
519 static QString fctName = "Dispatcher::showModifier()";
521 cout << "call to " << qPrintable(fctName) << endl;
524 ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
525 assoIface->clearInputModifier();
529 void Dispatcher::duplicateBoxItem(BoxItem *item){
530 static QString fctName = "Dispatcher::duplicateBoxItem()";
532 cout << "call to " << qPrintable(fctName) << endl;
535 GroupScene *scene = item->getScene();
536 AbstractBlock* block = item->getRefBlock();
537 AbstractBlock *newBlock;
539 // only duplicate functional blocks
540 if(block->isFunctionalBlock()) {
542 // adding to the model
543 FunctionalBlock* funBlock = (FunctionalBlock*)block;
544 newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock);
545 // adding to the view
546 scene->createBoxItem(newBlock);
548 params->unsaveModif = true;
552 void Dispatcher::duplicateSourceItem(SourceItem *item) {
553 static QString fctName = "Dispatcher::duplicateSourceItem()";
555 cout << "call to " << qPrintable(fctName) << endl;
558 GroupScene *scene = item->getScene();
559 AbstractBlock* block = item->getRefBlock();
560 AbstractBlock *newBlock;
562 // only duplicate functional blocks
563 if(block->isFunctionalBlock()) {
565 // adding to the model
566 FunctionalBlock* funBlock = (FunctionalBlock*)block;
567 newBlock = params->getGraph()->duplicateSourceBlock(funBlock);
568 // adding to the view
569 scene->createSourceItem(newBlock);
571 params->unsaveModif = true;
575 void Dispatcher::duplicateInterfaceItem(InterfaceItem *item) {
576 static QString fctName = "Dispatcher::duplicateInterfaceItem()";
578 cout << "call to " << qPrintable(fctName) << endl;
581 AbstractInterface *refI = item->refInter;
582 if (! refI->isFunctionalInterface()) return;
584 AbstractBlock *refB = refI->getOwner();
585 if(! refB->isFunctionalBlock()) return;
587 FunctionalInterface* iface = (FunctionalInterface*)refI;
588 AbstractInterface *cloneIface = iface->clone();
589 if (cloneIface == NULL) {
590 QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
594 refB->addInterface(cloneIface);
596 InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params);
597 item->getOwner()->addInterfaceItem(cloneIfaceItem,true);
599 // creating control interface if needed
600 if (refI->getAssociatedIface() != NULL) {
601 QString ctlName = cloneIface->getName()+"_enb";
602 ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
603 refB->addInterface(ctlIface);
604 if (! ctlIface->setAssociatedIface(cloneIface)) {
605 cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl;
611 BoxItem* Dispatcher::addBlock(int idCategory, int idBlock, int idScene) {
612 static QString fctName = "Dispatcher::addBlock()";
614 cout << "call to " << qPrintable(fctName) << endl;
616 bool newSource = false;
617 BoxItem* item = NULL;
618 GroupScene *scene = getSceneById(idScene);
619 ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
620 // if block has no inputs, propose to add it as a source to top scene
621 if ((scene->isTopScene()) && (ref->isGeneratorBlock())) {
622 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 ?");
623 if (ret == QMessageBox::Yes) {
628 FunctionalBlock* newOne = params->getGraph()->createSourceBlock(ref);
629 scene->createSourceItem(newOne);
632 GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
633 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref);
634 item = scene->createBoxItem(newOne);
635 params->blockToItem.insert(newOne,item);
637 params->unsaveModif = true;
642 GroupWidget *Dispatcher::createTopScene(){
643 static QString fctName = "Dispatcher::createTopScene()";
645 cout << "call to " << qPrintable(fctName) << endl;
648 // creating the model part of the group
649 Graph* graph = params->createGraph();
650 GroupBlock *topBlock = graph->getTopGroup();
651 // creating the clkrstgen block
652 ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen");
653 FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(topBlock, ref);
654 ConnectedInterface* fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_clk"));
655 ConnectedInterface* toIface = AI_TO_CON(newOne->getIfaceFromName("ext_clk"));
656 fromIface->connectTo(toIface);
657 fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_reset"));
658 toIface = AI_TO_CON(newOne->getIfaceFromName("ext_reset"));
659 fromIface->connectTo(toIface);
661 // creating a fake and not connected interface
662 //AbstractInterface* iface = new GroupInterface(refBlock,"grp_iface",AbstractInterface::Input,AbstractInterface::Top);
664 // creating the group widget
665 topGroup = new GroupWidget(NULL,this,params);
666 currentGroup = topGroup;
667 // getting the newly created scene
668 GroupScene *scene = topGroup->getScene();
669 scene->setId(sceneCounter++);
670 params->setTopScene(scene);
671 params->setCurrentScene(scene);
672 // creating the view part of the group
673 GroupItem *group = new GroupItem(NULL,topBlock,this,params);
676 // adding the fake interface to the top group item
677 //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
678 //group->addInterface(item,true);
680 scene->setGroupItem(group);
682 groupList.append(topGroup);
686 GroupWidget* Dispatcher::addNewEmptyGroup(GroupScene* scene, bool show) {
687 static QString fctName = "Dispatcher::addNewEmptyGroup();";
689 cout << "call to " << qPrintable(fctName) << endl;
692 // getting the parent block in the graph
693 GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
694 cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
695 GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent);
696 cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
697 // creating the BlockItem in the scene
698 BoxItem* newItem = scene->createBoxItem(groupBlock);
700 params->unsaveModif = true;
702 GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem);
703 if (show) child->show();
708 GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
709 static QString fctName = "Dispatcher::createChildScene()";
711 cout << "call to " << qPrintable(fctName) << endl;
714 GroupWidget* group = NULL;
715 /* NB: this method may be called during design process or when loading
716 a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
717 cannot be initialized yet. This is why there are 2 cases below
720 if (upperItemOfGroupItem != NULL) {
721 // getting back the goup block already created
722 GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
723 // creating the view part of the group
724 GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
726 // creating the group widget
727 group = new GroupWidget(parentWidget, this, params);
728 // getting the newly created scene
729 GroupScene *scene = group->getScene();
730 scene->setId(sceneCounter++);
731 // affecting group item to the scene
732 scene->setGroupItem(groupItem);
733 groupList.append(group);
735 mainWindow->getLibrary()->updateComboScene();
738 GroupItem *groupItem = new GroupItem(this,params);
739 // creating the group widget
740 group = new GroupWidget(parentWidget, this, params);
741 // getting the newly created scene
742 GroupScene *scene = group->getScene();
743 // affecting group item to the scene
744 scene->setGroupItem(groupItem);
745 groupList.append(group);
750 void Dispatcher::destroyScene(GroupScene *scene) {
751 foreach(GroupScene* s, scene->getChildrenScene()) {
755 if (scene->getNbChildScene() == 0) {
756 // remove scene from the parent list, if possible
757 if (scene->getParentScene() != NULL) {
758 scene->getParentScene()->removeChildScene(scene);
760 // destroy the GroupWidget
761 groupList.removeAll(scene->getGroupWidget());
762 scene->getGroupWidget()->deleteLater();
765 cerr << "Abnormal case when destroying a scene" << endl;
769 void Dispatcher::showRaiseWindow(BoxItem *item) {
770 static QString fctName = "Dispatcher::showRaiseWindow()";
772 cout << "call to " << qPrintable(fctName) << endl;
775 cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
776 GroupItem* child = item->getChildGroupItem();
778 cerr << "abnormal case: child group item is null " << endl;
782 GroupWidget* win = child->getScene()->getGroupWidget();
786 win->activateWindow();
789 params->setCurrentScene(currentGroup->getScene());
792 void Dispatcher::showRstClkIface(AbstractBoxItem *item) {
793 static QString fctName = "Dispatcher::showRstClkIface()";
795 cout << "call to " << qPrintable(fctName) << endl;
798 item->setRstClkVisible(!item->isRstClkVisible());
802 void Dispatcher::showWishboneIface(AbstractBoxItem *item) {
803 static QString fctName = "Dispatcher::showWishboneIface()";
805 cout << "call to " << qPrintable(fctName) << endl;
808 item->setWishboneVisible(!item->isWishboneVisible());
811 void Dispatcher::addNewFullGroup() {
812 static QString fctName = "Dispatcher::addNewFullGroup()";
814 cout << "call to " << qPrintable(fctName) << endl;
820 QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
821 QList<AbstractBlock*> listAbstractBlocks; //abstract blocks in the group
822 QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
824 /* What must be done:
825 1 - creating a new GroupBlock
826 2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
827 3 - creating a BlockItem that references the new GroupBlock
828 4 - creating a new GroupWidget
829 5 - creating a new GroupItem added to the scene of the GroupWidget
833 /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
834 associated to the GroupItem of the current scene
836 GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
837 GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
838 /* step 2: moving selected blocks */
839 foreach(BlockItem* blockItem, listBlocks) {
840 parentBlock->removeBlock(blockItem->getRefBlock());
841 newGroupBlock->addBlock(blockItem->getRefBlock());
844 GroupItem *parent = currentGroup->getScene()->getGroupItem();
845 GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
846 BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
847 GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
849 //create the new window
850 GroupWidget* win = new GroupWidget(this,params);
851 win->getScene()->setGroupItem(groupItem);
852 win->getScene()->addItem(groupItem);
853 ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
854 params->addWindow(win);
858 params->getCurrentScene()->addBlockItem(blockItem);
859 params->getCurrentScene()->addItem(blockItem);
860 ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
862 //replace selected blocks in the group
863 foreach(AbstractBoxItem *block, listBlocks){
864 ((GroupItem*)block->getParentItem())->removeBlockItem(block);
865 ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
866 params->getCurrentScene()->removeItem(block);
867 params->getCurrentScene()->removeBlockItem(block);
869 groupBlock->addBlock(block->getRefBlock());
870 listAbstractBlocks.append(block->getRefBlock());
872 block->setUpperItem(groupItem);
873 groupItem->addBlockItem(block);
874 win->getScene()->addItem(block);
875 win->getScene()->addBlockItem(block);
878 //replace connection between selected blocks in the group
879 foreach(ConnectionItem *conn, connections){
880 if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
881 if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
882 parent->removeConnection(conn);
883 params->getCurrentScene()->removeItem(conn);
885 groupItem->addConnection(conn);
886 win->getScene()->addItem(conn);
891 //create new interfaces and connections for the new group
892 foreach(AbstractBoxItem *block, listBlocks){
893 foreach(InterfaceItem *inter, block->getInterfaces()){
894 cout << "inter : " << inter->getName().toStdString() << endl;
895 if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
896 cout << "connected from non null" << endl;
897 if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
899 AbstractInterface *iface = inter->refInter->clone(0);
900 iface->setName(iface->getName()+"_group");
901 groupBlock->addInterface(iface);
903 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
904 blockItem->addInterface(ifaceItem);
905 blockItem->resetInterfacesPosition();
907 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
908 groupItem->addInterface(ifaceGroupItem);
909 groupItem->resetInterfacesPosition();
910 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
911 if(conn->getToInterfaceItem() == inter){
912 conn->setToInterfaceItem(ifaceItem);
913 ifaceItem->refInter->setConnectedFrom(NULL);
914 conn->getFromInterfaceItem()->refInter->clearConnectedTo();
915 connect(ifaceItem,conn->getFromInterfaceItem());
918 params->setCurrentWindow(win);
920 inter->refInter->setConnectedFrom(NULL);
921 ifaceGroupItem->refInter->clearConnectedTo();
922 connect(inter,ifaceGroupItem);
923 params->setCurrentWindow(mainWindow);
927 if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
928 cout << "connected to non null" << endl;
929 foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
930 if(!listAbstractBlocks.contains(iface->getOwner())){
932 AbstractInterface *iface = inter->refInter->clone(0);
933 iface->setName(iface->getName()+"_group");
934 groupBlock->addInterface(iface);
936 InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
937 blockItem->addInterface(ifaceItem);
938 blockItem->resetInterfacesPosition();
940 foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
941 if(conn->getFromInterfaceItem() == inter){
942 conn->setFromInterfaceItem(ifaceItem);
943 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
944 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
948 InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
949 groupItem->addInterface(ifaceGroupItem);
950 groupItem->resetInterfacesPosition();
951 inter->refInter->clearConnectedTo();
952 ifaceGroupItem->refInter->setConnectedFrom(NULL);
953 connect(ifaceGroupItem,inter);
962 parent->updateShape();
963 currentGroup->getScene()->updateConnectionItemsShape();
965 groupItem->updateShape();
966 win->getScene()->updateConnectionItemsShape();
967 groupItem->update(groupItem->boundingRect());
972 void Dispatcher::removeBoxItem(BoxItem *item) {
973 static QString fctName = "Dispatcher::removeBoxItem()";
975 cout << "call to " << qPrintable(fctName) << endl;
978 /* a BoxItem (group of func) can be removed only if none of its
979 interfaces is connected to a group interface that is itself
980 connected to another one.
982 bool canRemove = true;
984 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
985 foreach(ConnectionItem* conn, ifaceItem->connections) {
986 InterfaceItem* other = NULL;
987 if (conn->getFromInterfaceItem() == ifaceItem) {
988 other = conn->getToInterfaceItem();
991 other = conn->getFromInterfaceItem();
994 if (other->getOwner()->isGroupItem()) {
995 ConnectedInterface* ref = other->refInter;
996 if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
1003 QMessageBox::warning(NULL,"Forbidden operation",
1004 "The block has at least one connection to a group interface that is totally connected.",
1010 if (item->getRefBlock()->isFunctionalBlock()) {
1011 msg = "Removing block ";
1014 msg = "Removing group ";
1016 msg += item->getRefBlock()->getName();
1017 msg += " and all its connections.\n\nAre you sure ?";
1019 int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1020 if (ret == QMessageBox::Cancel) {
1023 removeAllBlockConnections(item);
1025 if (item->getRefBlock()->isFunctionalBlock()) {
1026 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1027 item->getScene()->removeBoxItem(item);
1028 params->getGraph()->removeFunctionalBlock(block);
1029 params->blockToItem.remove(block);
1032 else if (item->getRefBlock()->isGroupBlock()) {
1034 GroupBlock* group = AB_TO_GRP(item->getRefBlock());
1036 // remove all child scenes recursively
1037 GroupItem* subgroup = item->getChildGroupItem();
1038 destroyScene(subgroup->getScene());
1039 // remove the BoxItem
1040 item->getScene()->removeBoxItem(item);
1041 // remove the group from the graph
1042 params->getGraph()->removeGroupBlock(group);
1046 void Dispatcher::removeAllBlockConnections(AbstractBoxItem *item) {
1047 static QString fctName = "Dispatcher::removeAllBlockConnection()";
1048 #ifdef DEBUG_FCTNAME
1049 cout << "call to " << qPrintable(fctName) << endl;
1052 foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
1053 foreach(ConnectionItem* conn, ifaceItem->connections) {
1054 removeConnection(conn);
1059 void Dispatcher::removeSourceItem(SourceItem *item) {
1060 static QString fctName = "Dispatcher::removeSourceItem()";
1061 #ifdef DEBUG_FCTNAME
1062 cout << "call to " << qPrintable(fctName) << endl;
1065 QString msg = "Removing source ";
1067 msg += item->getRefBlock()->getName();
1068 msg += " and all its connections.\n\nAre you sure ?";
1070 int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
1071 if (ret == QMessageBox::Cancel) {
1074 removeAllBlockConnections(item);
1076 FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
1077 item->getScene()->removeSourceItem(item);
1078 params->getGraph()->removeSourceBlock(block);
1082 void Dispatcher::removeConnection(ConnectionItem *connItem) {
1083 static QString fctName = "Dispatcher::removeConnection()";
1084 #ifdef DEBUG_FCTNAME
1085 cout << "call to " << qPrintable(fctName) << endl;
1087 InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
1088 InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
1091 cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1094 InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1095 GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1097 ConnectedInterface *fromInter = fromIfaceItem->refInter;
1098 ConnectedInterface *toInter = toIfaceItem->refInter;
1100 // test if one of the interface bounded to item is owned by a GroupItem
1101 if (fromIfaceItem->getOwner()->isGroupItem()) {
1102 groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1103 groupIfaceItem = fromIfaceItem;
1105 else if (toIfaceItem->getOwner()->isGroupItem()) {
1106 groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1107 groupIfaceItem = toIfaceItem;
1110 groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1113 // removing the connection from graph
1115 cout << "removing connections from graph ..." ;
1117 fromInter->disconnectTo(toInter);
1120 cout << "done." << endl ;
1123 // removing the connection from scene
1125 cout << "removing connections from scene ..." ;
1127 groupItem->getScene()->removeConnectionItem(connItem);
1130 cout << "done." << endl ;
1133 // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1134 if (groupIfaceItem != NULL) {
1136 // determine if the interface must be removed since it has no more connections.
1137 bool groupInterRemove = false;
1138 if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1140 if (groupInterRemove) {
1141 // get the GroupInterface from interface item
1142 ConnectedInterface* groupInter = groupIfaceItem->refInter;
1143 // remove interface from GroupItem, and delete it.
1144 groupItem->removeInterfaceItem(groupIfaceItem);
1145 // get the parent BoxItem of GroupItem if it exists.
1146 BoxItem* parent2Item = groupItem->getParentItem();
1147 if (parent2Item != NULL) {
1148 InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1149 // remove interface intem in parent BoxItem
1150 parent2Item->removeInterfaceItem(group2IfaceItem);
1152 // remove GroupInterface in the graph.
1153 groupInter->getOwner()->removeInterface(groupInter);
1158 void Dispatcher::showBlocksLibrary(){
1159 cout << "showing block library" << endl;
1160 mainWindow->getLibrary()->show();
1161 mainWindow->getLibrary()->raise();
1164 void Dispatcher::showProperties(InterfaceItem *inter) {
1165 new InterfacePropertiesWindow(inter);
1168 /* connectInterToGroup() :
1169 The only way for a block (functional of group) within a GroupItem to be connected
1170 to the latter is to right-click on one of its interfaces and to choose "connect to group".
1171 That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1174 void Dispatcher::connectInterToGroup(InterfaceItem *item){
1176 // getting the GroupBlock and GroupItem that are parent of the block that owns item
1177 ConnectedInterface *refInter = item->refInter;
1178 cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1179 GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1180 cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1181 GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1183 // creating/adding the group interface in the graph model
1184 GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());
1185 parentItem->getRefBlock()->addInterface(groupInter);
1186 // creating/adding the group control interface in the graph model if the purpose is data
1187 if (refInter->getPurpose() == AbstractInterface::Data) {
1188 GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1189 groupCtlInter->setAssociatedIface(groupInter);
1190 parentItem->getRefBlock()->addInterface(groupCtlInter);
1192 // creating/adding the group interface in the current scene model, and connection item
1193 InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1194 parentItem->addInterfaceItem(groupIfaceItem,true);
1196 // creating the connection, in graph and with an item
1197 createConnection(item, groupIfaceItem);
1199 // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1200 BoxItem* parent2Item = parentItem->getParentItem();
1201 if(parent2Item != NULL){
1202 InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1203 parent2Item->addInterfaceItem(blockIfaceItem,true);
1207 parentItem->getScene()->updateConnectionItemsShape();
1209 params->unsaveModif = true;
1212 void Dispatcher::removeFunctionalInterface(InterfaceItem *item) {
1213 static QString fctName = "Dispatcher::removeBlockInterface()";
1214 #ifdef DEBUG_FCTNAME
1215 cout << "call to " << qPrintable(fctName) << endl;
1218 /* first, remove all connections from item
1219 NB: if there is a connection to a group interface, then this
1220 method should not be called if the group interface is also
1221 connected to another interface. Normally, this is not possible
1222 because such a check is done when creating the contextual menu
1223 that allows to remove an interface.
1225 foreach(ConnectionItem* conn, item->connections) {
1226 removeConnection(conn);
1229 ConnectedInterface* ref = item->refInter;
1230 item->getOwner()->removeInterfaceItem(item);
1231 FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1232 fun->removeInterface(ref);
1235 void Dispatcher::removeGroupInterface(InterfaceItem *item) {
1236 static QString fctName = "Dispatcher::removeGroupInterface()";
1237 #ifdef DEBUG_FCTNAME
1238 cout << "call to " << qPrintable(fctName) << endl;
1241 /* NB: just remove all connections from/to this item, since when there are no more
1242 ones to a GroupItem, it is automatically deleted.
1244 foreach(ConnectionItem* conn, item->connections) {
1245 removeConnection(conn);
1249 QMap<int, QString> Dispatcher::getAllGroupNames() {
1251 QMap<int, QString> list;
1252 foreach(GroupWidget *group, groupList) {
1253 list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1258 GroupScene* Dispatcher::getSceneById(int id) {
1259 foreach(GroupWidget *group, groupList){
1260 if(group->getScene()->getId() == id)
1261 return group->getScene();
1263 cout << "search scene by id :" << id << " :: not found..." << endl;
1267 GroupItem *Dispatcher::getGroupItemById(int id) {
1268 foreach(GroupWidget *group, groupList) {
1269 GroupScene* scene = group->getScene();
1270 if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1272 cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1276 BoxItem *Dispatcher::getBoxItemById(int id) {
1277 foreach(GroupWidget *group, groupList) {
1279 GroupScene* scene = group->getScene();
1280 foreach(BoxItem *item, scene->getBoxItems()){
1281 if(item->getId() == id){
1286 cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1290 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1292 foreach(GroupWidget *group, groupList) {
1294 GroupScene* scene = group->getScene();
1296 foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1297 if(item->getId() == id){
1301 foreach(BoxItem *block, scene->getBoxItems()){
1302 foreach(InterfaceItem *item, block->getInterfaces()){
1303 if(item->getId() == id){
1309 cout << "search interface by id :" << id << " :: not found..." << endl;
1313 void Dispatcher::findGraphModifications(FunctionalBlock *block) {
1314 static QString fctName = "Dispatcher::findGraphModifications()";
1315 #ifdef DEBUG_FCTNAME
1316 cout << "call to " << qPrintable(fctName) << endl;
1319 block->computeAdmittanceDelays();
1320 // get the block item that is associated to block
1321 BoxItem* toBlockItem = params->blockToItem.value(block);
1323 /* VERSION 1: just add delays if needed */
1324 QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1325 QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1326 while (iterD.hasNext()) {
1328 QList<int>* delay = iterD.value();
1329 if (delay->at(0) > 0) {
1330 // create delay and associate it to the connected input
1332 ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1333 AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1334 cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1335 toIface->setInputModifier(mod);
1337 toBlockItem->update();