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

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