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

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