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

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