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

Private GIT Repository
added impl xsd + patterns in impls
[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;
228   QString text = QInputDialog::getText(NULL, "Rename an interface",
229                                        "New name:", QLineEdit::Normal,
230                                        item->refInter->getName(), &ok);
231
232   /* CAUTION: when renaming an interface item, there are two cases :
233      - it refers to a functional block interface (fbi): the fbi keeps its name
234      and the new name is given to item
235      - it refers to a group block interface (gbi) : both gbi and item store the new name
236
237    */
238   if(ok && !text.isEmpty() && text.length() < 30) {
239     if (item->refInter->getOwner()->isGroupBlock()) {
240       item->refInter->setName(text);
241     }
242   }
243   else {
244     QMessageBox::warning(NULL,"Error in given name",
245                          "the interface name must be shorter than 30 characters and can't be empty!",
246                          QMessageBox::Ok);
247     renameInterface(item);
248   }
249 }
250
251 void Dispatcher::duplicateBlock(BoxItem *item){
252   static QString fctName = "Dispatcher::duplicateBlock()";
253 #ifdef DEBUG_FCTNAME
254   cout << "call to " << qPrintable(fctName) << endl;
255 #endif
256
257   GroupScene *scene = item->getScene();
258   AbstractBlock* block = item->getRefBlock();  
259   AbstractBlock *newBlock;
260
261   // only duplicate functional blocks
262   if(block->isFunctionalBlock()) {
263
264     // adding to the model
265     FunctionalBlock* funBlock = (FunctionalBlock*)block;
266     newBlock = params->duplicateFunctionalBlock(funBlock);
267     // adding to the view
268     scene->createBlockItem(newBlock);
269
270     params->unsaveModif = true;
271   }
272 }
273
274 void Dispatcher::duplicateInterface(InterfaceItem *item) {
275   static QString fctName = "Dispatcher::duplicateInterface()";
276 #ifdef DEBUG_FCTNAME
277   cout << "call to " << qPrintable(fctName) << endl;
278 #endif
279
280   AbstractInterface *refI = item->refInter;
281   if (! refI->isFunctionalInterface()) return;
282
283   AbstractBlock *refB = refI->getOwner();
284   if(! refB->isFunctionalBlock()) return;
285
286   FunctionalInterface* iface = (FunctionalInterface*)refI;
287   AbstractInterface *otherRef = iface->clone();
288   if (otherRef == NULL) {
289     QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
290     return;
291   }
292
293   refB->addInterface(otherRef);
294
295   InterfaceItem *otherIface = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)otherRef,item->getOwner(),params);
296   item->getOwner()->addInterface(otherIface,true);
297 }
298
299
300 void Dispatcher::addBlock(int idCategory, int idBlock, int idScene) {
301   static QString fctName = "Dispatcher::addBlock()";
302 #ifdef DEBUG_FCTNAME
303   cout << "call to " << qPrintable(fctName) << endl;
304 #endif
305
306   GroupScene *scene = searchSceneById(idScene);
307   ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
308   GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
309   FunctionalBlock* newOne = params->getGraph()->addFunctionalBlock(group, ref);
310   scene->createBlockItem(newOne);
311   params->unsaveModif = true;
312 }
313
314
315 GroupWidget *Dispatcher::createTopScene(){
316   static QString fctName = "Dispatcher::createTopScene()";
317 #ifdef DEBUG_FCTNAME
318   cout << "call to " << qPrintable(fctName) << endl;
319 #endif
320
321   // creating the model part of the group
322   Graph* graph = params->createGraph();
323   GroupBlock *refBlock = graph->getTopGroup();
324
325   // creating a fake and not connected interface
326   //AbstractInterface* iface = new GroupInterface(refBlock,"grp_iface",AbstractInterface::Input,AbstractInterface::Top);
327
328   // creating the group widget
329   topGroup = new GroupWidget(NULL,this,params);
330   currentGroup = topGroup;
331   // getting the newly created scene
332   GroupScene *scene = topGroup->getScene();
333   scene->setId(sceneCounter++);
334   params->setTopScene(scene);
335   params->setCurrentScene(scene);
336   // creating the view part of the group
337   GroupItem *group = new GroupItem(NULL,refBlock,this,params);
338
339   // adding the fake interface to the top group item
340   //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
341   //group->addInterface(item,true);
342
343   scene->setGroupItem(group);
344
345   groupList.append(topGroup);
346   return topGroup;
347 }
348
349 GroupWidget* Dispatcher::addNewEmptyGroup(GroupScene* scene, bool show) {
350   static QString fctName = "Dispatcher::addNewEmptyGroup();";
351 #ifdef DEBUG_FCTNAME
352   cout << "call to " << qPrintable(fctName) << endl;
353 #endif
354
355   // getting the parent block in the graph
356   GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
357   cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
358   GroupBlock* groupBlock = params->getGraph()->createChildBlock(parent);
359   cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
360   // creating the BlockItem in the scene
361   BoxItem* newItem = scene->createBlockItem(groupBlock);
362
363   params->unsaveModif = true;
364
365   GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem);
366   if (show) child->show();
367   return child;
368
369 }
370
371 GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
372   static QString fctName = "Dispatcher::createChildScene()";
373 #ifdef DEBUG_FCTNAME
374   cout << "call to " << qPrintable(fctName) << endl;
375 #endif
376
377   GroupWidget* group = NULL;
378   /* NB: this method may be called during design process or when loading
379      a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
380      cannot be initialized yet. This is why there are 2 cases below
381    */
382
383   if (upperItemOfGroupItem != NULL) {
384     // getting back the goup block already created
385     GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
386     // creating the view part of the group
387     GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
388     // creating the group widget
389     group = new GroupWidget(parentWidget, this, params);
390     // getting the newly created scene
391     GroupScene *scene = group->getScene();
392     scene->setId(sceneCounter++);
393     // affecting group item to the scene
394     scene->setGroupItem(groupItem);
395     groupList.append(group);
396
397     mainWindow->getLibrary()->updateComboScene();
398   }
399   else {
400     GroupItem *groupItem = new GroupItem(this,params);
401     // creating the group widget
402     group = new GroupWidget(parentWidget, this, params);
403     // getting the newly created scene
404     GroupScene *scene = group->getScene();
405     // affecting group item to the scene
406     scene->setGroupItem(groupItem);
407     groupList.append(group);
408   }
409   return group;
410 }
411
412 void Dispatcher::destroyScene(GroupScene *scene) {
413   foreach(GroupScene* s, scene->getChildrenScene()) {
414     destroyScene(s);
415   }
416
417   if (scene->getNbChildScene() == 0) {
418     // remove scene from the parent list
419     scene->getParentScene()->removeChildScene(scene);
420     // destroy the GroupWidget
421     groupList.removeAll(scene->getGroupWidget());
422     scene->getGroupWidget()->deleteLater();
423   }
424   else {
425     cerr << "Abnormal case when destroying a scene" << endl;
426   }
427 }
428
429 void Dispatcher::showRaiseWindow(BoxItem *item) {
430   static QString fctName = "Dispatcher::showRaiseWindow()";
431 #ifdef DEBUG_FCTNAME
432   cout << "call to " << qPrintable(fctName) << endl;
433 #endif
434
435   cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
436   GroupItem* child = item->getChildGroupItem();
437   if (child == NULL) {
438     cerr << "abnormal case: child group item is null " << endl;
439     return;
440   }
441
442   GroupWidget* win = child->getScene()->getGroupWidget();
443
444   win->showNormal();
445   win->raise();
446   win->activateWindow();
447
448   currentGroup = win;
449   params->setCurrentScene(currentGroup->getScene());
450 }
451
452 void Dispatcher::showRstClkInter(AbstractBoxItem *item) {
453   static QString fctName = "Dispatcher::showRstClkInter()";
454 #ifdef DEBUG_FCTNAME
455   cout << "call to " << qPrintable(fctName) << endl;
456 #endif
457
458   item->setRstClkVisible(!item->isRstClkVisible());
459   item->resetInterfacesPosition();
460
461   item->getScene()->updateConnectionItemsShape();
462 }
463
464 void Dispatcher::addNewFullGroup() {
465   static QString fctName = "Dispatcher::addNewFullGroup()";
466 #ifdef DEBUG_FCTNAME
467   cout << "call to " << qPrintable(fctName) << endl;
468 #endif
469
470
471 #ifdef DEBUG_INCLFUN
472
473   QList<BlockItem*> listBlocks = params->getCurrentScene()->getSelectedBlocks(); //selected blocks in the current scene
474   QList<AbstractBlock*> listAbstractBlocks;   //abstract blocks in the group
475   QList<ConnectionItem *> connections = params->getCurrentScene()->getConnectionItems();
476
477   /* What must be done:
478      1 - creating a new GroupBlock
479      2 - moving the selected blocks from the current GroupBlock to the new GroupBlock
480      3 - creating a BlockItem that references the new GroupBlock
481      4 - creating a new GroupWidget
482      5 - creating a new GroupItem added to the scene of the GroupWidget
483
484    */
485
486   /* step 1 : creating new GroupBlock that will have as a parent the GroupBlock
487      associated to the GroupItem of the current scene
488    */
489   GroupBlock* parentBlock = params->getCurrentScene()->getGroupItem()->getRefBlock();
490   GroupBlock* newGroupBlock = new GroupBlock(parentBlock);
491   /* step 2: moving selected blocks */
492   foreach(BlockItem* blockItem, listBlocks) {
493     parentBlock->removeBlock(blockItem->getRefBlock());
494     newGroupBlock->addBlock(blockItem->getRefBlock());
495   }
496
497   GroupItem *parent = currentGroup->getScene()->getGroupItem();
498   GroupBlock *groupBlock = new GroupBlock(((GroupBlock*)parent->getRefBlock()),params->currentWindow);
499   BlockItem *blockItem = new BlockItem(params->getCurrentScene()->getGroupItem(),groupBlock,this,params);
500   GroupItem *groupItem = new GroupItem(blockItem,groupBlock,this,params);
501
502   //create the new window
503   GroupWidget* win = new GroupWidget(this,params);
504   win->getScene()->setGroupItem(groupItem);
505   win->getScene()->addItem(groupItem);
506   ((GroupBlock*)groupItem->getRefBlock())->setWindow(win);
507   params->addWindow(win);
508   win->show();
509
510   //add the new group
511   params->getCurrentScene()->addBlockItem(blockItem);
512   params->getCurrentScene()->addItem(blockItem);
513   ((GroupItem*)params->getCurrentScene()->getGroupItem())->addBlockItem(blockItem);
514
515   //replace selected blocks in the group
516   foreach(AbstractBoxItem *block, listBlocks){
517     ((GroupItem*)block->getParentItem())->removeBlockItem(block);
518     ((GroupBlock*)block->getParentItem()->getRefBlock())->removeBlock(block->getRefBlock());
519     params->getCurrentScene()->removeItem(block);
520     params->getCurrentScene()->removeBlockItem(block);
521
522     groupBlock->addBlock(block->getRefBlock());
523     listAbstractBlocks.append(block->getRefBlock());
524
525     block->setUpperItem(groupItem);
526     groupItem->addBlockItem(block);
527     win->getScene()->addItem(block);
528     win->getScene()->addBlockItem(block);
529   }
530
531   //replace connection between selected blocks in the group
532   foreach(ConnectionItem *conn, connections){
533     if(listBlocks.contains(conn->getFromInterfaceItem()->getOwner())){
534       if(listBlocks.contains(conn->getToInterfaceItem()->getOwner())){
535         parent->removeConnection(conn);
536         params->getCurrentScene()->removeItem(conn);
537
538         groupItem->addConnection(conn);
539         win->getScene()->addItem(conn);
540       }
541     }
542   }
543
544   //create new interfaces and connections for the new group
545   foreach(AbstractBoxItem *block, listBlocks){
546     foreach(InterfaceItem *inter, block->getInterfaces()){
547       cout << "inter : " << inter->getName().toStdString() << endl;
548       if(inter->refInter->getConnectedFrom() != NULL && inter->refInter->getDirection() == AbstractInterface::Input){
549         cout << "connected from non null" << endl;
550         if(!listAbstractBlocks.contains(inter->refInter->getConnectedFrom()->getOwner())){
551
552           AbstractInterface *iface = inter->refInter->clone(0);
553           iface->setName(iface->getName()+"_group");
554           groupBlock->addInterface(iface);
555
556           InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
557           blockItem->addInterface(ifaceItem);
558           blockItem->resetInterfacesPosition();
559
560           InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::West,iface,groupItem,params);
561           groupItem->addInterface(ifaceGroupItem);
562           groupItem->resetInterfacesPosition();
563           foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
564             if(conn->getToInterfaceItem() == inter){
565               conn->setToInterfaceItem(ifaceItem);
566               ifaceItem->refInter->setConnectedFrom(NULL);
567               conn->getFromInterfaceItem()->refInter->clearConnectedTo();
568               connect(ifaceItem,conn->getFromInterfaceItem());
569             }
570           }
571           params->setCurrentWindow(win);
572
573           inter->refInter->setConnectedFrom(NULL);
574           ifaceGroupItem->refInter->clearConnectedTo();
575           connect(inter,ifaceGroupItem);
576           params->setCurrentWindow(mainWindow);
577         }
578       }
579
580       if(!inter->refInter->getConnectedTo().isEmpty() && inter->refInter->getDirection() == AbstractInterface::Output){
581         cout << "connected to non null" << endl;
582         foreach(AbstractInterface *iface, inter->refInter->getConnectedTo()){
583           if(!listAbstractBlocks.contains(iface->getOwner())){
584
585             AbstractInterface *iface = inter->refInter->clone(0);
586             iface->setName(iface->getName()+"_group");
587             groupBlock->addInterface(iface);
588
589             InterfaceItem *ifaceItem = new InterfaceItem(0,Parameters::East,iface,blockItem,params);
590             blockItem->addInterface(ifaceItem);
591             blockItem->resetInterfacesPosition();
592
593             foreach(ConnectionItem* conn, currentGroup->getScene()->getInterfaceConnections(inter)){
594               if(conn->getFromInterfaceItem() == inter){
595                 conn->setFromInterfaceItem(ifaceItem);
596                 iface->addConnectedTo(conn->getToInterfaceItem()->refInter);
597                 conn->getToInterfaceItem()->refInter->setConnectedFrom(iface);
598               }
599             }
600
601             InterfaceItem *ifaceGroupItem = new InterfaceItem(0,Parameters::East,iface,groupItem,params);
602             groupItem->addInterface(ifaceGroupItem);
603             groupItem->resetInterfacesPosition();
604             inter->refInter->clearConnectedTo();
605             ifaceGroupItem->refInter->setConnectedFrom(NULL);
606             connect(ifaceGroupItem,inter);
607           }
608         }
609       }
610     }
611   }
612
613   //update window
614
615   parent->updateShape();
616   currentGroup->getScene()->updateConnectionItemsShape();
617   currentGroup = win;
618   groupItem->updateShape();
619   win->getScene()->updateConnectionItemsShape();
620   groupItem->update(groupItem->boundingRect());
621
622 #endif
623 }
624
625 void Dispatcher::removeBlock(BoxItem *item) {
626   static QString fctName = "Dispatcher::removeBlock()";
627 #ifdef DEBUG_FCTNAME
628   cout << "call to " << qPrintable(fctName) << endl;
629 #endif
630
631   /* a BoxItem (group of func) can be removed only if none of its
632      interfaces is connected to a group interface that is itself
633      connected to another one.
634   */
635   bool canRemove = true;
636
637   foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
638     foreach(ConnectionItem* conn, ifaceItem->connections) {
639       InterfaceItem* other = NULL;
640       if (conn->getFromInterfaceItem() == ifaceItem) {
641         other = conn->getToInterfaceItem();
642       }
643       else {
644         other = conn->getFromInterfaceItem();
645       }
646
647       if (other->getOwner()->isGroupItem()) {
648         ConnectedInterface* ref = other->refInter;
649         if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
650           canRemove = false;
651         }
652       }
653     }
654   }
655   if (!canRemove) {
656     QMessageBox::warning(NULL,"Forbidden operation",
657                          "The block has at least one connection to a group interface that is totally connected.",
658                          QMessageBox::Ok);
659     return;
660   }
661
662   QString msg = "";
663   if (item->getRefBlock()->isFunctionalBlock()) {
664     msg = "Removing block ";
665   }
666   else {
667      msg = "Removing group ";
668   }
669   msg += item->getRefBlock()->getName();
670   msg += " and all its connections.\n\nAre you sure ?";
671
672   int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
673   if (ret == QMessageBox::Cancel) {
674     return;
675   }
676   removeAllBlockConnections(item);
677
678   if (item->getRefBlock()->isFunctionalBlock()) {
679     FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
680     GroupBlock* group = AB_TO_GRP(block->getParent());
681     item->getScene()->removeBlockItem(item);
682     params->getGraph()->removeFunctionalBlock(block,group);
683   }
684   else if (item->getRefBlock()->isGroupBlock()) {
685
686     GroupBlock* group = AB_TO_GRP(item->getRefBlock());
687
688     // remove all child scenes recursively
689     GroupItem* subgroup = item->getChildGroupItem();
690     destroyScene(subgroup->getScene());
691     // remove the BoxItem
692     item->getScene()->removeBlockItem(item);
693     // remove the group from the graph
694     params->getGraph()->removeGroupBlock(group);
695   }
696 }
697
698 void Dispatcher::removeAllBlockConnections(BoxItem *item) {
699   static QString fctName = "Dispatcher::removeAllBlockConnection()";
700 #ifdef DEBUG_FCTNAME
701   cout << "call to " << qPrintable(fctName) << endl;
702 #endif
703
704   foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
705     foreach(ConnectionItem* conn, ifaceItem->connections) {
706       removeConnection(conn);
707     }
708   }
709 }
710
711 void Dispatcher::removeConnection(ConnectionItem *conn) {
712   static QString fctName = "Dispatcher::removeConnection()";
713 #ifdef DEBUG_FCTNAME
714   cout << "call to " << qPrintable(fctName) << endl;
715 #endif
716   InterfaceItem* fromIfaceItem = conn->getFromInterfaceItem();
717   InterfaceItem* toIfaceItem = conn->getToInterfaceItem();
718
719 #ifdef DEBUG
720   cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
721 #endif
722
723   InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem
724   GroupItem* groupItem = NULL;
725
726   if (fromIfaceItem->getOwner()->isGroupItem()) {
727     groupIfaceItem = fromIfaceItem;
728     groupItem = toIfaceItem->getOwner()->getScene()->getGroupItem();
729   }
730   else if (toIfaceItem->getOwner()->isGroupItem()) {
731     groupIfaceItem = toIfaceItem;
732     groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
733   }
734   else {
735     groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
736   }
737
738   // removing the connection from graph
739 #ifdef DEBUG
740   cout << "removing connections from graph ..." ;
741 #endif
742   ConnectedInterface *fromInter = fromIfaceItem->refInter;
743   ConnectedInterface *toInter = toIfaceItem->refInter;
744   if (fromInter->getDirection() == AbstractInterface::InOut) {
745     fromInter->clearConnectedTo();
746     fromInter->clearConnectedFrom();
747     toInter->clearConnectedTo();
748     toInter->clearConnectedFrom();
749   }
750   else {
751     fromInter->removeConnectedTo(toInter);
752     toInter->clearConnectedFrom();
753   }
754 #ifdef DEBUG
755   cout << "done." << endl ;
756 #endif
757
758   // removing the connection from scene
759 #ifdef DEBUG
760   cout << "removing connections from scene ..." ;
761 #endif
762   fromIfaceItem->removeConnectionItem(conn);
763   toIfaceItem->removeConnectionItem(conn);
764   groupItem->getScene()->removeConnectionItem(conn);
765
766 #ifdef DEBUG
767   cout << "done." << endl ;
768 #endif
769
770   if (groupIfaceItem != NULL) {
771     ConnectedInterface* groupInter = groupIfaceItem->refInter;
772     groupItem->removeInterface(groupIfaceItem);
773
774     BoxItem* parent2Item = groupItem->getParentItem();
775     if (parent2Item != NULL) {
776       InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter);
777       parent2Item->removeInterface(group2IfaceItem);
778     }
779     groupInter->getOwner()->removeInterface(groupInter);
780   }
781 }
782
783 void Dispatcher::showBlocksLibrary(){
784   cout << "showing block library" << endl;
785   mainWindow->getLibrary()->show();
786   mainWindow->getLibrary()->raise();
787 }
788
789 void Dispatcher::showProperties(InterfaceItem *inter)
790 {
791   new InterfacePropertiesWindow(inter);
792 }
793
794 /* connectInterToGroup() :
795    The only way for a block (functional of group) within a GroupItem to be connected
796    to the latter is to right-click on one of its interfaces and to choose "connect to group".
797    That action will create a new InterfaceItem on the GroupItem and a connectionItem between the
798    interfaces.
799 */
800 void Dispatcher::connectInterToGroup(InterfaceItem *item){
801
802   // getting the GroupBlock and GroupItem that are parent of the block that owns item
803   ConnectedInterface *refInter = item->refInter;
804   cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
805   GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
806   cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
807   GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
808
809   // creating/adding the group interface in the graph model
810   GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection());
811   groupInter->setType(refInter->getType());
812   groupInter->setWidth(refInter->getWidth());
813   groupInter->setPurpose(refInter->getPurpose());
814   parentItem->getRefBlock()->addInterface(groupInter);
815
816   // connect both interface
817   bool ok = true;
818   if (refInter->getDirection() == AbstractInterface::Output) {
819     ok = refInter->connectTo(groupInter);
820     ok = ok & groupInter->connectFrom(refInter);    
821   }
822   else if (refInter->getDirection() == AbstractInterface::Input) {
823     ok = groupInter->connectTo(refInter);
824     ok = ok & refInter->connectFrom(groupInter);
825   }
826   else if (refInter->getDirection() == AbstractInterface::InOut) {
827     ok = refInter->connectTo(groupInter);
828     ok = ok & groupInter->connectFrom(refInter);
829     ok = ok & groupInter->connectTo(refInter);
830     ok = ok & refInter->connectFrom(groupInter);
831   }
832   if (!ok) {
833     cerr << "abnormal case while connecting a block iface to its parent group" << endl;
834   }
835   // creating/adding the group interface in the current scene model, and connection item
836   InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
837   parentItem->addInterface(groupIfaceItem,true);
838
839   parentItem->getScene()->createConnectionItem(item, groupIfaceItem);
840
841   // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
842   BoxItem* parent2Item = parentItem->getParentItem();
843   if(parent2Item != NULL){
844     InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
845     parent2Item->addInterface(blockIfaceItem,true);
846   }
847
848
849   parentItem->getScene()->updateConnectionItemsShape();
850   unselectAllItems();
851   params->unsaveModif = true;
852
853
854 }
855
856 void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) {
857   static QString fctName = "Dispatcher::disconnectInterFromGroup()";
858 #ifdef DEBUG_FCTNAME
859   cout << "call to " << qPrintable(fctName) << endl;
860 #endif
861
862   // getting the GroupBlock and GroupItem that are parent of the block that owns item
863   ConnectedInterface *refInter = item->refInter;
864   ConnectedInterface *groupInter = NULL;
865   GroupBlock* parentGroup = AB_TO_GRP(refInter->getOwner()->getParent());
866   GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
867
868   // removing the connection from graph
869 #ifdef DEBUG
870   cout << "removing connections from graph ..." ;
871 #endif
872
873   if (refInter->getDirection() == AbstractInterface::Output) {
874     groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to
875     refInter->removeConnectedTo(groupInter);
876     groupInter->clearConnectedFrom();
877   }
878   else if (refInter->getDirection() == AbstractInterface::Input) {
879     groupInter = refInter->getConnectedFrom();
880     refInter->clearConnectedFrom();
881     groupInter->clearConnectedTo();
882   }
883   else if (refInter->getDirection() == AbstractInterface::InOut) {
884     groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to
885     refInter->clearConnectedTo();
886     refInter->clearConnectedFrom();
887     groupInter->clearConnectedTo();
888     groupInter->clearConnectedFrom();
889   }
890 #ifdef DEBUG
891   cout << "done." << endl ;
892 #endif
893
894   if (groupInter == NULL) {
895     cerr << "abnormal case 1 while removing an interface item of a block, linked to a parent group" << endl;
896   }
897
898 #ifdef DEBUG
899   cout << "getting group interface item, and connection item ..." ;
900 #endif
901
902
903   InterfaceItem* groupIfaceItem = parentItem->searchInterfaceByRef(groupInter);
904   if (groupIfaceItem == NULL) {
905     cerr << "abnormal case 2 while removing an interface item of a block, linked to a parent group" << endl;
906   }
907   ConnectionItem* conn = parentItem->getScene()->searchConnectionItem(item,groupIfaceItem);
908   if (conn == NULL) {
909     cerr << "abnormal case 3 while removing an interface item of a block, linked to a parent group" << endl;
910   }
911 #ifdef DEBUG
912   cout << "done." << endl ;
913 #endif
914
915   // removing the interface group item from the group item, and the connection item
916 #ifdef DEBUG
917   cout << "removing group interface item, and connection item ..." ;
918 #endif
919
920   item->removeConnectionItem(conn);
921   groupIfaceItem->removeConnectionItem(conn);
922   parentItem->removeInterface(groupIfaceItem); // CAUTION : this deletes the interface item.
923   parentItem->getScene()->removeConnectionItem(conn);
924 #ifdef DEBUG
925   cout << "done." << endl ;
926 #endif
927
928   // removing the interface box item in the parent scene
929 #ifdef DEBUG
930   cout << "removing the inteeface item of box item in parent scene if needed ..." ;
931 #endif
932
933   BoxItem* parent2Item = parentItem->getParentItem();
934   if (parent2Item != NULL) {
935     InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter);
936     parent2Item->removeInterface(group2IfaceItem);
937   }
938 #ifdef DEBUG
939   cout << "done." << endl ;
940 #endif
941
942   // removing the interface group from the group
943 #ifdef DEBUG
944   cout << "removing group interface ..." ;
945 #endif
946   parentGroup->removeInterface(groupInter);
947 #ifdef DEBUG
948   cout << "done." << endl ;
949 #endif
950
951 }
952 void Dispatcher::removeBlockInterface(InterfaceItem *item) {
953   static QString fctName = "Dispatcher::removeBlockInterface()";
954 #ifdef DEBUG_FCTNAME
955   cout << "call to " << qPrintable(fctName) << endl;
956 #endif
957
958   /* first, remove all connections from item
959      NB:  if there is a connection to a group interface, then this
960      method should not be called if the group interface is also
961      connected to another interface. Normally, this is not possible
962      because such a check is done when creating the contextual menu
963      that allows to remove an interface.
964    */
965   foreach(ConnectionItem* conn, item->connections) {
966     removeConnection(conn);
967   }
968
969   ConnectedInterface* ref = item->refInter;
970   item->getOwner()->removeInterface(item);
971   FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
972   fun->removeInterface(ref);
973 }
974
975 void Dispatcher::removeGroupInterface(InterfaceItem *item) {
976   static QString fctName = "Dispatcher::removeGroupInterface()";
977 #ifdef DEBUG_FCTNAME
978   cout << "call to " << qPrintable(fctName) << endl;
979 #endif
980
981   /* NB: there is a single connection between item and another one that is owned
982      by a BoxItem. Thus, we just have to find it and to call disconnectInterFromGroup();
983    */
984   ConnectionItem* conn = item->connections.at(0);
985   if (conn->getFromInterfaceItem() == item) {
986     disconnectInterFromGroup(conn->getToInterfaceItem());
987   }
988   else {
989     disconnectInterFromGroup(conn->getFromInterfaceItem());
990   }
991 }
992
993 QMap<int, QString> Dispatcher::getAllGroupNames() {
994
995   QMap<int, QString> list;
996   foreach(GroupWidget *group, groupList) {
997     list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
998   }
999   return list;
1000 }
1001
1002 GroupScene* Dispatcher::searchSceneById(int id) {
1003   foreach(GroupWidget *group, groupList){
1004     if(group->getScene()->getId() == id)
1005       return group->getScene();
1006   }
1007   cout << "search scene by id :" << id << " :: not found..." << endl;
1008   return NULL;
1009 }
1010
1011 GroupItem *Dispatcher::searchGroupItemById(int id) {
1012   foreach(GroupWidget *group, groupList) {
1013     GroupScene* scene = group->getScene();
1014     if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
1015   }
1016   cout << "search GroupItem by id :" << id << " :: not found..." << endl;
1017   return NULL;
1018 }
1019
1020 BoxItem *Dispatcher::searchBlockItemById(int id) {
1021   foreach(GroupWidget *group, groupList) {
1022
1023     GroupScene* scene = group->getScene();
1024     foreach(BoxItem *item, scene->getBlockItems()){
1025       if(item->getId() == id){
1026           return item;
1027       }
1028     }
1029   }
1030   cout << "search BlockItem by id :" << id << " :: not found..." << endl;
1031   return NULL;
1032 }
1033
1034 InterfaceItem* Dispatcher::searchInterfaceItemById(int id) {
1035
1036   foreach(GroupWidget *group, groupList) {
1037
1038     GroupScene* scene = group->getScene();
1039
1040     foreach(InterfaceItem *item, scene->getGroupItem()->getInterfaces()){
1041       if(item->getId() == id){
1042         return item;
1043       }
1044     }
1045     foreach(BoxItem *block, scene->getBlockItems()){
1046       foreach(InterfaceItem *item, block->getInterfaces()){
1047         if(item->getId() == id){
1048           return item;
1049         }
1050       }
1051     }
1052   }
1053   cout << "search interface by id :" << id << " :: not found..." << endl;
1054   return NULL;
1055 }
1056