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

Private GIT Repository
insert/move/remove block/groups/interface done. Next to fo: loading project file
[blast.git] / Dispatcher.cpp
index a85b942eaf972f95b88302e0d697410aaf4884bf..b191651df14951e2d3a1b3a6bbb7d692163338e6 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "InterfacePropertiesWindow.h"
 
+int Dispatcher::sceneCounter = 0;
 
 Dispatcher::Dispatcher(Parameters* _params, MainWindow* _window) {
   params = _params;
@@ -48,6 +49,7 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) {
   currentGroup = topGroup;
   // getting the newly created scene
   GroupScene *scene = topGroup->getScene();
+
   params->setTopScene(scene);
   params->setCurrentScene(scene);
 
@@ -61,6 +63,7 @@ GroupWidget *Dispatcher::loadProject(const QString& filename) {
     return NULL;
   }
 
+  groupList.append(topGroup);
   return topGroup;
 }
 
@@ -176,10 +179,14 @@ void Dispatcher::changeConnectionMode(int mode){
   */
 }
 
-void Dispatcher::rename(AbstractBoxItem *item){
+void Dispatcher::renameBlockOrGroup(AbstractBoxItem *item){
+  static QString fctName = "Dispatcher::renameBlockOrGroup()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
   bool ok;
-  QString text = QInputDialog::getText(NULL, "Rename an element",
+  QString text = QInputDialog::getText(NULL, "Rename an block/group",
                                        "New name:", QLineEdit::Normal,
                                        item->getRefBlock()->getName(), &ok);
 
@@ -194,17 +201,24 @@ void Dispatcher::rename(AbstractBoxItem *item){
           currentGroup->setWindowTitle("blast - "+text);
         }
       }
+
+      mainWindow->getLibrary()->updateComboScene();
     }
     else {
       QMessageBox::warning(NULL,"Error in given name",
                            "the element name must be shorter than 30 characters and can't be empty!",
                            QMessageBox::Ok);
-      rename(item);
+      renameBlockOrGroup(item);
     }
   }
 }
 
-void Dispatcher::rename(InterfaceItem *item){
+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",
                                        "New name:", QLineEdit::Normal,
@@ -221,18 +235,23 @@ void Dispatcher::rename(InterfaceItem *item){
       item->refInter->setName(text);
     }
     item->setName(text);
+
   }
   else {
     QMessageBox::warning(NULL,"Error in given name",
                          "the interface name must be shorter than 30 characters and can't be empty!",
                          QMessageBox::Ok);
-    rename(item);
+    renameInterface(item);
   }
 }
 
 void Dispatcher::duplicateBlock(BoxItem *item){
+  static QString fctName = "Dispatcher::duplicateBlock()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
-  GroupScene *scene = params->getCurrentScene();
+  GroupScene *scene = item->getScene();
   AbstractBlock* block = item->getRefBlock();  
   AbstractBlock *newBlock;
 
@@ -249,7 +268,12 @@ void Dispatcher::duplicateBlock(BoxItem *item){
   }
 }
 
-void Dispatcher::duplicateInterface(InterfaceItem *item){
+void Dispatcher::duplicateInterface(InterfaceItem *item) {
+  static QString fctName = "Dispatcher::duplicateInterface()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
   AbstractInterface *refI = item->refInter;
   if (! refI->isFunctionalInterface()) return;
 
@@ -270,15 +294,26 @@ void Dispatcher::duplicateInterface(InterfaceItem *item){
 }
 
 
-void Dispatcher::addBlock(int idCategory, int idBlock) {
+void 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 = params->getCurrentScene();
-  FunctionalBlock* newOne = params->addFunctionalBlock(idCategory, idBlock);  
+  GroupScene *scene = searchSceneById(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);
+  params->unsaveModif = true;
 }
 
 
 GroupWidget *Dispatcher::createTopScene(){
+  static QString fctName = "Dispatcher::createTopScene()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
   // creating the model part of the group
   Graph* graph = params->createGraph();
@@ -292,6 +327,7 @@ GroupWidget *Dispatcher::createTopScene(){
   currentGroup = topGroup;
   // getting the newly created scene
   GroupScene *scene = topGroup->getScene();
+  scene->setId(sceneCounter++);
   params->setTopScene(scene);
   params->setCurrentScene(scene);
   // creating the view part of the group
@@ -303,45 +339,103 @@ GroupWidget *Dispatcher::createTopScene(){
 
   scene->setGroupItem(group);
 
+  groupList.append(topGroup);
   return topGroup;
 }
 
+void Dispatcher::addNewEmptyGroup(GroupScene* scene) {
+  static QString fctName = "Dispatcher::addNewEmptyGroup();";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
+  // 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);
+  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);
+
+  params->unsaveModif = true;
+
+  GroupWidget* child = createChildScene(scene->getGroupWidget(),newItem);
+  child->show();
+
+}
+
 GroupWidget *Dispatcher::createChildScene(GroupWidget* parentWidget, BoxItem *upperItemOfGroupItem) {
+  static QString fctName = "Dispatcher::createChildScene()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
-  GroupBlock* parentBlock = NULL;
+  // getting back the goup block already created
+  GroupBlock* groupBlock = NULL;
   if (upperItemOfGroupItem != NULL) {
-    parentBlock = AB_TO_GRP(upperItemOfGroupItem->getRefBlock());
-  }
-  // creating the model part of the group
-  GroupBlock *groupBlock = new GroupBlock(parentBlock);
-  groupBlock->setName("no name");
+    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();
 
   return group;
 }
 
-void Dispatcher::showRaiseWindow(AbstractBoxItem *item) {
-  GroupWidget* win = item->getScene()->getGroupWindow();
-  if (win->isTopGroup()) {
-    mainWindow->show();
-    mainWindow->raise();
+void Dispatcher::destroyScene(GroupScene *scene) {
+  foreach(GroupScene* s, scene->getChildrenScene()) {
+    destroyScene(s);
+  }
+
+  if (scene->getNbChildScene() == 0) {
+    // remove scene from the parent list
+    scene->getParentScene()->removeChildScene(scene);
+    // destroy the GroupWidget
+    groupList.removeAll(scene->getGroupWidget());
+    scene->getGroupWidget()->deleteLater();
   }
   else {
-    win->show();
-    win->raise();
+    cerr << "Abnormal case when destroying a scene" << endl;
   }
+}
+
+void Dispatcher::showRaiseWindow(BoxItem *item) {
+  static QString fctName = "Dispatcher::showRaiseWindow()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
+  cout << "raising child scene of " << qPrintable(item->getRefBlock()->getName()) << endl;
+  GroupItem* child = item->getChildGroupItem();
+  if (child == NULL) {
+    cerr << "abnormal case: child group item is null " << endl;
+    return;
+  }
+
+  GroupWidget* win = child->getScene()->getGroupWidget();
+
+  win->showNormal();
+  win->raise();
+  win->activateWindow();
+
   currentGroup = win;
   params->setCurrentScene(currentGroup->getScene());
 }
 
 void Dispatcher::showRstClkInter(AbstractBoxItem *item) {
+  static QString fctName = "Dispatcher::showRstClkInter()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
   item->setRstClkVisible(!item->isRstClkVisible());
   item->resetInterfacesPosition();
@@ -350,6 +444,11 @@ void Dispatcher::showRstClkInter(AbstractBoxItem *item) {
 }
 
 void Dispatcher::addNewFullGroup() {
+  static QString fctName = "Dispatcher::addNewFullGroup()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
 
 #ifdef DEBUG_INCLFUN
 
@@ -505,88 +604,162 @@ void Dispatcher::addNewFullGroup() {
 #endif
 }
 
-void Dispatcher::removeBlock(AbstractBoxItem *item) {
-
-#ifdef DEBUG_INCLFUN
-
-  GroupScene *scene = params->getCurrentScene();
-  AbstractBlock* block = item->getRefBlock();
-  if (block->isReferenceBlock()) return;
-
-  GroupBlock* group = (GroupBlock*)item->getParentItem()->getRefBlock();
+void Dispatcher::removeBlock(BoxItem *item) {
+  static QString fctName = "Dispatcher::removeBlock()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
-  removeConnections(item);
+  /* a BoxItem (group of func) can be removed only if none of its
+     interfaces is connected to a group interface that is itself
+     connected to another one.
+  */
+  bool canRemove = true;
 
-  //récupérer l'objet
-  group->removeBlock(block);
+  foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
+    foreach(ConnectionItem* conn, ifaceItem->connections) {
+      InterfaceItem* other = NULL;
+      if (conn->getFromInterfaceItem() == ifaceItem) {
+        other = conn->getToInterfaceItem();
+      }
+      else {
+        other = conn->getFromInterfaceItem();
+      }
 
-  //remove the associated window
-  if(block->isGroupBlock()){
-    foreach(QWidget *window, params->windows){
-      if(!window->inherits("MainWindow")){
-        if(((GroupWidget*)window)->getScene()->getGroupItem()->getRefBlock() == block){
-          params->removeWindow(window);
-          delete window;
+      if (other->getOwner()->isGroupItem()) {
+        ConnectedInterface* ref = other->refInter;
+        if ((ref->isConnectedFrom()) && (ref->isConnectedTo())) {
+          canRemove = false;
         }
       }
     }
   }
+  if (!canRemove) {
+    QMessageBox::warning(NULL,"Forbidden operation",
+                         "The block has at least one connection to a group interface that is totally connected.",
+                         QMessageBox::Ok);
+    return;
+  }
 
-  delete block;
+  QString msg = "";
+  if (item->getRefBlock()->isFunctionalBlock()) {
+    msg = "Removing block ";
+  }
+  else {
+     msg = "Removing group ";
+  }
+  msg += item->getRefBlock()->getName();
+  msg += " and all its connections.\n\nAre you sure ?";
 
-  //supprimer l'item de la scène
-  cout << "dispatcher : remove item of scene " << params->currentWindow << endl;
-  ((GroupItem *)scene->getGroupItem())->removeBlockItem(item);
-  scene->removeItem(item);
-  scene->removeBlockItem(item);
-  delete item;
+  int ret = QMessageBox::question(NULL,"Removing functional block",msg, QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+  if (ret == QMessageBox::Cancel) {
+    return;
+  }
+  removeAllBlockConnections(item);
 
-  ((GroupItem *)scene->getGroupItem())->updateShape();
+  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);
+  }
+  else if (item->getRefBlock()->isGroupBlock()) {
 
-  params->updateToolbar();
-  params->unsaveModif = true;
+    GroupBlock* group = AB_TO_GRP(item->getRefBlock());
 
-#endif
+    // remove all child scenes recursively
+    GroupItem* subgroup = item->getChildGroupItem();
+    destroyScene(subgroup->getScene());
+    // remove the BoxItem
+    item->getScene()->removeBlockItem(item);
+    // remove the group from the graph
+    params->getGraph()->removeGroupBlock(group);
+  }
 }
 
-void Dispatcher::removeAllBlockConnections(AbstractBoxItem *block) {
+void Dispatcher::removeAllBlockConnections(BoxItem *item) {
+  static QString fctName = "Dispatcher::removeAllBlockConnection()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
 
-  GroupScene* scene = block->getScene();
-  // supprimer les connections associées au bloc
-  foreach (ConnectionItem *conn, scene->getConnectionItems()) {
-    if(conn->getToInterfaceItem()->owner == block || conn->getFromInterfaceItem()->owner == block){
+  foreach(InterfaceItem* ifaceItem, item->getInterfaces()) {
+    foreach(ConnectionItem* conn, ifaceItem->connections) {
       removeConnection(conn);
     }
   }
-  scene->getGroupItem()->updateInterfacesAndConnections();
 }
 
 void Dispatcher::removeConnection(ConnectionItem *conn) {
+  static QString fctName = "Dispatcher::removeConnection()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+  InterfaceItem* fromIfaceItem = conn->getFromInterfaceItem();
+  InterfaceItem* toIfaceItem = conn->getToInterfaceItem();
 
-  GroupScene *scene = params->getCurrentScene();
-  GroupItem* currentGroup = scene->getGroupItem();
+#ifdef DEBUG
+  cout << "remove connection from " << qPrintable(fromIfaceItem->refInter->getName()) << " to " << qPrintable(toIfaceItem->refInter->getName()) << endl;
+#endif
 
-  conn->getFromInterfaceItem()->unconnectTo(conn->getToInterfaceItem());  
+  InterfaceItem* groupIfaceItem = NULL; // in case of one of the two interface belongs to the GroupItem
+  GroupItem* groupItem = NULL;
+
+  if (fromIfaceItem->getOwner()->isGroupItem()) {
+    groupIfaceItem = fromIfaceItem;
+    groupItem = toIfaceItem->getOwner()->getScene()->getGroupItem();
+  }
+  else if (toIfaceItem->getOwner()->isGroupItem()) {
+    groupIfaceItem = toIfaceItem;
+    groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
+  }
+  else {
+    groupItem = fromIfaceItem->getOwner()->getScene()->getGroupItem();
+  }
 
-  scene->removeConnectionItem(conn);
-  delete 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();
+  }
+#ifdef DEBUG
+  cout << "done." << endl ;
+#endif
 
-  currentGroup->updateInterfacesAndConnections();
-  params->unsaveModif = true;
-}
+  // removing the connection from scene
+#ifdef DEBUG
+  cout << "removing connections from scene ..." ;
+#endif
+  fromIfaceItem->removeConnectionItem(conn);
+  toIfaceItem->removeConnectionItem(conn);
+  groupItem->getScene()->removeConnectionItem(conn);
 
-void Dispatcher::removeUselessGroupInterfaces() {
+#ifdef DEBUG
+  cout << "done." << endl ;
+#endif
 
-  GroupScene *scene = params->getCurrentScene();
-  GroupItem* currentGroup = scene->getGroupItem();
+  if (groupIfaceItem != NULL) {
+    ConnectedInterface* groupInter = groupIfaceItem->refInter;
+    groupItem->removeInterface(groupIfaceItem);
 
-  foreach(InterfaceItem *inter, currentGroup->getInterfaces()) {
-    if(inter->refInter->getConnectedTo().length() == 0) {
-      // NB : remove from view also remove from model
-      currentGroup->removeInterface(inter);           
+    BoxItem* parent2Item = groupItem->getParentItem();
+    if (parent2Item != NULL) {
+      InterfaceItem* group2IfaceItem = parent2Item->searchInterfaceByRef(groupInter);
+      parent2Item->removeInterface(group2IfaceItem);
     }
+    groupInter->getOwner()->removeInterface(groupInter);
   }
-  scene->updateConnectionItemsShape();
 }
 
 void Dispatcher::showBlocksLibrary(){
@@ -610,7 +783,9 @@ void Dispatcher::connectInterToGroup(InterfaceItem *item){
 
   // getting the GroupBlock and GroupItem that are parent of the block that owns item
   ConnectedInterface *refInter = item->refInter;
+  cout << "owner of iface = " << qPrintable(refInter->getOwner()->getName()) << endl;
   GroupBlock* parentBlock = AB_TO_GRP(refInter->getOwner()->getParent());
+  cout << "create iface for parent group = " << qPrintable(parentBlock->getName()) << endl;
   GroupItem *parentItem = item->getOwner()->getScene()->getGroupItem();
 
   // creating/adding the group interface in the graph model
@@ -679,7 +854,7 @@ void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) {
 
   if (refInter->getDirection() == AbstractInterface::Output) {
     groupInter = refInter->getConnectionToParentGroup(); // must be a single connection to
-    refInter->clearConnectedTo();
+    refInter->removeConnectedTo(groupInter);
     groupInter->clearConnectedFrom();
   }
   else if (refInter->getDirection() == AbstractInterface::Input) {
@@ -756,6 +931,28 @@ void Dispatcher::disconnectInterFromGroup(InterfaceItem *item) {
 #endif
 
 }
+void Dispatcher::removeBlockInterface(InterfaceItem *item) {
+  static QString fctName = "Dispatcher::removeBlockInterface()";
+#ifdef DEBUG_FCTNAME
+  cout << "call to " << qPrintable(fctName) << endl;
+#endif
+
+  /* first, remove all connections from item
+     NB:  if there is a connection to a group interface, then this
+     method should not be called if the group interface is also
+     connected to another interface. Normally, this is not possible
+     because such a check is done when creating the contextual menu
+     that allows to remove an interface.
+   */
+  foreach(ConnectionItem* conn, item->connections) {
+    removeConnection(conn);
+  }
+
+  ConnectedInterface* ref = item->refInter;
+  item->getOwner()->removeInterface(item);
+  FunctionalBlock* fun = AB_TO_FUN(ref->getOwner());
+  fun->removeInterface(ref);
+}
 
 void Dispatcher::removeGroupInterface(InterfaceItem *item) {
   static QString fctName = "Dispatcher::removeGroupInterface()";
@@ -775,6 +972,15 @@ void Dispatcher::removeGroupInterface(InterfaceItem *item) {
   }
 }
 
+QMap<int, QString> Dispatcher::getAllGroupNames() {
+
+  QMap<int, QString> list;
+  foreach(GroupWidget *group, groupList) {
+    list.insert(group->getScene()->getId(), group->getScene()->getGroupItem()->getRefBlock()->getName());
+  }
+  return list;
+}
+
 GroupScene* Dispatcher::searchSceneById(int id) {
   foreach(GroupWidget *group, groupList){
     if(group->getScene()->getId() == id)