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

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