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

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