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

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