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

Private GIT Repository
started VHDL generation of GroupBlock
[blast.git] / Dispatcher.cpp
index b191651df14951e2d3a1b3a6bbb7d692163338e6..c3ff33fd91b713078ff111e3ec9e2389b630477c 100644 (file)
 #include "GroupScene.h"
 #include "GroupItem.h"
 #include "BoxItem.h"
+#include "SourceItem.h"
 #include "InterfaceItem.h"
 #include "ConnectionItem.h"
 
 #include "BlockLibraryWidget.h"
 #include "BlockLibraryTree.h"
 
+#include "AbstractInputModifier.h"
+#include "DelayInputModifier.h"
+
+
 #include "InterfacePropertiesWindow.h"
 
 int Dispatcher::sceneCounter = 0;
@@ -44,6 +49,7 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) {
     return NULL;
   }
 
+  /*
   // creating the top widget/scene
   topGroup = new GroupWidget(NULL,this,params);
   currentGroup = topGroup;
@@ -52,9 +58,9 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) {
 
   params->setTopScene(scene);
   params->setCurrentScene(scene);
-
+*/
   try {   
-    params->loadProject(root);
+    topGroup = params->loadProject(root);
   }
   catch(Exception e){
     cerr << qPrintable(e.getDefaultMessage()) << endl;
@@ -63,6 +69,9 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) {
     return NULL;
   }
 
+  QFileInfo info(filename);
+  params->projectPath = info.absolutePath();
+  cout << "project path = " << qPrintable(params->projectPath) << endl;
   groupList.append(topGroup);
   return topGroup;
 }
@@ -72,64 +81,50 @@ void Dispatcher::closeCurrentProject() {
   foreach(GroupWidget* win, groupList) {
     win->deleteLater();
   }
+  groupList.clear();
   params->destroyGraph();
+  topGroup = NULL;
+  currentGroup = NULL;
+  sceneCounter = 0;
 }
 
-bool Dispatcher::connect(InterfaceItem *iface1, InterfaceItem *iface2) {
-
+bool Dispatcher::createConnection(InterfaceItem *iface1, InterfaceItem *iface2, bool visible) {
+    
   ConnectedInterface* ref1 = iface1->refInter;
-  ConnectedInterface* ref2 = iface2->refInter;
+  ConnectedInterface* ref2 = iface2->refInter;  
   // connect both interface
 
   bool ok1 = false;
   bool ok2 = false;
 
-  if (ref1->canConnectTo(ref2)) {
-    ok1 = ref1->connectTo(ref2);
-    ok1 = ok1 & ref2->connectFrom(ref1);
+  // test the ref1->ref2 connection
+  if ((ref1->canConnectTo(ref2)) && (ref2->canConnectFrom(ref1))) {
+    ref1->connectTo(ref2);    
+    ok1 = true;
   }
-  if (ref2->canConnectTo(ref1)) {
-    ok2 = ref2->connectTo(ref1);
-    ok2 = ok2 & ref1->connectFrom(ref2);
+  // if the frist one did not work, test ref2->ref1
+  if ((ok1 == false) && (ref2->canConnectTo(ref1)) && (ref1->canConnectFrom(ref2))) {  
+    ref2->connectTo(ref1);    
+    ok2 = true;
   }
   if ((ok1 == true) || (ok2 == true)) {
 
-    iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2);
+    iface1->getOwner()->getScene()->createConnectionItem(iface1,iface2, visible);
 
     unselectAllItems();
     params->unsaveModif = true;
+    cout << "created a connection from " << qPrintable(ref1->getName()) << " to " << qPrintable(ref2->getName()) << endl;
     return true;
   }
   return false;
 }
 
-void Dispatcher::checkSelection(){
-  InterfaceItem *iface1 = NULL;
-  InterfaceItem *iface2 = NULL;
-
-  GroupScene *scene = params->getCurrentScene();
-  QList<AbstractBoxItem*> list = scene->getGroupAndBlocks();
-  foreach(AbstractBoxItem *block, list){
-    InterfaceItem *tmp = block->getCurrentInterface();
-    if (tmp != NULL) {
-      if (iface1 == NULL) {
-        iface1 = tmp;
-      }
-      else {
-        iface2 = tmp;
-      }
-    }
-  }
-  if(iface1 != NULL && iface2 != NULL){
-    connect(iface1,iface2);
-  }
-}
 
 void Dispatcher::unselectAllItems(int direction){
 
   GroupScene *scene = params->getCurrentScene();
 
-  foreach(BoxItem* block, scene->getBlockItems()) {
+  foreach(BoxItem* block, scene->getBoxItems()) {
     block->setSelected(false);
     block->setCurrentInterface(NULL);
   }
@@ -179,74 +174,293 @@ void Dispatcher::changeConnectionMode(int mode){
   */
 }
 
-void Dispatcher::renameBlockOrGroup(AbstractBoxItem *item){
-  static QString fctName = "Dispatcher::renameBlockOrGroup()";
+void Dispatcher::generateBlockVHDL(BoxItem *item){
+  static QString fctName = "Dispatcher::generateBlockVHDL()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
 
-  bool ok;
-  QString text = QInputDialog::getText(NULL, "Rename an block/group",
+  if (item->getRefBlock()->isFunctionalBlock()) {
+    FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
+    try {
+      block->generateVHDL(params->projectPath);      
+    }
+    catch(Exception e) {
+      cout << qPrintable(e.getMessage()) << endl;
+    }
+  }
+}
+
+void Dispatcher::renameFunctionalBlock(BoxItem *item){
+  static QString fctName = "Dispatcher::renameFunctionalBlock()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+    
+  GroupWidget* win = item->getScene()->getGroupWidget();
+  
+  bool ok = false;
+  QString text = "";  
+  while (!ok) {  
+    text = QInputDialog::getText(win, "Rename a functional block",
                                        "New name:", QLineEdit::Normal,
                                        item->getRefBlock()->getName(), &ok);
-
-  if(ok){
-    if(!text.isEmpty() && text.length() < 30){
-      item->getRefBlock()->setName(text);
-      if(item->isGroupItem()){
-        if (currentGroup->isTopGroup()) {
-          mainWindow->setWindowTitle("blast - "+text);
-        }
-        else {
-          currentGroup->setWindowTitle("blast - "+text);
-        }
+    if (!ok) return;
+    
+    if (text == item->getRefBlock()->getName()) return;
+    
+    if( (text.isEmpty()) || (text.length() > 30)) {
+      QMessageBox::warning(win,"Error in given name",
+                           "the block name must be shorter than 30 characters, cannot be empty",
+                           QMessageBox::Ok);
+      ok = false;
+    }
+    else {
+      FunctionalBlock* block = params->getGraph()->getFunctionalBlockByName(text, AB_TO_GRP(item->getRefBlock()->getParent()));
+      if (block != NULL) {
+        QMessageBox::warning(win,"Error in given name",
+                             "the name provided is similar to that of another functional block within the group",
+                             QMessageBox::Ok);
+        ok = false;
       }
+    }    
+  }  
+
+  item->getRefBlock()->setName(text);
+  item->nameChanged();
+}
 
-      mainWindow->getLibrary()->updateComboScene();
+void Dispatcher::renameGroupBlock(GroupItem *item){
+  static QString fctName = "Dispatcher::renameGroupBlock()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  
+  GroupWidget* win = item->getScene()->getGroupWidget();
+  
+  bool ok = false;
+  QString text = "";
+  while (!ok) {  
+    text = QInputDialog::getText(win, "Rename a group",
+                                       "New name:", QLineEdit::Normal,
+                                       item->getRefBlock()->getName(), &ok);
+    if (!ok) return;
+    
+    if (text == item->getRefBlock()->getName()) return;
+    
+    if( (text.isEmpty()) || (text.length() > 30)) {
+      QMessageBox::warning(win,"Error in given name",
+                           "the block name must be shorter than 30 characters, cannot be empty",
+                           QMessageBox::Ok);
+      ok = false;
     }
     else {
-      QMessageBox::warning(NULL,"Error in given name",
-                           "the element name must be shorter than 30 characters and can't be empty!",
+      GroupBlock* block = params->getGraph()->getGroupBlockByName(text);
+      if (block != NULL) {
+        QMessageBox::warning(win,"Error in given name",
+                             "the name provided is similar to that of another group",
+                             QMessageBox::Ok);
+        ok = false;
+      }
+    }    
+  }
+  
+  item->getRefBlock()->setName(text);
+  if(item->getScene()->getGroupWidget()->isTopGroup()) {
+    mainWindow->setWindowTitle("blast - "+text);
+  }
+  else {
+    item->getScene()->getGroupWidget()->setWindowTitle("blast - "+text);
+  }
+  item->nameChanged();
+  mainWindow->getLibrary()->updateComboScene();   
+}
+
+void Dispatcher::renameSourceBlock(SourceItem *item){
+  static QString fctName = "Dispatcher::renameSourceBlock()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+    
+  GroupWidget* win = item->getScene()->getGroupWidget();
+  
+  bool ok = false;
+  QString text = "";  
+  while (!ok) {  
+    text = QInputDialog::getText(win, "Rename a source",
+                                       "New name:", QLineEdit::Normal,
+                                       item->getRefBlock()->getName(), &ok);
+    if (!ok) return;
+    
+    if (text == item->getRefBlock()->getName()) return;
+    
+    if( (text.isEmpty()) || (text.length() > 30)) {
+      QMessageBox::warning(win,"Error in given name",
+                           "the block name must be shorter than 30 characters, cannot be empty",
                            QMessageBox::Ok);
-      renameBlockOrGroup(item);
+      ok = false;
     }
-  }
+    else {
+      FunctionalBlock* block = params->getGraph()->getSourceBlockByName(text);
+      if (block != NULL) {
+        QMessageBox::warning(win,"Error in given name",
+                             "the name provided is similar to that of another source block within the top group",
+                             QMessageBox::Ok);
+        ok = false;
+      }
+    }    
+  }  
+
+  item->getRefBlock()->setName(text);
+  item->nameChanged();
 }
 
+
 void Dispatcher::renameInterface(InterfaceItem *item) {
   static QString fctName = "Dispatcher::renameInterface()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
 
-  bool ok;
-  QString text = QInputDialog::getText(NULL, "Rename an interface",
+  GroupWidget* win = item->getOwner()->getScene()->getGroupWidget();
+  
+  bool ok = false;
+  QString text = "";
+  while (!ok) {
+    text = QInputDialog::getText(win, "Rename an interface",
                                        "New name:", QLineEdit::Normal,
                                        item->refInter->getName(), &ok);
+   
+    if (!ok) return;
+    
+    if (text == item->refInter->getName()) return;
+    
+    if( (text.isEmpty()) || (text.length() > 30)) {
+      QMessageBox::warning(win,"Error in given name",
+                           "the interface name must be shorter than 30 characters, cannot be empty",
+                           QMessageBox::Ok);
+      ok = false;
+    }
+    else {
+      AbstractInterface* iface = item->refInter->getOwner()->getIfaceFromName(text);
+      if (iface != NULL) {
+        QMessageBox::warning(win,"Error in given name",
+                             "the name provided is similar to that of another interface",
+                             QMessageBox::Ok);
+        ok = false;
+      }
+    }
+  }
+  item->refInter->setName(text);
+  AbstractInterface* assoIface = item->refInter->getAssociatedIface();
+  if (assoIface != NULL) {
+    assoIface->setName(text+"_enb");
+  }
+  item->updateName(text);
+  item->getOwner()->nameChanged();  
+}
 
-  /* CAUTION: when renaming an interface item, there are two cases :
-     - it refers to a functional block interface (fbi): the fbi keeps its name
-     and the new name is given to item
-     - it refers to a group block interface (gbi) : both gbi and item store the new name
+void Dispatcher::showPatterns(InterfaceItem *item) {
+  static QString fctName = "Dispatcher::showPatterns()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  QString msg = "";
+  if (item->refInter->getDirection() == AbstractInterface::Input) {
+    msg = "Input pattern of iface ";
+    msg += item->refInter->getName();
+    msg += " owned by ";
+    msg += item->refInter->getOwner()->getName();
+    msg += " is:\n";
+    // get the precursor output pattern
+    ConnectedInterface* connIface = AI_TO_CON(item->refInter->getAssociatedIface());
+    QList<char>* out = connIface->getConnectedFrom()->getOutputPattern();
+    // get the modifier
+    AbstractInputModifier* modifier = connIface->getInputModifier();
+    // check if the input is modified
+    if (modifier != NULL) {
+
+      out = modifier->getModifiedInput(out);
+    }
 
-   */
-  if(ok && !text.isEmpty() && text.length() < 30) {
-    if (item->refInter->getOwner()->isGroupBlock()) {
-      item->refInter->setName(text);
+    foreach(char c, *out) {
+      msg += QString::number((int)c);
+    }
+    msg += "\n";
+  }
+  else if (item->refInter->getDirection() == AbstractInterface::Output) {
+    msg = "Output pattern of iface ";
+    msg += item->refInter->getName();
+    msg += " owned by ";
+    msg += item->refInter->getOwner()->getName();
+    msg += " is:\n";
+    ConnectedInterface* iface = AI_TO_CON(item->refInter->getAssociatedIface());
+    if (iface->getOutputPattern() == NULL) return;
+    foreach(char c, *(iface->getOutputPattern())) {
+      msg += QString::number((int)c);
     }
-    item->setName(text);
+    msg += "\n";
+  }
+  QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
+}
+
+void Dispatcher::showModifier(InterfaceItem *item) {
+  static QString fctName = "Dispatcher::showModifier()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  QString msg = "";
+  ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
+  AbstractInputModifier* mod = assoIface->getInputModifier();
+  if (mod->isDelay()) {
+    DelayInputModifier* delay = (DelayInputModifier *)mod;
+    msg = "Pattern of iface ";
+    msg += item->refInter->getName();
+    msg += " owned by ";
+    msg += item->refInter->getOwner()->getName();
+    msg += " is modified by a simple delay of ";
+    msg += QString::number(delay->getDelayLength());
 
   }
-  else {
-    QMessageBox::warning(NULL,"Error in given name",
-                         "the interface name must be shorter than 30 characters and can't be empty!",
-                         QMessageBox::Ok);
-    renameInterface(item);
+  QMessageBox::information(NULL,"Interface pattern",msg,QMessageBox::Ok,QMessageBox::Ok);
+}
+
+void Dispatcher::removeModifier(InterfaceItem *item) {
+  static QString fctName = "Dispatcher::showModifier()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
+  ConnectedInterface* assoIface = AI_TO_CON(item->refInter->getAssociatedIface());
+  assoIface->clearInputModifier();
+}
+
+
+void Dispatcher::duplicateBoxItem(BoxItem *item){
+  static QString fctName = "Dispatcher::duplicateBoxItem()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
+  GroupScene *scene = item->getScene();
+  AbstractBlock* block = item->getRefBlock();  
+  AbstractBlock *newBlock;
+
+  // only duplicate functional blocks
+  if(block->isFunctionalBlock()) {
+
+    // adding to the model
+    FunctionalBlock* funBlock = (FunctionalBlock*)block;
+    newBlock = params->getGraph()->duplicateFunctionalBlock(funBlock);
+    // adding to the view
+    scene->createBoxItem(newBlock);
+
+    params->unsaveModif = true;
   }
 }
 
-void Dispatcher::duplicateBlock(BoxItem *item){
-  static QString fctName = "Dispatcher::duplicateBlock()";
+void Dispatcher::duplicateSourceItem(SourceItem *item) {
+  static QString fctName = "Dispatcher::duplicateSourceItem()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
@@ -260,16 +474,16 @@ void Dispatcher::duplicateBlock(BoxItem *item){
 
     // adding to the model
     FunctionalBlock* funBlock = (FunctionalBlock*)block;
-    newBlock = params->duplicateFunctionalBlock(funBlock);
+    newBlock = params->getGraph()->duplicateSourceBlock(funBlock);
     // adding to the view
-    scene->createBlockItem(newBlock);
+    scene->createSourceItem(newBlock);
 
     params->unsaveModif = true;
   }
 }
 
-void Dispatcher::duplicateInterface(InterfaceItem *item) {
-  static QString fctName = "Dispatcher::duplicateInterface()";
+void Dispatcher::duplicateInterfaceItem(InterfaceItem *item) {
+  static QString fctName = "Dispatcher::duplicateInterfaceItem()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
@@ -281,31 +495,57 @@ void Dispatcher::duplicateInterface(InterfaceItem *item) {
   if(! refB->isFunctionalBlock()) return;
 
   FunctionalInterface* iface = (FunctionalInterface*)refI;
-  AbstractInterface *otherRef = iface->clone();
-  if (otherRef == NULL) {
+  AbstractInterface *cloneIface = iface->clone();
+  if (cloneIface == NULL) {
     QMessageBox::warning(NULL,"Error while cloning an interface","the interface cannot be cloned because its maximum multiplicity is reached", QMessageBox::Ok);
     return;
   }
 
-  refB->addInterface(otherRef);
-
-  InterfaceItem *otherIface = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)otherRef,item->getOwner(),params);
-  item->getOwner()->addInterface(otherIface,true);
+  refB->addInterface(cloneIface);
+
+  InterfaceItem *cloneIfaceItem = new InterfaceItem(item->getPosition(),item->getOrientation(),(ConnectedInterface*)cloneIface,item->getOwner(),params);
+  item->getOwner()->addInterfaceItem(cloneIfaceItem,true);
+  
+  // creating control interface if needed
+  if (refI->getAssociatedIface() != NULL) {
+    QString ctlName = cloneIface->getName()+"_enb";
+    ReferenceInterface* ctlIface = new ReferenceInterface(refB,ctlName,cloneIface->getDirection(), AbstractInterface::Control,"boolean","1", AbstractInterface::LittleEndian, 1);
+    refB->addInterface(ctlIface);
+    if (! ctlIface->setAssociatedIface(cloneIface)) {
+      cerr << "Abnormal case while cloning an interface and creating its associated control interface" << endl;
+    }
+  }
 }
 
 
-void Dispatcher::addBlock(int idCategory, int idBlock, int idScene) {
+BoxItem* Dispatcher::addBlock(int idCategory, int idBlock, int idScene) {
   static QString fctName = "Dispatcher::addBlock()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
-
-  GroupScene *scene = searchSceneById(idScene);
+  bool newSource = false;
+  BoxItem* item = NULL;
+  GroupScene *scene = getSceneById(idScene);
   ReferenceBlock* ref = params->getReferenceBlock(idCategory,idBlock);
-  GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
-  FunctionalBlock* newOne = params->getGraph()->addFunctionalBlock(group, ref);
-  scene->createBlockItem(newOne);
+  // if block has no inputs, propose to add it as a source to top scene
+  if ((scene->isTopScene()) && (ref->isGeneratorBlock())) {
+    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 ?");
+    if (ret == QMessageBox::Yes) {
+      newSource = true;      
+    }   
+  }
+  if (newSource) {
+    FunctionalBlock* newOne = params->getGraph()->createSourceBlock(ref);
+    scene->createSourceItem(newOne);
+  }
+  else {
+    GroupBlock* group = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
+    FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(group, ref);
+    item = scene->createBoxItem(newOne);
+    params->blockToItem.insert(newOne,item);
+  }
   params->unsaveModif = true;
+  return item;
 }
 
 
@@ -317,7 +557,16 @@ GroupWidget *Dispatcher::createTopScene(){
 
   // creating the model part of the group
   Graph* graph = params->createGraph();
-  GroupBlock *refBlock = graph->getTopGroup();
+  GroupBlock *topBlock = graph->getTopGroup();
+  // creating the clkrstgen block
+  ReferenceBlock* ref = params->getHiddenReferenceBlock("clkrstgen");
+  FunctionalBlock* newOne = params->getGraph()->createFunctionalBlock(topBlock, ref);  
+  ConnectedInterface* fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_clk"));
+  ConnectedInterface* toIface = AI_TO_CON(newOne->getIfaceFromName("ext_clk"));
+  fromIface->connectTo(toIface);
+  fromIface = AI_TO_CON(topBlock->getIfaceFromName("ext_reset"));
+  toIface = AI_TO_CON(newOne->getIfaceFromName("ext_reset"));
+  fromIface->connectTo(toIface);
 
   // creating a fake and not connected interface
   //AbstractInterface* iface = new GroupInterface(refBlock,"grp_iface",AbstractInterface::Input,AbstractInterface::Top);
@@ -331,7 +580,8 @@ GroupWidget *Dispatcher::createTopScene(){
   params->setTopScene(scene);
   params->setCurrentScene(scene);
   // creating the view part of the group
-  GroupItem *group = new GroupItem(NULL,refBlock,this,params);
+  GroupItem *group = new GroupItem(NULL,topBlock,this,params);
+
 
   // adding the fake interface to the top group item
   //InterfaceItem* item = new InterfaceItem(0.0 , Parameters::West, (ConnectedInterface*)iface, group, params);
@@ -343,7 +593,7 @@ GroupWidget *Dispatcher::createTopScene(){
   return topGroup;
 }
 
-void Dispatcher::addNewEmptyGroup(GroupScene* scene) {
+GroupWidget* Dispatcher::addNewEmptyGroup(GroupScene* scene, bool show) {
   static QString fctName = "Dispatcher::addNewEmptyGroup();";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -352,15 +602,16 @@ void Dispatcher::addNewEmptyGroup(GroupScene* scene) {
   // getting the parent block in the graph
   GroupBlock* parent = AB_TO_GRP(scene->getGroupItem()->getRefBlock());
   cout << "new group : parent = "<< qPrintable(parent->getName()) << endl;
-  GroupBlock* groupBlock = params->getGraph()->createChildBlock(parent);
+  GroupBlock* groupBlock = params->getGraph()->createChildGroupBlock(parent);
   cout << "new group : child = "<< qPrintable(groupBlock->getName()) << ", child of " << qPrintable(groupBlock->getParent()->getName()) << endl;
   // creating the BlockItem in the scene
-  BoxItem* newItem = scene->createBlockItem(groupBlock);
+  BoxItem* newItem = scene->createBoxItem(groupBlock);
 
   params->unsaveModif = true;
 
   GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem);
-  child->show();
+  if (show) child->show();
+  return child;
 
 }
 
@@ -370,24 +621,39 @@ GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *up
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
 
-  // getting back the goup block already created
-  GroupBlock* groupBlock = NULL;
-  if (upperItemOfGroupItem != NULL) {
-    groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
-  }  
-  // creating the view part of the group
-  GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
-  // creating the group widget
-  GroupWidget* group = new GroupWidget(parentWidget, this, params);
-  // getting the newly created scene
-  GroupScene *scene = group->getScene();
-  scene->setId(sceneCounter++);
-  // affecting group item to the scene
-  scene->setGroupItem(groupItem);
-  groupList.append(group);
-
-  mainWindow->getLibrary()->updateComboScene();
+  GroupWidget* group = NULL;
+  /* NB: this method may be called during design process or when loading
+     a project. In this case, upperItemOfGroupItem is NULL, thus a lot of things
+     cannot be initialized yet. This is why there are 2 cases below
+   */
 
+  if (upperItemOfGroupItem != NULL) {
+    // getting back the goup block already created
+    GroupBlock* groupBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
+    // creating the view part of the group
+    GroupItem *groupItem = new GroupItem(upperItemOfGroupItem,groupBlock,this,params);
+
+    // creating the group widget
+    group = new GroupWidget(parentWidget, this, params);
+    // getting the newly created scene
+    GroupScene *scene = group->getScene();
+    scene->setId(sceneCounter++);
+    // affecting group item to the scene
+    scene->setGroupItem(groupItem);
+    groupList.append(group);
+
+    mainWindow->getLibrary()->updateComboScene();
+  }
+  else {
+    GroupItem *groupItem = new GroupItem(this,params);
+    // creating the group widget
+    group = new GroupWidget(parentWidget, this, params);
+    // getting the newly created scene
+    GroupScene *scene = group->getScene();
+    // affecting group item to the scene
+    scene->setGroupItem(groupItem);
+    groupList.append(group);
+  }
   return group;
 }
 
@@ -397,8 +663,10 @@ void Dispatcher::destroyScene(GroupScene *scene) {
   }
 
   if (scene->getNbChildScene() == 0) {
-    // remove scene from the parent list
-    scene->getParentScene()->removeChildScene(scene);
+    // remove scene from the parent list, if possible
+    if (scene->getParentScene() != NULL) {
+      scene->getParentScene()->removeChildScene(scene);
+    }
     // destroy the GroupWidget
     groupList.removeAll(scene->getGroupWidget());
     scene->getGroupWidget()->deleteLater();
@@ -431,16 +699,23 @@ void Dispatcher::showRaiseWindow(BoxItem *item) {
   params->setCurrentScene(currentGroup->getScene());
 }
 
-void Dispatcher::showRstClkInter(AbstractBoxItem *item) {
-  static QString fctName = "Dispatcher::showRstClkInter()";
+void Dispatcher::showRstClkIface(AbstractBoxItem *item) {
+  static QString fctName = "Dispatcher::showRstClkIface()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
 
   item->setRstClkVisible(!item->isRstClkVisible());
-  item->resetInterfacesPosition();
+  
+}
+
+void Dispatcher::showWishboneIface(AbstractBoxItem *item) {
+  static QString fctName = "Dispatcher::showWishboneIface()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
-  item->getScene()->updateConnectionItemsShape();
+  item->setWishboneVisible(!item->isWishboneVisible());  
 }
 
 void Dispatcher::addNewFullGroup() {
@@ -604,8 +879,8 @@ void Dispatcher::addNewFullGroup() {
 #endif
 }
 
-void Dispatcher::removeBlock(BoxItem *item) {
-  static QString fctName = "Dispatcher::removeBlock()";
+void Dispatcher::removeBoxItem(BoxItem *item) {
+  static QString fctName = "Dispatcher::removeBoxItem()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
@@ -658,10 +933,11 @@ void Dispatcher::removeBlock(BoxItem *item) {
   removeAllBlockConnections(item);
 
   if (item->getRefBlock()->isFunctionalBlock()) {
-    FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());
-    GroupBlock* group = AB_TO_GRP(block->getParent());
-    item->getScene()->removeBlockItem(item);
-    params->getGraph()->removeFunctionalBlock(block,group);
+    FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());    
+    item->getScene()->removeBoxItem(item);
+    params->getGraph()->removeFunctionalBlock(block);
+    params->blockToItem.remove(block);
+
   }
   else if (item->getRefBlock()->isGroupBlock()) {
 
@@ -671,13 +947,13 @@ void Dispatcher::removeBlock(BoxItem *item) {
     GroupItem* subgroup = item->getChildGroupItem();
     destroyScene(subgroup->getScene());
     // remove the BoxItem
-    item->getScene()->removeBlockItem(item);
+    item->getScene()->removeBoxItem(item);
     // remove the group from the graph
     params->getGraph()->removeGroupBlock(group);
   }
 }
 
-void Dispatcher::removeAllBlockConnections(BoxItem *item) {
+void Dispatcher::removeAllBlockConnections(AbstractBoxItem *item) {
   static QString fctName = "Dispatcher::removeAllBlockConnection()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -690,28 +966,55 @@ void Dispatcher::removeAllBlockConnections(BoxItem *item) {
   }
 }
 
-void Dispatcher::removeConnection(ConnectionItem *conn) {
+void Dispatcher::removeSourceItem(SourceItem *item) {
+  static QString fctName = "Dispatcher::removeSourceItem()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  
+  QString msg = "Removing source ";
+  
+  msg += item->getRefBlock()->getName();
+  msg += " and all its connections.\n\nAre you sure ?";
+
+  int ret = QMessageBox::question(NULL,"Removing source block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+  if (ret == QMessageBox::Cancel) {
+    return;
+  }
+  removeAllBlockConnections(item);
+  
+  FunctionalBlock* block = AB_TO_FUN(item->getRefBlock());  
+  item->getScene()->removeSourceItem(item);
+  params->getGraph()->removeSourceBlock(block);  
+}
+
+
+void Dispatcher::removeConnection(ConnectionItem *connItem) {
   static QString fctName = "Dispatcher::removeConnection()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
-  InterfaceItem* fromIfaceItem = conn->getFromInterfaceItem();
-  InterfaceItem* toIfaceItem = conn->getToInterfaceItem();
+  InterfaceItem* fromIfaceItem = connItem->getFromInterfaceItem();
+  InterfaceItem* toIfaceItem = connItem->getToInterfaceItem();
 
 #ifdef DEBUG
   cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
 #endif
 
-  InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem
-  GroupItem* groupItem = NULL;
+  InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem, and stays NULL if not
+  GroupItem* groupItem = NULL; // the GroupItem of the scene that contains connItem
 
+  ConnectedInterface *fromInter = fromIfaceItem->refInter;
+  ConnectedInterface *toInter = toIfaceItem->refInter;  
+  
+  // test if one of the interface bounded to item is owned by a GroupItem
   if (fromIfaceItem->getOwner()->isGroupItem()) {
-    groupIfaceItem = fromIfaceItem;
-    groupItem = toIfaceItem->getOwner()->getScene()->getGroupItem();
+    groupItem = ABI_TO_GI(fromIfaceItem->getOwner());
+    groupIfaceItem = fromIfaceItem;    
   }
   else if (toIfaceItem->getOwner()->isGroupItem()) {
-    groupIfaceItem = toIfaceItem;
-    groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
+    groupItem = ABI_TO_GI(toIfaceItem->getOwner());
+    groupIfaceItem = toIfaceItem;    
   }
   else {
     groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
@@ -720,19 +1023,9 @@ void Dispatcher::removeConnection(ConnectionItem *conn) {
   // removing the connection from graph
 #ifdef DEBUG
   cout << "removing connections from graph ..." ;
-#endif
-  ConnectedInterface *fromInter = fromIfaceItem->refInter;
-  ConnectedInterface *toInter = toIfaceItem->refInter;
-  if (fromInter->getDirection() == AbstractInterface::InOut) {
-    fromInter->clearConnectedTo();
-    fromInter->clearConnectedFrom();
-    toInter->clearConnectedTo();
-    toInter->clearConnectedFrom();
-  }
-  else {
-    fromInter->removeConnectedTo(toInter);
-    toInter->clearConnectedFrom();
-  }
+#endif  
+  fromInter->disconnectTo(toInter);
+  
 #ifdef DEBUG
   cout << "done." << endl ;
 #endif
@@ -740,25 +1033,35 @@ void Dispatcher::removeConnection(ConnectionItem *conn) {
   // removing the connection from scene
 #ifdef DEBUG
   cout << "removing connections from scene ..." ;
-#endif
-  fromIfaceItem->removeConnectionItem(conn);
-  toIfaceItem->removeConnectionItem(conn);
-  groupItem->getScene()->removeConnectionItem(conn);
+#endif  
+  groupItem->getScene()->removeConnectionItem(connItem);
 
 #ifdef DEBUG
   cout << "done." << endl ;
 #endif
-
+  
+  // if one of the interface bounded to connItem is owned by the GroupItem of the scene
   if (groupIfaceItem != NULL) {
-    ConnectedInterface* groupInter = groupIfaceItem->refInter;
-    groupItem->removeInterface(groupIfaceItem);
-
-    BoxItem* parent2Item = groupItem->getParentItem();
-    if (parent2Item != NULL) {
-      InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter);
-      parent2Item->removeInterface(group2IfaceItem);
+    
+    // determine if the interface must be removed since it has no more connections.
+    bool groupInterRemove = false;
+    if ((groupIfaceItem->refInter->isConnectedTo() == false) && (groupIfaceItem->refInter->isConnectedFrom() == false)) groupInterRemove = true;
+    
+    if (groupInterRemove) {
+      // get the GroupInterface from interface item
+      ConnectedInterface* groupInter = groupIfaceItem->refInter;            
+      // remove interface from GroupItem, and delete it.
+      groupItem->removeInterfaceItem(groupIfaceItem);      
+      // get the parent BoxItem of GroupItem if it exists.
+      BoxItem* parent2Item = groupItem->getParentItem();
+      if (parent2Item != NULL) {
+        InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceItemByRef(groupInter);
+        // remove interface intem in parent BoxItem
+        parent2Item->removeInterfaceItem(group2IfaceItem);
+      }
+      // remove GroupInterface in the graph.
+      groupInter->getOwner()->removeInterface(groupInter);
     }
-    groupInter->getOwner()->removeInterface(groupInter);
   }
 }
 
@@ -768,8 +1071,7 @@ void Dispatcher::showBlocksLibrary(){
   mainWindow->getLibrary()->raise();
 }
 
-void Dispatcher::showProperties(InterfaceItem *inter)
-{
+void Dispatcher::showProperties(InterfaceItem *inter) {
   new InterfacePropertiesWindow(inter);
 }
 
@@ -789,149 +1091,35 @@ void Dispatcher::connectInterToGroup(InterfaceItem *item){
   GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
 
   // creating/adding the group interface in the graph model
-  GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getLevel());
-  groupInter->setType(refInter->getType());
-  groupInter->setWidth(refInter->getWidth());
-  groupInter->setPurpose(refInter->getPurpose());
+  GroupInterface *groupInter = new GroupInterface(parentBlock,refInter->getName()+"_group",refInter->getDirection(),refInter->getPurpose());  
   parentItem->getRefBlock()->addInterface(groupInter);
-
-  // connect both interface
-  bool ok = true;
-  if (refInter->getDirection() == AbstractInterface::Output) {
-    ok = refInter->connectTo(groupInter);
-    ok = ok & groupInter->connectFrom(refInter);    
-  }
-  else if (refInter->getDirection() == AbstractInterface::Input) {
-    ok = groupInter->connectTo(refInter);
-    ok = ok & refInter->connectFrom(groupInter);
-  }
-  else if (refInter->getDirection() == AbstractInterface::InOut) {
-    ok = refInter->connectTo(groupInter);
-    ok = ok & groupInter->connectFrom(refInter);
-    ok = ok & groupInter->connectTo(refInter);
-    ok = ok & refInter->connectFrom(groupInter);
-  }
-  if (!ok) {
-    cerr << "abnormal case while connecting a block iface to its parent group" << endl;
+  // creating/adding the group control interface in the graph model if the purpose is data
+  if (refInter->getPurpose() == AbstractInterface::Data) {
+    GroupInterface *groupCtlInter = new GroupInterface(parentBlock,refInter->getName()+"_group_enb",refInter->getDirection(),AbstractInterface::Control);
+    groupCtlInter->setAssociatedIface(groupInter);
+    parentItem->getRefBlock()->addInterface(groupCtlInter);
   }
   // creating/adding the group interface in the current scene model, and connection item
   InterfaceItem *groupIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parentItem,params);
-  parentItem->addInterface(groupIfaceItem,true);
+  parentItem->addInterfaceItem(groupIfaceItem,true);
 
-  parentItem->getScene()->createConnectionItem(item, groupIfaceItem);
+  // creating the connection, in graph and with an item
+  createConnection(item, groupIfaceItem);
 
   // if groupItem is not topGroup, must also add a new interface to the parent BlockItem
   BoxItem* parent2Item = parentItem->getParentItem();
   if(parent2Item != NULL){
     InterfaceItem *blockIfaceItem = new InterfaceItem(0,item->getOrientation(),groupInter,parent2Item,params);
-    parent2Item->addInterface(blockIfaceItem,true);
+    parent2Item->addInterfaceItem(blockIfaceItem,true);
   }
 
 
   parentItem->getScene()->updateConnectionItemsShape();
   unselectAllItems();
   params->unsaveModif = true;
-
-
 }
 
-void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) {
-  static QString fctName = "Dispatcher::disconnectInterFromGroup()";
-#ifdef DEBUG_FCTNAME
-  cout << "call to " << qPrintable(fctName) << endl;
-#endif
-
-  // getting the GroupBlock and GroupItem that are parent of the block that owns item
-  ConnectedInterface *refInter = item->refInter;
-  ConnectedInterface *groupInter = NULL;
-  GroupBlock* parentGroup = AB_TO_GRP(refInter->getOwner()->getParent());
-  GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
-
-  // removing the connection from graph
-#ifdef DEBUG
-  cout << "removing connections from graph ..." ;
-#endif
-
-  if (refInter->getDirection() == AbstractInterface::Output) {
-    groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to
-    refInter->removeConnectedTo(groupInter);
-    groupInter->clearConnectedFrom();
-  }
-  else if (refInter->getDirection() == AbstractInterface::Input) {
-    groupInter = refInter->getConnectedFrom();
-    refInter->clearConnectedFrom();
-    groupInter->clearConnectedTo();
-  }
-  else if (refInter->getDirection() == AbstractInterface::InOut) {
-    groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to
-    refInter->clearConnectedTo();
-    refInter->clearConnectedFrom();
-    groupInter->clearConnectedTo();
-    groupInter->clearConnectedFrom();
-  }
-#ifdef DEBUG
-  cout << "done." << endl ;
-#endif
-
-  if (groupInter == NULL) {
-    cerr << "abnormal case 1 while removing an interface item of a block, linked to a parent group" << endl;
-  }
-
-#ifdef DEBUG
-  cout << "getting group interface item, and connection item ..." ;
-#endif
-
-
-  InterfaceItem* groupIfaceItem = parentItem->searchInterfaceByRef(groupInter);
-  if (groupIfaceItem == NULL) {
-    cerr << "abnormal case 2 while removing an interface item of a block, linked to a parent group" << endl;
-  }
-  ConnectionItem* conn = parentItem->getScene()->searchConnectionItem(item,groupIfaceItem);
-  if (conn == NULL) {
-    cerr << "abnormal case 3 while removing an interface item of a block, linked to a parent group" << endl;
-  }
-#ifdef DEBUG
-  cout << "done." << endl ;
-#endif
-
-  // removing the interface group item from the group item, and the connection item
-#ifdef DEBUG
-  cout << "removing group interface item, and connection item ..." ;
-#endif
-
-  item->removeConnectionItem(conn);
-  groupIfaceItem->removeConnectionItem(conn);
-  parentItem->removeInterface(groupIfaceItem); // CAUTION : this deletes the interface item.
-  parentItem->getScene()->removeConnectionItem(conn);
-#ifdef DEBUG
-  cout << "done." << endl ;
-#endif
-
-  // removing the interface box item in the parent scene
-#ifdef DEBUG
-  cout << "removing the inteeface item of box item in parent scene if needed ..." ;
-#endif
-
-  BoxItem* parent2Item = parentItem->getParentItem();
-  if (parent2Item != NULL) {
-    InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter);
-    parent2Item->removeInterface(group2IfaceItem);
-  }
-#ifdef DEBUG
-  cout << "done." << endl ;
-#endif
-
-  // removing the interface group from the group
-#ifdef DEBUG
-  cout << "removing group interface ..." ;
-#endif
-  parentGroup->removeInterface(groupInter);
-#ifdef DEBUG
-  cout << "done." << endl ;
-#endif
-
-}
-void Dispatcher::removeBlockInterface(InterfaceItem *item) {
+void Dispatcher::removeFunctionalInterface(InterfaceItem *item) {
   static QString fctName = "Dispatcher::removeBlockInterface()";
 #ifdef DEBUG_FCTNAME
   cout << "call to " << qPrintable(fctName) << endl;
@@ -949,7 +1137,7 @@ void Dispatcher::removeBlockInterface(InterfaceItem *item) {
   }
 
   ConnectedInterface* ref = item->refInter;
-  item->getOwner()->removeInterface(item);
+  item->getOwner()->removeInterfaceItem(item);
   FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
   fun->removeInterface(ref);
 }
@@ -960,15 +1148,11 @@ void Dispatcher::removeGroupInterface(InterfaceItem *item) {
   cout << "call to " << qPrintable(fctName) << endl;
 #endif
 
-  /* NB: there is a single connection between item and another one that is owned
-     by a BoxItem. Thus, we just have to find it and to call disconnectInterFromGroup();
+  /* NB: just remove all connections from/to this item, since when there are no more
+     ones to a GroupItem, it is automatically deleted.
    */
-  ConnectionItem* conn = item->connections.at(0);
-  if (conn->getFromInterfaceItem() == item) {
-    disconnectInterFromGroup(conn->getToInterfaceItem());
-  }
-  else {
-    disconnectInterFromGroup(conn->getFromInterfaceItem());
+  foreach(ConnectionItem* conn, item->connections) {
+    removeConnection(conn);
   }
 }
 
@@ -981,7 +1165,7 @@ QMap<int, QString> Dispatcher::getAllGroupNames() {
   return list;
 }
 
-GroupScene* Dispatcher::searchSceneById(int id) {
+GroupScene* Dispatcher::getSceneById(int id) {
   foreach(GroupWidget *group, groupList){
     if(group->getScene()->getId() == id)
       return group->getScene();
@@ -990,7 +1174,7 @@ GroupScene* Dispatcher::searchSceneById(int id) {
   return NULL;
 }
 
-GroupItem *Dispatcher::searchGroupItemById(int id) {
+GroupItem *Dispatcher::getGroupItemById(int id) {
   foreach(GroupWidget *group, groupList) {
     GroupScene* scene = group->getScene();
     if (scene->getGroupItem()->getId() == id) return scene->getGroupItem();
@@ -999,11 +1183,11 @@ GroupItem *Dispatcher::searchGroupItemById(int id) {
   return NULL;
 }
 
-BoxItem *Dispatcher::searchBlockItemById(int id) {
+BoxItem *Dispatcher::getBoxItemById(int id) {
   foreach(GroupWidget *group, groupList) {
 
     GroupScene* scene = group->getScene();
-    foreach(BoxItem *item, scene->getBlockItems()){
+    foreach(BoxItem *item, scene->getBoxItems()){
       if(item->getId() == id){
           return item;
       }
@@ -1013,7 +1197,7 @@ BoxItem *Dispatcher::searchBlockItemById(int id) {
   return NULL;
 }
 
-InterfaceItem* Dispatcher::searchInterfaceItemById(int id) {
+InterfaceItem* Dispatcher::getInterfaceItemById(int id) {
 
   foreach(GroupWidget *group, groupList) {
 
@@ -1024,7 +1208,7 @@ InterfaceItem* Dispatcher::searchInterfaceItemById(int id) {
         return item;
       }
     }
-    foreach(BoxItem *block, scene->getBlockItems()){
+    foreach(BoxItem *block, scene->getBoxItems()){
       foreach(InterfaceItem *item, block->getInterfaces()){
         if(item->getId() == id){
           return item;
@@ -1036,3 +1220,32 @@ InterfaceItem* Dispatcher::searchInterfaceItemById(int id) {
   return NULL;
 }
 
+void Dispatcher::findGraphModifications(FunctionalBlock *block) {
+  static QString fctName = "Dispatcher::findGraphModifications()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
+  block->computeAdmittanceDelays();
+  // get the block item that is associated to block
+  BoxItem* toBlockItem = params->blockToItem.value(block);
+
+  /* VERSION 1: just add delays if needed */
+  QMap<AbstractInterface*,QList<int>* > delays = block->getAdmittanceDelays();
+  QMapIterator<AbstractInterface*,QList<int>* > iterD(delays);
+  while (iterD.hasNext()) {
+    iterD.next();
+    QList<int>* delay = iterD.value();
+    if (delay->at(0) > 0) {
+      // create delay and associate it to the connected input
+
+      ConnectedInterface* toIface = AI_TO_CON(iterD.key());
+      AbstractInputModifier* mod = new DelayInputModifier(toIface, delay->at(0));
+      cout << "modify input of " << qPrintable(toIface->getName()) << endl;
+      toIface->setInputModifier(mod);
+      // repaint
+      toBlockItem->update();
+    }
+  }
+}
+