]> AND Private Git Repository - blast.git/blob - Dispatcher.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
a9beb481f8bdb412c7cec0e5414d5fd85ba5882d
[blast.git] / Dispatcher.cpp
1 #include "Dispatcher.h"
2 #include "Parameters.h"
3 #include "MainWindow.h"
4
5 #include "Graph.h"
6 #include "ReferenceBlock.h"
7 #include "GroupBlock.h"
8 #include "FunctionalBlock.h"
9
10 #include "ConnectedInterface.h"
11 #include "ReferenceInterface.h"
12 #include "GroupInterface.h"
13 #include "FunctionalInterface.h"
14
15 #include "GroupWidget.h"
16 #include "GroupScene.h"
17 #include "GroupItem.h"
18 #include "BoxItem.h"
19 #include "SourceItem.h"
20 #include "InterfaceItem.h"
21 #include "ConnectionItem.h"
22
23 #include "BlockLibraryWidget.h"
24 #include "BlockLibraryTree.h"
25
26 #include "AbstractInputModifier.h"
27 #include "DelayInputModifier.h"
28
29
30 #include "InterfacePropertiesWindow.h"
31
32 int Dispatcher::sceneCounter = 0;
33
34 Dispatcher::Dispatcher(Parameters* _params, MainWindow* _window) {
35   params = _params;
36   mainWindow =_window;
37   params->setDispatcher(this);
38   currentGroup = NULL;
39   topGroup = NULL;    
40 }
41
42 GroupWidget *Dispatcher::loadProject(const QString& filename) {
43
44   QDomElement root;
45   try {
46     root = params->openProjectFile(filename);
47   }
48   catch(Exception err) {
49     return NULL;
50   }
51
52   /*
53   // creating the top widget/scene
54   topGroup = new GroupWidget(NULL,this,params);
55   currentGroup = topGroup;
56   // getting the newly created scene
57   GroupScene *scene = topGroup->getScene();
58
59   params->setTopScene(scene);
60   params->setCurrentScene(scene);
61 */
62   try {   
63     topGroup = params->loadProject(root);
64   }
65   catch(Exception e){
66     cerr << qPrintable(e.getDefaultMessage()) << endl;
67     cerr << "Aborting ..." << endl;
68     // TO DO : deleteting topGroup and all
69     return NULL;
70   }
71
72   groupList.append(topGroup);
73   return topGroup;
74 }
75
76 void Dispatcher::closeCurrentProject() {
77
78   foreach(GroupWidget* win, groupList) {
79     win->deleteLater();
80   }
81   groupList.clear();
82   params->destroyGraph();
83   topGroup = NULL;
84   currentGroup = NULL;
85   sceneCounter = 0;
86 }
87
88 bool Dispatcher::createConnection(InterfaceItem *iface1, InterfaceItem *iface2, bool visible) {
89     
90   ConnectedInterface* ref1 = iface1->refInter;
91   ConnectedInterface* ref2 = iface2->refInter;  
92   // connect both interface
93
94   bool ok1 = false;
95   bool ok2 = false;
96
97   // test the ref1->ref2 connection
98   if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) {
99     ref1->connectTo(ref2);    
100     ok1 = true;
101   }
102   // if the frist one did not work, test ref2->ref1
103   if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) {  
104     ref2->connectTo(ref1);    
105     ok2 = true;
106   }
107   if ((ok1 == true) || (ok2 == true)) {
108
109     iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible);
110
111     unselectAllItems();
112     params->unsaveModif = true;
113     cout << "created a connection from " << qPrintable(ref1->getName()) << " to " << qPrintable(ref2->getName()) << endl;
114     return true;
115   }
116   return false;
117 }
118
119
120 void Dispatcher::unselectAllItems(int direction){
121
122   GroupScene *scene = params->getCurrentScene();
123
124   foreach(BoxItem* block, scene->getBoxItems()) {
125     block->setSelected(false);
126     block->setCurrentInterface(NULL);
127   }
128   scene->unselecteInterfaces();
129   scene->update();
130 }
131
132 void Dispatcher::setCurrentGroupWidget(GroupWidget *win){
133   win->setFocus();
134   win->changeConnectionMode(-1);
135   currentGroup = win;
136   params->setCurrentScene(win->getScene());
137 }
138
139 void Dispatcher::changeConnectionMode(int mode){
140
141   /*
142   foreach(GroupWidget* win, groupList){
143
144     QToolButton* buttonNewConnection = win->getButtonNewConnection();
145
146     QPalette pal = buttonNewConnection->palette();
147
148     if(mode == -1){
149       if(params->sceneMode != Parameters::EditOnConnection){
150         params->sceneMode = Parameters::EditOnConnection;
151         pal.setColor(QPalette::Button, QColor(Qt::lightGray));
152       } else {
153         params->sceneMode = Parameters::EditNoOperation;
154         pal.setColor(QPalette::Button, QColor("#edeceb"));
155       }
156     }
157     else if(mode == Parameters::EditOnConnection){
158       params->sceneMode = Parameters::EditOnConnection;
159       pal.setColor(QPalette::Button, QColor(Qt::lightGray));
160     }
161     else {
162       params->sceneMode = Parameters::EditNoOperation;
163       pal.setColor(QPalette::Button, QColor("#edeceb"));
164     }
165     unselectAllInterfaces();
166
167     buttonNewConnection->setAutoFillBackground(true);
168     buttonNewConnection->setPalette(pal);
169     buttonNewConnection->update();
170   }
171   */
172 }
173
174 void Dispatcher::generateBlockVHDL(BoxItem *item){
175   static QString fctName = "Dispatcher::generateBlockVHDL()";
176 #ifdef DEBUG_FCTNAME
177   cout << "call to " << qPrintable(fctName) << endl;
178 #endif
179
180   if (item->getRefBlock()->isFunctionalBlock()) {
181     FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
182     ReferenceBlock* ref = block->getReference();
183     BlockImplementation* impl = ref->getImplementations().at(0);
184     try {
185       impl->generateVHDL(block,params->projectPath);
186     }
187     catch(Exception e) {
188       cout << qPrintable(e.getMessage()) << endl;
189     }
190   }
191 }
192
193 void Dispatcher::renameFunctionalBlock(BoxItem *item){
194   static QString fctName = "Dispatcher::renameFunctionalBlock()";
195 #ifdef DEBUG_FCTNAME
196   cout << "call to " << qPrintable(fctName) << endl;
197 #endif
198     
199   GroupWidget* win = item->getScene()->getGroupWidget();
200   
201   bool ok = false;
202   QString text = "";  
203   while (!ok) {  
204     text = QInputDialog::getText(win, "Rename a functional block",
205                                        "New name:", QLineEdit::Normal,
206                                        item->getRefBlock()->getName(), &ok);
207     if (!ok) return;
208     
209     if (text == item->getRefBlock()->getName()) return;
210     
211     if( (text.isEmpty()) || (text.length() > 30)) {
212       QMessageBox::warning(win,"Error in given name",
213                            "the block name must be shorter than 30 characters, cannot be empty",
214                            QMessageBox::Ok);
215       ok = false;
216     }
217     else {
218       FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent()));
219       if (block != NULL) {
220         QMessageBox::warning(win,"Error in given name",
221                              "the name provided is similar to that of another functional block within the group",
222                              QMessageBox::Ok);
223         ok = false;
224       }
225     }    
226   }  
227
228   item->getRefBlock()->setName(text);
229   item->nameChanged();
230 }
231
232 void Dispatcher::renameGroupBlock(GroupItem *item){
233   static QString fctName = "Dispatcher::renameGroupBlock()";
234 #ifdef DEBUG_FCTNAME
235   cout << "call to " << qPrintable(fctName) << endl;
236 #endif
237   
238   GroupWidget* win = item->getScene()->getGroupWidget();
239   
240   bool ok = false;
241   QString text = "";
242   while (!ok) {  
243     text = QInputDialog::getText(win, "Rename a group",
244                                        "New name:", QLineEdit::Normal,
245                                        item->getRefBlock()->getName(), &ok);
246     if (!ok) return;
247     
248     if (text == item->getRefBlock()->getName()) return;
249     
250     if( (text.isEmpty()) || (text.length() > 30)) {
251       QMessageBox::warning(win,"Error in given name",
252                            "the block name must be shorter than 30 characters, cannot be empty",
253                            QMessageBox::Ok);
254       ok = false;
255     }
256     else {
257       GroupBlock* block = params->getGraph()->getGroupBlockByName(text);
258       if (block != NULL) {
259         QMessageBox::warning(win,"Error in given name",
260                              "the name provided is similar to that of another group",
261                              QMessageBox::Ok);
262         ok = false;
263       }
264     }    
265   }
266   
267   item->getRefBlock()->setName(text);
268   if(item->getScene()->getGroupWidget()->isTopGroup()) {
269     mainWindow->setWindowTitle("blast - "+text);
270   }
271   else {
272     item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text);
273   }
274   item->nameChanged();
275   mainWindow->getLibrary()->updateComboScene();   
276 }
277
278 void Dispatcher::renameSourceBlock(SourceItem *item){
279   static QString fctName = "Dispatcher::renameSourceBlock()";
280 #ifdef DEBUG_FCTNAME
281   cout << "call to " << qPrintable(fctName) << endl;
282 #endif
283     
284   GroupWidget* win = item->getScene()->getGroupWidget();
285   
286   bool ok = false;
287   QString text = "";  
288   while (!ok) {  
289     text = QInputDialog::getText(win, "Rename a source",
290                                        "New name:", QLineEdit::Normal,
291                                        item->getRefBlock()->getName(), &ok);
292     if (!ok) return;
293     
294     if (text == item->getRefBlock()->getName()) return;
295     
296     if( (text.isEmpty()) || (text.length() > 30)) {
297       QMessageBox::warning(win,"Error in given name",
298                            "the block name must be shorter than 30 characters, cannot be empty",
299                            QMessageBox::Ok);
300       ok = false;
301     }
302     else {
303       FunctionalBlock* block = params->getGraph()->getSourceBlockByName(text);
304       if (block != NULL) {
305         QMessageBox::warning(win,"Error in given name",
306                              "the name provided is similar to that of another source block within the top group",
307                              QMessageBox::Ok);
308         ok = false;
309       }
310     }    
311   }  
312
313   item->getRefBlock()->setName(text);
314   item->nameChanged();
315 }
316
317
318 void Dispatcher::renameInterface(InterfaceItem *item) {
319   static QString fctName = "Dispatcher::renameInterface()";
320 #ifdef DEBUG_FCTNAME
321   cout << "call to " << qPrintable(fctName) << endl;
322 #endif
323
324   GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
325   
326   bool ok = false;
327   QString text = "";
328   while (!ok) {
329     text = QInputDialog::getText(win, "Rename an interface",
330                                        "New name:", QLineEdit::Normal,
331                                        item->refInter->getName(), &ok);
332    
333     if (!ok) return;
334     
335     if (text == item->refInter->getName()) return;
336     
337     if( (text.isEmpty()) || (text.length() > 30)) {
338       QMessageBox::warning(win,"Error in given name",
339                            "the interface name must be shorter than 30 characters, cannot be empty",
340                            QMessageBox::Ok);
341       ok = false;
342     }
343     else {
344       AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text);
345       if (iface != NULL) {
346         QMessageBox::warning(win,"Error in given name",
347                              "the name provided is similar to that of another interface",
348                              QMessageBox::Ok);
349         ok = false;
350       }
351     }
352   }
353   item->refInter->setName(text);
354   AbstractInterface* assoIface = item->refInter->getAssociatedIface();
355   if (assoIface != NULL) {
356     assoIface->setName(text+"_enb");
357   }
358   item->updateName(text);
359   item->getOwner()->nameChanged();  
360 }
361
362 void Dispatcher::showPatterns(InterfaceItem *item) {
363   static QString fctName = "Dispatcher::showPatterns()";
364 #ifdef DEBUG_FCTNAME
365   cout << "call to " << qPrintable(fctName) << endl;
366 #endif
367   QString msg = "";
368   if (item->refInter->getDirection() == AbstractInterface::Input) {
369     msg = "Input pattern of iface ";
370     msg += item->refInter->getName();
371     msg += " owned by ";
372     msg += item->refInter->getOwner()->getName();
373     msg += " is:\n";
374     // get the precursor output pattern
375     ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface());
376     QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
377     // get the modifier
378     AbstractInputModifier* modifier = connIface->getInputModifier();
379     // check if the input is modified
380     if (modifier != NULL) {
381
382       out = modifier->getModifiedInput(out);
383     }
384
385     foreach(char c, *out) {
386       msg += QString::number((int)c);
387     }
388     msg += "\n";
389   }
390   else if (item->refInter->getDirection() == AbstractInterface::Output) {
391     msg = "Output pattern of iface ";
392     msg += item->refInter->getName();
393     msg += " owned by ";
394     msg += item->refInter->getOwner()->getName();
395     msg += " is:\n";
396     ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
397     if (iface->getOutputPattern() == NULL) return;
398     foreach(char c, *(iface->getOutputPattern())) {
399       msg += QString::number((int)c);
400     }
401     msg += "\n";
402   }
403   QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
404 }
405
406 void Dispatcher::showModifier(InterfaceItem *item) {
407   static QString fctName = "Dispatcher::showModifier()";
408 #ifdef DEBUG_FCTNAME
409   cout << "call to " << qPrintable(fctName) << endl;
410 #endif
411   QString msg = "";
412   ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
413   AbstractInputModifier* mod = assoIface->getInputModifier();
414   if (mod->isDelay()) {
415     DelayInputModifier* delay = (DelayInputModifier *)mod;
416     msg = "Pattern of iface ";
417     msg += item->refInter->getName();
418     msg += " owned by ";
419     msg += item->refInter->getOwner()->getName();
420     msg += " is modified by a simple delay of ";
421     msg += QString::number(delay->getDelayLength());
422
423   }
424   QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
425 }
426
427 void Dispatcher::removeModifier(InterfaceItem *item) {
428   static QString fctName = "Dispatcher::showModifier()";
429 #ifdef DEBUG_FCTNAME
430   cout << "call to " << qPrintable(fctName) << endl;
431 #endif
432
433   ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
434   assoIface->clearInputModifier();
435 }
436
437
438 void Dispatcher::duplicateBoxItem(BoxItem *item){
439   static QString fctName = "Dispatcher::duplicateBoxItem()";
440 #ifdef DEBUG_FCTNAME
441   cout << "call to " << qPrintable(fctName) << endl;
442 #endif
443
444   GroupScene *scene = item->getScene();
445   AbstractBlock* block = item->getRefBlock();  
446   AbstractBlock *newBlock;
447
448   // only duplicate functional blocks
449   if(block->isFunctionalBlock()) {
450
451     // adding to the model
452     FunctionalBlock* funBlock = (FunctionalBlock*)block;
453     newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock);
454     // adding to the view
455     scene->createBoxItem(newBlock);
456
457     params->unsaveModif = true;
458   }
459 }
460
461 void Dispatcher::duplicateSourceItem(SourceItem *item) {
462   static QString fctName = "Dispatcher::duplicateSourceItem()";
463 #ifdef DEBUG_FCTNAME
464   cout << "call to " << qPrintable(fctName) << endl;
465 #endif
466
467   GroupScene *scene = item->getScene();
468   AbstractBlock* block = item->getRefBlock();  
469   AbstractBlock *newBlock;
470
471   // only duplicate functional blocks
472   if(block->isFunctionalBlock()) {
473
474     // adding to the model
475     FunctionalBlock* funBlock = (FunctionalBlock*)block;
476     newBlock = params->getGraph()->duplicateSourceBlock(funBlock);
477     // adding to the view
478     scene->createSourceItem(newBlock);
479
480     params->unsaveModif = true;
481   }
482 }
483
484 void Dispatcher::duplicateInterfaceItem(InterfaceItem *item) {
485   static QString fctName = "Dispatcher::duplicateInterfaceItem()";
486 #ifdef DEBUG_FCTNAME
487   cout << "call to " << qPrintable(fctName) << endl;
488 #endif
489
490   AbstractInterface *refI = item->refInter;
491   if (! refI->isFunctionalInterface()) return;
492
493   AbstractBlock *refB = refI->getOwner();
494   if(! refB->isFunctionalBlock()) return;
495
496   FunctionalInterface* iface = (FunctionalInterface*)refI;
497   AbstractInterface *cloneIface = iface->clone();
498   if (cloneIface == NULL) {
499     QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
500     return;
501   }
502
503   refB->addInterface(cloneIface);
504
505   InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params);
506   item->getOwner()->addInterfaceItem(cloneIfaceItem,true);
507   
508   // creating control interface if needed
509   if (refI->getAssociatedIface() != NULL) {
510     QString ctlName = cloneIface->getName()+"_enb";
511     ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
512     refB->addInterface(ctlIface);
513     if (! ctlIface->setAssociatedIface(cloneIface)) {
514       cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl;
515     }
516   }
517 }
518
519
520 BoxItem* Dispatcher::addBlock(int idCategory, int idBlock, int idScene) {
521   static QString fctName = "Dispatcher::addBlock()";
522 #ifdef DEBUG_FCTNAME
523   cout << "call to " << qPrintable(fctName) << endl;
524 #endif
525   bool newSource = false;
526   BoxItem* item = NULL;
527   GroupScene *scene = getSceneById(idScene);
528   ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
529   // if block has no inputs, propose to add it as a source to top scene
530   if ((scene->isTopScene()) && (ref->isGeneratorBlock())) {
531     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 ?");
532     if (ret == QMessageBox::Yes) {
533       newSource = true;      
534     }   
535   }
536   if (newSource) {
537     FunctionalBlock* newOne = params->getGraph()->createSourceBlock(ref);
538     scene->createSourceItem(newOne);
539   }
540   else {
541     GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
542     FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref);
543     item = scene->createBoxItem(newOne);
544     params->blockToItem.insert(newOne,item);
545   }
546   params->unsaveModif = true;
547   return item;
548 }
549
550
551 GroupWidget *Dispatcher::createTopScene(){
552   static QString fctName = "Dispatcher::createTopScene()";
553 #ifdef DEBUG_FCTNAME
554   cout << "call to " << qPrintable(fctName) << endl;
555 #endif
556
557   // creating the model part of the group
558   Graph* graph = params->createGraph();
559   GroupBlock *topBlock = graph->getTopGroup();
560   // creating the clkrstgen block
561   ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen");
562   FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(topBlock, ref);
563   ConnectedInterface* fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_clk"));
564   ConnectedInterface* toIface = AI_TO_CON(newOne->getIfaceFromName("ext_clk"));
565   fromIface->connectTo(toIface);
566   fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_reset"));
567   toIface = AI_TO_CON(newOne->getIfaceFromName("ext_reset"));
568   fromIface->connectTo(toIface);
569
570   // creating a fake and not connected interface
571   //AbstractInterface* iface = new GroupInterface(refBlock,"grp_iface",AbstractInterface::Input,AbstractInterface::Top);
572
573   // creating the group widget
574   topGroup = new GroupWidget(NULL,this,params);
575   currentGroup = topGroup;
576   // getting the newly created scene
577   GroupScene *scene = topGroup->getScene();
578   scene->setId(sceneCounter++);
579   params->setTopScene(scene);
580   params->setCurrentScene(scene);
581   // creating the view part of the group
582   GroupItem *group = new GroupItem(NULL,topBlock,this,params);
583
584
585   // adding the fake interface to the top group item
586   //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
587   //group->addInterface(item,true);
588
589   scene->setGroupItem(group);
590
591   groupList.append(topGroup);
592   return topGroup;
593 }
594
595 GroupWidget* Dispatcher::addNewEmptyGroup(GroupScene* scene, bool show) {
596   static QString fctName = "Dispatcher::addNewEmptyGroup();";
597 #ifdef DEBUG_FCTNAME
598   cout << "call to " << qPrintable(fctName) << endl;
599 #endif
600
601   // getting the parent block in the graph
602   GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
603   cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
604   GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent);
605   cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
606   // creating the BlockItem in the scene
607   BoxItem* newItem = scene->createBoxItem(groupBlock);
608
609   params->unsaveModif = true;
610
611   GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem);
612   if (show) child->show();
613   return child;
614
615 }
616
617 GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
618   static QString fctName = "Dispatcher::createChildScene()";
619 #ifdef DEBUG_FCTNAME
620   cout << "call to " << qPrintable(fctName) << endl;
621 #endif
622
623   GroupWidget* group = NULL;
624   /* NB: this method may be called during design process or when loading
625      a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
626      cannot be initialized yet. This is why there are 2 cases below
627    */
628
629   if (upperItemOfGroupItem != NULL) {
630     // getting back the goup block already created
631     GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
632     // creating the view part of the group
633     GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
634
635     // creating the group widget
636     group = new GroupWidget(parentWidget, this, params);
637     // getting the newly created scene
638     GroupScene *scene = group->getScene();
639     scene->setId(sceneCounter++);
640     // affecting group item to the scene
641     scene->setGroupItem(groupItem);
642     groupList.append(group);
643
644     mainWindow->getLibrary()->updateComboScene();
645   }
646   else {
647     GroupItem *groupItem = new GroupItem(this,params);
648     // creating the group widget
649     group = new GroupWidget(parentWidget, this, params);
650     // getting the newly created scene
651     GroupScene *scene = group->getScene();
652     // affecting group item to the scene
653     scene->setGroupItem(groupItem);
654     groupList.append(group);
655   }
656   return group;
657 }
658
659 void Dispatcher::destroyScene(GroupScene *scene) {
660   foreach(GroupScene* s, scene->getChildrenScene()) {
661     destroyScene(s);
662   }
663
664   if (scene->getNbChildScene() == 0) {
665     // remove scene from the parent list, if possible
666     if (scene->getParentScene() != NULL) {
667       scene->getParentScene()->removeChildScene(scene);
668     }
669     // destroy the GroupWidget
670     groupList.removeAll(scene->getGroupWidget());
671     scene->getGroupWidget()->deleteLater();
672   }
673   else {
674     cerr << "Abnormal case when destroying a scene" << endl;
675   }
676 }
677
678 void Dispatcher::showRaiseWindow(BoxItem *item) {
679   static QString fctName = "Dispatcher::showRaiseWindow()";
680 #ifdef DEBUG_FCTNAME
681   cout << "call to " << qPrintable(fctName) << endl;
682 #endif
683
684   cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
685   GroupItem* child = item->getChildGroupItem();
686   if (child == NULL) {
687     cerr << "abnormal case: child group item is null " << endl;
688     return;
689   }
690
691   GroupWidget* win = child->getScene()->getGroupWidget();
692
693   win->showNormal();
694   win->raise();
695   win->activateWindow();
696
697   currentGroup = win;
698   params->setCurrentScene(currentGroup->getScene());
699 }
700
701 void Dispatcher::showRstClkIface(AbstractBoxItem *item) {
702   static QString fctName = "Dispatcher::showRstClkIface()";
703 #ifdef DEBUG_FCTNAME
704   cout << "call to " << qPrintable(fctName) << endl;
705 #endif
706
707   item->setRstClkVisible(!item->isRstClkVisible());
708   
709 }
710
711 void Dispatcher::showWishboneIface(AbstractBoxItem *item) {
712   static QString fctName = "Dispatcher::showWishboneIface()";
713 #ifdef DEBUG_FCTNAME
714   cout << "call to " << qPrintable(fctName) << endl;
715 #endif
716
717   item->setWishboneVisible(!item->isWishboneVisible());  
718 }
719
720 void Dispatcher::addNewFullGroup() {
721   static QString fctName = "Dispatcher::addNewFullGroup()";
722 #ifdef DEBUG_FCTNAME
723   cout << "call to " << qPrintable(fctName) << endl;
724 #endif
725
726
727 #ifdef DEBUG_INCLFUN
728
729   QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
730   QList<AbstractBlock*> listAbstractBlocks;   //abstract blocks in the group
731   QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
732
733   /* What must be done:
734      1 - creating a new GroupBlock
735      2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
736      3 - creating a BlockItem that references the new GroupBlock
737      4 - creating a new GroupWidget
738      5 - creating a new GroupItem added to the scene of the GroupWidget
739
740    */
741
742   /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
743      associated to the GroupItem of the current scene
744    */
745   GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
746   GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
747   /* step 2: moving selected blocks */
748   foreach(BlockItem* blockItem, listBlocks) {
749     parentBlock->removeBlock(blockItem->getRefBlock());
750     newGroupBlock->addBlock(blockItem->getRefBlock());
751   }
752
753   GroupItem *parent = currentGroup->getScene()->getGroupItem();
754   GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
755   BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
756   GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
757
758   //create the new window
759   GroupWidget* win = new GroupWidget(this,params);
760   win->getScene()->setGroupItem(groupItem);
761   win->getScene()->addItem(groupItem);
762   ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
763   params->addWindow(win);
764   win->show();
765
766   //add the new group
767   params->getCurrentScene()->addBlockItem(blockItem);
768   params->getCurrentScene()->addItem(blockItem);
769   ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
770
771   //replace selected blocks in the group
772   foreach(AbstractBoxItem *block, listBlocks){
773     ((GroupItem*)block->getParentItem())->removeBlockItem(block);
774     ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
775     params->getCurrentScene()->removeItem(block);
776     params->getCurrentScene()->removeBlockItem(block);
777
778     groupBlock->addBlock(block->getRefBlock());
779     listAbstractBlocks.append(block->getRefBlock());
780
781     block->setUpperItem(groupItem);
782     groupItem->addBlockItem(block);
783     win->getScene()->addItem(block);
784     win->getScene()->addBlockItem(block);
785   }
786
787   //replace connection between selected blocks in the group
788   foreach(ConnectionItem *conn, connections){
789     if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
790       if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
791         parent->removeConnection(conn);
792         params->getCurrentScene()->removeItem(conn);
793
794         groupItem->addConnection(conn);
795         win->getScene()->addItem(conn);
796       }
797     }
798   }
799
800   //create new interfaces and connections for the new group
801   foreach(AbstractBoxItem *block, listBlocks){
802     foreach(InterfaceItem *inter, block->getInterfaces()){
803       cout << "inter : " << inter->getName().toStdString() << endl;
804       if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
805         cout << "connected from non null" << endl;
806         if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
807
808           AbstractInterface *iface = inter->refInter->clone(0);
809           iface->setName(iface->getName()+"_group");
810           groupBlock->addInterface(iface);
811
812           InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
813           blockItem->addInterface(ifaceItem);
814           blockItem->resetInterfacesPosition();
815
816           InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
817           groupItem->addInterface(ifaceGroupItem);
818           groupItem->resetInterfacesPosition();
819           foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
820             if(conn->getToInterfaceItem() == inter){
821               conn->setToInterfaceItem(ifaceItem);
822               ifaceItem->refInter->setConnectedFrom(NULL);
823               conn->getFromInterfaceItem()->refInter->clearConnectedTo();
824               connect(ifaceItem,conn->getFromInterfaceItem());
825             }
826           }
827           params->setCurrentWindow(win);
828
829           inter->refInter->setConnectedFrom(NULL);
830           ifaceGroupItem->refInter->clearConnectedTo();
831           connect(inter,ifaceGroupItem);
832           params->setCurrentWindow(mainWindow);
833         }
834       }
835
836       if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
837         cout << "connected to non null" << endl;
838         foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
839           if(!listAbstractBlocks.contains(iface->getOwner())){
840
841             AbstractInterface *iface = inter->refInter->clone(0);
842             iface->setName(iface->getName()+"_group");
843             groupBlock->addInterface(iface);
844
845             InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
846             blockItem->addInterface(ifaceItem);
847             blockItem->resetInterfacesPosition();
848
849             foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
850               if(conn->getFromInterfaceItem() == inter){
851                 conn->setFromInterfaceItem(ifaceItem);
852                 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
853                 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
854               }
855             }
856
857             InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
858             groupItem->addInterface(ifaceGroupItem);
859             groupItem->resetInterfacesPosition();
860             inter->refInter->clearConnectedTo();
861             ifaceGroupItem->refInter->setConnectedFrom(NULL);
862             connect(ifaceGroupItem,inter);
863           }
864         }
865       }
866     }
867   }
868
869   //update window
870
871   parent->updateShape();
872   currentGroup->getScene()->updateConnectionItemsShape();
873   currentGroup = win;
874   groupItem->updateShape();
875   win->getScene()->updateConnectionItemsShape();
876   groupItem->update(groupItem->boundingRect());
877
878 #endif
879 }
880
881 void Dispatcher::removeBoxItem(BoxItem *item) {
882   static QString fctName = "Dispatcher::removeBoxItem()";
883 #ifdef DEBUG_FCTNAME
884   cout << "call to " << qPrintable(fctName) << endl;
885 #endif
886
887   /* a BoxItem (group of func) can be removed only if none of its
888      interfaces is connected to a group interface that is itself
889      connected to another one.
890   */
891   bool canRemove = true;
892
893   foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
894     foreach(ConnectionItem* conn, ifaceItem->connections) {
895       InterfaceItem* other = NULL;
896       if (conn->getFromInterfaceItem() == ifaceItem) {
897         other = conn->getToInterfaceItem();
898       }
899       else {
900         other = conn->getFromInterfaceItem();
901       }
902
903       if (other->getOwner()->isGroupItem()) {
904         ConnectedInterface* ref = other->refInter;
905         if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
906           canRemove = false;
907         }
908       }
909     }
910   }
911   if (!canRemove) {
912     QMessageBox::warning(NULL,"Forbidden operation",
913                          "The block has at least one connection to a group interface that is totally connected.",
914                          QMessageBox::Ok);
915     return;
916   }
917
918   QString msg = "";
919   if (item->getRefBlock()->isFunctionalBlock()) {
920     msg = "Removing block ";
921   }
922   else {
923      msg = "Removing group ";
924   }
925   msg += item->getRefBlock()->getName();
926   msg += " and all its connections.\n\nAre you sure ?";
927
928   int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
929   if (ret == QMessageBox::Cancel) {
930     return;
931   }
932   removeAllBlockConnections(item);
933
934   if (item->getRefBlock()->isFunctionalBlock()) {
935     FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());    
936     item->getScene()->removeBoxItem(item);
937     params->getGraph()->removeFunctionalBlock(block);
938     params->blockToItem.remove(block);
939
940   }
941   else if (item->getRefBlock()->isGroupBlock()) {
942
943     GroupBlock* group = AB_TO_GRP(item->getRefBlock());
944
945     // remove all child scenes recursively
946     GroupItem* subgroup = item->getChildGroupItem();
947     destroyScene(subgroup->getScene());
948     // remove the BoxItem
949     item->getScene()->removeBoxItem(item);
950     // remove the group from the graph
951     params->getGraph()->removeGroupBlock(group);
952   }
953 }
954
955 void Dispatcher::removeAllBlockConnections(AbstractBoxItem *item) {
956   static QString fctName = "Dispatcher::removeAllBlockConnection()";
957 #ifdef DEBUG_FCTNAME
958   cout << "call to " << qPrintable(fctName) << endl;
959 #endif
960
961   foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
962     foreach(ConnectionItem* conn, ifaceItem->connections) {
963       removeConnection(conn);
964     }
965   }
966 }
967
968 void Dispatcher::removeSourceItem(SourceItem *item) {
969   static QString fctName = "Dispatcher::removeSourceItem()";
970 #ifdef DEBUG_FCTNAME
971   cout << "call to " << qPrintable(fctName) << endl;
972 #endif
973   
974   QString msg = "Removing source ";
975   
976   msg += item->getRefBlock()->getName();
977   msg += " and all its connections.\n\nAre you sure ?";
978
979   int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
980   if (ret == QMessageBox::Cancel) {
981     return;
982   }
983   removeAllBlockConnections(item);
984   
985   FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());  
986   item->getScene()->removeSourceItem(item);
987   params->getGraph()->removeSourceBlock(block);  
988 }
989
990
991 void Dispatcher::removeConnection(ConnectionItem *connItem) {
992   static QString fctName = "Dispatcher::removeConnection()";
993 #ifdef DEBUG_FCTNAME
994   cout << "call to " << qPrintable(fctName) << endl;
995 #endif
996   InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
997   InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
998
999 #ifdef DEBUG
1000   cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
1001 #endif
1002
1003   InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
1004   GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
1005
1006   ConnectedInterface *fromInter = fromIfaceItem->refInter;
1007   ConnectedInterface *toInter = toIfaceItem->refInter;  
1008   
1009   // test if one of the interface bounded to item is owned by a GroupItem
1010   if (fromIfaceItem->getOwner()->isGroupItem()) {
1011     groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
1012     groupIfaceItem = fromIfaceItem;    
1013   }
1014   else if (toIfaceItem->getOwner()->isGroupItem()) {
1015     groupItem = ABI_TO_GI(toIfaceItem->getOwner());
1016     groupIfaceItem = toIfaceItem;    
1017   }
1018   else {
1019     groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
1020   }
1021
1022   // removing the connection from graph
1023 #ifdef DEBUG
1024   cout << "removing connections from graph ..." ;
1025 #endif  
1026   fromInter->disconnectTo(toInter);
1027   
1028 #ifdef DEBUG
1029   cout << "done." << endl ;
1030 #endif
1031
1032   // removing the connection from scene
1033 #ifdef DEBUG
1034   cout << "removing connections from scene ..." ;
1035 #endif  
1036   groupItem->getScene()->removeConnectionItem(connItem);
1037
1038 #ifdef DEBUG
1039   cout << "done." << endl ;
1040 #endif
1041   
1042   // if one of the interface bounded to connItem is owned by the GroupItem of the scene
1043   if (groupIfaceItem != NULL) {
1044     
1045     // determine if the interface must be removed since it has no more connections.
1046     bool groupInterRemove = false;
1047     if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
1048     
1049     if (groupInterRemove) {
1050       // get the GroupInterface from interface item
1051       ConnectedInterface* groupInter = groupIfaceItem->refInter;            
1052       // remove interface from GroupItem, and delete it.
1053       groupItem->removeInterfaceItem(groupIfaceItem);      
1054       // get the parent BoxItem of GroupItem if it exists.
1055       BoxItem* parent2Item = groupItem->getParentItem();
1056       if (parent2Item != NULL) {
1057         InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
1058         // remove interface intem in parent BoxItem
1059         parent2Item->removeInterfaceItem(group2IfaceItem);
1060       }
1061       // remove GroupInterface in the graph.
1062       groupInter->getOwner()->removeInterface(groupInter);
1063     }
1064   }
1065 }
1066
1067 void Dispatcher::showBlocksLibrary(){
1068   cout << "showing block library" << endl;
1069   mainWindow->getLibrary()->show();
1070   mainWindow->getLibrary()->raise();
1071 }
1072
1073 void Dispatcher::showProperties(InterfaceItem *inter) {
1074   new InterfacePropertiesWindow(inter);
1075 }
1076
1077 /* connectInterToGroup() :
1078    The only way for a block (functional of group) within a GroupItem to be connected
1079    to the latter is to right-click on one of its interfaces and to choose "connect to group".
1080    That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
1081    interfaces.
1082 */
1083 void Dispatcher::connectInterToGroup(InterfaceItem *item){
1084
1085   // getting the GroupBlock and GroupItem that are parent of the block that owns item
1086   ConnectedInterface *refInter = item->refInter;
1087   cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
1088   GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
1089   cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
1090   GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
1091
1092   // creating/adding the group interface in the graph model
1093   GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());  
1094   parentItem->getRefBlock()->addInterface(groupInter);
1095   // creating/adding the group control interface in the graph model if the purpose is data
1096   if (refInter->getPurpose() == AbstractInterface::Data) {
1097     GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
1098     groupCtlInter->setAssociatedIface(groupInter);
1099     parentItem->getRefBlock()->addInterface(groupCtlInter);
1100   }
1101   // creating/adding the group interface in the current scene model, and connection item
1102   InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
1103   parentItem->addInterfaceItem(groupIfaceItem,true);
1104
1105   // creating the connection, in graph and with an item
1106   createConnection(item, groupIfaceItem);
1107
1108   // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
1109   BoxItem* parent2Item = parentItem->getParentItem();
1110   if(parent2Item != NULL){
1111     InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
1112     parent2Item->addInterfaceItem(blockIfaceItem,true);
1113   }
1114
1115
1116   parentItem->getScene()->updateConnectionItemsShape();
1117   unselectAllItems();
1118   params->unsaveModif = true;
1119 }
1120
1121 void Dispatcher::removeFunctionalInterface(InterfaceItem *item) {
1122   static QString fctName = "Dispatcher::removeBlockInterface()";
1123 #ifdef DEBUG_FCTNAME
1124   cout << "call to " << qPrintable(fctName) << endl;
1125 #endif
1126
1127   /* first, remove all connections from item
1128      NB:  if there is a connection to a group interface, then this
1129      method should not be called if the group interface is also
1130      connected to another interface. Normally, this is not possible
1131      because such a check is done when creating the contextual menu
1132      that allows to remove an interface.
1133    */
1134   foreach(ConnectionItem* conn, item->connections) {
1135     removeConnection(conn);
1136   }
1137
1138   ConnectedInterface* ref = item->refInter;
1139   item->getOwner()->removeInterfaceItem(item);
1140   FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
1141   fun->removeInterface(ref);
1142 }
1143
1144 void Dispatcher::removeGroupInterface(InterfaceItem *item) {
1145   static QString fctName = "Dispatcher::removeGroupInterface()";
1146 #ifdef DEBUG_FCTNAME
1147   cout << "call to " << qPrintable(fctName) << endl;
1148 #endif
1149
1150   /* NB: just remove all connections from/to this item, since when there are no more
1151      ones to a GroupItem, it is automatically deleted.
1152    */
1153   foreach(ConnectionItem* conn, item->connections) {
1154     removeConnection(conn);
1155   }
1156 }
1157
1158 QMap<int, QString> Dispatcher::getAllGroupNames() {
1159
1160   QMap<int, QString> list;
1161   foreach(GroupWidget *group, groupList) {
1162     list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
1163   }
1164   return list;
1165 }
1166
1167 GroupScene* Dispatcher::getSceneById(int id) {
1168   foreach(GroupWidget *group, groupList){
1169     if(group->getScene()->getId() == id)
1170       return group->getScene();
1171   }
1172   cout << "search scene by id :" << id << " :: not found..." << endl;
1173   return NULL;
1174 }
1175
1176 GroupItem *Dispatcher::getGroupItemById(int id) {
1177   foreach(GroupWidget *group, groupList) {
1178     GroupScene* scene = group->getScene();
1179     if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1180   }
1181   cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1182   return NULL;
1183 }
1184
1185 BoxItem *Dispatcher::getBoxItemById(int id) {
1186   foreach(GroupWidget *group, groupList) {
1187
1188     GroupScene* scene = group->getScene();
1189     foreach(BoxItem *item, scene->getBoxItems()){
1190       if(item->getId() == id){
1191           return item;
1192       }
1193     }
1194   }
1195   cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1196   return NULL;
1197 }
1198
1199 InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
1200
1201   foreach(GroupWidget *group, groupList) {
1202
1203     GroupScene* scene = group->getScene();
1204
1205     foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1206       if(item->getId() == id){
1207         return item;
1208       }
1209     }
1210     foreach(BoxItem *block, scene->getBoxItems()){
1211       foreach(InterfaceItem *item, block->getInterfaces()){
1212         if(item->getId() == id){
1213           return item;
1214         }
1215       }
1216     }
1217   }
1218   cout << "search interface by id :" << id << " :: not found..." << endl;
1219   return NULL;
1220 }
1221
1222 void Dispatcher::findGraphModifications(FunctionalBlock *block) {
1223   static QString fctName = "Dispatcher::findGraphModifications()";
1224 #ifdef DEBUG_FCTNAME
1225   cout << "call to " << qPrintable(fctName) << endl;
1226 #endif
1227
1228   block->computeAdmittanceDelays();
1229   // get the block item that is associated to block
1230   BoxItem* toBlockItem = params->blockToItem.value(block);
1231
1232   /* VERSION 1: just add delays if needed */
1233   QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
1234   QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
1235   while (iterD.hasNext()) {
1236     iterD.next();
1237     QList<int>* delay = iterD.value();
1238     if (delay->at(0) > 0) {
1239       // create delay and associate it to the connected input
1240
1241       ConnectedInterface* toIface = AI_TO_CON(iterD.key());
1242       AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
1243       cout << "modify input of " << qPrintable(toIface->getName()) << endl;
1244       toIface->setInputModifier(mod);
1245       // repaint
1246       toBlockItem->update();
1247     }
1248   }
1249 }
1250